Merge "Fix build broken by cad8269d45f5478b2a9." am: b53880e298 am: 69b200cf29
am: afdfcaf806
* commit 'afdfcaf806d6d5ff0341a8c1c28dca422d7a5e86':
Fix build broken by cad8269d45f5478b2a9.
diff --git a/CtsBuild.mk b/CtsBuild.mk
index ba158ce..c745885 100644
--- a/CtsBuild.mk
+++ b/CtsBuild.mk
@@ -40,10 +40,6 @@
$(foreach executable,$(1),$(CTS_TESTCASES_OUT)/$(executable))
endef
-define cts-get-deqp-api-test-xmls
- $(foreach file,$(call find-files-in-subdirs, external/deqp/android/cts/master, 'com.drawelements.deqp.$(1).*xml', .),$(CTS_TESTCASES_OUT)/$(file))
-endef
-
define cts-get-deqp-test-xmls
- $(foreach api,$(1),$(call cts-get-deqp-api-test-xmls,$(api)))
+ $(foreach api,$(1),$(CTS_TESTCASES_OUT)/com.drawelements.deqp.$(api).xml)
endef
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 25ca6dd..04e79f9 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -17,6 +17,7 @@
CtsAppWithData \
CtsDocumentProvider \
CtsDocumentClient \
+ CtsEncryptionApp \
CtsExternalStorageApp \
CtsInstrumentationAppDiffCert \
CtsNetSecPolicyUsesCleartextTrafficFalse \
@@ -75,31 +76,31 @@
CtsUnaffiliatedAccountAuthenticators
cts_support_packages := \
- CtsAccelerationTestStubs \
+ CtsAccountManagementDevicePolicyApp \
CtsAlarmClockService \
CtsAppTestStubs \
+ CtsAppUsageTestApp \
CtsAssistService \
CtsAssistApp \
CtsAtraceTestApp \
CtsCertInstallerApp \
- CtsDeviceAdmin \
- CtsDeviceOpenGl \
+ CtsContactDirectoryProvider \
+ CtsAdminApp \
CtsWifiConfigCreator \
CtsDeviceAndProfileOwnerApp \
- CtsDeviceAppUsageTestApp \
CtsDeviceInfo \
CtsDeviceOsTestApp \
CtsDeviceOwnerApp \
- CtsDeviceTaskswitchingAppA \
- CtsDeviceTaskswitchingAppB \
- CtsDeviceTaskswitchingControl \
- CtsDeviceUi \
+ CtsServicesTestApp \
+ CtsDeviceTaskSwitchingAppA \
+ CtsDeviceTaskSwitchingAppB \
+ CtsDeviceTaskSwitchingControl \
CtsHostsideNetworkTestsApp \
CtsIntentReceiverApp \
CtsIntentSenderApp \
CtsLauncherAppsTests \
CtsLauncherAppsTestsSupport \
- CtsLeanbackJank \
+ CtsLeanbackJankApp \
CtsManagedProfileApp \
CtsMonkeyApp \
CtsMonkeyApp2 \
@@ -110,7 +111,7 @@
CtsSomeAccessibilityServices \
CtsThemeDeviceApp \
TestDeviceSetup \
- CtsUiAutomatorApp \
+ CtsUiAutomatorTestApp \
CtsUsbSerialTestApp \
CtsVoiceInteractionService \
CtsVoiceInteractionApp \
@@ -132,14 +133,7 @@
# Test packages that require an associated test package XML.
cts_test_packages := \
- CtsDeviceFilePerf \
- CtsDeviceUi \
- CtsDeviceDram \
- CtsDeviceSimpleCpu \
- CtsDeviceBrowserBench \
- CtsDeviceVideoPerf \
- CtsDeviceOpenGl \
- CtsDeviceTvProviderPerf \
+ CtsIcuTestCases \
CtsAccelerationTestCases \
CtsAccountManagerTestCases \
CtsAccessibilityServiceTestCases \
@@ -150,7 +144,9 @@
CtsAppTestCases \
CtsAppWidgetTestCases \
CtsAssistTestCases \
+ CtsAutomotiveTestCases \
CtsBluetoothTestCases \
+ CtsBrowserTestCases \
CtsCalendarcommon2TestCases \
CtsCallLogTestCases \
CtsCameraTestCases \
@@ -159,16 +155,18 @@
CtsDisplayTestCases \
CtsDpiTestCases \
CtsDpiTestCases2 \
+ CtsDramTestCases \
CtsDreamsTestCases \
CtsDrmTestCases \
CtsEffectTestCases \
+ CtsFileSystemTestCases \
CtsGestureTestCases \
CtsGraphicsTestCases \
CtsGraphics2TestCases \
CtsHardwareTestCases \
- CtsJankTestCases \
+ CtsJankDeviceTestCases \
CtsLeanbackJankTestCases \
- CtsJobSchedulerDeviceTestCases \
+ CtsJobSchedulerTestCases \
CtsJniTestCases \
CtsKeystoreTestCases \
CtsLibcoreLegacy22TestCases \
@@ -177,7 +175,6 @@
CtsMediaStressTestCases \
CtsMediaTestCases \
CtsMidiTestCases \
- CtsNativeOpenGLTestCases \
CtsNdefTestCases \
CtsNetSecPolicyUsesCleartextTrafficFalseTestCases \
CtsNetSecPolicyUsesCleartextTrafficTrueTestCases \
@@ -187,6 +184,7 @@
CtsNetTestCasesLegacyPermission22 \
CtsOpenGLTestCases \
CtsOpenGlPerfTestCases \
+ CtsOpenGlPerf2TestCases \
CtsOsTestCases \
CtsPermissionTestCases \
CtsPermission2TestCases \
@@ -201,6 +199,7 @@
CtsSaxTestCases \
CtsSecurityTestCases \
CtsSignatureTestCases \
+ CtsSimpleCpuTestCases \
CtsSpeechTestCases \
CtsSystemUiTestCases \
CtsTelecomTestCases \
@@ -208,13 +207,16 @@
CtsTelephonyTestCases \
CtsTextTestCases \
CtsTextureViewTestCases \
- CtsThemeTestCases \
+ CtsThemeDeviceTestCases \
CtsTransitionTestCases \
+ CtsTvProviderTestCases \
CtsTvTestCases \
CtsUiAutomationTestCases \
CtsUiRenderingTestCases \
+ CtsUiDeviceTestCases \
CtsUsageStatsTestCases \
CtsUtilTestCases \
+ CtsVideoTestCases \
CtsViewTestCases \
CtsVoiceInteractionTestCases \
CtsVoiceSettingsTestCases \
@@ -228,20 +230,21 @@
# Host side only tests
cts_host_libraries := \
- CtsAdbTests \
- CtsAppSecurityTests \
+ CtsAadbHostTestCases \
+ CtsAppSecurityHostTestCases \
+ CtsAppUsageHostTestCases \
CtsAtraceHostTestCases \
CtsDevicePolicyManagerTestCases \
CtsDumpsysHostTestCases \
- CtsHostJank \
+ CtsJankHostTestCases \
CtsHostsideNetworkTests \
- CtsHostUi \
CtsJdwpSecurityHostTestCases \
CtsMonkeyTestCases \
CtsOsHostTestCases \
- CtsThemeHostTestCases \
- CtsUsageHostTestCases \
CtsSecurityHostTestCases \
+ CtsServicesHostTestCases \
+ CtsThemeHostTestCases \
+ CtsUiHostTestCases \
CtsUsbTests
# List of native tests. For 32 bit targets, assumes that there will be
@@ -249,18 +252,18 @@
# that there will be two executables, one that ends in 32 for the 32
# bit executable and one that ends in 64 for the 64 bit executable.
cts_native_tests := \
- NativeMediaTest_SL \
- NativeMediaTest_XA \
+ CtsNativeMediaSlTestCases \
+ CtsNativeMediaXaTestCases \
ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
-cts_native_tests += bionic-unit-tests-cts
+cts_native_tests += CtsBionicTestCases
endif
cts_ui_tests := \
- CtsUiAutomatorTests
+ CtsUiAutomatorTestCases
cts_device_jars := \
- CtsDeviceJank \
+ CtsJankTestJar \
CtsJdwpApp
cts_target_junit_tests := \
diff --git a/apps/CameraITS/build/envsetup.sh b/apps/CameraITS/build/envsetup.sh
index 6069341..bcf294a 100644
--- a/apps/CameraITS/build/envsetup.sh
+++ b/apps/CameraITS/build/envsetup.sh
@@ -17,6 +17,8 @@
# and that the unit tests for the modules passed (indicating that the setup
# is correct).
+CAMERA_ITS_TOP=$PWD
+
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || \
{ echo ">> Script must be sourced with 'source $0'" >&2; exit 1; }
@@ -43,3 +45,6 @@
echo ">> Unit test for $M failed" >&2
done
+alias gpylint='gpylint --disable=F0401 --disable=C6304 --rcfile=$CAMERA_ITS_TOP"/build/scripts/gpylint_rcfile"'
+# F0401 ignores import errors since gpylint does not have the python paths
+# C6304 ignore Copyright line errors.
diff --git a/apps/CameraITS/build/scripts/gpylint_rcfile b/apps/CameraITS/build/scripts/gpylint_rcfile
new file mode 100644
index 0000000..43d3dbc
--- /dev/null
+++ b/apps/CameraITS/build/scripts/gpylint_rcfile
@@ -0,0 +1,388 @@
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all.
+confidence=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+disable=design,similarities,no-self-use,attribute-defined-outside-init,locally-disabled,star-args,pointless-except,bad-option-value,global-statement,fixme,suppressed-message,useless-suppression
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time. See also the "--disable" option for examples.
+#enable=
+
+
+[MODES]
+
+# DEPRECATED.
+disable-docstring=no
+
+# DEPRECATED, use --mode=base
+google=no
+
+# The configuration modes to activate (default: base).
+mode=base
+
+# The mode to use when import path setup fails (default: style).
+safe-mode=base
+
+# DEPRECATED, use --mode=style
+single-file=no
+
+# DEPRECATED, use --mode=test
+test=no
+
+# A pattern for file names that should activate test mode.
+test-filename-pattern=_(unit|reg)?test\.py$
+
+# The configuration mode to use for tests (default: test).
+test-mode=test
+
+
+[PATHS]
+
+# Directories to add to sys.path.
+#import-paths=
+
+# Inject some known modules.
+inject-known-modules=no
+
+# The import path resolver
+resolver=blaze
+
+
+[REPORTS]
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# String to print as the module footer.
+#module-footer-template=
+
+# Template for the module header. %(filename)s will be replaced with the name
+# of the file under analysis.
+#module-header-template=
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details
+#msg-template=
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=sorted-text
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+
+[BASIC]
+
+# Regular expression which should only match correct argument names
+argument-rgx=^[a-z][a-z0-9_]*$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=^_{0,2}[a-z][a-z0-9_]*$
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=input,apply,reduce
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=
+
+# Regular expression which should only match correct attribute names in class
+# bodies
+class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
+
+# Regular expression which should only match correct class names
+class-rgx=^_?[A-Z][a-zA-Z0-9]*$
+
+# Regular expression which should only match correct module level names
+const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=10
+
+# Regular expression which should only match correct function names
+# function-rgx=^(?:(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$
+function-rgx=^(?:(?P<snake_case>_?[a-z][a-z0-9_]*))$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=main,_
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=^[a-z][a-z0-9_]*$
+
+# Regular expression which should only match correct method names
+# method-rgx=^(?:(?P<exempt>__[a-z0-9_]+__|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$
+method-rgx=^(?:(?P<exempt>__[a-z0-9_]+__|next)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$
+
+# Regular expression which should only match correct module names
+module-rgx=^(_?[a-z][a-z0-9_]*)|__init__|PRESUBMIT|PRESUBMIT_unittest$
+
+# Colon delimited types of objects which should have the same naming style,
+# separated by a comma
+name-group=function:method
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=(__.*__|main)
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# Regular expression which should only match correct variable names
+variable-rgx=^[a-z][a-z0-9_]*$
+
+
+[CLASSES]
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls,class_
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[DESIGN]
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=StandardError,Exception
+
+
+[FORMAT]
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=(^\s*(import|from)\s|^__version__\s=\s['"]\$Id:|^\s*(# )?<?https?://\S+>?$)
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+# Maximum number of characters on a single line.
+max-line-length=80
+
+# Maximum number of lines in a module
+max-module-lines=99999
+
+# List of optional constructs for which whitespace checking is disabled
+no-space-check=
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=yes
+
+
+[GOOGLE AST]
+
+# List of module members that should be marked as deprecated.
+deprecated-members=string.atof,string.atoi,string.atol,string.capitalize,string.expandtabs,string.find,string.rfind,string.index,string.rindex,string.count,string.lower,string.split,string.rsplit,string.splitfields,string.join,string.joinfields,string.lstrip,string.rstrip,string.strip,string.swapcase,string.translate,string.upper,string.ljust,string.rjust,string.center,string.zfill,string.replace,sys.exitfunc
+
+# Maximum line length for lambdas.
+short-func-length=1
+
+
+[GOOGLE DOCSTRING]
+
+# List of exceptions that do not need to be mentioned in the Raises section of
+# a docstring.
+ignore-exceptions=NotImplementedError,StopIteration
+
+
+[GOOGLE IMPORTS]
+
+# List of modules that should be ignored if unused.
+ignore-unused-imports=google3
+
+
+[GOOGLE LINES]
+
+# Regexp for a proper copyright notice.
+copyright=Copyright \d{4} Google Inc\. +All Rights Reserved\.
+
+
+[GOOGLE TOKENS]
+
+# A regex for finding comments that do not have a space between leading comment
+# separators and textual content.
+comment-starts-without-space=\A#[^\s\w]*\w
+
+# Regexp for a proper TODO comment; the uid group, if any, should match the
+# user ID of the relevant person
+good-todo=# ?TODO\((?P<uid>[a-z][a-z0-9-]*)|b/(?P<bugid>[0-9]+)\):?
+
+# Number of spaces of indent required when the last token on the preceding line
+# is an open (, [, or {.
+indent-after-paren=4
+
+# Minimum number of spaces between the end of a line and an inline comment.
+min-comment-space=2
+
+# Regexp for a TODO comment, which may be incorrect.
+todo=(?i)#\s*todo
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,TERMIOS,Bastion,rexec
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[LOGGING]
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format
+logging-modules=logging,google3.pyglib.logging
+
+
+[MASTER]
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Arbitrary Python code to execute before linting.
+#init-hook=
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Pickle collected data for later comparisons.
+persistent=no
+
+# Use a custom configuration file for linting.
+#rcfile=
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=
+
+
+[SIMILARITIES]
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[TYPECHECK]
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+
+[VARIABLES]
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index cb525c8..2d8f6a9 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -27,7 +27,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := android-ex-camera2 \
android-support-v4 \
- compatibility-common-util-devicesidelib_v2 \
+ compatibility-common-util-devicesidelib \
cts-sensors-tests \
ctstestrunner \
apache-commons-math \
@@ -37,7 +37,7 @@
android-support-v4 \
mockito-target \
mockwebserver \
- compatibility-device-util_v2 \
+ compatibility-device-util \
LOCAL_PACKAGE_NAME := CtsVerifier
@@ -73,8 +73,8 @@
$(call all-Iaidl-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 \
- compatibility-common-util-devicesidelib_v2 \
- compatibility-device-util_v2 \
+ compatibility-common-util-devicesidelib \
+ compatibility-device-util \
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index e03f5dd..f15b6ee 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -58,6 +58,7 @@
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
+ <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<!-- Needed by the Audio Quality Verifier to store the sound samples that will be mailed. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -1076,6 +1077,15 @@
<meta-data android:name="test_category" android:value="@string/test_category_notifications" />
</activity>
+ <activity android:name=".notifications.ConditionProviderVerifierActivity"
+ android:label="@string/cp_test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_notifications" />
+ </activity>
+
<activity android:name=".notifications.AttentionManagementVerifierActivity"
android:label="@string/attention_test">
<intent-filter>
@@ -1107,6 +1117,15 @@
</intent-filter>
</service>
+ <service android:name=".notifications.MockConditionProvider"
+ android:exported="true"
+ android:label="@string/cp_service_name"
+ android:permission="android.permission.BIND_CONDITION_PROVIDER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.notification.ConditionProviderService" />
+ </intent-filter>
+ </service>
+
<service android:name=".notifications.InteractiveVerifierActivity$DismissService"/>
<activity android:name=".security.CAInstallNotificationVerifierActivity"
@@ -1456,6 +1475,18 @@
<meta-data android:name="test_required_features" android:value="android.software.managed_users:android.software.device_admin" />
</activity>
+ <activity android:name=".managedprovisioning.ByodProvisioningTestActivity"
+ android:label="@string/provisioning_tests_byod">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_managed_provisioning" />
+ <meta-data android:name="test_required_features" android:value="android.software.managed_users:android.software.device_admin" />
+ </activity>
+
+ <activity android:name=".managedprovisioning.ByodProvisioningTestActivity$ProvisioningStartingActivity" />
+
<activity android:name=".managedprovisioning.ByodHelperActivity">
<intent-filter>
<action android:name="com.android.cts.verifier.managedprovisioning.BYOD_QUERY" />
@@ -1835,6 +1866,16 @@
<meta-data android:name="test_required_features" android:value="android.hardware.usb.host" />
</activity>
+ <activity android:name=".audio.AudioFrequencyUnprocessedActivity"
+ android:label="@string/audio_frequency_unprocessed_test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_audio" />
+ <meta-data android:name="test_required_features" android:value="android.hardware.microphone" />
+ </activity>
+
<service android:name=".tv.MockTvInputService"
android:permission="android.permission.BIND_TV_INPUT">
<intent-filter>
diff --git a/apps/CtsVerifier/proguard.flags b/apps/CtsVerifier/proguard.flags
index 5a2beb5..591d3db 100644
--- a/apps/CtsVerifier/proguard.flags
+++ b/apps/CtsVerifier/proguard.flags
@@ -27,3 +27,10 @@
-dontwarn java.util.concurrent.ConcurrentLinkedDeque
-dontwarn android.cts.util.**
-dontwarn junit.**
+
+# Jack seems less rigorous than proguard when it comes to warning about
+# transitive dependencies.
+-dontwarn com.android.org.bouncycastle.**
+-dontwarn com.android.okhttp.**
+-dontwarn org.opencv.**
+-dontwarn android.support.test.internal.runner.hidden.ExposedInstrumentationApi
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
new file mode 100644
index 0000000..abc8033
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
@@ -0,0 +1,80 @@
+<?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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dip"
+ android:orientation="vertical"
+>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/scrollView"
+ >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ >
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scrollbars="vertical"
+ android:gravity="bottom"
+ android:id="@+id/audio_frequency_unprocessed_defined"/>
+
+ <ProgressBar
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:id="@+id/audio_frequency_unprocessed_progress_bar" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:id="@+id/audio_frequency_unprocessed_layout_test1"
+ >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/audio_frequency_unprocessed_instructions2"
+ android:id="@+id/audio_frequency_unprocessed_instructions2" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/audio_frequency_unprocessed_test1_btn"
+ android:id="@+id/audio_frequency_unprocessed_test1_btn" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/audio_frequency_unprocessed_results_text"
+ android:id="@+id/audio_frequency_unprocessed_results1_text" />
+ </LinearLayout>
+
+
+ <include layout="@layout/pass_fail_buttons" />
+ </LinearLayout>
+ </ScrollView>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 985767c..34d21cd 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1150,6 +1150,23 @@
<string name="nls_clear_all">Check that service can clear all notifications.</string>
<string name="nls_service_stopped">Service should stop once disabled.</string>
<string name="nls_note_missed">Check that notification was not received.</string>
+ <string name="cp_test">Condition Provider test</string>
+ <string name="cp_service_name">Condition Provider for CTS Verifier</string>
+ <string name="cp_info">This test checks that a ConditionProviderService can be enabled
+ and disabled, and that once enabled the service is able to create, query, edit, and delete
+ automatic zen rules.
+ </string>
+ <string name="cp_enable_service">Please enable \"CTS Verifier\" under Do Not Disturb access and return here.</string>
+ <string name="cp_disable_service">Please disable \"CTS Verifier\" under Do Not Disturb access and return here.</string>
+ <string name="cp_start_settings">Launch Settings</string>
+ <string name="cp_create_rule">Creating Automatic Zen Rule</string>
+ <string name="cp_subscribe_rule">Subscribing to Automatic Zen Rule</string>
+ <string name="cp_service_started">Service should start once enabled.</string>
+ <string name="cp_service_stopped">Service should stop once disabled.</string>
+ <string name="cp_unsubscribe_rule">Unsubscribing to Automatic Zen Rule</string>
+ <string name="cp_delete_rule">Deleting Automatic Zen Rule</string>
+ <string name="cp_get_rules">Retrieving Automatic Zen Rules</string>
+ <string name="cp_get_rule">Retrieving Automatic Zen Rule</string>
<string name="location_mode_high_accuracy_test">High Accuracy Mode Test</string>
<string name="location_mode_high_accuracy_info">
@@ -1464,7 +1481,22 @@
<!-- Strings common for BYOD and DO managed provisioning tests. -->
<string name="afw_device_admin">CTS Verifier</string>
- <!-- Strings for BYOD managed provisioning tests (ByodFlowTestActivity) -->
+ <string name="provisioning_tests_byod">BYOD Provisioning tests</string>
+
+ <string name="provisioning_tests_byod_custom_color"> Custom provisioning color </string>
+ <string name="provisioning_tests_byod_custom_color_info">
+ Please press the Go button to start the provisioning.
+ Check that the status bar is green.
+ Then hit back and stop the provisioning.
+ </string>
+ <string name="provisioning_tests_byod_custom_image"> Custom provisioning image </string>
+ <string name="provisioning_tests_byod_custom_image_info">
+ Please press the Go button to start the provisioning.
+ Check that the CtsVerifier logo is displayed at the top of the page.
+ Then hit back and stop the provisioning.
+ </string>
+
+ <!-- Strings for BYOD managed provisioning (ByodFlowTestActivity) -->
<string name="test_category_managed_provisioning">Managed Provisioning</string>
<string name="provisioning_byod">BYOD Managed Provisioning</string>
<string name="provisioning_byod_info">
@@ -1910,6 +1942,17 @@
\n
Use the Back button to return to this page.
</string>
+ <string name="device_owner_disallow_data_roaming">Disallow data roaming</string>
+ <string name="device_owner_disallow_data_roaming_info">
+ Please press the Set restriction button to set the user restriction.
+ Then press Go to open the Cellular network page in Settings.
+ Confirm that:\n
+ \n
+ - Data roaming is disabled.\n
+ - You cannot enable data roaming.\n
+ \n
+ Use the Back button to return to this page.
+ </string>
<string name="device_owner_user_restriction_set">Set restriction</string>
<string name="device_owner_settings_go">Go</string>
@@ -2186,6 +2229,8 @@
Please consider addressing them for a future release.</string>
<string name="audio_general_test_passed">Test Successful</string>
<string name="audio_general_test_failed">Test Failed</string>
+ <string name="audio_general_default_false_string">false</string>
+ <string name="audio_general_default_true_string">true</string>
<!-- Audio Loopback Latency Test -->
<string name="audio_loopback_test">Audio Loopback Latency Test</string>
@@ -2269,4 +2314,20 @@
<string name="audio_frequency_mic_test2_btn">Test 2</string>
<string name="audio_frequency_mic_results_text">Results...</string>
+ <!-- Audio Frequency Unprocessed Test -->
+ <string name="audio_frequency_unprocessed_test">Audio Frequency Unprocessed Test</string>
+ <string name="audio_frequency_unprocessed_info">
+ This test requires an external broadband noise source (or click/impulse).
+ Please be prepared to activate the noise source when asked to.
+ The system will measure frequency response of the built in microphone using the UNPROCESSED
+ audio source.
+ </string>
+ <string name="audio_frequency_unprocessed_defined">Audio Frequency Unprocessed feature is defined. Test is mandatory</string>
+ <string name="audio_frequency_unprocessed_not_defined">Audio Frequency Unprocessed feature is NOT defined. Test is optional</string>
+ <string name="audio_frequency_unprocessed_instructions2">
+ Once you press the [TEST] button, you have 5 seconds to play a broadband sound (click or white noise).
+ </string>
+ <string name="audio_frequency_unprocessed_test1_btn">Test 1</string>
+ <string name="audio_frequency_unprocessed_results_text">Results...</string>
+
</resources>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
index dc2502c..76eb8a1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
@@ -16,17 +16,17 @@
package com.android.cts.verifier;
+import android.content.Context;
+import android.os.Build;
+import android.text.TextUtils;
+import android.util.Xml;
+
import com.android.compatibility.common.util.MetricsXmlSerializer;
import com.android.compatibility.common.util.ReportLog;
import com.android.cts.verifier.TestListAdapter.TestListItem;
import org.xmlpull.v1.XmlSerializer;
-import android.content.Context;
-import android.os.Build;
-import android.text.TextUtils;
-import android.util.Xml;
-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.DateFormat;
@@ -130,6 +130,7 @@
xml.endTag(null, TEST_DETAILS_TAG);
}
+ // TODO(stuartscott): For v2: ReportLog.serialize(xml, mAdapter.getReportLog(i));
ReportLog reportLog = mAdapter.getReportLog(i);
if (reportLog != null) {
MetricsXmlSerializer metricsXmlSerializer = new MetricsXmlSerializer(xml);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyLineActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyLineActivity.java
index edb3bf0..c0f6750 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyLineActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyLineActivity.java
@@ -78,7 +78,7 @@
private final int mBlockSizeSamples = 1024;
private final int mSamplingRate = 48000;
- private final int mSelectedRecordSource = MediaRecorder.AudioSource.VOICE_RECOGNITION;
+ private final int mSelectedRecordSource = MediaRecorder.AudioSource.UNPROCESSED;//VOICE_RECOGNITION;// UNPROCESSED;
private final int mChannelConfig = AudioFormat.CHANNEL_IN_MONO;
private final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
private volatile Thread mRecordThread;
@@ -601,11 +601,13 @@
mRecorder = new AudioRecord(mSelectedRecordSource, mSamplingRate,
mChannelConfig, mAudioFormat, 2 * minRecordBuffSizeInBytes);
} catch (IllegalArgumentException e) {
+ Log.v(TAG, "Error: " + e.toString());
return false;
}
if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
mRecorder.release();
mRecorder = null;
+ Log.v(TAG, "Error: mRecorder not initialized");
return false;
}
mRecorder.setRecordPositionUpdateListener(this);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
new file mode 100644
index 0000000..13ec1f8
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
@@ -0,0 +1,695 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.verifier.audio;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.audio.wavelib.*;
+import com.android.compatibility.common.util.ReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import android.content.Context;
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import android.media.AudioDeviceCallback;
+import android.media.AudioDeviceInfo;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+
+import android.util.Log;
+
+import android.view.View;
+import android.view.View.OnClickListener;
+
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.SeekBar;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+
+/**
+ * Tests Audio built in Microphone response for Unprocessed audio source feature.
+ */
+public class AudioFrequencyUnprocessedActivity extends PassFailButtons.Activity implements Runnable,
+ AudioRecord.OnRecordPositionUpdateListener {
+ private static final String TAG = "AudioFrequencyUnprocessedActivity";
+
+ private static final int TEST_STARTED = 900;
+ private static final int TEST_ENDED = 901;
+ private static final int TEST_MESSAGE = 902;
+ private static final int TEST1_MESSAGE = 903;
+ private static final int TEST1_ENDED = 904;
+ private static final double MIN_ENERGY_BAND_1 = -50.0; //dB Full Scale
+ private static final double MAX_ENERGY_BAND_1_BASE = -60.0; //dB Full Scale
+ private static final double MIN_FRACTION_POINTS_IN_BAND = 0.3;
+ private static final double MAX_VAL = Math.pow(2, 15);
+ private static final double CLIP_LEVEL = (MAX_VAL-10) / MAX_VAL;
+
+ final OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
+ Context mContext;
+
+ Button mTest1Button; //execute test 1
+ Button mTest2Button; //user to start test
+ String mUsbDevicesInfo; //usb device info for report
+ LinearLayout mLayoutTest1;
+ TextView mTest1Result;
+ ProgressBar mProgressBar;
+
+ private boolean mIsRecording = false;
+ private final Object mRecordingLock = new Object();
+ private AudioRecord mRecorder;
+ private int mMinRecordBufferSizeInSamples = 0;
+ private short[] mAudioShortArray;
+ private short[] mAudioShortArray2;
+
+ private final int mBlockSizeSamples = 4096;
+ private final int mSamplingRate = 48000;
+ private final int mSelectedRecordSource = MediaRecorder.AudioSource.UNPROCESSED;
+ private final int mChannelConfig = AudioFormat.CHANNEL_IN_MONO;
+ private final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
+ private Thread mRecordThread;
+
+ PipeShort mPipe = new PipeShort(65536);
+
+ private boolean mSupportsUnprocessed = false;
+
+ private DspBufferComplex mC;
+ private DspBufferDouble mData;
+
+ private DspWindow mWindow;
+ private DspFftServer mFftServer;
+ private VectorAverage mFreqAverageMain = new VectorAverage();
+ private VectorAverage mFreqAverageBuiltIn = new VectorAverage();
+
+ int mBands = 4;
+ AudioBandSpecs[] bandSpecsArray = new AudioBandSpecs[mBands];
+ private TextView mTextViewUnprocessedStatus;
+
+ int mMaxLevel;
+ private class OnBtnClickListener implements OnClickListener {
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.audio_frequency_unprocessed_test1_btn:
+ startTest1();
+ break;
+ }
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.audio_frequency_unprocessed_activity);
+ mContext = this;
+ mTextViewUnprocessedStatus = (TextView) findViewById(
+ R.id.audio_frequency_unprocessed_defined);
+ //unprocessed test
+ mSupportsUnprocessed = supportsUnprocessed();
+ if (mSupportsUnprocessed) {
+ mTextViewUnprocessedStatus.setText(
+ getResources().getText(R.string.audio_frequency_unprocessed_defined));
+ } else {
+ mTextViewUnprocessedStatus.setText(
+ getResources().getText(R.string.audio_frequency_unprocessed_not_defined));
+ }
+
+ mTest1Button = (Button)findViewById(R.id.audio_frequency_unprocessed_test1_btn);
+ mTest1Button.setOnClickListener(mBtnClickListener);
+ mTest1Result = (TextView)findViewById(R.id.audio_frequency_unprocessed_results1_text);
+ mLayoutTest1 = (LinearLayout) findViewById(R.id.audio_frequency_unprocessed_layout_test1);
+ mProgressBar = (ProgressBar)findViewById(R.id.audio_frequency_unprocessed_progress_bar);
+ showWait(false);
+ enableLayout(mLayoutTest1, true);
+
+ //Init FFT stuff
+ mAudioShortArray2 = new short[mBlockSizeSamples*2];
+ mData = new DspBufferDouble(mBlockSizeSamples);
+ mC = new DspBufferComplex(mBlockSizeSamples);
+ mFftServer = new DspFftServer(mBlockSizeSamples);
+
+ int overlap = mBlockSizeSamples / 2;
+
+ mWindow = new DspWindow(DspWindow.WINDOW_HANNING, mBlockSizeSamples, overlap);
+
+ setPassFailButtonClickListeners();
+ getPassButton().setEnabled(false);
+ setInfoResources(R.string.audio_frequency_unprocessed_test,
+ R.string.audio_frequency_unprocessed_info, -1);
+
+ //Init bands for BuiltIn/Reference test
+ bandSpecsArray[0] = new AudioBandSpecs(
+ 2, 500, /* frequency start,stop */
+ 30.0, -50, /* start top,bottom value */
+ 30.0, -4.0 /* stop top,bottom value */);
+
+ bandSpecsArray[1] = new AudioBandSpecs(
+ 500,4000, /* frequency start,stop */
+ 4.0, -4.0, /* start top,bottom value */
+ 4.0, -4.0 /* stop top,bottom value */);
+
+ bandSpecsArray[2] = new AudioBandSpecs(
+ 4000, 12000, /* frequency start,stop */
+ 4.0, -4.0, /* start top,bottom value */
+ 5.0, -5.0 /* stop top,bottom value */);
+
+ bandSpecsArray[3] = new AudioBandSpecs(
+ 12000, 20000, /* frequency start,stop */
+ 5.0, -5.0, /* start top,bottom value */
+ 5.0, -30.0 /* stop top,bottom value */);
+
+ mSupportsUnprocessed = supportsUnprocessed();
+ Log.v(TAG, "Supports unprocessed: " + mSupportsUnprocessed);
+ }
+
+ /**
+ * enable test ui elements
+ */
+ private void enableLayout(LinearLayout layout, boolean enable) {
+ for (int i = 0; i < layout.getChildCount(); i++) {
+ View view = layout.getChildAt(i);
+ view.setEnabled(enable);
+ }
+ }
+
+ /**
+ * show active progress bar
+ */
+ private void showWait(boolean show) {
+ if (show) {
+ mProgressBar.setVisibility(View.VISIBLE);
+ } else {
+ mProgressBar.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ private void setMaxLevel() {
+ AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ mMaxLevel = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(mMaxLevel), 0);
+ }
+
+ private void setMinLevel() {
+ AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
+ }
+
+ private boolean supportsUnprocessed() {
+ boolean unprocessedSupport = false;
+ AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ String unprocessedSupportString = am.getProperty(
+ AudioManager.PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED);
+ Log.v(TAG,"unprocessed support: " + unprocessedSupportString);
+ if (unprocessedSupportString == null ||
+ unprocessedSupportString.equalsIgnoreCase(getResources().getString(
+ R.string.audio_general_default_false_string))) {
+ unprocessedSupport = false;
+ } else {
+ unprocessedSupport = true;
+ }
+ return unprocessedSupport;
+ }
+
+ /**
+ * Start the loopback audio test
+ */
+ private void startTest1() {
+ if (mTestThread != null && !mTestThread.isAlive()) {
+ mTestThread = null; //kill it.
+ }
+
+ if (mTestThread == null) {
+ Log.v(TAG,"Executing test Thread");
+ mTestThread = new Thread(mTest1Runnable);
+ mTestThread.start();
+ } else {
+ Log.v(TAG,"test Thread already running.");
+ }
+ }
+
+ Thread mTestThread;
+ Runnable mTest1Runnable = new Runnable() {
+ public void run() {
+ Message msg = Message.obtain();
+ msg.what = TEST_STARTED;
+ mMessageHandler.sendMessage(msg);
+
+ setMaxLevel();
+ sendMessage("Testing Built in Microphone");
+ mFreqAverageBuiltIn.reset();
+ mFreqAverageBuiltIn.setCaptureType(VectorAverage.CAPTURE_TYPE_MAX);
+ play();
+
+ sendMessage("Testing Completed");
+
+ Message msg2 = Message.obtain();
+ msg2.what = TEST1_ENDED;
+ mMessageHandler.sendMessage(msg2);
+ }
+
+ private void play() {
+ startRecording();
+
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ //restore interrupted status
+ Thread.currentThread().interrupt();
+ }
+ stopRecording();
+ }
+
+ private void sendMessage(String str) {
+ Message msg = Message.obtain();
+ msg.what = TEST1_MESSAGE;
+ msg.obj = str;
+ mMessageHandler.sendMessage(msg);
+ }
+ };
+
+ private Handler mMessageHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch (msg.what) {
+ case TEST_STARTED:
+ showWait(true);
+ getPassButton().setEnabled(false);
+ break;
+ case TEST_ENDED:
+ showWait(false);
+// computeTest2Results();
+ break;
+ case TEST1_MESSAGE: {
+ String str = (String)msg.obj;
+ if (str != null) {
+ mTest1Result.setText(str);
+ }
+ }
+ break;
+ case TEST1_ENDED:
+ showWait(false);
+ computeTest1Results();
+ break;
+ case TEST_MESSAGE: {
+ }
+ break;
+ default:
+ Log.e(TAG, String.format("Unknown message: %d", msg.what));
+ }
+ }
+ };
+
+ private class Results {
+ private String mLabel;
+ public double[] mValuesLog;
+ int[] mPointsPerBand = new int[mBands];
+ double[] mAverageEnergyPerBand = new double[mBands];
+ int[] mInBoundPointsPerBand = new int[mBands];
+ public Results(String label) {
+ mLabel = label;
+ }
+
+ //append results
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format("Channel %s\n", mLabel));
+ sb.append("Level in Band 1 : " + (testLevel() ? "OK" :"FAILED") + "\n");
+ for (int b = 0; b < mBands; b++) {
+ double percent = 0;
+ if (mPointsPerBand[b] > 0) {
+ percent = 100.0 * (double) mInBoundPointsPerBand[b] / mPointsPerBand[b];
+ }
+ sb.append(String.format(
+ " Band %d: Av. Level: %.1f dB InBand: %d/%d (%.1f%%) %s\n",
+ b, mAverageEnergyPerBand[b],
+ mInBoundPointsPerBand[b],
+ mPointsPerBand[b],
+ percent,
+ (testInBand(b) ? "OK" : "FAILED")));
+ }
+ return sb.toString();
+ }
+
+ public boolean testLevel() {
+ if (mAverageEnergyPerBand[1] >= MIN_ENERGY_BAND_1) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean testInBand(int b) {
+ if (b >= 0 && b < mBands && mPointsPerBand[b] > 0) {
+ if ((double) mInBoundPointsPerBand[b] / mPointsPerBand[b] >
+ MIN_FRACTION_POINTS_IN_BAND) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean testAll() {
+ if (!testLevel()) {
+ return false;
+ }
+ for (int b = 0; b < mBands; b++) {
+ if (!testInBand(b)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+
+ /**
+ * compute test1 results
+ */
+ private void computeTest1Results() {
+ Results resultsBuiltIn = new Results("BuiltIn");
+ if (computeResultsForVector(mFreqAverageBuiltIn, resultsBuiltIn, bandSpecsArray)) {
+ appendResultsToScreen(resultsBuiltIn.toString(), mTest1Result);
+ recordTestResults(resultsBuiltIn);
+ }
+ if (mSupportsUnprocessed) { //test is mandatory
+ appendResultsToScreen(getResources().getText(
+ R.string.audio_frequency_unprocessed_defined).toString(), mTest1Result);
+ if (resultsBuiltIn.testAll()) {
+ //tst passed
+ getPassButton().setEnabled(true);
+ String strSuccess = getResources().getString(R.string.audio_general_test_passed);
+ appendResultsToScreen(strSuccess, mTest1Result);
+ } else {
+ getPassButton().setEnabled(false);
+ String strFailed = getResources().getString(R.string.audio_general_test_failed);
+ appendResultsToScreen(strFailed, mTest1Result);
+ }
+ } else {
+ //test optional
+ appendResultsToScreen(getResources().getText(
+ R.string.audio_frequency_unprocessed_not_defined).toString(), mTest1Result);
+ getPassButton().setEnabled(true);
+ }
+ }
+
+ private boolean computeResultsForVector(VectorAverage freqAverage, Results results,
+ AudioBandSpecs[] bandSpecs) {
+
+ int points = freqAverage.getSize();
+ if (points > 0) {
+ //compute vector in db
+ double[] values = new double[points];
+ freqAverage.getData(values, false);
+ results.mValuesLog = new double[points];
+ for (int i = 0; i < points; i++) {
+ results.mValuesLog[i] = 20 * Math.log10(values[i]);
+ }
+
+ int currentBand = 0;
+ for (int i = 0; i < points; i++) {
+ double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples;
+ if (freq > bandSpecs[currentBand].mFreqStop) {
+ currentBand++;
+ if (currentBand >= mBands)
+ break;
+ }
+
+ if (freq >= bandSpecs[currentBand].mFreqStart) {
+ results.mAverageEnergyPerBand[currentBand] += results.mValuesLog[i];
+ results.mPointsPerBand[currentBand]++;
+ }
+ }
+
+ for (int b = 0; b < mBands; b++) {
+ if (results.mPointsPerBand[b] > 0) {
+ results.mAverageEnergyPerBand[b] =
+ results.mAverageEnergyPerBand[b] / results.mPointsPerBand[b];
+ }
+ }
+
+ //set offset relative to band 1 level
+ for (int b = 0; b < mBands; b++) {
+ bandSpecs[b].setOffset(results.mAverageEnergyPerBand[1]);
+ }
+
+ //test points in band.
+ currentBand = 0;
+ for (int i = 0; i < points; i++) {
+ double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples;
+ if (freq > bandSpecs[currentBand].mFreqStop) {
+ currentBand++;
+ if (currentBand >= mBands)
+ break;
+ }
+
+ if (freq >= bandSpecs[currentBand].mFreqStart) {
+ double value = results.mValuesLog[i];
+ if (bandSpecs[currentBand].isInBounds(freq, value)) {
+ results.mInBoundPointsPerBand[currentBand]++;
+ }
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ //append results
+ private void appendResultsToScreen(String str, TextView text) {
+ String currentText = text.getText().toString();
+ text.setText(currentText + "\n" + str);
+ }
+
+ /**
+ * Store test results in log
+ */
+ private void recordTestResults(Results results) {
+ String channelLabel = "channel_" + results.mLabel;
+
+ for (int b = 0; b < mBands; b++) {
+ String bandLabel = String.format(channelLabel + "_%d", b);
+ getReportLog().addValue(
+ bandLabel + "_Level",
+ results.mAverageEnergyPerBand[b],
+ ResultType.HIGHER_BETTER,
+ ResultUnit.NONE);
+
+ getReportLog().addValue(
+ bandLabel + "_pointsinbound",
+ results.mInBoundPointsPerBand[b],
+ ResultType.HIGHER_BETTER,
+ ResultUnit.COUNT);
+
+ getReportLog().addValue(
+ bandLabel + "_pointstotal",
+ results.mPointsPerBand[b],
+ ResultType.NEUTRAL,
+ ResultUnit.COUNT);
+ }
+
+ getReportLog().addValues(channelLabel + "_magnitudeSpectrumLog",
+ results.mValuesLog,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ Log.v(TAG, "Results Recorded");
+ }
+
+ private void recordHeasetPortFound(boolean found) {
+ getReportLog().addValue(
+ "User Reported Headset Port",
+ found ? 1.0 : 0,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ }
+
+ private void startRecording() {
+ synchronized (mRecordingLock) {
+ mIsRecording = true;
+ }
+
+ boolean successful = initRecord();
+ if (successful) {
+ startRecordingForReal();
+ } else {
+ Log.v(TAG, "Recorder initialization error.");
+ synchronized (mRecordingLock) {
+ mIsRecording = false;
+ }
+ }
+ }
+
+ private void startRecordingForReal() {
+ // start streaming
+ if (mRecordThread == null) {
+ mRecordThread = new Thread(AudioFrequencyUnprocessedActivity.this);
+ mRecordThread.setName("FrequencyAnalyzerThread");
+ }
+ if (!mRecordThread.isAlive()) {
+ mRecordThread.start();
+ }
+
+ mPipe.flush();
+
+ long startTime = SystemClock.uptimeMillis();
+ mRecorder.startRecording();
+ if (mRecorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
+ stopRecording();
+ return;
+ }
+ Log.v(TAG, "Start time: " + (long) (SystemClock.uptimeMillis() - startTime) + " ms");
+ }
+
+ private void stopRecording() {
+ synchronized (mRecordingLock) {
+ stopRecordingForReal();
+ mIsRecording = false;
+ }
+ }
+
+ private void stopRecordingForReal() {
+
+ // stop streaming
+ Thread zeThread = mRecordThread;
+ mRecordThread = null;
+ if (zeThread != null) {
+ zeThread.interrupt();
+ try {
+ zeThread.join();
+ } catch(InterruptedException e) {
+ //restore interrupted status of recording thread
+ zeThread.interrupt();
+ }
+ }
+ // release recording resources
+ if (mRecorder != null) {
+ mRecorder.stop();
+ mRecorder.release();
+ mRecorder = null;
+ }
+ }
+
+ private boolean initRecord() {
+ int minRecordBuffSizeInBytes = AudioRecord.getMinBufferSize(mSamplingRate,
+ mChannelConfig, mAudioFormat);
+ Log.v(TAG,"FrequencyAnalyzer: min buff size = " + minRecordBuffSizeInBytes + " bytes");
+ if (minRecordBuffSizeInBytes <= 0) {
+ return false;
+ }
+
+ mMinRecordBufferSizeInSamples = minRecordBuffSizeInBytes / 2;
+ // allocate the byte array to read the audio data
+
+ mAudioShortArray = new short[mMinRecordBufferSizeInSamples];
+
+ Log.v(TAG, "Initiating record:");
+ Log.v(TAG, " using source " + mSelectedRecordSource);
+ Log.v(TAG, " at " + mSamplingRate + "Hz");
+
+ try {
+ mRecorder = new AudioRecord(mSelectedRecordSource, mSamplingRate,
+ mChannelConfig, mAudioFormat, 2 * minRecordBuffSizeInBytes);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
+ mRecorder.release();
+ mRecorder = null;
+ return false;
+ }
+ mRecorder.setRecordPositionUpdateListener(this);
+ mRecorder.setPositionNotificationPeriod(mBlockSizeSamples / 2);
+ return true;
+ }
+
+ // ---------------------------------------------------------
+ // Implementation of AudioRecord.OnPeriodicNotificationListener
+ // --------------------
+ public void onPeriodicNotification(AudioRecord recorder) {
+ int samplesAvailable = mPipe.availableToRead();
+ int samplesNeeded = mBlockSizeSamples;
+ if (samplesAvailable >= samplesNeeded) {
+ mPipe.read(mAudioShortArray2, 0, samplesNeeded);
+
+ //compute stuff.
+ int clipcount = 0;
+ double sum = 0;
+ double maxabs = 0;
+ int i;
+
+ for (i = 0; i < samplesNeeded; i++) {
+ double value = mAudioShortArray2[i] / MAX_VAL;
+ double valueabs = Math.abs(value);
+
+ if (valueabs > maxabs) {
+ maxabs = valueabs;
+ }
+
+ if (valueabs > CLIP_LEVEL) {
+ clipcount++;
+ }
+
+ sum += value * value;
+ //fft stuff
+ mData.mData[i] = value;
+ }
+
+ //for the current frame, compute FFT and send to the viewer.
+
+ //apply window and pack as complex for now.
+ DspBufferMath.mult(mData, mData, mWindow.mBuffer);
+ DspBufferMath.set(mC, mData);
+ mFftServer.fft(mC, 1);
+
+ double[] halfMagnitude = new double[mBlockSizeSamples / 2];
+ for (i = 0; i < mBlockSizeSamples / 2; i++) {
+ halfMagnitude[i] = Math.sqrt(mC.mReal[i] * mC.mReal[i] + mC.mImag[i] * mC.mImag[i]);
+ }
+
+ mFreqAverageMain.setData(halfMagnitude, false); //average all of them!
+ mFreqAverageBuiltIn.setData(halfMagnitude, false);
+ }
+ }
+
+ public void onMarkerReached(AudioRecord track) {
+ }
+
+ // ---------------------------------------------------------
+ // Implementation of Runnable for the audio recording + playback
+ // --------------------
+ public void run() {
+ Thread thisThread = Thread.currentThread();
+ while (!thisThread.isInterrupted()) {
+ // read from native recorder
+ int nSamplesRead = mRecorder.read(mAudioShortArray, 0, mMinRecordBufferSizeInSamples);
+ if (nSamplesRead > 0) {
+ mPipe.write(mAudioShortArray, 0, nSamplesRead);
+ }
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/VectorAverage.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/VectorAverage.java
index 41f0411..8783cbb 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/VectorAverage.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/VectorAverage.java
@@ -24,6 +24,12 @@
private double[] mData;
private int mValueCount = 0;
+ public static final int CAPTURE_TYPE_AVERAGE = 0;
+ public static final int CAPTURE_TYPE_MAX = 1;
+ public static final int CAPTURE_TYPE_MIN = 2;
+
+ private int mCaptureType = CAPTURE_TYPE_AVERAGE;
+
public void setData(double[] data, boolean replace) {
int size = data.length;
if (mData == null || mData.length != size) {
@@ -34,10 +40,34 @@
System.arraycopy(data, 0, mData, 0, size);
mValueCount = 1;
} else {
- for (int i = 0; i < size; i++) {
- mData[i] += data[i];
+ switch(mCaptureType) {
+ default:
+ case CAPTURE_TYPE_AVERAGE: {
+ for (int i = 0; i < size; i++) {
+ mData[i] += data[i];
+ }
+ mValueCount++;
+ }
+ break;
+ case CAPTURE_TYPE_MAX: {
+ for (int i = 0; i < size; i++) {
+ if (data[i] > mData[i]) {
+ mData[i] = data[i];
+ }
+ }
+ mValueCount = 1;
+ }
+ break;
+ case CAPTURE_TYPE_MIN: {
+ for (int i = 0; i < size; i++) {
+ if (data[i] < mData[i]) {
+ mData[i] = data[i];
+ }
+ }
+ mValueCount = 1;
+ }
+ break;
}
- mValueCount++;
}
}
@@ -77,6 +107,22 @@
mValueCount = 0;
}
+ public void setCaptureType(int type) {
+ switch(type) {
+ case CAPTURE_TYPE_AVERAGE:
+ case CAPTURE_TYPE_MAX:
+ case CAPTURE_TYPE_MIN:
+ mCaptureType = type;
+ break;
+ default:
+ mCaptureType = CAPTURE_TYPE_AVERAGE;
+ }
+ }
+
+ public int getCaptureType() {
+ return mCaptureType;
+ }
+
private final String SERIALIZED_VERSION = "VECTOR_AVERAGE_VERSION";
private final String SERIALIZED_COUNT = "COUNT";
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index 9e3b2aa..9d04c2a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -159,7 +159,7 @@
public void finish() {
// Pass and fail buttons are known to call finish() when clicked, and this is when we want to
// clean up the provisioned profile.
- requestDeleteProfileOwner();
+ Utils.requestDeleteManagedProfile(this);
enableComponent(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
super.finish();
}
@@ -491,8 +491,6 @@
mAdminReceiverComponent);
if (sending.resolveActivity(getPackageManager()) != null) {
- // ManagedProvisioning must be started with startActivityForResult, but we don't
- // care about the result, so passing 0 as a requestCode
startActivityForResult(sending, REQUEST_MANAGED_PROVISIONING);
} else {
showToast(R.string.provisioning_byod_disabled);
@@ -513,17 +511,6 @@
}
}
- private void requestDeleteProfileOwner() {
- try {
- Intent intent = new Intent(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
- startActivity(intent);
- showToast(R.string.provisioning_byod_delete_profile);
- }
- catch (ActivityNotFoundException e) {
- Log.d(TAG, "requestDeleteProfileOwner: ActivityNotFoundException", e);
- }
- }
-
private void checkIntentFilters() {
try {
// Enable component HandleIntentActivity before intent filters are checked.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
index ef7c952..d02d2e1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -66,7 +66,7 @@
// Managed -> primary intent: update profile owner test status in primary's CtsVerifer
public static final String ACTION_PROFILE_OWNER_STATUS = "com.android.cts.verifier.managedprovisioning.BYOD_STATUS";
// Primary -> managed intent: request to delete the current profile
- public static final String ACTION_REMOVE_PROFILE_OWNER = "com.android.cts.verifier.managedprovisioning.BYOD_REMOVE";
+ public static final String ACTION_REMOVE_MANAGED_PROFILE = "com.android.cts.verifier.managedprovisioning.BYOD_REMOVE";
// Managed -> managed intent: provisioning completed successfully
public static final String ACTION_PROFILE_PROVISIONED = "com.android.cts.verifier.managedprovisioning.BYOD_PROVISIONED";
// Primage -> managed intent: request to capture and check an image
@@ -188,7 +188,7 @@
response.putExtra(EXTRA_PROVISIONED, isProfileOwner());
setResult(RESULT_OK, response);
// Request to delete work profile.
- } else if (action.equals(ACTION_REMOVE_PROFILE_OWNER)) {
+ } else if (action.equals(ACTION_REMOVE_MANAGED_PROFILE)) {
if (isProfileOwner()) {
Log.d(TAG, "Clearing cross profile intents");
mDevicePolicyManager.clearCrossProfileIntentFilters(mAdminReceiverComponent);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodProvisioningTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodProvisioningTestActivity.java
new file mode 100644
index 0000000..dfbbb31
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodProvisioningTestActivity.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.admin.DevicePolicyManager;
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.graphics.Color;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.cts.verifier.ArrayTestListAdapter;
+import com.android.cts.verifier.IntentDrivenTestActivity.ButtonInfo;
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+public class ByodProvisioningTestActivity extends PassFailButtons.TestListActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.pass_fail_list);
+ setPassFailButtonClickListeners();
+
+ final ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
+
+ Intent colorIntent = new Intent(this, ProvisioningStartingActivity.class)
+ .putExtra(DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR, Color.GREEN);
+ adapter.add(Utils.createInteractiveTestItem(this, "BYOD_CustomColor",
+ R.string.provisioning_tests_byod_custom_color,
+ R.string.provisioning_tests_byod_custom_color_info,
+ new ButtonInfo(R.string.go_button_text, colorIntent)));
+ Uri logoUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getPackageName()
+ + "/" + R.drawable.icon);
+ Intent imageIntent = new Intent(this, ProvisioningStartingActivity.class)
+ .putExtra(DevicePolicyManager.EXTRA_PROVISIONING_LOGO_URI, logoUri);
+ adapter.add(Utils.createInteractiveTestItem(this, "BYOD_CustomImage",
+ R.string.provisioning_tests_byod_custom_image,
+ R.string.provisioning_tests_byod_custom_image_info,
+ new ButtonInfo(R.string.go_button_text, imageIntent)));
+
+ setTestListAdapter(adapter);
+ }
+
+ @Override
+ public void finish() {
+ // Pass and fail buttons are known to call finish() when clicked, and this is when we want
+ // to clean up the provisioned profile in case the user has added one.
+ Utils.requestDeleteManagedProfile(this);
+ super.finish();
+ }
+
+ // We need this activity because the provisioning needs to be started with
+ // startActivityForResult
+ public static class ProvisioningStartingActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent provisioningIntent = new Intent(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
+ // forward all the extras we received.
+ provisioningIntent.putExtras(getIntent().getExtras());
+ provisioningIntent.putExtra(
+ DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
+ new ComponentName(this, DeviceAdminTestReceiver.class.getName()));
+ startActivityForResult(provisioningIntent, 0);
+ finish();
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
index 039cc09..095ed7d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -56,7 +56,7 @@
// Primary -> work direction
IntentFilter filter = new IntentFilter();
filter.addAction(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
- filter.addAction(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
+ filter.addAction(ByodHelperActivity.ACTION_REMOVE_MANAGED_PROFILE);
filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK);
filter.addAction(ByodHelperActivity.ACTION_CHECK_INTENT_FILTERS);
filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_IMAGE);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerNegativeTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerNegativeTestActivity.java
index 3c0955d..5dac13b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerNegativeTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerNegativeTestActivity.java
@@ -16,6 +16,7 @@
package com.android.cts.verifier.managedprovisioning;
+import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import android.database.DataSetObserver;
import android.os.Bundle;
@@ -33,10 +34,8 @@
*/
public class DeviceOwnerNegativeTestActivity extends PassFailButtons.TestListActivity {
- private static final String ACTION_PROVISION_MANAGED_DEVICE
- = "com.android.managedprovisioning.ACTION_PROVISION_MANAGED_DEVICE";
private static final Intent PROVISION_DEVICE_INTENT =
- new Intent(ACTION_PROVISION_MANAGED_DEVICE);
+ new Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE);
private static final String DEVICE_OWNER_NEGATIVE_TEST = "DEVICE_OWNER_PROVISIONING_NEGATIVE";
private static final TestInfo DEVICE_OWNER_NEGATIVE_TEST_INFO = new TestInfo(
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index 72361c1..f64d6da 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -16,6 +16,8 @@
package com.android.cts.verifier.managedprovisioning;
+import static com.android.cts.verifier.managedprovisioning.Utils.createInteractiveTestItem;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.app.admin.DevicePolicyManager;
@@ -78,6 +80,7 @@
private static final String DISALLOW_CONFIG_VPN_ID = "DISALLOW_CONFIG_VPN";
//TODO(rgl): This symbol should be available in android.provider.settings
private static final String ACTION_VPN_SETTINGS = "android.net.vpn.SETTINGS";
+ private static final String DISALLOW_DATA_ROAMING_ID = "DISALLOW_DATA_ROAMING";
private static final String REMOVE_DEVICE_OWNER_TEST_ID = "REMOVE_DEVICE_OWNER";
@Override
@@ -178,6 +181,19 @@
R.string.device_owner_vpn_test,
new Intent(this, VpnTestActivity.class))}));
+ // DISALLOW_DATA_ROAMING
+ adapter.add(createInteractiveTestItem(this, DISALLOW_DATA_ROAMING_ID,
+ R.string.device_owner_disallow_data_roaming,
+ R.string.device_owner_disallow_data_roaming_info,
+ new ButtonInfo[] {
+ new ButtonInfo(
+ R.string.device_owner_user_restriction_set,
+ createSetUserRestrictionIntent(
+ UserManager.DISALLOW_DATA_ROAMING)),
+ new ButtonInfo(
+ R.string.device_owner_settings_go,
+ new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS))}));
+
// DISALLOW_CONFIG_BLUETOOTH
if (packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
adapter.add(createInteractiveTestItem(this, DISALLOW_CONFIG_BT_ID,
@@ -235,27 +251,11 @@
createTearDownIntent())));
}
- static TestListItem createInteractiveTestItem(Activity activity, String id, int titleRes,
- int infoRes, ButtonInfo buttonInfo) {
- return createInteractiveTestItem(activity, id, titleRes, infoRes,
- new ButtonInfo[] { buttonInfo });
- }
-
- static TestListItem createInteractiveTestItem(Activity activity, String id, int titleRes,
- int infoRes, ButtonInfo[] buttonInfos) {
- return TestListItem.newTest(activity, titleRes,
- id, new Intent(activity, IntentDrivenTestActivity.class)
- .putExtra(IntentDrivenTestActivity.EXTRA_ID, id)
- .putExtra(IntentDrivenTestActivity.EXTRA_TITLE, titleRes)
- .putExtra(IntentDrivenTestActivity.EXTRA_INFO, infoRes)
- .putExtra(IntentDrivenTestActivity.EXTRA_BUTTONS, buttonInfos),
- null);
- }
static TestListItem createTestItem(Activity activity, String id, int titleRes,
Intent intent) {
- return TestListItem.newTest(activity, titleRes, id, intent.putExtra(EXTRA_TEST_ID, id),
- null);
+ intent.putExtra(EXTRA_TEST_ID, id);
+ return TestListItem.newTest(activity, titleRes, id, intent, null);
}
private Intent createTearDownIntent() {
@@ -339,6 +339,7 @@
dpm.clearUserRestriction(admin, UserManager.DISALLOW_CONFIG_BLUETOOTH);
dpm.clearUserRestriction(admin, UserManager.DISALLOW_CONFIG_WIFI);
dpm.clearUserRestriction(admin, UserManager.DISALLOW_CONFIG_VPN);
+ dpm.clearUserRestriction(admin, UserManager.DISALLOW_DATA_ROAMING);
dpm.clearDeviceOwnerApp(getPackageName());
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
index 21c7331..58a1fef 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
@@ -148,7 +148,6 @@
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
forwardedIntentsFromManaged.addAll(Arrays.asList(
new Intent(Intent.ACTION_DIAL).setData(Uri.parse("tel:123")),
- new Intent(Intent.ACTION_CALL).setData(Uri.parse("tel:123")),
new Intent("android.intent.action.CALL_EMERGENCY").setData(
Uri.parse("tel:123")),
new Intent("android.intent.action.CALL_PRIVILEGED").setData(
@@ -174,6 +173,8 @@
Uri.parse("mmsto:07700900100?body=Hello%20world")).addCategory(
Intent.CATEGORY_BROWSABLE),
new Intent(Settings.ACTION_APN_SETTINGS)));
+ notForwardedIntentsFromManaged
+ .add(new Intent(Intent.ACTION_CALL).setData(Uri.parse("tel:123")));
}
if (pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
new file mode 100644
index 0000000..abccb43
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.Activity;
+import android.widget.Toast;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.cts.verifier.IntentDrivenTestActivity;
+import com.android.cts.verifier.IntentDrivenTestActivity.ButtonInfo;
+import com.android.cts.verifier.managedprovisioning.ByodHelperActivity;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.TestListAdapter.TestListItem;
+
+public class Utils {
+
+ private static final String TAG = "CtsVerifierByodUtils";
+
+ static TestListItem createInteractiveTestItem(Activity activity, String id, int titleRes,
+ int infoRes, ButtonInfo[] buttonInfos) {
+ return TestListItem.newTest(activity, titleRes,
+ id, new Intent(activity, IntentDrivenTestActivity.class)
+ .putExtra(IntentDrivenTestActivity.EXTRA_ID, id)
+ .putExtra(IntentDrivenTestActivity.EXTRA_TITLE, titleRes)
+ .putExtra(IntentDrivenTestActivity.EXTRA_INFO, infoRes)
+ .putExtra(IntentDrivenTestActivity.EXTRA_BUTTONS, buttonInfos),
+ null);
+ }
+
+ static TestListItem createInteractiveTestItem(Activity activity, String id, int titleRes,
+ int infoRes, ButtonInfo buttonInfo) {
+ return createInteractiveTestItem(activity, id, titleRes, infoRes,
+ new ButtonInfo[] { buttonInfo });
+ }
+
+ static void requestDeleteManagedProfile(Context context) {
+ try {
+ Intent intent = new Intent(ByodHelperActivity.ACTION_REMOVE_MANAGED_PROFILE);
+ context.startActivity(intent);
+ String message = context.getString(R.string.provisioning_byod_delete_profile);
+ Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+ }
+ catch (ActivityNotFoundException e) {
+ Log.d(TAG, "requestDeleteProfileOwner: ActivityNotFoundException", e);
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/WifiLockdownTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/WifiLockdownTestActivity.java
index 77f36b6..d3ba56b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/WifiLockdownTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/WifiLockdownTestActivity.java
@@ -132,22 +132,22 @@
}
private void addTestsToAdapter(final ArrayTestListAdapter adapter) {
- adapter.add(DeviceOwnerPositiveTestActivity.createInteractiveTestItem(this,
+ adapter.add(Utils.createInteractiveTestItem(this,
CONFIG_MODIFIABLE_WHEN_UNLOCKED_TEST_ID,
R.string.device_owner_wifi_config_unlocked_modification_test,
R.string.device_owner_wifi_config_unlocked_modification_test_info,
mSwitchLockdownOffButtonInfos));
- adapter.add(DeviceOwnerPositiveTestActivity.createInteractiveTestItem(this,
+ adapter.add(Utils.createInteractiveTestItem(this,
CONFIG_NOT_MODIFIABLE_WHEN_LOCKED_TEST_ID,
R.string.device_owner_wifi_config_locked_modification_test,
R.string.device_owner_wifi_config_locked_modification_test_info,
mSwitchLockdownOnButtonInfos));
- adapter.add(DeviceOwnerPositiveTestActivity.createInteractiveTestItem(this,
+ adapter.add(Utils.createInteractiveTestItem(this,
CONFIG_CONNECTABLE_WHEN_LOCKED_TEST_ID,
R.string.device_owner_wifi_config_locked_connection_test,
R.string.device_owner_wifi_config_locked_connection_test_info,
mSwitchLockdownOnButtonInfos));
- adapter.add(DeviceOwnerPositiveTestActivity.createInteractiveTestItem(this,
+ adapter.add(Utils.createInteractiveTestItem(this,
CONFIG_REMOVABLE_WHEN_UNLOCKED_TEST_ID,
R.string.device_owner_wifi_config_unlocked_removal_test,
R.string.device_owner_wifi_config_unlocked_removal_test_info,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
new file mode 100644
index 0000000..47a928c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
@@ -0,0 +1,554 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.verifier.notifications;
+
+import com.android.cts.verifier.R;
+
+import android.app.AutomaticZenRule;
+import android.app.NotificationManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Parcelable;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ConditionProviderVerifierActivity extends InteractiveVerifierActivity
+ implements Runnable {
+ protected static final String CP_PACKAGE = "com.android.cts.verifier";
+ protected static final String CP_PATH = CP_PACKAGE +
+ "/com.android.cts.verifier.notifications.MockConditionProvider";
+
+ @Override
+ int getTitleResource() {
+ return R.string.cp_test;
+ }
+
+ @Override
+ int getInstructionsResource() {
+ return R.string.cp_info;
+ }
+
+ // Test Setup
+
+ @Override
+ protected List<InteractiveTestCase> createTestItems() {
+ List<InteractiveTestCase> tests = new ArrayList<>(9);
+ tests.add(new IsEnabledTest());
+ tests.add(new ServiceStartedTest());
+ tests.add(new CreateAutomaticZenRuleTest());
+ tests.add(new GetAutomaticZenRuleTest());
+ tests.add(new GetAutomaticZenRulesTest());
+ tests.add(new SubscribeAutomaticZenRuleTest());
+ tests.add(new DeleteAutomaticZenRuleTest());
+ tests.add(new UnsubscribeAutomaticZenRuleTest());
+ tests.add(new IsDisabledTest());
+ tests.add(new ServiceStoppedTest());
+ return tests;
+ }
+
+ protected class IsEnabledTest extends InteractiveTestCase {
+ @Override
+ View inflate(ViewGroup parent) {
+ return createSettingsItem(parent, R.string.cp_enable_service);
+ }
+
+ @Override
+ boolean autoStart() {
+ return true;
+ }
+
+ @Override
+ void test() {
+ Intent settings = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
+ if (settings.resolveActivity(mPackageManager) == null) {
+ logFail("no settings activity");
+ status = FAIL;
+ } else {
+ String cpPackages = Secure.getString(getContentResolver(),
+ Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
+ if (cpPackages != null && cpPackages.contains(CP_PACKAGE)) {
+ status = PASS;
+ } else {
+ status = WAIT_FOR_USER;
+ }
+ next();
+ }
+ }
+
+ void tearDown() {
+ // wait for the service to start
+ delay();
+ }
+ }
+
+ protected class ServiceStartedTest extends InteractiveTestCase {
+ @Override
+ View inflate(ViewGroup parent) {
+ return createAutoItem(parent, R.string.cp_service_started);
+ }
+
+ @Override
+ void test() {
+ MockConditionProvider.probeConnected(mContext,
+ new MockConditionProvider.BooleanResultCatcher() {
+ @Override
+ public void accept(boolean result) {
+ if (result) {
+ status = PASS;
+ } else {
+ logFail();
+ status = RETEST;
+ delay();
+ }
+ next();
+ }
+ });
+ delay(); // in case the catcher never returns
+ }
+
+ @Override
+ void tearDown() {
+ MockConditionProvider.resetData(mContext);
+ delay();
+ }
+ }
+
+ private class CreateAutomaticZenRuleTest extends InteractiveTestCase {
+ private String id = null;
+
+ @Override
+ View inflate(ViewGroup parent) {
+ return createAutoItem(parent, R.string.cp_create_rule);
+ }
+
+ @Override
+ void test() {
+ long now = System.currentTimeMillis();
+ AutomaticZenRule ruleToCreate =
+ createRule("Rule", "value", NotificationManager.INTERRUPTION_FILTER_ALARMS);
+ AutomaticZenRule createdRule = mNm.addAutomaticZenRule(ruleToCreate);
+
+ if (createdRule != null
+ && ruleToCreate.getName().equals(createdRule.getName())
+ && ruleToCreate.getOwner().equals(createdRule.getOwner())
+ && ruleToCreate.getConditionId().equals(createdRule.getConditionId())
+ && ruleToCreate.isEnabled() == createdRule.isEnabled()
+ && !TextUtils.isEmpty(createdRule.getId())
+ && createdRule.getCreationTime() > now) {
+ id = createdRule.getId();
+ status = PASS;
+ } else {
+ logFail();
+ status = FAIL;
+ }
+ next();
+ }
+
+ @Override
+ void tearDown() {
+ if (id != null) {
+ mNm.removeAutomaticZenRule(id);
+ }
+ MockConditionProvider.resetData(mContext);
+ delay();
+ }
+ }
+
+ private class SubscribeAutomaticZenRuleTest extends InteractiveTestCase {
+ private String id = null;
+ private AutomaticZenRule ruleToCreate;
+
+ @Override
+ View inflate(ViewGroup parent) {
+ return createAutoItem(parent, R.string.cp_subscribe_rule);
+ }
+
+ @Override
+ void setUp() {
+ ruleToCreate = createRule("RuleSubscribe", "Subscribevalue",
+ NotificationManager.INTERRUPTION_FILTER_ALARMS);
+ AutomaticZenRule createdRule = mNm.addAutomaticZenRule(ruleToCreate);
+ id = createdRule == null ? null : createdRule.getId();
+ status = READY;
+ delay();
+ }
+
+ @Override
+ void test() {
+
+ MockConditionProvider.probeSubscribe(mContext,
+ new MockConditionProvider.ParcelableListResultCatcher() {
+ @Override
+ public void accept(List<Parcelable> result) {
+ boolean foundMatch = false;
+ for (Parcelable p : result) {
+ Uri uri = (Uri) p;
+ if (ruleToCreate.getConditionId().equals(uri)) {
+ foundMatch = true;
+ break;
+ }
+ }
+ if (foundMatch) {
+ status = PASS;
+ } else {
+ logFail();
+ status = RETEST;
+ }
+ next();
+ }
+ });
+ delay(); // in case the catcher never returns
+ }
+
+ @Override
+ void tearDown() {
+ if (id != null) {
+ mNm.removeAutomaticZenRule(id);
+ }
+ MockConditionProvider.resetData(mContext);
+ // wait for intent to move through the system
+ delay();
+ }
+ }
+
+ private class GetAutomaticZenRuleTest extends InteractiveTestCase {
+ private String id = null;
+ private AutomaticZenRule ruleToCreate;
+ private AutomaticZenRule createdRule;
+
+ @Override
+ View inflate(ViewGroup parent) {
+ return createAutoItem(parent, R.string.cp_get_rule);
+ }
+
+ @Override
+ void setUp() {
+ ruleToCreate = createRule("RuleGet", "valueGet",
+ NotificationManager.INTERRUPTION_FILTER_ALARMS);
+ createdRule = mNm.addAutomaticZenRule(ruleToCreate);
+ id = createdRule == null ? null : createdRule.getId();
+ status = READY;
+ delay();
+ }
+
+ @Override
+ void test() {
+ if (createdRule != null) {
+ id = createdRule.getId();
+ AutomaticZenRule queriedRule = mNm.getAutomaticZenRule(id);
+ if (queriedRule != null
+ && ruleToCreate.getName().equals(queriedRule.getName())
+ && ruleToCreate.getOwner().equals(queriedRule.getOwner())
+ && ruleToCreate.getConditionId().equals(queriedRule.getConditionId())
+ && ruleToCreate.isEnabled() == queriedRule.isEnabled()
+ && queriedRule.getId().equals(id)
+ && createdRule.getCreationTime() == queriedRule.getCreationTime()) {
+ status = PASS;
+ } else {
+ logFail();
+ status = FAIL;
+ }
+ } else {
+ logFail();
+ status = FAIL;
+ }
+ next();
+ }
+
+ @Override
+ void tearDown() {
+ if (id != null) {
+ mNm.removeAutomaticZenRule(id);
+ }
+ MockConditionProvider.resetData(mContext);
+ delay();
+ }
+ }
+
+ private class GetAutomaticZenRulesTest extends InteractiveTestCase {
+ private List<String> ids = new ArrayList<>();
+ AutomaticZenRule createdRule1;
+ AutomaticZenRule createdRule2;
+
+ @Override
+ View inflate(ViewGroup parent) {
+ return createAutoItem(parent, R.string.cp_get_rules);
+ }
+
+ @Override
+ void setUp() {
+ AutomaticZenRule rule1 =
+ createRule("Rule1", "value1", NotificationManager.INTERRUPTION_FILTER_ALARMS);
+ AutomaticZenRule rule2 =
+ createRule("Rule2", "value2", NotificationManager.INTERRUPTION_FILTER_NONE);
+ createdRule1 = mNm.addAutomaticZenRule(rule1);
+ createdRule2 = mNm.addAutomaticZenRule(rule2);
+ ids.add(createdRule1.getId());
+ ids.add(createdRule2.getId());
+ status = READY;
+ delay();
+ }
+
+ @Override
+ void test() {
+ List<AutomaticZenRule> rules = mNm.getAutomaticZenRules();
+
+ if (rules == null || rules.size() < 2) {
+ logFail();
+ status = FAIL;
+ next();
+ return;
+ }
+
+ if (rules.contains(createdRule1) && rules.contains(createdRule2)) {
+ status = PASS;
+ } else {
+ logFail();
+ status = FAIL;
+ }
+ next();
+ }
+
+ @Override
+ void tearDown() {
+ for (String id : ids) {
+ mNm.removeAutomaticZenRule(id);
+ }
+ MockConditionProvider.resetData(mContext);
+ delay();
+ }
+ }
+
+ private class DeleteAutomaticZenRuleTest extends InteractiveTestCase {
+ private String id = null;
+
+ @Override
+ View inflate(ViewGroup parent) {
+ return createAutoItem(parent, R.string.cp_delete_rule);
+ }
+
+ @Override
+ void test() {
+ AutomaticZenRule ruleToCreate = createRule("RuleDelete", "Deletevalue",
+ NotificationManager.INTERRUPTION_FILTER_ALARMS);
+ AutomaticZenRule createdRule = mNm.addAutomaticZenRule(ruleToCreate);
+
+ if (createdRule != null) {
+ id = createdRule.getId();
+ if (mNm.removeAutomaticZenRule(id)) {
+ if (mNm.getAutomaticZenRule(id) == null) {
+ status = PASS;
+ } else {
+ logFail();
+ status = FAIL;
+ }
+ } else {
+ logFail();
+ status = FAIL;
+ }
+ } else {
+ logFail("Couldn't test rule deletion; creation failed.");
+ status = FAIL;
+ }
+ next();
+ }
+
+ @Override
+ void tearDown() {
+ MockConditionProvider.resetData(mContext);
+ delay();
+ }
+ }
+
+ private class UnsubscribeAutomaticZenRuleTest extends InteractiveTestCase {
+ private String id = null;
+ private AutomaticZenRule ruleToCreate;
+ private AutomaticZenRule createdRule;
+
+ @Override
+ View inflate(ViewGroup parent) {
+ return createAutoItem(parent, R.string.cp_unsubscribe_rule);
+ }
+
+ @Override
+ void setUp() {
+ ruleToCreate = createRule("RuleUnsubscribe", "valueUnsubscribe",
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY);
+ createdRule = mNm.addAutomaticZenRule(ruleToCreate);
+ id = createdRule == null ? null : createdRule.getId();
+ status = READY;
+ delay();
+ }
+
+ @Override
+ void test() {
+ MockConditionProvider.probeSubscribe(mContext,
+ new MockConditionProvider.ParcelableListResultCatcher() {
+ @Override
+ public void accept(List<Parcelable> result) {
+ boolean foundMatch = false;
+ for (Parcelable p : result) {
+ Uri uri = (Uri) p;
+ if (ruleToCreate.getConditionId().equals(uri)) {
+ foundMatch = true;
+ break;
+ }
+ }
+ if (foundMatch) {
+ // Now that it's subscribed, remove the rule and verify that it
+ // unsubscribes.
+ mNm.removeAutomaticZenRule(id);
+ MockConditionProvider.probeSubscribe(mContext,
+ new MockConditionProvider.ParcelableListResultCatcher() {
+ @Override
+ public void accept(List<Parcelable> result) {
+ boolean foundMatch = false;
+ for (Parcelable p : result) {
+ Uri uri = (Uri) p;
+ if (ruleToCreate.getConditionId().equals(uri)) {
+ foundMatch = true;
+ break;
+ }
+ }
+ if (foundMatch) {
+ logFail();
+ status = RETEST;
+ } else {
+ status = PASS;
+ }
+ next();
+ }
+ });
+ } else {
+ logFail("Couldn't test unsubscribe; subscribe failed.");
+ status = RETEST;
+ next();
+ }
+ }
+ });
+ delay(); // in case the catcher never returns
+ }
+
+ @Override
+ void tearDown() {
+ mNm.removeAutomaticZenRule(id);
+ MockConditionProvider.resetData(mContext);
+ // wait for intent to move through the system
+ delay();
+ }
+ }
+
+ private class IsDisabledTest extends InteractiveTestCase {
+ @Override
+ View inflate(ViewGroup parent) {
+ return createSettingsItem(parent, R.string.cp_disable_service);
+ }
+
+ @Override
+ boolean autoStart() {
+ return true;
+ }
+
+ @Override
+ void test() {
+ String cpPackages = Secure.getString(getContentResolver(),
+ Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
+ if (cpPackages == null || !cpPackages.contains(CP_PACKAGE)) {
+ status = PASS;
+ } else {
+ status = WAIT_FOR_USER;
+ }
+ next();
+ }
+
+ @Override
+ void tearDown() {
+ MockConditionProvider.resetData(mContext);
+ delay();
+ }
+ }
+
+ private class ServiceStoppedTest extends InteractiveTestCase {
+ @Override
+ View inflate(ViewGroup parent) {
+ return createAutoItem(parent, R.string.cp_service_stopped);
+ }
+
+ @Override
+ void test() {
+ MockConditionProvider.probeConnected(mContext,
+ new MockConditionProvider.BooleanResultCatcher() {
+ @Override
+ public void accept(boolean result) {
+ if (result) {
+ logFail();
+ status = RETEST;
+ delay();
+ } else {
+ status = PASS;
+ }
+ next();
+ }
+ });
+ delay(); // in case the catcher never returns
+ }
+
+ @Override
+ void tearDown() {
+ MockConditionProvider.resetData(mContext);
+ // wait for intent to move through the system
+ delay();
+ }
+ }
+
+ private AutomaticZenRule createRule(String name, String queryValue, int status) {
+ return new AutomaticZenRule(name,
+ ComponentName.unflattenFromString(CP_PATH),
+ MockConditionProvider.toConditionId(queryValue),
+ status,
+ true);
+ }
+
+ protected View createSettingsItem(ViewGroup parent, int messageId) {
+ return createUserItem(parent, R.string.cp_start_settings, messageId);
+ }
+
+ public void launchSettings() {
+ startActivity(new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS));
+ }
+
+ public void actionPressed(View v) {
+ Object tag = v.getTag();
+ if (tag instanceof Integer) {
+ int id = ((Integer) tag).intValue();
+ if (id == R.string.cp_start_settings) {
+ launchSettings();
+ } else if (id == R.string.attention_ready) {
+ mCurrentTest.status = READY;
+ next();
+ }
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockConditionProvider.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockConditionProvider.java
new file mode 100644
index 0000000..4b90d9a
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockConditionProvider.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2013 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 com.android.cts.verifier.notifications;
+
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.service.notification.Condition;
+import android.service.notification.ConditionProviderService;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MockConditionProvider extends ConditionProviderService {
+ static final String TAG = "MockConditionProvider";
+
+ static final String PACKAGE_NAME = "com.android.cts.verifier.notifications";
+ static final String PATH = "mock_cp";
+ static final String QUERY = "query_item";
+
+ static final String SERVICE_BASE = "android.service.notification.cts.MockConditionProvider.";
+ static final String SERVICE_CHECK = SERVICE_BASE + "SERVICE_CHECK";
+ static final String SERVICE_RESET = SERVICE_BASE + "SERVICE_RESET";
+ static final String SERVICE_SUBSCRIBE = SERVICE_BASE + "SERVICE_SUBSCRIBE";
+
+ static final String EXTRA_PAYLOAD = "PAYLOAD";
+ static final String EXTRA_INT = "INT";
+ static final String EXTRA_BOOLEAN = "BOOLEAN";
+ static final String EXTRA_TAG = "TAG";
+ static final String EXTRA_CODE = "CODE";
+
+ static final int RESULT_NO_SERVER = Activity.RESULT_FIRST_USER + 1;
+
+
+ private ArrayList<Uri> mSubscriptions = new ArrayList<>();
+ private boolean mConnected = false;
+ private BroadcastReceiver mReceiver;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Log.d(TAG, "created");
+
+ mSubscriptions = new ArrayList<Uri>();
+
+ mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (SERVICE_CHECK.equals(action)) {
+ Log.d(TAG, "SERVICE_CHECK");
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(EXTRA_BOOLEAN, mConnected);
+ setResultExtras(bundle);
+ setResultCode(Activity.RESULT_OK);
+ } else if (SERVICE_SUBSCRIBE.equals(action)) {
+ Log.d(TAG, "SERVICE_SUBSCRIBE");
+ Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(EXTRA_PAYLOAD, mSubscriptions);
+ setResultExtras(bundle);
+ setResultCode(Activity.RESULT_OK);
+ } else if (SERVICE_RESET.equals(action)) {
+ Log.d(TAG, "SERVICE_RESET");
+ resetData();
+ } else {
+ Log.w(TAG, "unknown action");
+ setResultCode(Activity.RESULT_CANCELED);
+ }
+ }
+ };
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(SERVICE_CHECK);
+ filter.addAction(SERVICE_SUBSCRIBE);
+ filter.addAction(SERVICE_RESET);
+ registerReceiver(mReceiver, filter);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mConnected = false;
+ unregisterReceiver(mReceiver);
+ mReceiver = null;
+ Log.d(TAG, "destroyed");
+ }
+
+ public void resetData() {
+ mSubscriptions.clear();
+ }
+
+ public static void resetData(Context context) {
+ sendCommand(context, SERVICE_RESET, null, 0);
+ }
+
+ public static void probeConnected(Context context, BooleanResultCatcher catcher) {
+ requestConnected(context, SERVICE_CHECK, catcher);
+ }
+
+ public static void probeSubscribe(Context context, ParcelableListResultCatcher catcher) {
+ requestParcelableListResult(context, SERVICE_SUBSCRIBE, catcher);
+ }
+
+ private static void sendCommand(Context context, String action, String tag, int code) {
+ Intent broadcast = new Intent(action);
+ if (tag != null) {
+ broadcast.putExtra(EXTRA_TAG, tag);
+ broadcast.putExtra(EXTRA_CODE, code);
+ }
+ context.sendBroadcast(broadcast);
+ }
+
+ public static Uri toConditionId(String queryValue) {
+ return new Uri.Builder().scheme(Condition.SCHEME)
+ .authority(PACKAGE_NAME)
+ .appendPath(PATH)
+ .appendQueryParameter(QUERY, queryValue)
+ .build();
+ }
+
+ @Override
+ public void onConnected() {
+ Log.d(TAG, "connected");
+ mConnected = true;
+ }
+
+ @Override
+ public void onRequestConditions(int relevance) {
+
+ }
+
+ @Override
+ public void onSubscribe(Uri conditionId) {
+ Log.d(TAG, "subscribed to " + conditionId);
+ mSubscriptions.add(conditionId);
+ }
+
+ @Override
+ public void onUnsubscribe(Uri conditionId) {
+ Log.d(TAG, "unsubscribed from " + conditionId);
+ mSubscriptions.remove(conditionId);
+ }
+
+ public abstract static class BooleanResultCatcher extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ accept(getResultExtras(true).getBoolean(EXTRA_BOOLEAN, false));
+ }
+
+ abstract public void accept(boolean result);
+ }
+
+ private static void requestConnected(Context context, String action,
+ BooleanResultCatcher catcher) {
+ Intent broadcast = new Intent(action);
+ context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
+ }
+
+ public abstract static class ParcelableListResultCatcher extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ accept(getResultExtras(true).getParcelableArrayList(EXTRA_PAYLOAD));
+ }
+
+ abstract public void accept(List<Parcelable> result);
+ }
+
+ private static void requestParcelableListResult(Context context, String action,
+ ParcelableListResultCatcher catcher) {
+ Intent broadcast = new Intent(action);
+ context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sample/SampleTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sample/SampleTestActivity.java
index 41bc303..678aeca 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sample/SampleTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sample/SampleTestActivity.java
@@ -77,14 +77,15 @@
double[] metricValues = new double[] {1, 11, 21, 1211, 111221};
// Record metric results
- getReportLog().setSummary(
- "Sample Summary", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
- getReportLog().addValues("Sample Values", metricValues, ResultType.NEUTRAL, ResultUnit.FPS);
+ getReportLog().setSummary("Sample Summary", 1.0, ResultType.HIGHER_BETTER,
+ ResultUnit.BYTE);
+ getReportLog().addValues("Sample Values", metricValues, ResultType.NEUTRAL,
+ ResultUnit.FPS);
// Alternatively, activities can invoke TestResult directly to record metrics
ReportLog reportLog = new PassFailButtons.CtsVerifierReportLog();
reportLog.setSummary("Sample Summary", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
- getReportLog().addValues("Sample Values", metricValues, ResultType.NEUTRAL, ResultUnit.FPS);
+ reportLog.addValues("Sample Values", metricValues, ResultType.NEUTRAL, ResultUnit.FPS);
TestResult.setPassedResult(this, "manualSample", "manualDetails", reportLog);
}
diff --git a/build/compatibility_test_suite.mk b/build/compatibility_test_suite.mk
new file mode 100644
index 0000000..6430efa
--- /dev/null
+++ b/build/compatibility_test_suite.mk
@@ -0,0 +1,51 @@
+# 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.
+
+#
+# Builds a compatibility test suite.
+#
+
+# Generate the SuiteInfo.java
+suite_info_java := $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_MODULE),true,COMMON)/com/android/compatibility/SuiteInfo.java
+$(suite_info_java): PRIVATE_SUITE_BUILD_NUMBER := $(LOCAL_SUITE_BUILD_NUMBER)
+$(suite_info_java): PRIVATE_SUITE_NAME := $(LOCAL_SUITE_NAME)
+$(suite_info_java): PRIVATE_SUITE_FULLNAME := $(LOCAL_SUITE_FULLNAME)
+$(suite_info_java): PRIVATE_SUITE_VERSION := $(LOCAL_SUITE_VERSION)
+$(suite_info_java): cts/build/compatibility_test_suite.mk $(LOCAL_MODULE_MAKEFILE)
+ @echo Generating: $@
+ $(hide) mkdir -p $(dir $@)
+ $(hide) echo "/* This file is auto generated by Android.mk. Do not modify. */" > $@
+ $(hide) echo "package com.android.compatibility;" >> $@
+ $(hide) echo "public class SuiteInfo {" >> $@
+ $(hide) echo " public static final String BUILD_NUMBER = \"$(PRIVATE_SUITE_BUILD_NUMBER)\";" >> $@
+ $(hide) echo " public static final String NAME = \"$(PRIVATE_SUITE_NAME)\";" >> $@
+ $(hide) echo " public static final String FULLNAME = \"$(PRIVATE_SUITE_FULLNAME)\";" >> $@
+ $(hide) echo " public static final String VERSION = \"$(PRIVATE_SUITE_VERSION)\";" >> $@
+ $(hide) echo "}" >> $@
+
+# Reset variables
+LOCAL_SUITE_BUILD_NUMBER :=
+LOCAL_SUITE_NAME :=
+LOCAL_SUITE_FULLNAME :=
+LOCAL_SUITE_VERSION :=
+
+# Include the SuiteInfo.java
+LOCAL_GENERATED_SOURCES := $(suite_info_java)
+
+# Add the base libraries
+LOCAL_JAVA_LIBRARIES += tradefed-prebuilt hosttestlib compatibility-host-util
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/build/config.mk b/build/config.mk
index 56d4ae6..eae7c00 100644
--- a/build/config.mk
+++ b/build/config.mk
@@ -16,6 +16,8 @@
# directory before creating the final CTS distribution.
CTS_TESTCASES_OUT := $(HOST_OUT)/cts/android-cts/repository/testcases
+COMPATIBILITY_TESTCASES_OUT_cts_v2 := $(HOST_OUT)/cts_v2/android-cts_v2/testcases
+
# Scanners of source files for tests which are then inputed into
# the XML generator to produce test XMLs.
CTS_NATIVE_TEST_SCANNER := $(HOST_OUT_EXECUTABLES)/cts-native-scanner
@@ -38,6 +40,7 @@
CTS_MODULE_TEST_CONFIG := AndroidTest.xml
# CTS build rules
+BUILD_COMPATIBILITY_SUITE := cts/build/compatibility_test_suite.mk
BUILD_CTS_EXECUTABLE := cts/build/test_executable.mk
BUILD_CTS_PACKAGE := cts/build/test_package.mk
BUILD_CTS_GTEST_PACKAGE := cts/build/test_gtest_package.mk
diff --git a/build/device_info_package.mk b/build/device_info_package.mk
index 0aaa8aa..1f4d350 100644
--- a/build/device_info_package.mk
+++ b/build/device_info_package.mk
@@ -17,9 +17,33 @@
#
DEVICE_INFO_PACKAGE := com.android.compatibility.common.deviceinfo
-DEVICE_INFO_INSTRUMENT := com.android.compatibility.common.deviceinfo.DeviceInfoInstrument
+DEVICE_INFO_INSTRUMENT := android.support.test.runner.AndroidJUnitRunner
DEVICE_INFO_PERMISSIONS += android.permission.WRITE_EXTERNAL_STORAGE
-DEVICE_INFO_ACTIVITIES += $(DEVICE_INFO_PACKAGE).GenericDeviceInfo $(DEVICE_INFO_PACKAGE).PackageDeviceInfo
+DEVICE_INFO_ACTIVITIES += \
+ $(DEVICE_INFO_PACKAGE).CameraDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).ConfigurationDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).CpuDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).FeatureDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).GenericDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).GlesStubActivity \
+ $(DEVICE_INFO_PACKAGE).GraphicsDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).LibraryDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).LocaleDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).MediaDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).MemoryDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).PackageDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).PropertyDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).ScreenDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).StorageDeviceInfo \
+ $(DEVICE_INFO_PACKAGE).UserDeviceInfo
+
+ifeq ($(DEVICE_INFO_MIN_SDK),)
+DEVICE_INFO_MIN_SDK := 8
+endif
+
+ifeq ($(DEVICE_INFO_TARGET_SDK),)
+DEVICE_INFO_TARGET_SDK := 8
+endif
# Add the base device info
LOCAL_STATIC_JAVA_LIBRARIES += compatibility-device-info
@@ -34,6 +58,8 @@
$(manifest_xml): PRIVATE_INFO_ACTIVITIES := $(foreach activity,$(DEVICE_INFO_ACTIVITIES),-a $(activity))
$(manifest_xml): PRIVATE_PACKAGE := $(DEVICE_INFO_PACKAGE)
$(manifest_xml): PRIVATE_INSTRUMENT := $(DEVICE_INFO_INSTRUMENT)
+$(manifest_xml): PRIVATE_MIN_SDK := $(DEVICE_INFO_MIN_SDK)
+$(manifest_xml): PRIVATE_TARGET_SDK := $(DEVICE_INFO_TARGET_SDK)
# Regenerate manifest.xml if the generator jar, */cts-device-info/Android.mk, or this file is changed.
$(manifest_xml): $(MANIFEST_GENERATOR_JAR) $(LOCAL_PATH)/Android.mk cts/build/device_info_package.mk
@@ -44,9 +70,13 @@
$(PRIVATE_INFO_ACTIVITIES) \
-p $(PRIVATE_PACKAGE) \
-i $(PRIVATE_INSTRUMENT) \
+ -s $(PRIVATE_MIN_SDK) \
+ -t $(PRIVATE_TARGET_SDK) \
-o $@
# Reset variables
+DEVICE_INFO_MIN_SDK :=
+DEVICE_INFO_TARGET_SDK :=
DEVICE_INFO_PACKAGE :=
DEVICE_INFO_INSTRUMENT :=
DEVICE_INFO_PERMISSIONS :=
diff --git a/build/module_test_config.mk b/build/module_test_config.mk
index 6584ef2..fec4893 100644
--- a/build/module_test_config.mk
+++ b/build/module_test_config.mk
@@ -12,10 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cts_module_test_config := $(if $(wildcard \
- $(LOCAL_PATH)/$(CTS_MODULE_TEST_CONFIG)), \
- $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).config)
-ifneq ($(cts_module_test_config),)
-$(cts_module_test_config): $(LOCAL_PATH)/$(CTS_MODULE_TEST_CONFIG) | $(ACP)
+ifneq ($(LOCAL_CTS_MODULE_CONFIG),)
+cts_module_test_config := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).config
+$(cts_module_test_config): $(LOCAL_CTS_MODULE_CONFIG) | $(ACP)
$(call copy-file-to-target)
endif
+# clear var
+LOCAL_CTS_MODULE_CONFIG :=
diff --git a/build/test_deqp_package.mk b/build/test_deqp_package.mk
index 570669d..f98f342 100644
--- a/build/test_deqp_package.mk
+++ b/build/test_deqp_package.mk
@@ -18,13 +18,13 @@
CTS_DEQP_CONFIG_PATH := $(call my-dir)
-cts_library_xmls:=$(foreach xml_file, $(call find-files-in-subdirs, external/deqp/android/cts/master, 'com.drawelements.deqp.$(DEQP_API).*xml', .), $(CTS_TESTCASES_OUT)/$(xml_file))
-$(cts_library_xmls) : PRIVATE_API := $(DEQP_API)
-$(cts_library_xmls) : PRIVATE_TEST_NAME := $(DEQP_TEST_NAME)
-$(cts_library_xmls) : PRIVATE_TEST_PACKAGE := com.drawelements.deqp.$(DEQP_API)
-$(cts_library_xmls) : PRIVATE_DUMMY_CASELIST := $(CTS_DEQP_CONFIG_PATH)/deqp_dummy_test_list
-$(cts_library_xmls) : $(CTS_TESTCASES_OUT)/%.xml: external/deqp/android/cts/master/%.xml $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_XML_GENERATOR)
- $(hide) echo Generating test description $@
+cts_library_xml := $(CTS_TESTCASES_OUT)/com.drawelements.deqp.$(DEQP_API).xml
+$(cts_library_xml): MUSTPASS_XML_FILE := external/deqp/android/cts/master/com.drawelements.deqp.$(DEQP_API).xml
+$(cts_library_xml): PRIVATE_TEST_NAME := $(DEQP_TEST_NAME)
+$(cts_library_xml): PRIVATE_TEST_PACKAGE := com.drawelements.deqp.$(DEQP_API)
+$(cts_library_xml): PRIVATE_DUMMY_CASELIST := $(CTS_DEQP_CONFIG_PATH)/deqp_dummy_test_list
+$(cts_library_xml): external/deqp/android/cts/master/com.drawelements.deqp.$(DEQP_API).xml external/deqp/android/cts/mnc/$(DEQP_API)-master.txt $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_XML_GENERATOR)
+ $(hide) echo Generating test description for $(PRIVATE_TEST_NAME)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
# Query build ABIs by routing a dummy test list through xml generator and parse result. Use sed to insert the ABI string into the XML files.
@@ -37,5 +37,5 @@
< $(PRIVATE_DUMMY_CASELIST) \
| grep --only-matching -e " abis=\"[^\"]*\""` && \
$(SED_EXTENDED) -e "s:^(\s*)<Test ((.[^/]|[^/])*)(/?)>$$:\1<Test \2 $${SUPPORTED_ABI_ATTR}\4>:" \
- < $< \
+ < $(MUSTPASS_XML_FILE) \
> $@
diff --git a/build/test_host_java_library.mk b/build/test_host_java_library.mk
index b4c7e63..7fdefb5 100644
--- a/build/test_host_java_library.mk
+++ b/build/test_host_java_library.mk
@@ -29,11 +29,6 @@
cts_src_dirs := $(addprefix -s , $(cts_src_dirs))
cts_library_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).xml
-ifeq ($(cts_runtime_hint),)
-$(cts_library_xml): PRIVATE_CTS_RUNTIME_HINT := "0"
-else
-$(cts_library_xml): PRIVATE_CTS_RUNTIME_HINT := $(cts_runtime_hint)
-endif
$(cts_library_xml): PRIVATE_SRC_DIRS := $(cts_src_dirs)
$(cts_library_xml): PRIVATE_TEST_PACKAGE := $(LOCAL_CTS_TEST_PACKAGE)
$(cts_library_xml): PRIVATE_LIBRARY := $(LOCAL_MODULE)
@@ -49,7 +44,6 @@
-j $(PRIVATE_JAR_PATH) \
-n $(PRIVATE_LIBRARY) \
-p $(PRIVATE_TEST_PACKAGE) \
- -x "runtimeHint->$(PRIVATE_CTS_RUNTIME_HINT)" \
-e $(CTS_EXPECTATIONS) \
-b $(CTS_UNSUPPORTED_ABIS) \
-a $(CTS_TARGET_ARCH) \
diff --git a/build/test_package.mk b/build/test_package.mk
index 13e582e..c6b0865 100644
--- a/build/test_package.mk
+++ b/build/test_package.mk
@@ -39,11 +39,6 @@
else
PRIVATE_CTS_TEST_PACKAGE_NAME_ := android.$(notdir $(LOCAL_PATH))
endif
-ifeq ($(cts_runtime_hint),)
-$(cts_package_xml): PRIVATE_CTS_RUNTIME_HINT := "0"
-else
-$(cts_package_xml): PRIVATE_CTS_RUNTIME_HINT := $(cts_runtime_hint)
-endif
$(cts_package_xml): PRIVATE_TEST_PACKAGE := $(PRIVATE_CTS_TEST_PACKAGE_NAME_)
$(cts_package_xml): PRIVATE_MANIFEST := $(LOCAL_PATH)/AndroidManifest.xml
$(cts_package_xml): PRIVATE_TEST_TYPE := $(if $(LOCAL_CTS_TEST_RUNNER),$(LOCAL_CTS_TEST_RUNNER),'')
@@ -61,13 +56,9 @@
-i "$(PRIVATE_INSTRUMENTATION)" \
-n $(PRIVATE_PACKAGE) \
-p $(PRIVATE_TEST_PACKAGE) \
- -x "runtimeHint->$(PRIVATE_CTS_RUNTIME_HINT)" \
-e $(CTS_EXPECTATIONS) \
-b $(CTS_UNSUPPORTED_ABIS) \
-a $(CTS_TARGET_ARCH) \
-o $@
# Have the module name depend on the cts files; so the cts files get generated when you run mm/mmm/mma/mmma.
$(my_register_name) : $(cts_package_xml) $(cts_module_test_config)
-
-# Make sure we clear cts_runtime_hint, so other parents will use the default if they do not set cts_runtime_hint.
-cts_runtime_hint :=
diff --git a/common/device-side/device-info/Android.mk b/common/device-side/device-info/Android.mk
index 0f5e8d3..927101b 100644
--- a/common/device-side/device-info/Android.mk
+++ b/common/device-side/device-info/Android.mk
@@ -25,6 +25,8 @@
# uncomment when b/13282254 is fixed
#LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
include $(BUILD_STATIC_JAVA_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/CameraDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/CameraDeviceInfo.java
new file mode 100644
index 0000000..4e379dc
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/CameraDeviceInfo.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.media.CamcorderProfile;
+
+/**
+ * Camera information collector.
+ */
+public final class CameraDeviceInfo extends DeviceInfo {
+
+ @Override
+ protected void collectDeviceInfo() {
+ addResult("profile_480p", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P));
+ addResult("profile_720p", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P));
+ addResult("profile_1080p", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_1080P));
+ addResult("profile_cif", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_CIF));
+ addResult("profile_qcif", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QCIF));
+ addResult("profile_qvga", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QVGA));
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ConfigurationDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ConfigurationDeviceInfo.java
new file mode 100644
index 0000000..4ce905e
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ConfigurationDeviceInfo.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.content.res.Configuration;
+
+/**
+ * Configuration device info collector.
+ */
+public final class ConfigurationDeviceInfo extends DeviceInfo {
+
+ @Override
+ protected void collectDeviceInfo() {
+ Configuration con = getInstrumentation().getContext().getResources().getConfiguration();
+ addResult("touchscreen", con.touchscreen);
+ addResult("navigation", con.navigation);
+ addResult("keyboard", con.keyboard);
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/CpuDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/CpuDeviceInfo.java
new file mode 100644
index 0000000..45d8e47
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/CpuDeviceInfo.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+/**
+ * CPU device info collector.
+ */
+public final class CpuDeviceInfo extends DeviceInfo {
+
+ @Override
+ protected void collectDeviceInfo() {
+ addResult("available_processors", Runtime.getRuntime().availableProcessors());
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
new file mode 100644
index 0000000..151e89a
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
@@ -0,0 +1,474 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Environment;
+import android.test.InstrumentationTestCase;
+import android.text.TextUtils;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Collect device information on target device and write to a JSON file.
+ */
+public abstract class DeviceInfo extends InstrumentationTestCase {
+
+ private enum ResultCode {
+ // Collection started.
+ STARTED,
+ // Collection completed.
+ COMPLETED,
+ // Collection completed with error.
+ ERROR,
+ // Collection failed to complete.
+ FAILED
+ }
+
+ private static final int MAX_STRING_VALUE_LENGTH = 1000;
+ private static final int MAX_ARRAY_LENGTH = 1000;
+
+ private static final String LOG_TAG = "ExtendedDeviceInfo";
+
+ private JsonWriter mJsonWriter = null;
+ private String mResultFilePath = null;
+ private String mErrorMessage = null;
+ private ResultCode mResultCode = ResultCode.STARTED;
+
+ Set<String> mActivityList = new HashSet<String>();
+
+ public void testCollectDeviceInfo() {
+ if (!mActivityList.contains(getClass().getName())) {
+ return;
+ }
+
+ if (createFilePath()) {
+ createJsonWriter();
+ startJsonWriter();
+ try {
+ collectDeviceInfo();
+ } catch(Exception | Error e) {
+ error(e.getMessage());
+ }
+ closeJsonWriter();
+
+ if (mResultCode == ResultCode.STARTED) {
+ mResultCode = ResultCode.COMPLETED;
+ }
+ }
+
+ sendStatus();
+
+ String message = getClass().getSimpleName() + " collection completed.";
+ assertEquals(message, ResultCode.COMPLETED, mResultCode);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Build the list of supported activities that can run collection.
+ ActivityInfo[] activities = null;
+ try {
+ activities = getContext().getPackageManager().getPackageInfo(
+ getContext().getPackageName(), PackageManager.GET_ACTIVITIES).activities;
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Exception occurred while getting activities.", e);
+ return;
+ }
+
+ for (ActivityInfo activityInfo : activities) {
+ mActivityList.add(activityInfo.name);
+ }
+ }
+
+ /**
+ * Method to collect device information.
+ */
+ protected abstract void collectDeviceInfo();
+
+ protected Context getContext() {
+ return getInstrumentation().getContext();
+ }
+
+ /**
+ * Sends status to instrumentation.
+ */
+ void sendStatus() {
+ Bundle bundle = new Bundle();
+ String className = getClass().getSimpleName();
+ if (this instanceof GenericDeviceInfo) {
+ ((GenericDeviceInfo) this).putDeviceInfo(bundle);
+ }
+ if (!TextUtils.isEmpty(mErrorMessage)) {
+ bundle.putString("DEVICE_INFO_ERROR_" + className, mErrorMessage);
+ }
+ if (mResultCode == ResultCode.COMPLETED) {
+ bundle.putString("DEVICE_INFO_FILE_" + className, mResultFilePath);
+ }
+ getInstrumentation().sendStatus(Activity.RESULT_OK, bundle);
+ }
+
+ /**
+ * Returns the path to the json file if collector completed successfully.
+ */
+ String getResultFilePath() {
+ return mResultFilePath;
+ }
+
+ private void error(String message) {
+ mResultCode = ResultCode.ERROR;
+ mErrorMessage = message;
+ Log.e(LOG_TAG, message);
+ }
+
+ private void failed(String message) {
+ mResultCode = ResultCode.FAILED;
+ mErrorMessage = message;
+ Log.e(LOG_TAG, message);
+ }
+
+ private boolean createFilePath() {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ failed("External storage is not mounted");
+ return false;
+ }
+ final File dir = new File(Environment.getExternalStorageDirectory(), "device-info-files");
+ if (!dir.mkdirs() && !dir.isDirectory()) {
+ failed("Cannot create directory for device info files");
+ return false;
+ }
+
+ // Create file at /sdcard/device-info-files/<class_name>.deviceinfo.json
+ final File jsonFile = new File(dir, getClass().getSimpleName() + ".deviceinfo.json");
+ try {
+ jsonFile.createNewFile();
+ } catch (Exception e) {
+ failed("Cannot create file to collect device info");
+ return false;
+ }
+ mResultFilePath = jsonFile.getAbsolutePath();
+ return true;
+ }
+
+ private void createJsonWriter() {
+ try {
+ FileOutputStream out = new FileOutputStream(mResultFilePath);
+ mJsonWriter = new JsonWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
+ // TODO(agathaman): remove to make json output less pretty
+ mJsonWriter.setIndent(" ");
+ } catch (Exception e) {
+ failed("Failed to create JSON writer: " + e.getMessage());
+ }
+ }
+
+ private void startJsonWriter() {
+ try {
+ mJsonWriter.beginObject();
+ } catch (Exception e) {
+ failed("Failed to begin JSON object: " + e.getMessage());
+ }
+ }
+
+ private void closeJsonWriter() {
+ try {
+ mJsonWriter.endObject();
+ mJsonWriter.close();
+ } catch (Exception e) {
+ failed("Failed to close JSON object: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Start a new group of result.
+ */
+ public void startGroup() {
+ try {
+ mJsonWriter.beginObject();
+ } catch (Exception e) {
+ error("Failed to begin JSON group: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Start a new group of result with specified name.
+ */
+ public void startGroup(String name) {
+ try {
+ mJsonWriter.name(name);
+ mJsonWriter.beginObject();
+ } catch (Exception e) {
+ error("Failed to begin JSON group: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Complete adding result to the last started group.
+ */
+ public void endGroup() {
+ try {
+ mJsonWriter.endObject();
+ } catch (Exception e) {
+ error("Failed to end JSON group: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Start a new array of result.
+ */
+ public void startArray() {
+ try {
+ mJsonWriter.beginArray();
+ } catch (Exception e) {
+ error("Failed to begin JSON array: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Start a new array of result with specified name.
+ */
+ public void startArray(String name) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name);
+ mJsonWriter.beginArray();
+ } catch (Exception e) {
+ error("Failed to begin JSON array: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Complete adding result to the last started array.
+ */
+ public void endArray() {
+ try {
+ mJsonWriter.endArray();
+ } catch (Exception e) {
+ error("Failed to end JSON group: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add a double value result.
+ */
+ public void addResult(String name, double value) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name).value(value);
+ } catch (Exception e) {
+ error("Failed to add result for type double: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add a long value result.
+ */
+ public void addResult(String name, long value) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name).value(value);
+ } catch (Exception e) {
+ error("Failed to add result for type long: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add an int value result.
+ */
+ public void addResult(String name, int value) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name).value((Number) value);
+ } catch (Exception e) {
+ error("Failed to add result for type int: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add a boolean value result.
+ */
+ public void addResult(String name, boolean value) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name).value(value);
+ } catch (Exception e) {
+ error("Failed to add result for type boolean: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add a String value result.
+ */
+ public void addResult(String name, String value) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name).value(checkString(value));
+ } catch (Exception e) {
+ error("Failed to add result for type String: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add a double array result.
+ */
+ public void addArray(String name, double[] list) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name);
+ mJsonWriter.beginArray();
+ for (double value : checkArray(list)) {
+ mJsonWriter.value(value);
+ }
+ mJsonWriter.endArray();
+ } catch (Exception e) {
+ error("Failed to add result array for type double: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add a long array result.
+ */
+ public void addArray(String name, long[] list) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name);
+ mJsonWriter.beginArray();
+ for (long value : checkArray(list)) {
+ mJsonWriter.value(value);
+ }
+ mJsonWriter.endArray();
+ } catch (Exception e) {
+ error("Failed to add result array for type long: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add an int array result.
+ */
+ public void addArray(String name, int[] list) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name);
+ mJsonWriter.beginArray();
+ for (int value : checkArray(list)) {
+ mJsonWriter.value((Number) value);
+ }
+ mJsonWriter.endArray();
+ } catch (Exception e) {
+ error("Failed to add result array for type int: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add a boolean array result.
+ */
+ public void addArray(String name, boolean[] list) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name);
+ mJsonWriter.beginArray();
+ for (boolean value : checkArray(list)) {
+ mJsonWriter.value(value);
+ }
+ mJsonWriter.endArray();
+ } catch (Exception e) {
+ error("Failed to add result array for type boolean: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Add a String array result.
+ */
+ public void addArray(String name, String[] list) {
+ checkName(name);
+ try {
+ mJsonWriter.name(name);
+ mJsonWriter.beginArray();
+ for (String value : checkArray(list)) {
+ mJsonWriter.value(checkString(value));
+ }
+ mJsonWriter.endArray();
+ } catch (Exception e) {
+ error("Failed to add result array for type Sting: " + e.getMessage());
+ }
+ }
+
+ private static boolean[] checkArray(boolean[] values) {
+ if (values.length > MAX_ARRAY_LENGTH) {
+ return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
+ } else {
+ return values;
+ }
+ }
+
+ private static double[] checkArray(double[] values) {
+ if (values.length > MAX_ARRAY_LENGTH) {
+ return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
+ } else {
+ return values;
+ }
+ }
+
+ private static int[] checkArray(int[] values) {
+ if (values.length > MAX_ARRAY_LENGTH) {
+ return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
+ } else {
+ return values;
+ }
+ }
+
+ private static long[] checkArray(long[] values) {
+ if (values.length > MAX_ARRAY_LENGTH) {
+ return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
+ } else {
+ return values;
+ }
+ }
+
+ private static String[] checkArray(String[] values) {
+ if (values.length > MAX_ARRAY_LENGTH) {
+ return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
+ } else {
+ return values;
+ }
+ }
+
+ private static String checkString(String value) {
+ if (value.length() > MAX_STRING_VALUE_LENGTH) {
+ return value.substring(0, MAX_STRING_VALUE_LENGTH);
+ }
+ return value;
+ }
+
+ private static String checkName(String value) {
+ if (TextUtils.isEmpty(value)) {
+ throw new NullPointerException();
+ }
+ return value;
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivity.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivity.java
deleted file mode 100644
index f9de6eb..0000000
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivity.java
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * 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.
- */
-package com.android.compatibility.common.deviceinfo;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Environment;
-import android.text.TextUtils;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * Collect device information on target device and write to a JSON file.
- */
-public abstract class DeviceInfoActivity extends Activity {
-
- /** Device info result code: collector failed to complete. */
- private static final int DEVICE_INFO_RESULT_FAILED = -2;
- /** Device info result code: collector completed with error. */
- private static final int DEVICE_INFO_RESULT_ERROR = -1;
- /** Device info result code: collector has started but not completed. */
- private static final int DEVICE_INFO_RESULT_STARTED = 0;
- /** Device info result code: collector completed success. */
- private static final int DEVICE_INFO_RESULT_OK = 1;
-
- private static final int MAX_STRING_VALUE_LENGTH = 1000;
- private static final int MAX_ARRAY_LENGTH = 1000;
-
- private static final String LOG_TAG = "DeviceInfoActivity";
-
- private CountDownLatch mDone = new CountDownLatch(1);
- private JsonWriter mJsonWriter = null;
- private String mResultFilePath = null;
- private String mErrorMessage = "Collector has started.";
- private int mResultCode = DEVICE_INFO_RESULT_STARTED;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (createFilePath()) {
- createJsonWriter();
- startJsonWriter();
- collectDeviceInfo();
- closeJsonWriter();
-
- if (mResultCode == DEVICE_INFO_RESULT_STARTED) {
- mResultCode = DEVICE_INFO_RESULT_OK;
- }
- }
-
- Intent data = new Intent();
- if (mResultCode == DEVICE_INFO_RESULT_OK) {
- data.setData(Uri.parse(mResultFilePath));
- setResult(RESULT_OK, data);
- } else {
- data.setData(Uri.parse(mErrorMessage));
- setResult(RESULT_CANCELED, data);
- }
-
- mDone.countDown();
- finish();
- }
-
- /**
- * Method to collect device information.
- */
- protected abstract void collectDeviceInfo();
-
- void waitForActivityToFinish() {
- try {
- mDone.await();
- } catch (Exception e) {
- failed("Exception while waiting for activity to finish: " + e.getMessage());
- }
- }
-
- /**
- * Returns the error message if collector did not complete successfully.
- */
- String getErrorMessage() {
- if (mResultCode == DEVICE_INFO_RESULT_OK) {
- return null;
- }
- return mErrorMessage;
- }
-
- /**
- * Returns the path to the json file if collector completed successfully.
- */
- String getResultFilePath() {
- if (mResultCode == DEVICE_INFO_RESULT_OK) {
- return mResultFilePath;
- }
- return null;
- }
-
- private void error(String message) {
- mResultCode = DEVICE_INFO_RESULT_ERROR;
- mErrorMessage = message;
- Log.e(LOG_TAG, message);
- }
-
- private void failed(String message) {
- mResultCode = DEVICE_INFO_RESULT_FAILED;
- mErrorMessage = message;
- Log.e(LOG_TAG, message);
- }
-
- private boolean createFilePath() {
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- failed("External storage is not mounted");
- return false;
- }
- final File dir = new File(Environment.getExternalStorageDirectory(), "device-info-files");
- if (!dir.mkdirs() && !dir.isDirectory()) {
- failed("Cannot create directory for device info files");
- return false;
- }
-
- // Create file at /sdcard/device-info-files/<class_name>.deviceinfo.json
- final File jsonFile = new File(dir, getClass().getSimpleName() + ".deviceinfo.json");
- try {
- jsonFile.createNewFile();
- } catch (Exception e) {
- failed("Cannot create file to collect device info");
- return false;
- }
- mResultFilePath = jsonFile.getAbsolutePath();
- return true;
- }
-
- private void createJsonWriter() {
- try {
- FileOutputStream out = new FileOutputStream(mResultFilePath);
- mJsonWriter = new JsonWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
- // TODO(agathaman): remove to make json output less pretty
- mJsonWriter.setIndent(" ");
- } catch (Exception e) {
- failed("Failed to create JSON writer: " + e.getMessage());
- }
- }
-
- private void startJsonWriter() {
- try {
- mJsonWriter.beginObject();
- } catch (Exception e) {
- failed("Failed to begin JSON object: " + e.getMessage());
- }
- }
-
- private void closeJsonWriter() {
- try {
- mJsonWriter.endObject();
- mJsonWriter.close();
- } catch (Exception e) {
- failed("Failed to close JSON object: " + e.getMessage());
- }
- }
-
- /**
- * Start a new group of result.
- */
- public void startGroup() {
- try {
- mJsonWriter.beginObject();
- } catch (Exception e) {
- error("Failed to begin JSON group: " + e.getMessage());
- }
- }
-
- /**
- * Start a new group of result with specified name.
- */
- public void startGroup(String name) {
- try {
- mJsonWriter.name(name);
- mJsonWriter.beginObject();
- } catch (Exception e) {
- error("Failed to begin JSON group: " + e.getMessage());
- }
- }
-
- /**
- * Complete adding result to the last started group.
- */
- public void endGroup() {
- try {
- mJsonWriter.endObject();
- } catch (Exception e) {
- error("Failed to end JSON group: " + e.getMessage());
- }
- }
-
- /**
- * Start a new array of result.
- */
- public void startArray() {
- try {
- mJsonWriter.beginArray();
- } catch (Exception e) {
- error("Failed to begin JSON array: " + e.getMessage());
- }
- }
-
- /**
- * Start a new array of result with specified name.
- */
- public void startArray(String name) {
- checkName(name);
- try {
- mJsonWriter.name(name);
- mJsonWriter.beginArray();
- } catch (Exception e) {
- error("Failed to begin JSON array: " + e.getMessage());
- }
- }
-
- /**
- * Complete adding result to the last started array.
- */
- public void endArray() {
- try {
- mJsonWriter.endArray();
- } catch (Exception e) {
- error("Failed to end JSON group: " + e.getMessage());
- }
- }
-
- /**
- * Add a double value result.
- */
- public void addResult(String name, double value) {
- checkName(name);
- try {
- mJsonWriter.name(name).value(value);
- } catch (Exception e) {
- error("Failed to add result for type double: " + e.getMessage());
- }
- }
-
- /**
- * Add a long value result.
- */
- public void addResult(String name, long value) {
- checkName(name);
- try {
- mJsonWriter.name(name).value(value);
- } catch (Exception e) {
- error("Failed to add result for type long: " + e.getMessage());
- }
- }
-
- /**
- * Add an int value result.
- */
- public void addResult(String name, int value) {
- checkName(name);
- try {
- mJsonWriter.name(name).value((Number) value);
- } catch (Exception e) {
- error("Failed to add result for type int: " + e.getMessage());
- }
- }
-
- /**
- * Add a boolean value result.
- */
- public void addResult(String name, boolean value) {
- checkName(name);
- try {
- mJsonWriter.name(name).value(value);
- } catch (Exception e) {
- error("Failed to add result for type boolean: " + e.getMessage());
- }
- }
-
- /**
- * Add a String value result.
- */
- public void addResult(String name, String value) {
- checkName(name);
- try {
- mJsonWriter.name(name).value(checkString(value));
- } catch (Exception e) {
- error("Failed to add result for type String: " + e.getMessage());
- }
- }
-
- /**
- * Add a double array result.
- */
- public void addArray(String name, double[] list) {
- checkName(name);
- try {
- mJsonWriter.name(name);
- mJsonWriter.beginArray();
- for (double value : checkArray(list)) {
- mJsonWriter.value(value);
- }
- mJsonWriter.endArray();
- } catch (Exception e) {
- error("Failed to add result array for type double: " + e.getMessage());
- }
- }
-
- /**
- * Add a long array result.
- */
- public void addArray(String name, long[] list) {
- checkName(name);
- try {
- mJsonWriter.name(name);
- mJsonWriter.beginArray();
- for (long value : checkArray(list)) {
- mJsonWriter.value(value);
- }
- mJsonWriter.endArray();
- } catch (Exception e) {
- error("Failed to add result array for type long: " + e.getMessage());
- }
- }
-
- /**
- * Add an int array result.
- */
- public void addArray(String name, int[] list) {
- checkName(name);
- try {
- mJsonWriter.name(name);
- mJsonWriter.beginArray();
- for (int value : checkArray(list)) {
- mJsonWriter.value((Number) value);
- }
- mJsonWriter.endArray();
- } catch (Exception e) {
- error("Failed to add result array for type int: " + e.getMessage());
- }
- }
-
- /**
- * Add a boolean array result.
- */
- public void addArray(String name, boolean[] list) {
- checkName(name);
- try {
- mJsonWriter.name(name);
- mJsonWriter.beginArray();
- for (boolean value : checkArray(list)) {
- mJsonWriter.value(value);
- }
- mJsonWriter.endArray();
- } catch (Exception e) {
- error("Failed to add result array for type boolean: " + e.getMessage());
- }
- }
-
- /**
- * Add a String array result.
- */
- public void addArray(String name, String[] list) {
- checkName(name);
- try {
- mJsonWriter.name(name);
- mJsonWriter.beginArray();
- for (String value : checkArray(list)) {
- mJsonWriter.value(checkString(value));
- }
- mJsonWriter.endArray();
- } catch (Exception e) {
- error("Failed to add result array for type Sting: " + e.getMessage());
- }
- }
-
- private static boolean[] checkArray(boolean[] values) {
- if (values.length > MAX_ARRAY_LENGTH) {
- return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
- } else {
- return values;
- }
- }
-
- private static double[] checkArray(double[] values) {
- if (values.length > MAX_ARRAY_LENGTH) {
- return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
- } else {
- return values;
- }
- }
-
- private static int[] checkArray(int[] values) {
- if (values.length > MAX_ARRAY_LENGTH) {
- return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
- } else {
- return values;
- }
- }
-
- private static long[] checkArray(long[] values) {
- if (values.length > MAX_ARRAY_LENGTH) {
- return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
- } else {
- return values;
- }
- }
-
- private static String[] checkArray(String[] values) {
- if (values.length > MAX_ARRAY_LENGTH) {
- return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
- } else {
- return values;
- }
- }
-
- private static String checkString(String value) {
- if (value.length() > MAX_STRING_VALUE_LENGTH) {
- return value.substring(0, MAX_STRING_VALUE_LENGTH);
- }
- return value;
- }
-
- private static String checkName(String value) {
- if (TextUtils.isEmpty(value)) {
- throw new NullPointerException();
- }
- return value;
- }
-}
-
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoInstrument.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoInstrument.java
deleted file mode 100644
index 2f80911..0000000
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoInstrument.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.
- */
-package com.android.compatibility.common.deviceinfo;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * An instrumentation that runs all activities that extends DeviceInfoActivity.
- */
-public class DeviceInfoInstrument extends Instrumentation {
-
- private static final String LOG_TAG = "ExtendedDeviceInfo";
- private static final String COLLECTOR = "collector";
-
- // List of collectors to run. If null or empty, all collectors will run.
- private Set<String> mCollectorSet = new HashSet<String>();
-
- // Results sent to the caller when this istrumentation completes.
- private Bundle mBundle = new Bundle();
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (savedInstanceState != null) {
- String collectorList = savedInstanceState.getString(COLLECTOR);
- if (!TextUtils.isEmpty(collectorList)) {
- for (String collector : TextUtils.split(collectorList, ",")) {
- if (!TextUtils.isEmpty(collector)) {
- mCollectorSet.add(collector);
- }
- }
- }
- }
- start();
- }
-
- @Override
- public void onStart() {
- try {
- Context context = getContext();
- ActivityInfo[] activities = context.getPackageManager().getPackageInfo(
- context.getPackageName(), PackageManager.GET_ACTIVITIES).activities;
- for (ActivityInfo activityInfo : activities) {
- runActivity(activityInfo.name);
- }
- } catch (Exception e) {
- Log.e(LOG_TAG, "Exception occurred while running activities.", e);
- // Returns INSTRUMENTATION_CODE: 0
- finish(Activity.RESULT_CANCELED, mBundle);
- }
- // Returns INSTRUMENTATION_CODE: -1
- finish(Activity.RESULT_OK, mBundle);
- }
-
- /**
- * Returns true if the activity meets the criteria to run; otherwise, false.
- */
- private boolean isActivityRunnable(Class activityClass) {
- // Don't run the base DeviceInfoActivity class.
- if (DeviceInfoActivity.class == activityClass) {
- return false;
- }
- // Don't run anything that doesn't extends DeviceInfoActivity.
- if (!DeviceInfoActivity.class.isAssignableFrom(activityClass)) {
- return false;
- }
- // Only run activity if mCollectorSet is empty or contains it.
- if (mCollectorSet != null && mCollectorSet.size() > 0) {
- return mCollectorSet.contains(activityClass.getName());
- }
- // Run anything that makes it here.
- return true;
- }
-
- /**
- * Runs a device info activity and return the file path where the results are written to.
- */
- private void runActivity(String activityName) throws Exception {
- Class activityClass = null;
- try {
- activityClass = Class.forName(activityName);
- } catch (ClassNotFoundException e) {
- return;
- }
-
- if (activityClass == null || !isActivityRunnable(activityClass)) {
- return;
- }
-
- Intent intent = new Intent();
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setClassName(this.getContext(), activityName);
-
- DeviceInfoActivity activity = (DeviceInfoActivity) startActivitySync(intent);
- waitForIdleSync();
- activity.waitForActivityToFinish();
-
- String className = activityClass.getSimpleName();
- String errorMessage = activity.getErrorMessage();
- if (TextUtils.isEmpty(errorMessage)) {
- mBundle.putString(className, activity.getResultFilePath());
- } else {
- mBundle.putString(className, errorMessage);
- throw new Exception(errorMessage);
- }
- }
-}
-
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/FeatureDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/FeatureDeviceInfo.java
new file mode 100644
index 0000000..dff2313
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/FeatureDeviceInfo.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Feature device info collector.
+ */
+public final class FeatureDeviceInfo extends DeviceInfo {
+
+ @Override
+ protected void collectDeviceInfo() {
+ PackageManager packageManager = getInstrumentation().getContext().getPackageManager();
+ startArray("feature");
+
+ Set<String> checkedFeatures = new HashSet<String>();
+ for (String featureName : getPackageManagerFeatures()) {
+ checkedFeatures.add(featureName);
+ boolean hasFeature = packageManager.hasSystemFeature(featureName);
+ addFeature(featureName, "sdk", hasFeature);
+ }
+
+ FeatureInfo[] featureInfos = packageManager.getSystemAvailableFeatures();
+ if (featureInfos != null) {
+ for (FeatureInfo featureInfo : featureInfos) {
+ if (featureInfo.name != null && !checkedFeatures.contains(featureInfo.name)) {
+ addFeature(featureInfo.name, "other", true);
+ }
+ }
+ }
+
+ endArray();
+ }
+
+ /**
+ * Use reflection to get the features defined by the SDK. If there are features that do not fit
+ * the convention of starting with "FEATURE_" then they will still be shown under the
+ * "Other Features" section.
+ *
+ * @return list of feature names from sdk
+ */
+ private List<String> getPackageManagerFeatures() {
+ try {
+ List<String> features = new ArrayList<String>();
+ Field[] fields = PackageManager.class.getFields();
+ for (Field field : fields) {
+ if (field.getName().startsWith("FEATURE_")) {
+ String feature = (String) field.get(null);
+ features.add(feature);
+ }
+ }
+ return features;
+ } catch (IllegalAccessException illegalAccess) {
+ throw new RuntimeException(illegalAccess);
+ }
+ }
+
+ private void addFeature(String name, String type, boolean available) {
+ startGroup();
+ addResult("name", name);
+ addResult("type", type);
+ addResult("available", available);
+ endGroup();
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
index 7df3dae..467269e 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
@@ -15,13 +15,6 @@
*/
package com.android.compatibility.common.deviceinfo;
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.FeatureInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
@@ -29,29 +22,20 @@
import android.os.UserManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.Display;
-import android.view.WindowManager;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Scanner;
-import java.util.Set;
+import java.lang.Integer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
-import com.android.compatibility.common.deviceinfo.DeviceInfoActivity;
+import com.android.compatibility.common.deviceinfo.DeviceInfo;
/**
* Generic device info collector.
*/
-public class GenericDeviceInfo extends DeviceInfoActivity {
+public class GenericDeviceInfo extends DeviceInfo {
+ public static final String DEVICE_INFO_GENERIC = "DEVICE_INFO_GENERIC_%s";
public static final String BUILD_ID = "build_id";
public static final String BUILD_PRODUCT = "build_product";
public static final String BUILD_DEVICE = "build_device";
@@ -69,48 +53,58 @@
public static final String BUILD_SERIAL = "build_serial";
public static final String BUILD_VERSION_RELEASE = "build_version_release";
public static final String BUILD_VERSION_SDK = "build_version_sdk";
+ public static final String BUILD_VERSION_SDK_INT = "build_version_sdk_int";
public static final String BUILD_VERSION_BASE_OS = "build_version_base_os";
public static final String BUILD_VERSION_SECURITY_PATCH = "build_version_security_patch";
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
+ private final Map<String, String> mDeviceInfo = new HashMap<>();
@Override
protected void collectDeviceInfo() {
- addResult(BUILD_ID, Build.ID);
- addResult(BUILD_PRODUCT, Build.PRODUCT);
- addResult(BUILD_DEVICE, Build.DEVICE);
- addResult(BUILD_BOARD, Build.BOARD);
- addResult(BUILD_MANUFACTURER, Build.MANUFACTURER);
- addResult(BUILD_BRAND, Build.BRAND);
- addResult(BUILD_MODEL, Build.MODEL);
- addResult(BUILD_TYPE, Build.TYPE);
- addResult(BUILD_FINGERPRINT, Build.FINGERPRINT);
- addResult(BUILD_ABI, Build.CPU_ABI);
- addResult(BUILD_ABI2, Build.CPU_ABI2);
- addResult(BUILD_SERIAL, Build.SERIAL);
- addResult(BUILD_VERSION_RELEASE, Build.VERSION.RELEASE);
- addResult(BUILD_VERSION_SDK, Build.VERSION.SDK);
+ addDeviceInfo(BUILD_ID, Build.ID);
+ addDeviceInfo(BUILD_PRODUCT, Build.PRODUCT);
+ addDeviceInfo(BUILD_DEVICE, Build.DEVICE);
+ addDeviceInfo(BUILD_BOARD, Build.BOARD);
+ addDeviceInfo(BUILD_MANUFACTURER, Build.MANUFACTURER);
+ addDeviceInfo(BUILD_BRAND, Build.BRAND);
+ addDeviceInfo(BUILD_MODEL, Build.MODEL);
+ addDeviceInfo(BUILD_TYPE, Build.TYPE);
+ addDeviceInfo(BUILD_FINGERPRINT, Build.FINGERPRINT);
+ addDeviceInfo(BUILD_ABI, Build.CPU_ABI);
+ addDeviceInfo(BUILD_ABI2, Build.CPU_ABI2);
+ addDeviceInfo(BUILD_SERIAL, Build.SERIAL);
+ addDeviceInfo(BUILD_VERSION_RELEASE, Build.VERSION.RELEASE);
+ addDeviceInfo(BUILD_VERSION_SDK, Build.VERSION.SDK);
+ addDeviceInfo(BUILD_VERSION_SDK_INT, Integer.toString(Build.VERSION.SDK_INT));
- // Collect build fields available in API level 21
+ // Collect build fields available in API level 21
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- addResult(BUILD_ABIS, TextUtils.join(",", Build.SUPPORTED_ABIS));
- addResult(BUILD_ABIS_32, TextUtils.join(",", Build.SUPPORTED_32_BIT_ABIS));
- addResult(BUILD_ABIS_64, TextUtils.join(",", Build.SUPPORTED_64_BIT_ABIS));
+ addDeviceInfo(BUILD_ABIS, TextUtils.join(",", Build.SUPPORTED_ABIS));
+ addDeviceInfo(BUILD_ABIS_32, TextUtils.join(",", Build.SUPPORTED_32_BIT_ABIS));
+ addDeviceInfo(BUILD_ABIS_64, TextUtils.join(",", Build.SUPPORTED_64_BIT_ABIS));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- addResult(BUILD_VERSION_BASE_OS, Build.VERSION.BASE_OS);
- addResult(BUILD_VERSION_SECURITY_PATCH, Build.VERSION.SECURITY_PATCH);
+ addDeviceInfo(BUILD_VERSION_BASE_OS, Build.VERSION.BASE_OS);
+ addDeviceInfo(BUILD_VERSION_SECURITY_PATCH, Build.VERSION.SECURITY_PATCH);
} else {
// Access system properties directly because Build.Version.BASE_OS and
// Build.Version.SECURITY_PATCH are not defined pre-M.
- addResult(BUILD_VERSION_BASE_OS,
+ addDeviceInfo(BUILD_VERSION_BASE_OS,
SystemProperties.get("ro.build.version.base_os", ""));
- addResult(BUILD_VERSION_SECURITY_PATCH,
+ addDeviceInfo(BUILD_VERSION_SECURITY_PATCH,
SystemProperties.get("ro.build.version.security_patch", ""));
}
}
+
+ private void addDeviceInfo(String key, String value) {
+ mDeviceInfo.put(key, value);
+ addResult(key, value);
+ }
+
+ protected void putDeviceInfo(Bundle bundle) {
+ for (Entry<String, String> entry : mDeviceInfo.entrySet()) {
+ bundle.putString(String.format(DEVICE_INFO_GENERIC, entry.getKey()), entry.getValue());
+ }
+ }
}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GlesStubActivity.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GlesStubActivity.java
new file mode 100644
index 0000000..1f93aaa
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GlesStubActivity.java
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.view.Window;
+import android.view.WindowManager;
+import android.opengl.GLES20;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+import android.util.Log;
+
+import java.util.Locale;
+import java.util.HashSet;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/** Stub activity to collect data from the GlesView */
+public final class GlesStubActivity extends Activity {
+
+ private static final String LOG_TAG = "GlesStubActivity";
+ private int mVersion = -1;
+ private GraphicsDeviceInfo mGraphicsDeviceInfo;
+ private CountDownLatch mDone = new CountDownLatch(1);
+ private HashSet<String> mOpenGlExtensions = new HashSet<String>();
+ private HashSet<String> mFormats = new HashSet<String>();
+ private String mGraphicsVendor;
+ private String mGraphicsRenderer;
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ // Dismiss keyguard and keep screen on while this test is on.
+ Window window = getWindow();
+ window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
+ WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
+ WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ super.onCreate(bundle);
+
+ window.setFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
+ WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+
+ ActivityManager activityManager =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = activityManager.getDeviceConfigurationInfo();
+
+ mVersion = (info.reqGlEsVersion & 0xffff0000) >> 16;
+
+ new Thread() {
+ @Override
+ public void run() {
+ runIterations(mVersion);
+ }
+ }.start();
+ }
+
+ /**
+ * Wait for this activity to finish gathering information
+ */
+ public void waitForActivityToFinish() {
+ try {
+ mDone.await();
+ } catch (InterruptedException e) {
+ // just move on
+ }
+ }
+
+ private void runIterations(int glVersion) {
+ for (int i = 1; i <= glVersion; i++) {
+ final CountDownLatch done = new CountDownLatch(1);
+ final int version = i;
+ GlesStubActivity.this.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ setContentView(new GlesSurfaceView(GlesStubActivity.this, version, done));
+ }
+ });
+ try {
+ done.await();
+ } catch (InterruptedException e) {
+ // just move on
+ }
+ }
+ mDone.countDown();
+ }
+
+ int getGlVersion() {
+ return mVersion;
+ }
+
+ String[] getOpenGlExtensions() {
+ return mOpenGlExtensions.toArray(new String[mOpenGlExtensions.size()]);
+ }
+
+ void addOpenGlExtension(String openGlExtension) {
+ mOpenGlExtensions.add(openGlExtension);
+ }
+
+ String[] getCompressedTextureFormats() {
+ return mFormats.toArray(new String[mFormats.size()]);
+ }
+
+ void addCompressedTextureFormat(String format) {
+ mFormats.add(format);
+ }
+
+ String getVendor() {
+ return mGraphicsVendor;
+ }
+
+ void setVendor(String vendor) {
+ mGraphicsVendor = vendor;
+ }
+
+ String getRenderer() {
+ return mGraphicsRenderer;
+ }
+
+ void setRenderer(String renderer) {
+ mGraphicsRenderer = renderer;
+ }
+
+ static class GlesSurfaceView extends GLSurfaceView {
+
+ public GlesSurfaceView(GlesStubActivity parent, int glVersion, CountDownLatch done) {
+ super(parent);
+
+ if (glVersion > 1) {
+ // Default is 1 so only set if bigger than 1
+ setEGLContextClientVersion(glVersion);
+ }
+ setRenderer(new OpenGlesRenderer(parent, glVersion, done));
+ }
+ }
+
+ static class OpenGlesRenderer implements GLSurfaceView.Renderer {
+
+ private final GlesStubActivity mParent;
+ private final int mGlVersion;
+ private final CountDownLatch mDone;
+
+ OpenGlesRenderer(GlesStubActivity parent, int glVersion, CountDownLatch done) {
+ mParent = parent;
+ mGlVersion = glVersion;
+ mDone = done;
+ }
+
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ String extensions;
+ String vendor;
+ String renderer;
+ if (mGlVersion == 2) {
+ extensions = GLES20.glGetString(GLES20.GL_EXTENSIONS);
+ vendor = GLES20.glGetString(GLES20.GL_VENDOR);
+ renderer = GLES20.glGetString(GLES20.GL_RENDERER);
+ } else if (mGlVersion == 3) {
+ extensions = GLES30.glGetString(GLES30.GL_EXTENSIONS);
+ vendor = GLES30.glGetString(GLES30.GL_VENDOR);
+ renderer = GLES30.glGetString(GLES30.GL_RENDERER);
+ } else {
+ extensions = gl.glGetString(GL10.GL_EXTENSIONS);
+ vendor = gl.glGetString(GL10.GL_VENDOR);
+ renderer = gl.glGetString(GL10.GL_RENDERER);
+ }
+ mParent.setVendor(vendor);
+ mParent.setRenderer(renderer);
+ Scanner scanner = new Scanner(extensions);
+ scanner.useDelimiter(" ");
+ while (scanner.hasNext()) {
+ String ext = scanner.next();
+ mParent.addOpenGlExtension(ext);
+ if (ext.contains("texture")) {
+ if (ext.contains("compression") || ext.contains("compressed")) {
+ mParent.addCompressedTextureFormat(ext);
+ }
+ }
+ }
+ scanner.close();
+ mDone.countDown();
+ }
+
+ @Override
+ public void onSurfaceChanged(GL10 gl, int width, int height) {}
+
+ @Override
+ public void onDrawFrame(GL10 gl) {}
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GraphicsDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GraphicsDeviceInfo.java
new file mode 100644
index 0000000..d7dcc08
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GraphicsDeviceInfo.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.os.Bundle;
+
+/**
+ * Graphics device info collector.
+ */
+public final class GraphicsDeviceInfo extends DeviceInfo {
+
+ private static final String LOG_TAG = "GraphicsDeviceInfo";
+
+ @Override
+ protected void collectDeviceInfo() {
+ GlesStubActivity stubActivity = GraphicsDeviceInfo.this.launchActivity(
+ "com.android.compatibility.common.deviceinfo",
+ GlesStubActivity.class,
+ new Bundle());
+ stubActivity.waitForActivityToFinish();
+
+ addResult("gl_version", stubActivity.getGlVersion());
+ addResult("vendor", stubActivity.getVendor());
+ addResult("renderer", stubActivity.getRenderer());
+
+ addArray("gl_texture", stubActivity.getCompressedTextureFormats());
+ addArray("gl_extension", stubActivity.getOpenGlExtensions());
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LibraryDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LibraryDeviceInfo.java
new file mode 100644
index 0000000..40bf754
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LibraryDeviceInfo.java
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.util.Log;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Formatter;
+
+/**
+ * Library device info collector.
+ */
+public final class LibraryDeviceInfo extends DeviceInfo {
+
+ private static final String TAG = "LibraryDeviceInfo";
+ private static final int BUFFER_SIZE_BYTES = 4096;
+
+ @Override
+ protected void collectDeviceInfo() {
+ collectSystemLibs();
+ collectVendorLibs();
+ collectFrameworkJars();
+ }
+
+ private void collectSystemLibs() {
+ startArray("lib");
+ collectFileDetails("/system/lib", ".so");
+ endArray();
+ }
+
+ private void collectVendorLibs() {
+ startArray("vendor_lib");
+ collectFileDetails("/system/vendor/lib", ".so");
+ endArray();
+ }
+
+ private void collectFrameworkJars() {
+ startArray("framework_jar");
+ collectFileDetails("/system/framework", ".jar");
+ endArray();
+ }
+
+ private void collectFileDetails(String path, String suffix) {
+ File dir = new File(path);
+ for (File file : dir.listFiles()) {
+ String name = file.getName();
+ if (file.isFile() && name.endsWith(suffix)) {
+ String sha1 = "unknown";
+ try {
+ sha1 = getSha1sum(file);
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to hash " + file + ": ", e);
+ }
+ startGroup();
+ addResult("name", name);
+ addResult("sha1", sha1);
+ endGroup();
+ }
+ }
+ }
+
+ private static String getSha1sum(File file) throws IOException {
+ InputStream in = null;
+ try {
+ in = new FileInputStream(file);
+ return sha1(in);
+ } finally {
+ close(in);
+ }
+ }
+
+ private static void close(Closeable s) throws IOException {
+ if (s == null) {
+ return;
+ }
+ s.close();
+ }
+
+ /**
+ * @return the SHA-1 digest of input as a hex string
+ */
+ public static String sha1(InputStream input) throws IOException {
+ try {
+ return toHexString(digest(input, "sha1"));
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static byte[] digest(InputStream in, String algorithm)
+ throws NoSuchAlgorithmException, IOException {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ byte[] buffer = new byte[BUFFER_SIZE_BYTES];
+ while (true) {
+ int read = in.read(buffer);
+ if (read < 0) {
+ break;
+ }
+ digest.update(buffer, 0, read);
+ }
+ return digest.digest();
+ }
+
+ private static String toHexString(byte[] buffer) {
+ Formatter formatter = new Formatter();
+ try {
+ for (byte b : buffer) {
+ formatter.format("%02X", b);
+ }
+ return formatter.toString();
+ } finally {
+ formatter.close();
+ }
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LocaleDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LocaleDeviceInfo.java
new file mode 100644
index 0000000..831075f
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LocaleDeviceInfo.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+/**
+ * Locale device info collector.
+ */
+public final class LocaleDeviceInfo extends DeviceInfo {
+
+ @Override
+ protected void collectDeviceInfo() {
+
+ String[] locales = getInstrumentation().getContext().getAssets().getLocales();
+ if (locales.length == 0) {
+ // default locale
+ addArray("locale", new String[] {"en_US"});
+ } else {
+ addArray("locale", locales);
+ }
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MediaDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MediaDeviceInfo.java
new file mode 100644
index 0000000..dbe3f48
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MediaDeviceInfo.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.MemoryInfo;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Build;
+
+import android.media.CamcorderProfile;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecProfileLevel;
+import android.media.MediaCodecList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Media information collector.
+ */
+public final class MediaDeviceInfo extends DeviceInfo {
+
+ @Override
+ protected void collectDeviceInfo() {
+
+ startArray("media_codec_info");
+
+ for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
+ MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+
+ startGroup();
+ addResult("name", info.getName());
+ addResult("encoder", info.isEncoder());
+
+ startArray("supported_type");
+ for (String type : info.getSupportedTypes()) {
+
+ startGroup();
+ addResult("type", type);
+ if (info.getCapabilitiesForType(type).profileLevels.length > 0) {
+
+ List<Integer> levelList = new ArrayList<>();
+ List<Integer> profileList = new ArrayList<>();
+ startArray("codec_profile_level");
+
+ for (CodecProfileLevel profileLevel :
+ info.getCapabilitiesForType(type).profileLevels) {
+ startGroup();
+ addResult("level", profileLevel.level);
+ addResult("profile", profileLevel.profile);
+ endGroup();
+ }
+ endArray(); // codec_profile_level
+ }
+ endGroup();
+ }
+ endArray();
+ endGroup();
+ }
+
+ endArray(); // media_codec_profile
+ }
+
+ static int[] toIntArray(List<Integer> integerList) {
+ int[] intArray = new int[integerList.size()];
+ for (int i = 0; i < integerList.size(); i++) {
+ intArray[i] = integerList.get(i);
+ }
+ return intArray;
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MemoryDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MemoryDeviceInfo.java
new file mode 100644
index 0000000..d5a12b4
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MemoryDeviceInfo.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.MemoryInfo;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.compatibility.common.deviceinfo.DeviceInfo;
+
+/**
+ * MemoryDeviceInfo collector.
+ */
+public final class MemoryDeviceInfo extends DeviceInfo {
+
+ @Override
+ protected void collectDeviceInfo() {
+ ActivityManager activityManager = (ActivityManager)getInstrumentation()
+ .getTargetContext().getSystemService(Context.ACTIVITY_SERVICE);
+ addResult("low_ram_device", activityManager.isLowRamDevice());
+ addResult("memory_class", activityManager.getMemoryClass());
+ addResult("large_memory_class", activityManager.getLargeMemoryClass());
+
+ MemoryInfo memoryInfo = new MemoryInfo();
+ activityManager.getMemoryInfo(memoryInfo);
+ addResult("total_memory", memoryInfo.totalMem);
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
index 4d9ad46..0dd24be 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
@@ -19,12 +19,12 @@
import android.content.pm.PackageManager;
import android.os.Bundle;
-import com.android.compatibility.common.deviceinfo.DeviceInfoActivity;
+import com.android.compatibility.common.deviceinfo.DeviceInfo;
/**
* PackageDeviceInfo collector.
*/
-public class PackageDeviceInfo extends DeviceInfoActivity {
+public class PackageDeviceInfo extends DeviceInfo {
private static final String PACKAGE = "package";
private static final String NAME = "name";
@@ -34,7 +34,7 @@
@Override
protected void collectDeviceInfo() {
- PackageManager pm = this.getPackageManager();
+ PackageManager pm = getContext().getPackageManager();
startArray(PACKAGE);
for (PackageInfo pkg : pm.getInstalledPackages(0)) {
startGroup();
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PropertyDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PropertyDeviceInfo.java
new file mode 100644
index 0000000..1844b37
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PropertyDeviceInfo.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * System property info collector.
+ */
+public final class PropertyDeviceInfo extends DeviceInfo {
+
+ private static final String LOG_TAG = "PropertyDeviceInfo";
+
+ @Override
+ protected void collectDeviceInfo() {
+ try {
+ collectRoProperties();
+ } catch (IOException e) {
+ Log.w(LOG_TAG, "Failed to collect properties", e);
+ }
+ }
+
+ private void collectRoProperties() throws IOException {
+ startArray("ro_property");
+ Pattern pattern = Pattern.compile("\\[(ro.+)\\]: \\[(.+)\\]");
+ Scanner scanner = null;
+ try {
+ Process getprop = new ProcessBuilder("getprop").start();
+ scanner = new Scanner(getprop.getInputStream());
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine();
+ Matcher matcher = pattern.matcher(line);
+ if (matcher.matches()) {
+ String name = matcher.group(1);
+ String value = matcher.group(2);
+
+ startGroup();
+ addResult("name", name);
+ addResult("value", value);
+ endGroup();
+ }
+ }
+ } finally {
+ endArray();
+ if (scanner != null) {
+ scanner.close();
+ }
+ }
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ScreenDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ScreenDeviceInfo.java
new file mode 100644
index 0000000..5524531
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ScreenDeviceInfo.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.WindowManager;
+
+/**
+ * Screen device info collector.
+ */
+public final class ScreenDeviceInfo extends DeviceInfo {
+
+ @Override
+ protected void collectDeviceInfo() {
+
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager windowManager =
+ (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+ Display display = windowManager.getDefaultDisplay();
+ display.getRealMetrics(metrics);
+
+ addResult("width_pixels", metrics.widthPixels);
+ addResult("height_pixels", metrics.heightPixels);
+ addResult("x_dpi", metrics.xdpi);
+ addResult("y_dpi", metrics.ydpi);
+ addResult("density", metrics.density);
+ addResult("density_dpi", metrics.densityDpi);
+
+ Configuration configuration = getContext().getResources().getConfiguration();
+ addResult("screen_size", getScreenSize(configuration));
+ addResult("smallest_screen_width_dp", configuration.smallestScreenWidthDp);
+ }
+
+ private static String getScreenSize(Configuration configuration) {
+ int screenLayout = configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
+ String screenSize = String.format("0x%x", screenLayout);
+ switch (screenLayout) {
+ case Configuration.SCREENLAYOUT_SIZE_SMALL:
+ screenSize = "small";
+ break;
+
+ case Configuration.SCREENLAYOUT_SIZE_NORMAL:
+ screenSize = "normal";
+ break;
+
+ case Configuration.SCREENLAYOUT_SIZE_LARGE:
+ screenSize = "large";
+ break;
+
+ case Configuration.SCREENLAYOUT_SIZE_XLARGE:
+ screenSize = "xlarge";
+ break;
+
+ case Configuration.SCREENLAYOUT_SIZE_UNDEFINED:
+ screenSize = "undefined";
+ break;
+ }
+ return screenSize;
+ }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/StorageDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/StorageDeviceInfo.java
new file mode 100644
index 0000000..823b355
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/StorageDeviceInfo.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+/**
+ * Storage device info collector.
+ */
+public class StorageDeviceInfo extends DeviceInfo {
+ private static final String TAG = "StorageDeviceInfo";
+
+ @Override
+ protected void collectDeviceInfo() {
+ int total = 0;
+ total = Math.max(total, getContext().getExternalCacheDirs().length);
+ total = Math.max(total, getContext().getExternalFilesDirs(null).length);
+ total = Math.max(
+ total, getContext().getExternalFilesDirs(Environment.DIRECTORY_PICTURES).length);
+ total = Math.max(total, getContext().getObbDirs().length);
+
+ int emulated = 0;
+ int physical = 0;
+ if (Environment.isExternalStorageEmulated()) {
+ if (total == 1) {
+ emulated = 1;
+ } else {
+ emulated = 1;
+ physical = total - 1;
+ }
+ } else {
+ physical = total;
+ }
+
+ addResult("num_physical", physical);
+ addResult("num_emulated", emulated);
+
+ addArray("raw_partition", scanPartitions());
+ }
+
+ private String[] scanPartitions() {
+ List<String> partitionList = new ArrayList<>();
+ try {
+ Process df = new ProcessBuilder("df").start();
+ Scanner scanner = new Scanner(df.getInputStream());
+ try {
+ while (scanner.hasNextLine()) {
+ partitionList.add(scanner.nextLine());
+ }
+ } finally {
+ scanner.close();
+ }
+ } catch (Exception e) {
+ Log.w(TAG, Log.getStackTraceString(e));
+ }
+ return partitionList.toArray(new String[partitionList.size()]);
+ }
+
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/UserDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/UserDeviceInfo.java
new file mode 100644
index 0000000..2886e23
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/UserDeviceInfo.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.os.UserManager;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * User device info collector.
+ */
+public final class UserDeviceInfo extends DeviceInfo {
+
+ @Override
+ protected void collectDeviceInfo() {
+ addResult("max_supported_users", getMaxSupportedUsers());
+ }
+
+ private int getMaxSupportedUsers() {
+ try {
+ Method method = UserManager.class.getMethod("getMaxSupportedUsers");
+ return (Integer) method.invoke(null);
+ } catch (ClassCastException |
+ NoSuchMethodException |
+ InvocationTargetException |
+ IllegalAccessException e) {}
+ return -1;
+ }
+}
diff --git a/common/device-side/device-info/tests/Android.mk b/common/device-side/device-info/tests/Android.mk
index e24c5c1..a8d9e038 100644
--- a/common/device-side/device-info/tests/Android.mk
+++ b/common/device-side/device-info/tests/Android.mk
@@ -27,4 +27,3 @@
LOCAL_MODULE := compatibility-device-info-tests
include $(BUILD_STATIC_JAVA_LIBRARY)
-
diff --git a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivityTest.java b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivityTest.java
deleted file mode 100644
index d092f4e..0000000
--- a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivityTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.
- */
-package com.android.compatibility.common.deviceinfo;
-
-import android.test.ActivityInstrumentationTestCase2;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-/**
- * Test for {@link DeviceInfoActivity}.
- */
-public class DeviceInfoActivityTest extends ActivityInstrumentationTestCase2<TestDeviceInfo> {
-
- private static final String EXPECTED_FILE_PATH =
- "/storage/emulated/0/device-info-files/TestDeviceInfo.deviceinfo.json";
-
- private TestDeviceInfo mActivity;
-
- public DeviceInfoActivityTest() {
- super(TestDeviceInfo.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // Start the activity and get a reference to it.
- mActivity = getActivity();
- // Wait for the activity to finish.
- mActivity.waitForActivityToFinish();
- }
-
- @Override
- protected void tearDown() throws Exception {
- mActivity = null;
- super.tearDown();
- }
-
- public void testJsonFile() throws IOException {
- String resultFilePath = mActivity.getResultFilePath();
- // Check file path exist
- assertNotNull("Expected a non-null resultFilePath", resultFilePath);
- // Check file path location
- assertEquals("Incorrect file path", EXPECTED_FILE_PATH, resultFilePath);
- // Check json file content
- String jsonContent = readFile(resultFilePath);
- assertEquals("Incorrect json output", ExampleObjects.testDeviceInfoJson(), jsonContent);
- }
-
- private String readFile(String filePath) throws IOException {
- InputStreamReader inputStreamReader = new InputStreamReader(
- new FileInputStream(filePath), "UTF-8");
- StringBuilder stringBuilder = new StringBuilder();
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
- String line;
- while((line = bufferedReader.readLine()) != null) {
- stringBuilder.append(line);
- stringBuilder.append('\n');
- }
- bufferedReader.close();
- return stringBuilder.toString();
- }
-}
-
diff --git a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoTest.java b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoTest.java
new file mode 100644
index 0000000..3459d59
--- /dev/null
+++ b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * Test for {@link DeviceInfo}.
+ */
+public class DeviceInfoTest extends AndroidTestCase {
+
+ private static final String EXPECTED_FILE_PATH =
+ "/storage/emulated/0/device-info-files/TestDeviceInfo.deviceinfo.json";
+
+ private TestDeviceInfo testDeviceInfo = new TestDeviceInfo();
+
+ public void testJsonFile() throws Exception {
+ testDeviceInfo.setUp();
+ testDeviceInfo.testCollectDeviceInfo();
+ String resultFilePath = testDeviceInfo.getResultFilePath();
+ // Check file path exist
+ assertNotNull("Expected a non-null resultFilePath", resultFilePath);
+ // Check file path location
+ assertEquals("Incorrect file path", EXPECTED_FILE_PATH, resultFilePath);
+ // Check json file content
+ String jsonContent = readFile(resultFilePath);
+ assertEquals("Incorrect json output", ExampleObjects.testDeviceInfoJson(), jsonContent);
+ }
+
+ private String readFile(String filePath) throws IOException {
+ InputStreamReader inputStreamReader = new InputStreamReader(
+ new FileInputStream(filePath), "UTF-8");
+ StringBuilder stringBuilder = new StringBuilder();
+ BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+ String line;
+ while((line = bufferedReader.readLine()) != null) {
+ stringBuilder.append(line);
+ stringBuilder.append('\n');
+ }
+ bufferedReader.close();
+ return stringBuilder.toString();
+ }
+}
\ No newline at end of file
diff --git a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/ExampleObjects.java b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/ExampleObjects.java
index 570bdd5..9411cd2 100644
--- a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/ExampleObjects.java
+++ b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/ExampleObjects.java
@@ -16,12 +16,12 @@
package com.android.compatibility.common.deviceinfo;
/**
- * Example Objects for {@link DeviceInfoActivity} test package.
+ * Example Objects for {@link DeviceInfo} test package.
*/
public final class ExampleObjects {
- // Must match DeviceInfoActivity.MAX_STRING_VALUE_LENGTH and
- // DeviceInfoActivity.MAX_ARRAY_LENGTH
+ // Must match DeviceInfo.MAX_STRING_VALUE_LENGTH and
+ // DeviceInfo.MAX_ARRAY_LENGTH
private static final int MAX_LENGTH = 1000;
private static final String TEST_DEVICE_INFO_JSON = "{\n" +
diff --git a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/SampleDeviceInfo.java b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/SampleDeviceInfo.java
deleted file mode 100644
index 7da9951..0000000
--- a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/SampleDeviceInfo.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-package com.android.compatibility.common.deviceinfo;
-
-import android.os.Bundle;
-
-import java.lang.StringBuilder;
-
-/**
- * Sample device info collector.
- */
-public class SampleDeviceInfo extends DeviceInfoActivity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- protected void collectDeviceInfo() {
- boolean[] booleans = {Boolean.TRUE, Boolean.FALSE};
- double[] doubles = {Double.MAX_VALUE, Double.MIN_VALUE};
- int[] ints = {Integer.MAX_VALUE, Integer.MIN_VALUE};
- long[] longs = {Long.MAX_VALUE, Long.MIN_VALUE};
-
- // Group Foo
- startGroup("foo");
- addResult("foo_boolean", Boolean.TRUE);
-
- // Group Bar
- startGroup("bar");
- addArray("bar_string", new String[] {
- "bar-string-1",
- "bar-string-2",
- "bar-string-3"});
-
- addArray("bar_boolean", booleans);
- addArray("bar_double", doubles);
- addArray("bar_int", ints);
- addArray("bar_long", longs);
- endGroup(); // bar
-
- addResult("foo_double", Double.MAX_VALUE);
- addResult("foo_int", Integer.MAX_VALUE);
- addResult("foo_long", Long.MAX_VALUE);
- addResult("foo_string", "foo-string");
-
- StringBuilder sb = new StringBuilder();
- int[] arr = new int[1001];
- for (int i = 0; i < 1001; i++) {
- sb.append("a");
- arr[i] = i;
- }
- addResult("long_string", sb.toString());
- addArray("long_int_array", arr);
-
- endGroup(); // foo
- }
-}
-
diff --git a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/TestDeviceInfo.java b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/TestDeviceInfo.java
index 7f82942..1360312 100644
--- a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/TestDeviceInfo.java
+++ b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/TestDeviceInfo.java
@@ -18,15 +18,17 @@
import android.os.Bundle;
import java.lang.StringBuilder;
+import java.util.HashSet;
/**
- * Collector for testing DeviceInfoActivity
+ * Collector for testing DeviceInfo
*/
-public class TestDeviceInfo extends DeviceInfoActivity {
+public class TestDeviceInfo extends DeviceInfo {
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ protected void setUp() throws Exception {
+ mActivityList = new HashSet<String>();
+ mActivityList.add(getClass().getName());
}
@Override
@@ -82,4 +84,7 @@
addResult("max_length_string", sb.toString());
addArray("max_num_ints", arr);
}
+
+ @Override
+ void sendStatus() {}
}
diff --git a/common/device-side/device-setup/Android.mk b/common/device-side/device-setup/Android.mk
deleted file mode 100644
index bc7c504..0000000
--- a/common/device-side/device-setup/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2014 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE := compatibility-device-setup_v2
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-###############################################################################
-# Build the tests
-###############################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, tests/src)
-
-LOCAL_JAVA_LIBRARIES := junit
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE := compatibility-device-setup-tests_v2
-
-include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/common/device-side/device-setup/src/com/android/compatibility/common/devicesetup/DeviceInfoConstants.java b/common/device-side/device-setup/src/com/android/compatibility/common/devicesetup/DeviceInfoConstants.java
deleted file mode 100644
index 7b19b00..0000000
--- a/common/device-side/device-setup/src/com/android/compatibility/common/devicesetup/DeviceInfoConstants.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.devicesetup;
-
-/**
- * Constants for device info attributes to be sent as instrumentation keys.
- */
-public interface DeviceInfoConstants {
-
- public static final String BUILD_ABI = "buildAbi";
- public static final String BUILD_ABI2 = "buildAbi2";
- public static final String BUILD_BOARD = "buildBoard";
- public static final String BUILD_BRAND = "buildBrand";
- public static final String BUILD_DEVICE = "buildDevice";
- public static final String BUILD_FINGERPRINT = "buildFingerprint";
- public static final String BUILD_ID = "buildId";
- public static final String BUILD_MANUFACTURER = "buildManufacturer";
- public static final String BUILD_MODEL = "buildModel";
- public static final String BUILD_TAGS = "buildTags";
- public static final String BUILD_TYPE = "buildType";
- public static final String BUILD_VERSION = "buildVersion";
-
- public static final String FEATURES = "features";
-
- public static final String GRAPHICS_RENDERER = "graphicsRenderer";
- public static final String GRAPHICS_VENDOR = "graphicsVendor";
-
- public static final String IMEI = "imei";
- public static final String IMSI = "imsi";
-
- public static final String KEYPAD = "keypad";
-
- public static final String LOCALES = "locales";
-
- public static final String MULTI_USER = "multiUser";
-
- public static final String NAVIGATION = "navigation";
- public static final String NETWORK = "network";
-
- public static final String OPEN_GL_ES_VERSION = "openGlEsVersion";
- public static final String OPEN_GL_EXTENSIONS = "openGlExtensions";
- public static final String OPEN_GL_COMPRESSED_TEXTURE_FORMATS =
- "openGlCompressedTextureFormats";
-
- public static final String PARTITIONS = "partitions";
- public static final String PHONE_NUMBER = "phoneNumber";
- public static final String PROCESSES = "processes";
- public static final String PRODUCT_NAME = "productName";
-
- public static final String RESOLUTION = "resolution";
-
- public static final String SCREEN_DENSITY = "screenDensity";
- public static final String SCREEN_DENSITY_BUCKET = "screenDensityBucket";
- public static final String SCREEN_DENSITY_X = "screenDensityX";
- public static final String SCREEN_DENSITY_Y = "screenDensityY";
- public static final String SCREEN_SIZE = "screenSize";
- public static final String SERIAL_NUMBER = "deviceId";
- public static final String STORAGE_DEVICES = "storageDevices";
- public static final String SYS_LIBRARIES = "systemLibraries";
-
- public static final String TOUCH = "touch";
-
- public static final String VERSION_RELEASE = "versionRelease";
- public static final String VERSION_SDK_INT = "versionSdkInt";
-}
diff --git a/common/device-side/device-setup/tests/src/com/android/compatibility/common/devicesetup/DeviceSetupTest.java b/common/device-side/device-setup/tests/src/com/android/compatibility/common/devicesetup/DeviceSetupTest.java
deleted file mode 100644
index ee55a66..0000000
--- a/common/device-side/device-setup/tests/src/com/android/compatibility/common/devicesetup/DeviceSetupTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.devicesetup;
-
-import junit.framework.TestCase;
-
-public class DeviceSetupTest extends TestCase {
-
- // TODO(stuartscott): Add tests when there is something to test.
-
-}
diff --git a/common/device-side/preconditions/Android.mk b/common/device-side/preconditions/Android.mk
new file mode 100644
index 0000000..75c981b
--- /dev/null
+++ b/common/device-side/preconditions/Android.mk
@@ -0,0 +1,31 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-common-util-devicesidelib
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := compatibility-device-preconditions
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ExternalStorageHelper.java b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ExternalStorageHelper.java
new file mode 100644
index 0000000..f398ea8
--- /dev/null
+++ b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ExternalStorageHelper.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.preconditions;
+
+import android.os.Environment;
+
+/**
+ * ExternalStorageHelper is used to check whether the device's external storage is readable
+ * and writeable.
+ */
+public class ExternalStorageHelper {
+
+ /* Checks if external storage is available for read and write */
+ public static boolean isExternalStorageWritable() {
+ String state = Environment.getExternalStorageState();
+ return Environment.MEDIA_MOUNTED.equals(state);
+ }
+
+ /* Checks if external storage is available to at least read */
+ public static boolean isExternalStorageReadable() {
+ String state = Environment.getExternalStorageState();
+ return (Environment.MEDIA_MOUNTED.equals(state) ||
+ Environment.MEDIA_MOUNTED_READ_ONLY.equals(state));
+ }
+
+}
diff --git a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java
new file mode 100644
index 0000000..d2380af
--- /dev/null
+++ b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.preconditions;
+
+import android.app.KeyguardManager;
+import android.content.Context;
+
+/**
+ * ScreenLockHelper is used to check whether the device is protected by a locked screen.
+ */
+public class ScreenLockHelper {
+
+ /*
+ * This helper returns false for the Screen Lock set to 'Swipe' or 'None', as it seems there
+ * is no way to programmatically distinguish between the two.
+ */
+ public static boolean isDeviceSecure(Context context) {
+ KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
+ return km.isDeviceSecure();
+ }
+
+}
diff --git a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/WifiHelper.java b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/WifiHelper.java
new file mode 100644
index 0000000..70a4b03
--- /dev/null
+++ b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/WifiHelper.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.preconditions;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+/**
+ * WifiHelper is used to check whether the device is connected to WiFi.
+ * This is required for a subset of the CTS test modules.
+ */
+public class WifiHelper {
+
+ public static boolean isWifiConnected(Context context) {
+ ConnectivityManager cm = (ConnectivityManager)
+ context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo wifiNetworkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ return wifiNetworkInfo.isConnected();
+ }
+
+}
diff --git a/common/device-side/test-app/Android.mk b/common/device-side/test-app/Android.mk
new file mode 100755
index 0000000..6adce97
--- /dev/null
+++ b/common/device-side/test-app/Android.mk
@@ -0,0 +1,40 @@
+# 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.
+
+# Build an APK which contains the device-side libraries and their tests,
+# this then gets instrumented in order to test the aforementioned libraries.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_DEX_PREOPT := false
+LOCAL_PROGUARD_ENABLED := disabled
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test\
+ compatibility-common-util-devicesidelib\
+ compatibility-device-info-tests\
+ compatibility-device-info\
+ compatibility-device-util-tests\
+ compatibility-device-util
+
+LOCAL_PACKAGE_NAME := CompatibilityTestApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/common/device-side/test-app/AndroidManifest.xml b/common/device-side/test-app/AndroidManifest.xml
new file mode 100755
index 0000000..9c857f0
--- /dev/null
+++ b/common/device-side/test-app/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.compatibility.common">
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:name="com.android.compatibility.common.deviceinfo.TestDeviceInfo" />
+ </application>
+
+ <!-- self-instrumenting test package. -->
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.compatibility.common"
+ android:label="Tests for device-side Compatibility common code">
+ </instrumentation>
+
+</manifest>
+
diff --git a/common/device-side/test-app/run_tests.sh b/common/device-side/test-app/run_tests.sh
new file mode 100755
index 0000000..fa5f553
--- /dev/null
+++ b/common/device-side/test-app/run_tests.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# 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.
+
+CTS_DIR=$(dirname ${0})/../../..
+source ${CTS_DIR}/test_defs.sh
+
+if [ `adb devices | wc -l` -lt 2 ]; then
+ echo "NO DEVICES/EMULATORS AVAILABLE. CONNECT ONE."
+ exit 1
+fi
+
+# Take the last serial in the list of devices
+SERIAL=`adb devices | egrep -o "^\w+" | tail -n1`
+if [ -z ${SERIAL} ]; then
+ echo "FAILED TO GET ADB DEVICE SERIAL FOR TEST. EXITING"
+ exit 1
+fi
+
+echo "Running device side tests on device: ${SERIAL}"
+
+APK=${ANDROID_PRODUCT_OUT}/data/app/CompatibilityTestApp/CompatibilityTestApp.apk
+checkFile ${APK}
+
+COMMON_PACKAGE=com.android.compatibility.common
+RUNNER=android.support.test.runner.AndroidJUnitRunner
+# TODO [2015-12-09 kalle] Fail & exit on failing install?
+adb -s ${SERIAL} install -r -g ${APK}
+build_jar_path ${JAR_DIR} "${JARS}"
+java $RDBG_FLAG -cp ${JAR_PATH} ${TF_CONSOLE} run singleCommand instrument --serial ${SERIAL} --package ${COMMON_PACKAGE} --runner ${RUNNER}
+adb -s ${SERIAL} uninstall ${COMMON_PACKAGE}
diff --git a/common/device-side/util/Android.mk b/common/device-side/util/Android.mk
index c8104bf..350c2db 100644
--- a/common/device-side/util/Android.mk
+++ b/common/device-side/util/Android.mk
@@ -12,34 +12,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-common-util-devicesidelib_v2
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-common-util-devicesidelib
LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := compatibility-device-util_v2
+LOCAL_MODULE := compatibility-device-util
LOCAL_SDK_VERSION := current
include $(BUILD_STATIC_JAVA_LIBRARY)
-################################################################################
-# Build the tests
-###############################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, tests/src)
-
-LOCAL_JAVA_LIBRARIES := junit
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE := compatibility-device-util-tests_v2
-
-include $(BUILD_HOST_JAVA_LIBRARY)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java b/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
index 273cdf5..d87ebbc 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
@@ -22,6 +22,10 @@
import com.android.compatibility.common.util.ReportLog;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
/**
* Handles adding results to the report for device side tests.
*
@@ -30,13 +34,20 @@
*/
public class DeviceReportLog extends ReportLog {
private static final String TAG = DeviceReportLog.class.getSimpleName();
- private static final String RESULT = "RESULT";
+ private static final String RESULT = "COMPATIBILITY_TEST_RESULT";
+ private static final int INST_STATUS_ERROR = -1;
private static final int INST_STATUS_IN_PROGRESS = 2;
public void submit(Instrumentation instrumentation) {
- Log.i(TAG, "submit");
- Bundle output = new Bundle();
- output.putSerializable(RESULT, this);
- instrumentation.sendStatus(INST_STATUS_IN_PROGRESS, output);
+ Log.i(TAG, "Submit");
+ try {
+ Bundle output = new Bundle();
+ output.putString(RESULT, serialize(this));
+ instrumentation.sendStatus(INST_STATUS_IN_PROGRESS, output);
+ } catch (IllegalArgumentException | IllegalStateException | XmlPullParserException
+ | IOException e) {
+ Log.e(TAG, "Submit Failed", e);
+ instrumentation.sendStatus(INST_STATUS_ERROR, null);
+ }
}
}
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/DynamicConfigDeviceSide.java b/common/device-side/util/src/com/android/compatibility/common/util/DynamicConfigDeviceSide.java
new file mode 100644
index 0000000..303efec
--- /dev/null
+++ b/common/device-side/util/src/com/android/compatibility/common/util/DynamicConfigDeviceSide.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.util;
+
+import android.os.Environment;
+import android.util.Log;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Load dynamic config for device side test cases
+ */
+public class DynamicConfigDeviceSide extends DynamicConfig {
+ private static String LOG_TAG = DynamicConfigDeviceSide.class.getSimpleName();
+
+ public DynamicConfigDeviceSide(String moduleName) throws XmlPullParserException, IOException {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ throw new IOException("External storage is not mounted");
+ }
+ File configFile = getConfigFile(new File(CONFIG_FOLDER_ON_DEVICE), moduleName);
+ initConfigFromXml(configFile);
+ }
+}
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/EvaluateJsResultPollingCheck.java b/common/device-side/util/src/com/android/compatibility/common/util/EvaluateJsResultPollingCheck.java
index 521dc40..61f1bb8 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/EvaluateJsResultPollingCheck.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/EvaluateJsResultPollingCheck.java
@@ -18,7 +18,7 @@
import android.webkit.ValueCallback;
-public class EvaluateJsResultPollingCheck extends PollingCheck
+public class EvaluateJsResultPollingCheck extends PollingCheck
implements ValueCallback<String> {
private String mActualResult;
private String mExpectedResult;
diff --git a/common/device-side/util/tests/Android.mk b/common/device-side/util/tests/Android.mk
new file mode 100644
index 0000000..fa7424d
--- /dev/null
+++ b/common/device-side/util/tests/Android.mk
@@ -0,0 +1,27 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := compatibility-device-util-tests
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceReportTest.java b/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceReportTest.java
new file mode 100644
index 0000000..7dbece0
--- /dev/null
+++ b/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceReportTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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
+ */
+package com.android.compatibility.common.util;
+
+import android.app.Instrumentation;
+import android.os.Bundle;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@line DeviceReportLog}.
+ */
+public class DeviceReportTest extends TestCase {
+
+ /**
+ * A stub of {@link Instrumentation}
+ */
+ public class TestInstrumentation extends Instrumentation {
+
+ private int mResultCode = -1;
+ private Bundle mResults = null;
+
+ @Override
+ public void sendStatus(int resultCode, Bundle results) {
+ mResultCode = resultCode;
+ mResults = results;
+ }
+ }
+
+ private static final int RESULT_CODE = 2;
+ private static final String RESULT_KEY = "COMPATIBILITY_TEST_RESULT";
+ private static final String TEST_MESSAGE_1 = "Foo";
+ private static final double TEST_VALUE_1 = 3;
+ private static final ResultType TEST_TYPE_1 = ResultType.HIGHER_BETTER;
+ private static final ResultUnit TEST_UNIT_1 = ResultUnit.SCORE;
+ private static final String TEST_MESSAGE_2 = "Bar";
+ private static final double TEST_VALUE_2 = 5;
+ private static final ResultType TEST_TYPE_2 = ResultType.LOWER_BETTER;
+ private static final ResultUnit TEST_UNIT_2 = ResultUnit.COUNT;
+
+ public void testSubmit() throws Exception {
+ DeviceReportLog log = new DeviceReportLog();
+ log.addValue(TEST_MESSAGE_1, TEST_VALUE_1, TEST_TYPE_1, TEST_UNIT_1);
+ log.setSummary(TEST_MESSAGE_2, TEST_VALUE_2, TEST_TYPE_2, TEST_UNIT_2);
+ TestInstrumentation inst = new TestInstrumentation();
+ log.submit(inst);
+ assertEquals("Incorrect result code", RESULT_CODE, inst.mResultCode);
+ assertNotNull("Bundle missing", inst.mResults);
+ String metrics = inst.mResults.getString(RESULT_KEY);
+ assertNotNull("Metrics missing", metrics);
+ ReportLog result = ReportLog.parse(metrics);
+ assertNotNull("Metrics could not be decoded", result);
+ }
+}
diff --git a/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceUtilTest.java b/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceUtilTest.java
deleted file mode 100644
index a7e81d7..0000000
--- a/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceUtilTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.util;
-
-import junit.framework.TestCase;
-
-public class DeviceUtilTest extends TestCase {
-
-}
diff --git a/common/host-side/java-scanner/Android.mk b/common/host-side/java-scanner/Android.mk
deleted file mode 100644
index 7c101ff..0000000
--- a/common/host-side/java-scanner/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2014 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := compatibility-common-util-hostsidelib_v2
-
-LOCAL_JAR_MANIFEST := MANIFEST.mf
-
-LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
-
-LOCAL_MODULE := compatibility-java-scanner_v2
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-################################################################################
-# Build the tests
-###############################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, tests/src)
-
-LOCAL_JAVA_LIBRARIES := compatibility-tradefed_v2 compatibility-java-scanner_v2 junit
-
-LOCAL_MODULE := compatibility-java-scanner-tests_v2
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/common/host-side/java-scanner/MANIFEST.mf b/common/host-side/java-scanner/MANIFEST.mf
deleted file mode 100644
index 975b1ef..0000000
--- a/common/host-side/java-scanner/MANIFEST.mf
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Main-Class: com.android.compatibility.common.scanner.JavaScanner
-Class-Path: compatibility-common-util-hostsidelib_v2.jar
diff --git a/common/host-side/java-scanner/src/com/android/compatibility/common/scanner/JavaScanner.java b/common/host-side/java-scanner/src/com/android/compatibility/common/scanner/JavaScanner.java
deleted file mode 100644
index f3f8a49..0000000
--- a/common/host-side/java-scanner/src/com/android/compatibility/common/scanner/JavaScanner.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.scanner;
-
-import com.android.compatibility.common.util.KeyValueArgsParser;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Scans a source directory for java tests and outputs a list of test classes and methods.
- */
-public class JavaScanner {
-
- static final String[] SOURCE_PATHS = {
- "./frameworks/base/core/java",
- "./frameworks/base/test-runner/src",
- "./external/junit/src",
- "./development/tools/hosttestlib/src",
- "./libcore/dalvik/src/main/java",
- "./common/device-side/util/src",
- "./common/host-side/tradefed/src",
- "./common/util/src"
- };
- static final String[] CLASS_PATHS = {
- "./prebuilts/misc/common/tradefed/tradefed-prebuilt.java",
- "./prebuilts/misc/common/ub-uiautomator/ub-uiautomator.java"
- };
- private final File mSourceDir;
- private final File mDocletDir;
-
- /**
- * @param sourceDir The directory holding the source to scan.
- * @param docletDir The directory holding the doclet (or its jar).
- */
- JavaScanner(File sourceDir, File docletDir) {
- this.mSourceDir = sourceDir;
- this.mDocletDir = docletDir;
- }
-
- int scan() throws Exception {
- final ArrayList<String> args = new ArrayList<String>();
- args.add("javadoc");
- args.add("-doclet");
- args.add("com.android.compatibility.common.scanner.JavaScannerDoclet");
- args.add("-sourcepath");
- args.add(getSourcePath(mSourceDir));
- args.add("-classpath");
- args.add(getClassPath());
- args.add("-docletpath");
- args.add(mDocletDir.toString());
- args.addAll(getSourceFiles(mSourceDir));
-
- // Dont want p to get blocked due to a full pipe.
- final Process p = new ProcessBuilder(args).redirectErrorStream(true).start();
- final BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
- try {
- String line = null;
- while ((line = in.readLine()) != null) {
- if (line.startsWith("suite:") ||
- line.startsWith("case:") ||
- line.startsWith("test:")) {
- System.out.println(line);
- }
- }
- } finally {
- if (in != null) {
- in.close();
- }
- }
-
- return p.waitFor();
- }
-
- private static String getSourcePath(File sourceDir) {
- final ArrayList<String> sourcePath = new ArrayList<String>(Arrays.asList(SOURCE_PATHS));
- sourcePath.add(sourceDir.toString());
- return join(sourcePath, ":");
- }
-
- private static String getClassPath() {
- return join(Arrays.asList(CLASS_PATHS), ":");
- }
-
- private static ArrayList<String> getSourceFiles(File sourceDir) {
- final ArrayList<String> sourceFiles = new ArrayList<String>();
- final File[] files = sourceDir.listFiles(new FileFilter() {
- public boolean accept(File pathname) {
- return pathname.isDirectory() || pathname.toString().endsWith(".java");
- }
- });
- for (File f : files) {
- if (f.isDirectory()) {
- sourceFiles.addAll(getSourceFiles(f));
- } else {
- sourceFiles.add(f.toString());
- }
- }
- return sourceFiles;
- }
-
- private static String join(List<String> list, String delimiter) {
- final StringBuilder builder = new StringBuilder();
- for (String s : list) {
- builder.append(s);
- builder.append(delimiter);
- }
- // Adding the delimiter each time and then removing the last one at the end is more
- // efficient than doing a check in each iteration of the loop.
- return builder.substring(0, builder.length() - delimiter.length());
- }
-
- public static void main(String[] args) throws Exception {
- final HashMap<String, String> argsMap = KeyValueArgsParser.parse(args);
- final String sourcePath = argsMap.get("-s");
- final String docletPath = argsMap.get("-d");
- if (sourcePath == null || docletPath == null) {
- usage(args);
- }
- System.exit(new JavaScanner(new File(sourcePath), new File(docletPath)).scan());
- }
-
- private static void usage(String[] args) {
- System.err.println("Arguments: " + Arrays.toString(args));
- System.err.println("Usage: javascanner -s SOURCE_DIR -d DOCLET_PATH");
- System.exit(1);
- }
-}
diff --git a/common/host-side/java-scanner/src/com/android/compatibility/common/scanner/JavaScannerDoclet.java b/common/host-side/java-scanner/src/com/android/compatibility/common/scanner/JavaScannerDoclet.java
deleted file mode 100644
index 94eccd0..0000000
--- a/common/host-side/java-scanner/src/com/android/compatibility/common/scanner/JavaScannerDoclet.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.scanner;
-
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.Doclet;
-import com.sun.javadoc.MethodDoc;
-import com.sun.javadoc.RootDoc;
-
-import java.io.PrintWriter;
-
-/**
- * Doclet that scans java files looking for tests.
- *
- * Sample Ouput;
- * suite:com.android.sample.cts
- * case:SampleDeviceTest
- * test:testSharedPreferences
- */
-public class JavaScannerDoclet extends Doclet {
-
- private static final String JUNIT_TEST_CASE_CLASS_NAME = "junit.framework.testcase";
-
- public static boolean start(RootDoc root) {
- ClassDoc[] classes = root.classes();
- if (classes == null) {
- return false;
- }
-
- PrintWriter writer = new PrintWriter(System.out);
-
- for (ClassDoc clazz : classes) {
- if (clazz.isAbstract() || !isValidJUnitTestCase(clazz)) {
- continue;
- }
- writer.append("suite:").println(clazz.containingPackage().name());
- writer.append("case:").println(clazz.name());
- for (; clazz != null; clazz = clazz.superclass()) {
- for (MethodDoc method : clazz.methods()) {
- if (method.name().startsWith("test")) {
- writer.append("test:").println(method.name());
- }
- }
- }
- }
-
- writer.close();
- return true;
- }
-
- private static boolean isValidJUnitTestCase(ClassDoc clazz) {
- while ((clazz = clazz.superclass()) != null) {
- if (JUNIT_TEST_CASE_CLASS_NAME.equals(clazz.qualifiedName().toLowerCase())) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/common/host-side/java-scanner/tests/src/com/android/compatibility/common/scanner/JavaScannerTest.java b/common/host-side/java-scanner/tests/src/com/android/compatibility/common/scanner/JavaScannerTest.java
deleted file mode 100644
index 4159f0e..0000000
--- a/common/host-side/java-scanner/tests/src/com/android/compatibility/common/scanner/JavaScannerTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.scanner;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-import junit.framework.TestCase;
-
-public class JavaScannerTest extends TestCase {
-
- private static final String JAR = "out/host/linux-x86/framework/compatibility-java-scanner_v2.jar";
- private static final String VALID_RESULT =
- "suite:com.android.test" +
- "case:ValidTest" +
- "test:testA";
-
- private static final String VALID_FILENAME = "ValidTest";
- private static final String VALID =
- "package com.android.test;" +
- "import junit.framework.TestCase;" +
- "public class ValidTest extends TestCase {" +
- " public void testA() throws Exception {" +
- " helper();" +
- " }" +
- " public void helper() {" +
- " fail();" +
- " }" +
- "}";
-
- // TestCases must have TestCase in their hierarchy
- private static final String INVALID_A_FILENAME = "NotTestCase";
- private static final String INVALID_A =
- "package com.android.test;" +
- "public class NotTestCase {" +
- " public void testA() throws Exception {" +
- " helper();" +
- " }" +
- " public void helper() {" +
- " fail();" +
- " }" +
- "}";
-
- // TestCases cant be abstract classes
- private static final String INVALID_B_FILENAME = "AbstractClass";
- private static final String INVALID_B =
- "package com.android.test;" +
- "import junit.framework.TestCase;" +
- "public abstract class AbstractClass extends TestCase {" +
- " public void testA() throws Exception {" +
- " helper();" +
- " }" +
- " public void helper() {" +
- " fail();" +
- " }" +
- "}";
-
- public void testValidFile() throws Exception {
- String result = runScanner(VALID_FILENAME, VALID);
- assertEquals(VALID_RESULT, result);
- }
-
- public void testInvalidFileA() throws Exception {
- assertEquals("", runScanner(INVALID_A_FILENAME, INVALID_A));
- }
-
- public void testInvalidFileB() throws Exception {
- assertEquals("", runScanner(INVALID_B_FILENAME, INVALID_B));
- }
-
- private static String runScanner(String filename, String content) throws Exception {
- final File parent0 = new File(System.getProperty("java.io.tmpdir"));
- final File parent1 = new File(parent0, "tmp" + System.currentTimeMillis());
- final File parent2 = new File(parent1, "com");
- final File parent3 = new File(parent2, "android");
- final File parent4 = new File(parent3, "test");
- File f = null;
- try {
- parent4.mkdirs();
- f = new File(parent4, filename + ".java");
- final PrintWriter out = new PrintWriter(f);
- out.print(content);
- out.flush();
- out.close();
- ArrayList<String> args = new ArrayList<String>();
- args.add("java");
- args.add("-jar");
- args.add(JAR);
- args.add("-s");
- args.add(parent1.toString());
- args.add("-d");
- args.add(JAR);
-
- final Process p = new ProcessBuilder(args).start();
- final StringBuilder output = new StringBuilder();
- final BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line = null;
- while ((line = in.readLine()) != null) {
- output.append(line);
- }
- int ret = p.waitFor();
- if (ret == 0) {
- return output.toString();
- }
- } finally {
- if (f != null) {
- f.delete();
- }
- parent4.delete();
- parent3.delete();
- parent2.delete();
- parent1.delete();
- }
- return null;
- }
-}
diff --git a/common/host-side/manifest-generator/Android.mk b/common/host-side/manifest-generator/Android.mk
index ca08928..b976329 100644
--- a/common/host-side/manifest-generator/Android.mk
+++ b/common/host-side/manifest-generator/Android.mk
@@ -30,4 +30,4 @@
include $(BUILD_HOST_JAVA_LIBRARY)
-include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/common/host-side/manifest-generator/src/com/android/compatibility/common/generator/ManifestGenerator.java b/common/host-side/manifest-generator/src/com/android/compatibility/common/generator/ManifestGenerator.java
index e23e254..7241ada 100644
--- a/common/host-side/manifest-generator/src/com/android/compatibility/common/generator/ManifestGenerator.java
+++ b/common/host-side/manifest-generator/src/com/android/compatibility/common/generator/ManifestGenerator.java
@@ -25,9 +25,11 @@
public class ManifestGenerator {
+ private static final String DEFAULT_MIN_SDK = "8";
+
private static final String USAGE = "Usage: "
+ "manifest-generator -n NAME -p PACKAGE_NAME -o OUTPUT_FILE -i INSTRUMENT_NAME "
- + "[-r PERMISSION]+ [-a ACTIVITY]+";
+ + "[-s MIN_SDK_VERSION] [-t TARGET_SDK_VERSION] [-r PERMISSION]+ [-a ACTIVITY]+";
private static final String MANIFEST = "manifest";
private static final String USES_SDK = "uses-sdk";
private static final String USES_PERMISSION = "uses-permission";
@@ -38,6 +40,8 @@
public static void main(String[] args) {
String pkgName = null;
String instrumentName = null;
+ String minSdk = DEFAULT_MIN_SDK;
+ String targetSdk = null;
List<String> permissions = new ArrayList<>();
List<String> activities = new ArrayList<>();
String output = null;
@@ -53,6 +57,10 @@
instrumentName = args[++i];
} else if (args[i].equals("-r")) {
permissions.add(args[++i]);
+ } else if (args[i].equals("-s")) {
+ minSdk = args[++i];
+ } else if (args[i].equals("-t")) {
+ targetSdk = args[++i];
}
}
@@ -69,7 +77,7 @@
FileOutputStream out = null;
try {
out = new FileOutputStream(output);
- generate(out, pkgName, instrumentName, permissions, activities);
+ generate(out, pkgName, instrumentName, minSdk, targetSdk, permissions, activities);
} catch (Exception e) {
System.err.println("Couldn't create manifest file");
} finally {
@@ -84,7 +92,8 @@
}
/*package*/ static void generate(OutputStream out, String pkgName, String instrumentName,
- List<String> permissions, List<String> activities) throws Exception {
+ String minSdk, String targetSdk, List<String> permissions, List<String> activities)
+ throws Exception {
final String ns = null;
KXmlSerializer serializer = new KXmlSerializer();
serializer.setOutput(out, "UTF-8");
@@ -94,7 +103,10 @@
serializer.attribute(ns, "xmlns:android", "http://schemas.android.com/apk/res/android");
serializer.attribute(ns, "package", pkgName);
serializer.startTag(ns, USES_SDK);
- serializer.attribute(ns, "android:minSdkVersion", "8");
+ serializer.attribute(ns, "android:minSdkVersion", minSdk);
+ if (targetSdk != null) {
+ serializer.attribute(ns, "android:targetSdkVersion", targetSdk);
+ }
serializer.endTag(ns, USES_SDK);
for (String permission : permissions) {
serializer.startTag(ns, USES_PERMISSION);
@@ -122,5 +134,4 @@
System.err.println(USAGE);
System.exit(1);
}
-
}
diff --git a/common/host-side/manifest-generator/tests/run_tests.sh b/common/host-side/manifest-generator/tests/run_tests.sh
new file mode 100755
index 0000000..758589c
--- /dev/null
+++ b/common/host-side/manifest-generator/tests/run_tests.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# 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.
+
+# Helper script for running unit tests for compatibility libraries
+
+CTS_DIR=$(dirname ${0})/../../../..
+source ${CTS_DIR}/test_defs.sh
+
+JARS="
+ compatibility-manifest-generator\
+ compatibility-manifest-generator-tests"
+
+run_tests "com.android.compatibility.common.generator.ManifestGeneratorTest" "${JARS}" "${@}"
+
diff --git a/common/host-side/manifest-generator/tests/src/com/android/compatibility/common/generator/ManifestGeneratorTest.java b/common/host-side/manifest-generator/tests/src/com/android/compatibility/common/generator/ManifestGeneratorTest.java
index 457bbb8..a0565e1 100644
--- a/common/host-side/manifest-generator/tests/src/com/android/compatibility/common/generator/ManifestGeneratorTest.java
+++ b/common/host-side/manifest-generator/tests/src/com/android/compatibility/common/generator/ManifestGeneratorTest.java
@@ -29,10 +29,12 @@
private static final String PACKAGE = "test.package";
private static final String INSTRUMENT = "test.package.TestInstrument";
+ private static final String MIN_SDK = "8";
+ private static final String TARGET_SDK = "9";
private static final String MANIFEST = "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>\r\n"
+ "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
+ "package=\"test.package\">\r\n"
- + " <uses-sdk android:minSdkVersion=\"8\" />\r\n"
+ + " <uses-sdk android:minSdkVersion=\"8\" android:targetSdkVersion=\"9\" />\r\n"
+ "%s"
+ " <application>\r\n"
+ "%s"
@@ -66,7 +68,8 @@
return this.string.toString();
}
};
- ManifestGenerator.generate(output, PACKAGE, INSTRUMENT, permissions, activities);
+ ManifestGenerator.generate(output, PACKAGE, INSTRUMENT, MIN_SDK, TARGET_SDK,
+ permissions, activities);
String permissionXml = String.format(PERMISSION, PERMISSION_A)
+ String.format(PERMISSION, PERMISSION_B);
String activityXml = String.format(ACTIVITY, ACTIVITY_A)
diff --git a/common/host-side/native-scanner/Android.mk b/common/host-side/native-scanner/Android.mk
deleted file mode 100644
index 184cdc0..0000000
--- a/common/host-side/native-scanner/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2014 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAR_MANIFEST := MANIFEST.mf
-
-LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
-
-LOCAL_JAVA_LIBRARIES := compatibility-common-util-hostsidelib_v2
-
-LOCAL_MODULE := compatibility-native-scanner_v2
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-################################################################################
-# Build the tests
-###############################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, tests/src)
-
-LOCAL_JAVA_LIBRARIES := compatibility-tradefed_v2 compatibility-native-scanner_v2 junit
-
-LOCAL_MODULE := compatibility-native-scanner-tests_v2
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/common/host-side/native-scanner/MANIFEST.mf b/common/host-side/native-scanner/MANIFEST.mf
deleted file mode 100644
index c5641ca..0000000
--- a/common/host-side/native-scanner/MANIFEST.mf
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Main-Class: com.android.compatibility.common.scanner.NativeScanner
-Class-Path: compatibility-common-util-hostsidelib_v2.jar
diff --git a/common/host-side/native-scanner/src/com/android/compatibility/common/scanner/NativeScanner.java b/common/host-side/native-scanner/src/com/android/compatibility/common/scanner/NativeScanner.java
deleted file mode 100644
index 7b9e447..0000000
--- a/common/host-side/native-scanner/src/com/android/compatibility/common/scanner/NativeScanner.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.scanner;
-
-import com.android.compatibility.common.util.KeyValueArgsParser;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * Passes the gtest output and outputs a list of test classes and methods.
- */
-public final class NativeScanner {
-
- private static final String TEST_SUITE_ARG = "t";
- private static final String USAGE = "Usage: compatibility-native-scanner -t TEST_SUITE"
- + " This code reads from stdin the list of tests."
- + " The format expected:"
- + " TEST_CASE_NAME."
- + " TEST_NAME";
-
- /**
- * @return An {@link ArrayList} of suites, classes and method names.
- */
- static ArrayList<String> getTestNames(BufferedReader reader, String testSuite)
- throws IOException {
- ArrayList<String> testNames = new ArrayList<String>();
- testNames.add("suite:" + testSuite);
-
- String testCaseName = null;
- String line;
- while ((line = reader.readLine()) != null) {
- if (line.length() == 0) {
- continue;
- }
- if (line.charAt(0) == ' ') {
- if (testCaseName == null) {
- throw new RuntimeException("TEST_CASE_NAME not defined before first test.");
- }
- testNames.add("test:" + line.trim());
- } else {
- testCaseName = line.trim();
- if (testCaseName.endsWith(".")) {
- testCaseName = testCaseName.substring(0, testCaseName.length()-1);
- }
- testNames.add("case:" + testCaseName);
- }
- }
- return testNames;
- }
-
- /** Lookup test suite argument and scan {@code System.in} for test cases */
- public static void main(String[] args) throws IOException {
- HashMap<String, String> argMap = KeyValueArgsParser.parse(args);
- if (!argMap.containsKey(TEST_SUITE_ARG)) {
- System.err.println(USAGE);
- System.exit(1);
- }
-
- String testSuite = argMap.get(TEST_SUITE_ARG);
-
- BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
- for (String name : getTestNames(reader, testSuite)) {
- System.out.println(name);
- }
- }
-}
diff --git a/common/host-side/native-scanner/tests/src/com/android/compatibility/common/scanner/NativeScannerTest.java b/common/host-side/native-scanner/tests/src/com/android/compatibility/common/scanner/NativeScannerTest.java
deleted file mode 100644
index c5d3157..0000000
--- a/common/host-side/native-scanner/tests/src/com/android/compatibility/common/scanner/NativeScannerTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.scanner;
-
-import com.android.compatibility.common.scanner.NativeScanner;
-
-import junit.framework.TestCase;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.List;
-import java.util.Iterator;
-
-public class NativeScannerTest extends TestCase {
-
- public void testSingleTestNamesCase() throws Exception {
- StringReader singleTestString = new StringReader("FakeTestCase.\n FakeTestName\n");
- BufferedReader reader = new BufferedReader(singleTestString);
-
- List<String> names = NativeScanner.getTestNames(reader, "TestSuite");
- Iterator<String> it = names.iterator();
- assertEquals("suite:TestSuite", it.next());
- assertEquals("case:FakeTestCase", it.next());
- assertEquals("test:FakeTestName", it.next());
- assertFalse(it.hasNext());
- }
-
- public void testMultipleTestNamesCase() throws Exception {
- StringReader singleTestString = new StringReader(
- "Case1.\n Test1\n Test2\nCase2.\n Test3\n Test4\n");
- BufferedReader reader = new BufferedReader(singleTestString);
-
- List<String> names = NativeScanner.getTestNames(reader, "TestSuite");
-
- Iterator<String> it = names.iterator();
- assertEquals("suite:TestSuite", it.next());
- assertEquals("case:Case1", it.next());
- assertEquals("test:Test1", it.next());
- assertEquals("test:Test2", it.next());
- assertEquals("case:Case2", it.next());
- assertEquals("test:Test3", it.next());
- assertEquals("test:Test4", it.next());
- assertFalse(it.hasNext());
- }
-
- public void testMissingTestCaseNameCase() throws IOException {
- StringReader singleTestString = new StringReader(" Test1\n");
- BufferedReader reader = new BufferedReader(singleTestString);
-
- try {
- NativeScanner.getTestNames(reader, "TestSuite");
- fail("Expected RuntimeException");
- } catch (RuntimeException expected) {}
- }
-}
diff --git a/common/host-side/scripts/compatibility-tests_v2 b/common/host-side/scripts/compatibility-tests_v2
deleted file mode 100755
index 797909e..0000000
--- a/common/host-side/scripts/compatibility-tests_v2
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 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.
-
-checkFile() {
- if [ ! -f "$1" ]; then
- echo "Unable to locate $1"
- exit
- fi;
-}
-
-HOST_JAR_DIR=${ANDROID_HOST_OUT}/framework
-HOST_JARS="ddmlib-prebuilt tradefed-prebuilt hosttestlib\
- compatibility-tradefed_v2 compatibility-tradefed-tests_v2\
- compatibility-java-scanner_v2 compatibility-java-scanner-tests_v2\
- compatibility-native-scanner_v2 compatibility-native-scanner-tests_v2\
- compatibility-xml-plan-generator_v2 compatibility-xml-plan-generator-tests_v2\
- compatibility-device-util-tests_v2 compatibility-device-setup-tests_v2\
- compatibility-common-util-hostsidelib_v2 compatibility-common-util-tests_v2"
-
-for JAR in ${HOST_JARS}; do
- checkFile ${HOST_JAR_DIR}/${JAR}.jar
- JAR_PATH=${JAR_PATH}:${HOST_JAR_DIR}/${JAR}.jar
-done
-
-DEVICE_LIBS_DIR=${ANDROID_PRODUCT_OUT}/obj/JAVA_LIBRARIES
-DEVICE_LIBS="compatibility-common-util-devicesidelib_v2 compatibility-device-util_v2\
- compatibility-device-setup_v2"
-
-for LIB in ${DEVICE_LIBS}; do
- checkFile ${DEVICE_LIBS_DIR}/${LIB}_intermediates/javalib.jar
- JAR_PATH=${JAR_PATH}:${DEVICE_LIBS_DIR}/${LIB}_intermediates/javalib.jar
-done
-
-# TODO(stuartscott): Currently the test classes are explicitly set here, but
-# once our wrappers for tradefed are in place we can make it scan and generate
-# the list of test at runtime.
-TEST_CLASSES="com.android.compatibility.common.devicesetup.DeviceSetupTest\
- com.android.compatibility.common.scanner.JavaScannerTest\
- com.android.compatibility.common.scanner.NativeScannerTest\
- com.android.compatibility.common.tradefed.TradefedTest\
- com.android.compatibility.common.util.DeviceUtilTest\
- com.android.compatibility.common.util.CommonUtilTest\
- com.android.compatibility.common.xmlgenerator.XmlPlanGeneratorTest"
-
-for CLASS in ${TEST_CLASSES}; do
- java $RDBG_FLAG -cp ${JAR_PATH} com.android.compatibility.common.tradefed.command.CompatibilityConsole run\
- singleCommand host -n --class ${CLASS} "$@"
-done
diff --git a/common/host-side/scripts/compatibility-tradefed_v2 b/common/host-side/scripts/compatibility-tradefed_v2
deleted file mode 100755
index f64e273..0000000
--- a/common/host-side/scripts/compatibility-tradefed_v2
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 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.
-echo "TODO(stuartscott): Add the wrapper to launch the executable. This will be done in the next CL"
diff --git a/common/host-side/tradefed/Android.mk b/common/host-side/tradefed/Android.mk
index 8ff7c8c..3ed225ed 100644
--- a/common/host-side/tradefed/Android.mk
+++ b/common/host-side/tradefed/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2014 The Android Open Source Project
+# 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.
@@ -12,40 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-###############################################################################
-# Builds the compatibility tradefed host library
-###############################################################################
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-#LOCAL_JAVA_RESOURCE_DIRS := res
-
-LOCAL_MODULE := compatibility-tradefed_v2
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_JAVA_LIBRARIES := tradefed-prebuilt hosttestlib compatibility-common-util-hostsidelib_v2
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-###############################################################################
-# Build the compatibility tradefed tests
-###############################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, tests/src)
-
-LOCAL_MODULE := compatibility-tradefed-tests_v2
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_JAVA_LIBRARIES := tradefed-prebuilt compatibility-tradefed_v2 junit
-
-LOCAL_STATIC_JAVA_LIBRARIES := easymock
-
-include $(BUILD_HOST_JAVA_LIBRARY)
+include $(call all-subdir-makefiles)
\ No newline at end of file
diff --git a/common/host-side/tradefed/res/config/common-compatibility-config.xml b/common/host-side/tradefed/res/config/common-compatibility-config.xml
new file mode 100644
index 0000000..5bac748
--- /dev/null
+++ b/common/host-side/tradefed/res/config/common-compatibility-config.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Common config for Compatibility suites">
+
+ <device_recovery class="com.android.tradefed.device.WaitDeviceRecovery" />
+ <build_provider class="com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider" />
+ <test class="com.android.compatibility.common.tradefed.testtype.CompatibilityTest" />
+ <logger class="com.android.tradefed.log.FileLogger" />
+ <result_reporter class="com.android.compatibility.common.tradefed.result.ResultReporter" />
+
+</configuration>
diff --git a/common/host-side/tradefed/res/config/everything.xml b/common/host-side/tradefed/res/config/everything.xml
new file mode 100644
index 0000000..d1ac900
--- /dev/null
+++ b/common/host-side/tradefed/res/config/everything.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<configuration description="Common config for Compatibility suites to run all modules">
+
+ <include name="common-compatibility-config" />
+ <option name="compatibility:plan" value="everything" />
+
+</configuration>
diff --git a/common/host-side/tradefed/res/report/compatibility_result.css b/common/host-side/tradefed/res/report/compatibility_result.css
new file mode 100644
index 0000000..699f45a
--- /dev/null
+++ b/common/host-side/tradefed/res/report/compatibility_result.css
@@ -0,0 +1,164 @@
+/* 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.
+*/
+
+body {
+ font-family:arial,sans-serif;
+ color:#000;
+ font-size:13px;
+ color:#333;
+ padding:10;
+ margin:10;
+}
+
+/* Report logo and device name */
+table.title {
+ padding:5px;
+ border-width: 0px;
+ margin-left:auto;
+ margin-right:auto;
+ vertical-align:middle;
+}
+
+table.summary {
+ background-color: rgb(212, 233, 169);
+ border-collapse:collapse;
+ border: 0px solid #A5C639;
+ margin-left:auto;
+ margin-right:auto;
+}
+
+table.summary th {
+ background-color: #A5C639;
+ font-size: 1.2em;
+ padding: 0.5em;
+}
+
+table.summary td {
+ border-width: 0px 0px 0px 0px;
+ border-color: gray;
+ border-style: inset;
+ font-size: 1em;
+ padding: 0.5em;
+ vertical-align: top;
+}
+
+table.testsummary {
+ background-color: rgb(212, 233, 169);
+ border-collapse:collapse;
+ margin-left:auto;
+ margin-right:auto;
+}
+
+table.testsummary th {
+ background-color: #A5C639;
+ border: 1px outset gray;
+ padding: 0.5em;
+}
+
+table.testsummary td {
+ border: 1px outset #A5C639;
+ padding: 0.5em;
+ text-align: center;
+}
+
+table.testdetails {
+ background-color: rgb(212, 233, 169);
+ border-collapse:collapse;
+ border-width:1;
+ border-color: #A5C639;
+ margin-left:auto;
+ margin-right:auto;
+ margin-bottom: 2em;
+ vertical-align: top;
+ width: 95%;
+}
+
+table.testdetails th {
+ background-color: #A5C639;
+ border-width: 1px;
+ border-color: gray;
+ border-style: outset;
+ height: 2em;
+ padding: 0.2em;
+}
+
+table.testdetails td {
+ border-width: 1px;
+ border-color: #A5C639;
+ border-style: outset;
+ text-align: left;
+ vertical-align: top;
+ padding: 0.2em;
+}
+
+table.testdetails td.module {
+ background-color: white;
+ border: 0px;
+ font-weight: bold;
+}
+
+/* Test cell details */
+td.failed {
+ background-color: #FA5858;
+ font-weight:bold;
+ vertical-align: top;
+ text-align: center;
+}
+
+td.failuredetails {
+ text-align: left;
+}
+
+td.pass {
+ text-align: center;
+ margin-left:auto;
+ margin-right:auto;
+}
+
+td.not_executed {
+ background-color: #A5C639;
+ vertical-align: top;
+ text-align: center;
+}
+
+td.testname {
+ border-width: 1px;
+ border-color: #A5C639;
+ border-style: outset;
+ text-align: left;
+ vertical-align: top;
+ padding:1;
+ overflow:hidden;
+}
+
+td.testcase {
+ border-width: 1px;
+ border-color: #A5C639;
+ border-style: outset;
+ text-align: left;
+ vertical-align: top;
+ padding:1;
+ overflow:hidden;
+ font-weight:bold;
+}
+
+div.details {
+ white-space: pre-wrap; /* css-3 */
+ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ word-wrap: break-word; /* Internet Explorer 5.5+ */
+ overflow:auto;
+}
diff --git a/common/host-side/tradefed/res/report/compatibility_result.xsd b/common/host-side/tradefed/res/report/compatibility_result.xsd
new file mode 100644
index 0000000..9b2758c
--- /dev/null
+++ b/common/host-side/tradefed/res/report/compatibility_result.xsd
@@ -0,0 +1,127 @@
+<?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.
+ -->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://compatibility.android.com/compatibility_result/1.15"
+ xmlns="http://compatibility.android.com/compatibility_result/1.15"
+ elementFormDefault="qualified">
+
+ <xs:element name="Result">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Summary" type="summaryType"/>
+ <xs:element name="Module" type="moduleType" minOccurs="1" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="start" type="xs:string"/>
+ <xs:attribute name="end" type="xs:string"/>
+ <xs:attribute name="plan" type="xs:string"/>
+ <xs:attribute name="suite_name" type="xs:string"/>
+ <xs:attribute name="suite_version" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="summaryType">
+ <xs:attribute name="failed" type="xs:integer"/>
+ <xs:attribute name="not_executed" type="xs:integer"/>
+ <xs:attribute name="pass" type="xs:integer"/>
+ </xs:complexType>
+
+ <xs:complexType name="moduleType">
+ <xs:sequence>
+ <xs:element name="Test" type="testType" minOccurs="1" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="abi" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:simpleType name="unitType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="ms"/>
+ <xs:enumeration value="fps"/>
+ <xs:enumeration value="ops"/>
+ <xs:enumeration value="kbps"/>
+ <xs:enumeration value="mbps"/>
+ <xs:enumeration value="byte"/>
+ <xs:enumeration value="count"/>
+ <xs:enumeration value="score"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="scoreTypeType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="higher-better"/>
+ <xs:enumeration value="lower-better"/>
+ <xs:enumeration value="neutral"/>
+ <xs:enumeration value="warning"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="testType">
+ <xs:sequence>
+ <xs:element name="Failure" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="StackTrace" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ <xs:attribute name="message" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Summary" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:decimal">
+ <xs:attribute name="message" type="xs:string" use="required" />
+ <xs:attribute name="scoreType" type="scoreTypeType" use="required" />
+ <xs:attribute name="unit" type="unitType" use="required" />
+ <xs:attribute name="target" type="xs:decimal" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Details" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ValueArray" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Value" type="xs:decimal" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="source" type="xs:string" use="required" />
+ <xs:attribute name="message" type="xs:string" use="required" />
+ <xs:attribute name="scoreType" type="scoreTypeType" use="required" />
+ <xs:attribute name="unit" type="unitType" use="required" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="result" type="resultType" use="required"/>
+ <xs:attribute name="start" type="xs:string"/>
+ <xs:attribute name="end" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:simpleType name="resultType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="pass"/>
+ <xs:enumeration value="fail"/>
+ <xs:enumeration value="not_executed"/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
\ No newline at end of file
diff --git a/common/host-side/tradefed/res/report/compatibility_result.xsl b/common/host-side/tradefed/res/report/compatibility_result.xsl
new file mode 100644
index 0000000..1fb4e83
--- /dev/null
+++ b/common/host-side/tradefed/res/report/compatibility_result.xsl
@@ -0,0 +1,273 @@
+<?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.
+-->
+
+<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
+
+ <xsl:template match="/">
+
+ <html>
+ <head>
+ <title>Test Report</title>
+ <style type="text/css">
+ @import "compatibility_result.css";
+ </style>
+ </head>
+ <body>
+ <div>
+ <table class="title">
+ <tr>
+ <td width="40%" align="left"><img src="logo.png"></img></td>
+ <td width="60%" align="left">
+ <h1>Test Report</h1>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <img src="newrule_green.png" align="left"></img>
+
+ <br></br>
+
+ <center>
+ <a href="device-info/GenericDeviceInfo.deviceinfo.json" >Device Information</a>
+ </center>
+
+ <br></br>
+
+ <div>
+ <table class="summary">
+ <tr>
+ <th colspan="2">Test Summary</th>
+ </tr>
+ <tr>
+ <td class="rowtitle">Compatibility Suite</td>
+ <td>
+ <xsl:value-of select="Result/@suite_name"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Compatibility Version</td>
+ <td>
+ <xsl:value-of select="Result/@suite_version"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Report Version</td>
+ <td>
+ <xsl:value-of select="Result/@report_version"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Host Info</td>
+ <td>
+ <xsl:value-of select="Result/@host_name"/>
+ (<xsl:value-of select="Result/@os_name"/> - <xsl:value-of select="Result/@os_version"/>)
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Plan</td>
+ <td>
+ <xsl:value-of select="Result/@plan"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Start time</td>
+ <td>
+ <xsl:value-of select="Result/@start"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">End time</td>
+ <td>
+ <xsl:value-of select="Result/@end"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Tests Passed</td>
+ <td>
+ <xsl:value-of select="Result/Summary/@pass"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Tests Failed</td>
+ <td>
+ <xsl:value-of select="Result/Summary/@failed"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Tests Not Executed</td>
+ <td>
+ <xsl:value-of select="Result/Summary/@not_executed"/>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <!-- High level summary of test execution -->
+ <h2 align="center">Test Summary by Module</h2>
+ <div>
+ <table class="testsummary">
+ <tr>
+ <th>Module</th>
+ <th>Passed</th>
+ <th>Failed</th>
+ <th>Not Executed</th>
+ <th>Total Tests</th>
+ </tr>
+ <xsl:for-each select="Result/Module">
+ <tr>
+ <td>
+ <xsl:variable name="href"><xsl:value-of select="@name"/> - <xsl:value-of select="@abi"/></xsl:variable>
+ <a href="#{$href}"><xsl:value-of select="@name"/> - <xsl:value-of select="@abi"/></a>
+ </td>
+ <td>
+ <xsl:value-of select="count(Test[@result = 'pass'])"/>
+ </td>
+ <td>
+ <xsl:value-of select="count(Test[@result = 'fail'])"/>
+ </td>
+ <td>
+ <xsl:value-of select="count(Test[@result = 'not_executed'])"/>
+ </td>
+ <td>
+ <xsl:value-of select="count(Test)"/>
+ </td>
+ </tr>
+ </xsl:for-each> <!-- end Module -->
+ </table>
+ </div>
+
+ <xsl:call-template name="filteredResultTestReport">
+ <xsl:with-param name="header" select="'Failured Tests'" />
+ <xsl:with-param name="resultFilter" select="'fail'" />
+ </xsl:call-template>
+
+ <xsl:call-template name="filteredResultTestReport">
+ <xsl:with-param name="header" select="'Not Executed Tests'" />
+ <xsl:with-param name="resultFilter" select="'not_executed'" />
+ </xsl:call-template>
+
+ <h2 align="center">Detailed Test Report</h2>
+ <xsl:call-template name="detailedTestReport" />
+
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template name="filteredResultTestReport">
+ <xsl:param name="header" />
+ <xsl:param name="resultFilter" />
+ <xsl:variable name="numMatching" select="count(Result/Module/Test[@result=$resultFilter])" />
+ <xsl:if test="$numMatching > 0">
+ <h2 align="center"><xsl:value-of select="$header" /> (<xsl:value-of select="$numMatching"/>)</h2>
+ <xsl:call-template name="detailedTestReport">
+ <xsl:with-param name="resultFilter" select="$resultFilter"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="detailedTestReport">
+ <xsl:param name="resultFilter" />
+ <div>
+ <xsl:for-each select="Result/Module">
+ <xsl:if test="$resultFilter=''
+ or count(Test[@result=$resultFilter]) > 0">
+
+ <table class="testdetails">
+ <tr>
+ <td class="module" colspan="3">
+ <xsl:variable name="href"><xsl:value-of select="@name"/> - <xsl:value-of select="@abi"/></xsl:variable>
+ <a name="{$href}"><xsl:value-of select="@name"/> - <xsl:value-of select="@abi"/></a>
+ </td>
+ </tr>
+
+ <tr>
+ <th width="30%">Test</th>
+ <th width="5%">Result</th>
+ <th>Details</th>
+ </tr>
+
+ <!-- test -->
+ <xsl:for-each select="Test">
+ <xsl:if test="$resultFilter='' or $resultFilter=@result">
+ <tr>
+ <td class="testname"> -- <xsl:value-of select="@name"/></td>
+
+ <!-- test results -->
+ <xsl:if test="@result='pass'">
+ <td class="pass">
+ <div style="text-align: center; margin-left:auto; margin-right:auto;">
+ <xsl:value-of select="@result"/>
+ </div>
+ </td>
+ <td class="failuredetails"/>
+ </xsl:if>
+
+ <xsl:if test="@result='fail'">
+ <td class="failed">
+ <div style="text-align: center; margin-left:auto; margin-right:auto;">
+ <xsl:value-of select="@result"/>
+ </div>
+ </td>
+ <td class="failuredetails">
+ <div class="details">
+ <xsl:value-of select="Failure/@message"/>
+ </div>
+ </td>
+ </xsl:if>
+
+ <xsl:if test="@result='not_executed'">
+ <td class="not_executed">
+ <div style="text-align: center; margin-left:auto; margin-right:auto;">
+ <xsl:value-of select="@result"/>
+ </div>
+ </td>
+ <td class="failuredetails"></td>
+ </xsl:if>
+ </tr> <!-- finished with a row -->
+ </xsl:if>
+ </xsl:for-each> <!-- end test -->
+ </table>
+ </xsl:if>
+ </xsl:for-each> <!-- end test Module -->
+ </div>
+ </xsl:template>
+
+ <!-- Take a delimited string and insert line breaks after a some number of elements. -->
+ <xsl:template name="formatDelimitedString">
+ <xsl:param name="string" />
+ <xsl:param name="numTokensPerRow" select="10" />
+ <xsl:param name="tokenIndex" select="1" />
+ <xsl:if test="$string">
+ <!-- Requires the last element to also have a delimiter after it. -->
+ <xsl:variable name="token" select="substring-before($string, ';')" />
+ <xsl:value-of select="$token" />
+ <xsl:text> </xsl:text>
+
+ <xsl:if test="$tokenIndex mod $numTokensPerRow = 0">
+ <br />
+ </xsl:if>
+
+ <xsl:call-template name="formatDelimitedString">
+ <xsl:with-param name="string" select="substring-after($string, ';')" />
+ <xsl:with-param name="numTokensPerRow" select="$numTokensPerRow" />
+ <xsl:with-param name="tokenIndex" select="$tokenIndex + 1" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/common/host-side/tradefed/res/report/logo.png b/common/host-side/tradefed/res/report/logo.png
new file mode 100644
index 0000000..61970b3
--- /dev/null
+++ b/common/host-side/tradefed/res/report/logo.png
Binary files differ
diff --git a/common/host-side/tradefed/res/report/newrule_green.png b/common/host-side/tradefed/res/report/newrule_green.png
new file mode 100644
index 0000000..10a4194
--- /dev/null
+++ b/common/host-side/tradefed/res/report/newrule_green.png
Binary files differ
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
new file mode 100644
index 0000000..f2ce00b
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.build;
+
+import com.android.compatibility.SuiteInfo;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.build.IFolderBuildInfo;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A simple helper that stores and retrieves information from a {@link IBuildInfo}.
+ */
+public class CompatibilityBuildHelper {
+
+ private static final String ROOT_DIR = "ROOT_DIR";
+ private static final String SUITE_BUILD = "SUITE_BUILD";
+ private static final String SUITE_NAME = "SUITE_NAME";
+ private static final String SUITE_FULL_NAME = "SUITE_FULL_NAME";
+ private static final String SUITE_VERSION = "SUITE_VERSION";
+ private static final String SUITE_PLAN = "SUITE_PLAN";
+ private static final String RESULT_DIR = "RESULT_DIR";
+ private static final String CONFIG_PATH_PREFIX = "DYNAMIC_CONFIG_FILE:";
+ private static final String DYNAMIC_CONFIG_OVERRIDE_URL = "DYNAMIC_CONFIG_OVERRIDE_URL";
+ private final IBuildInfo mBuildInfo;
+ private boolean mInitialized = false;
+
+ /**
+ * Creates a {@link CompatibilityBuildHelper} wrapping the given {@link IBuildInfo}.
+ */
+ public CompatibilityBuildHelper(IBuildInfo buildInfo) {
+ mBuildInfo = buildInfo;
+ }
+
+ /**
+ * Initializes the {@link IBuildInfo} from the manifest.
+ */
+ public void init(String suitePlan, String dynamicConfigUrl) {
+ if (mInitialized) {
+ return;
+ }
+ mInitialized = true;
+ mBuildInfo.addBuildAttribute(SUITE_BUILD, SuiteInfo.BUILD_NUMBER);
+ mBuildInfo.addBuildAttribute(SUITE_NAME, SuiteInfo.NAME);
+ mBuildInfo.addBuildAttribute(SUITE_FULL_NAME, SuiteInfo.FULLNAME);
+ mBuildInfo.addBuildAttribute(SUITE_VERSION, SuiteInfo.VERSION);
+ mBuildInfo.addBuildAttribute(SUITE_PLAN, suitePlan);
+ String rootDirPath = null;
+ if (mBuildInfo instanceof IFolderBuildInfo) {
+ File rootDir = ((IFolderBuildInfo) mBuildInfo).getRootDir();
+ if (rootDir != null) {
+ rootDirPath = rootDir.getAbsolutePath();
+ }
+ }
+ rootDirPath = System.getProperty(String.format("%s_ROOT", SuiteInfo.NAME), rootDirPath);
+ if (rootDirPath == null || rootDirPath.trim().equals("")) {
+ throw new IllegalArgumentException(
+ String.format("Missing install path property %s_ROOT", SuiteInfo.NAME));
+ }
+ File rootDir = new File(rootDirPath);
+ if (!rootDir.exists()) {
+ throw new IllegalArgumentException(
+ String.format("Root directory doesn't exist %s", rootDir.getAbsolutePath()));
+ }
+ mBuildInfo.addBuildAttribute(ROOT_DIR, rootDir.getAbsolutePath());
+ if (dynamicConfigUrl != null && !dynamicConfigUrl.isEmpty()) {
+ mBuildInfo.addBuildAttribute(DYNAMIC_CONFIG_OVERRIDE_URL,
+ dynamicConfigUrl.replace("{suite-name}", getSuiteName()));
+ }
+ }
+
+ public String getSuiteBuild() {
+ return mBuildInfo.getBuildAttributes().get(SUITE_BUILD);
+ }
+
+ public String getSuiteName() {
+ return mBuildInfo.getBuildAttributes().get(SUITE_NAME);
+ }
+
+ public String getSuiteFullName() {
+ return mBuildInfo.getBuildAttributes().get(SUITE_FULL_NAME);
+ }
+
+ public String getSuiteVersion() {
+ return mBuildInfo.getBuildAttributes().get(SUITE_VERSION);
+ }
+
+ public String getSuitePlan() {
+ return mBuildInfo.getBuildAttributes().get(SUITE_PLAN);
+ }
+
+ public String getDynamicConfigUrl() {
+ return mBuildInfo.getBuildAttributes().get(DYNAMIC_CONFIG_OVERRIDE_URL);
+ }
+
+ public void addDynamicConfigFile(String moduleName, File configFile) {
+ mBuildInfo.addBuildAttribute(CONFIG_PATH_PREFIX + moduleName, configFile.getAbsolutePath());
+ }
+
+ public Map<String, File> getDynamicConfigFiles() {
+ Map<String, File> configMap = new HashMap<>();
+ for (String key : mBuildInfo.getBuildAttributes().keySet()) {
+ if (key.startsWith(CONFIG_PATH_PREFIX)) {
+ configMap.put(key.substring(CONFIG_PATH_PREFIX.length()),
+ new File(mBuildInfo.getBuildAttributes().get(key)));
+ }
+ }
+ return configMap;
+ }
+
+ /**
+ * @return a {@link File} representing the directory holding the Compatibility installation
+ * @throws FileNotFoundException if the directory does not exist
+ */
+ public File getRootDir() throws FileNotFoundException {
+ File dir = new File(mBuildInfo.getBuildAttributes().get(ROOT_DIR));
+ if (!dir.exists()) {
+ throw new FileNotFoundException(String.format(
+ "Compatibility root directory %s does not exist",
+ dir.getAbsolutePath()));
+ }
+ return dir;
+ }
+
+ /**
+ * @return a {@link File} representing the "android-<suite>" folder of the Compatibility
+ * installation
+ * @throws FileNotFoundException if the directory does not exist
+ */
+ public File getDir() throws FileNotFoundException {
+ File dir = new File(getRootDir(), String.format("android-%s", getSuiteName().toLowerCase()));
+ if (!dir.exists()) {
+ throw new FileNotFoundException(String.format(
+ "Compatibility install folder %s does not exist",
+ dir.getAbsolutePath()));
+ }
+ return dir;
+ }
+
+ /**
+ * @return a {@link File} representing the results directory.
+ * @throws FileNotFoundException if the directory structure is not valid.
+ */
+ public File getResultsDir() throws FileNotFoundException {
+ return new File(getDir(), "results");
+ }
+
+ /**
+ * Sets the name of the current invocation's result directory.
+ */
+ public void setResultDir(String resultDir) {
+ mBuildInfo.addBuildAttribute(RESULT_DIR, resultDir);
+ }
+
+ /**
+ * @return a {@link File} representing the result directory of the current invocation.
+ * @throws FileNotFoundException if the directory structure is not valid.
+ */
+ public File getResultDir() throws FileNotFoundException {
+ return new File(getResultsDir(), mBuildInfo.getBuildAttributes().get(RESULT_DIR));
+ }
+
+ /**
+ * @return a {@link File} representing the directory to store result logs.
+ * @throws FileNotFoundException if the directory structure is not valid.
+ */
+ public File getLogsDir() throws FileNotFoundException {
+ return new File(getDir(), "logs");
+ }
+
+ /**
+ * @return a {@link File} representing the test modules directory.
+ * @throws FileNotFoundException if the directory structure is not valid.
+ */
+ public File getTestsDir() throws FileNotFoundException {
+ File testsDir = new File(getDir(), "testcases");
+ if (!testsDir.exists()) {
+ throw new FileNotFoundException(String.format(
+ "Compatibility tests folder %s does not exist",
+ testsDir.getAbsolutePath()));
+ }
+ return testsDir;
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
new file mode 100644
index 0000000..65f60bd
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.build;
+
+import com.android.tradefed.build.BuildInfo;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.build.IBuildProvider;
+import com.android.tradefed.config.OptionClass;
+
+/**
+ * A simple {@link IBuildProvider} that uses a pre-existing Compatibility install.
+ */
+@OptionClass(alias="compatibility-build-provider")
+public class CompatibilityBuildProvider implements IBuildProvider {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IBuildInfo getBuild() {
+ // Create a blank BuildInfo which will get populated later.
+ return new BuildInfo();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void buildNotTested(IBuildInfo info) {
+ // ignore
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void cleanUp(IBuildInfo info) {
+ // ignore
+ }
+}
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 dfd1c71..db4ac73 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
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -13,19 +13,213 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.compatibility.common.tradefed.command;
+import com.android.compatibility.SuiteInfo;
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider;
+import com.android.compatibility.common.tradefed.result.IInvocationResultRepo;
+import com.android.compatibility.common.tradefed.result.InvocationResultRepo;
+import com.android.compatibility.common.tradefed.testtype.ModuleRepo;
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.TestStatus;
import com.android.tradefed.command.Console;
import com.android.tradefed.config.ConfigurationException;
+import com.android.tradefed.util.ArrayUtil;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.RegexTrie;
+import com.android.tradefed.util.TableFormatter;
+import com.android.tradefed.util.TimeUtil;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
/**
* An extension of Tradefed's console which adds features specific to compatibility testing.
*/
public class CompatibilityConsole extends Console {
+ private CompatibilityBuildHelper mBuildHelper;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run() {
+ printLine(String.format("Android %s %s (%s)", SuiteInfo.FULLNAME, SuiteInfo.VERSION,
+ SuiteInfo.BUILD_NUMBER));
+ super.run();
+ }
+
+ /**
+ * Adds the 'list plans', 'list modules' and 'list results' commands
+ */
+ @Override
+ protected void setCustomCommands(RegexTrie<Runnable> trie, List<String> genericHelp,
+ Map<String, String> commandHelp) {
+ trie.put(new Runnable() {
+ @Override
+ public void run() {
+ // TODO(stuartscott)" listPlans(buildHelper);
+ }
+ }, LIST_PATTERN, "p(?:lans)?");
+ trie.put(new Runnable() {
+ @Override
+ public void run() {
+ listModules();
+ }
+ }, LIST_PATTERN, "m(?:odules)?");
+ trie.put(new Runnable() {
+ @Override
+ public void run() {
+ listResults();
+ }
+ }, LIST_PATTERN, "r(?:esults)?");
+
+ // find existing help for 'LIST_PATTERN' commands, and append these commands help
+ String listHelp = commandHelp.get(LIST_PATTERN);
+ if (listHelp == null) {
+ // no help? Unexpected, but soldier on
+ listHelp = new String();
+ }
+ String combinedHelp = listHelp +
+ "\tp[lans]\tList all plans" + LINE_SEPARATOR +
+ "\tm[odules]\tList all modules" + LINE_SEPARATOR +
+ "\tr[esults]\tList all results" + LINE_SEPARATOR;
+ commandHelp.put(LIST_PATTERN, combinedHelp);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getConsolePrompt() {
+ return String.format("%s-tf > ", SuiteInfo.NAME.toLowerCase());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getGenericHelpString(List<String> genericHelp) {
+ StringBuilder helpBuilder = new StringBuilder();
+ helpBuilder.append(SuiteInfo.FULLNAME);
+ helpBuilder.append("\n\n");
+ helpBuilder.append(SuiteInfo.NAME);
+ helpBuilder.append(" is the test harness for running the Android Compatibility Suite, ");
+ helpBuilder.append("built on top of Trade Federation.\n\n");
+ helpBuilder.append("Available commands and options\n");
+ helpBuilder.append("Host:\n");
+ 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("invocations have completed.\n");
+ helpBuilder.append("Run:\n");
+ final String runPrompt = " run <plan> ";
+ helpBuilder.append(runPrompt);
+ helpBuilder.append("--module/-m <module>: run a test module.\n");
+ helpBuilder.append(runPrompt);
+ helpBuilder.append("--module/-m <module> --test/-t <test_name>: run a specific test from");
+ helpBuilder.append(" the module. Test name can be <package>.<class>, ");
+ helpBuilder.append("<package>.<class>#<method> or <native_name>.\n");
+ helpBuilder.append(runPrompt);
+ helpBuilder.append("--retry <session_id>: run all failed tests from a previous session.\n");
+ helpBuilder.append(runPrompt);
+ helpBuilder.append("--help/--help-all: get help for ");
+ helpBuilder.append(SuiteInfo.FULLNAME);
+ helpBuilder.append(".\n");
+ helpBuilder.append("Options:\n");
+ helpBuilder.append(" --serial/-s <device_id>: The device to run the test on.\n");
+ helpBuilder.append(" --abi/-a <abi>: The ABI to run the test against.\n");
+ helpBuilder.append(" --shard <shards>: Shards a run into the given number of independant");
+ helpBuilder.append(" chunks, to run on multiple devices in parallel.\n");
+ helpBuilder.append(" --logcat-on-failure: Capture logcat when a test fails.\n");
+ helpBuilder.append(" --bugreport-on-failure: Capture a bugreport when a test fails.\n");
+ helpBuilder.append(" --screenshot-on-failure: Capture a screenshot when a test fails.\n");
+ helpBuilder.append("List:\n");
+ helpBuilder.append(" l/list d/devices: list connected devices and their state\n");
+ helpBuilder.append(" l/list m/modules: list test modules\n");
+ helpBuilder.append(" l/list i/invocations: list invocations aka test runs currently in ");
+ helpBuilder.append("progress\n");
+ helpBuilder.append(" l/list c/commands: list commands aka test run commands currently");
+ helpBuilder.append(" in the queue waiting to be allocated devices\n");
+ helpBuilder.append(" l/list r/results: list results currently in the repository\n");
+ helpBuilder.append("Dump:\n");
+ helpBuilder.append(" d/dump l/logs: dump the tradefed logs for all running invocations\n");
+ return helpBuilder.toString();
+ }
+
+ private void listModules() {
+ File[] files = null;
+ try {
+ files = getBuildHelper().getTestsDir().listFiles(new ModuleRepo.ConfigFilter());
+ } catch (FileNotFoundException e) {
+ printLine(e.getMessage());
+ e.printStackTrace();
+ }
+ if (files != null && files.length > 0) {
+ List<String> modules = new ArrayList<>();
+ for (File moduleFile : files) {
+ modules.add(FileUtil.getBaseName(moduleFile.getName()));
+ }
+ Collections.sort(modules);
+ for (String module : modules) {
+ printLine(module);
+ }
+ } else {
+ printLine("No modules found");
+ }
+ }
+
+ private void listResults() {
+ TableFormatter tableFormatter = new TableFormatter();
+ List<List<String>> table = new ArrayList<>();
+ table.add(Arrays.asList("Session","Pass", "Fail", "Not Executed", "Start Time", "Test Plan",
+ "Device serial(s)"));
+ IInvocationResultRepo testResultRepo = null;
+ List<IInvocationResult> results = null;
+ try {
+ testResultRepo = new InvocationResultRepo(getBuildHelper().getResultsDir());
+ results = testResultRepo.getResults();
+ } catch (FileNotFoundException e) {
+ printLine(e.getMessage());
+ e.printStackTrace();
+ }
+ if (testResultRepo != null && results.size() > 0) {
+ for (int i = 0; i < results.size(); i++) {
+ IInvocationResult result = results.get(i);
+ table.add(Arrays.asList(Integer.toString(i),
+ Integer.toString(result.countResults(TestStatus.PASS)),
+ Integer.toString(result.countResults(TestStatus.FAIL)),
+ Integer.toString(result.countResults(TestStatus.NOT_EXECUTED)),
+ TimeUtil.formatTimeStamp(result.getStartTime()),
+ result.getTestPlan(),
+ ArrayUtil.join(", ", result.getDeviceSerials())));
+ }
+ tableFormatter.displayTable(table, new PrintWriter(System.out, true));
+ } else {
+ printLine(String.format("No results found"));
+ }
+ }
+
+ private CompatibilityBuildHelper getBuildHelper() {
+ if (mBuildHelper == null) {
+ CompatibilityBuildProvider buildProvider = new CompatibilityBuildProvider();
+ mBuildHelper = new CompatibilityBuildHelper(buildProvider.getBuild());
+ mBuildHelper.init("" /* suite plan */, "" /* dynamic config url */);
+ }
+ return mBuildHelper;
+ }
+
public static void main(String[] args) throws InterruptedException, ConfigurationException {
- CompatibilityConsole console = new CompatibilityConsole();
+ Console console = new CompatibilityConsole();
Console.startConsole(console, args);
}
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/IInvocationResultRepo.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/IInvocationResultRepo.java
new file mode 100644
index 0000000..c07223b0
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/IInvocationResultRepo.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.result;
+
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.InvocationResult;
+
+import java.util.List;
+
+/**
+ * Repository for Compatibility results.
+ */
+public interface IInvocationResultRepo {
+
+ /**
+ * @return the list of {@link IInvocationResult}s. The index is its session id
+ */
+ List<IInvocationResult> getResults();
+
+ /**
+ * Get the {@link IInvocationResult} for given session id.
+ *
+ * @param sessionId the session id
+ * @return the {@link InvocationResult} or <code>null</null> if the result with that session id
+ * cannot be retrieved
+ */
+ IInvocationResult getResult(int sessionId);
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/IModuleListener.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/IModuleListener.java
new file mode 100644
index 0000000..213d293
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/IModuleListener.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.result;
+
+import com.android.tradefed.result.ITestInvocationListener;
+
+/**
+ * Listener for Compatibility tests.
+ * <p>
+ * This listener wraps around the normal listener to convert from module name to module id.
+ */
+public interface IModuleListener extends ITestInvocationListener {
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/InvocationResultRepo.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/InvocationResultRepo.java
new file mode 100644
index 0000000..e046e12
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/InvocationResultRepo.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.result;
+
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.ResultHandler;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An implementation of {@link IInvocationResultRepo}.
+ */
+public class InvocationResultRepo implements IInvocationResultRepo {
+
+ /**
+ * Ordered list of result directories. the index of each file is its session id.
+ */
+ private List<IInvocationResult> mResults;
+
+ /**
+ * Create a {@link InvocationResultRepo} from a directory of results
+ *
+ * @param testResultDir the parent directory of results
+ */
+ public InvocationResultRepo(File testResultDir) {
+ mResults = ResultHandler.getResults(testResultDir);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<IInvocationResult> getResults() {
+ return new ArrayList<IInvocationResult>(mResults);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IInvocationResult getResult(int sessionId) {
+ if (sessionId < 0 || sessionId >= mResults.size()) {
+ return null;
+ }
+ return mResults.get(sessionId);
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ModuleListener.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ModuleListener.java
new file mode 100644
index 0000000..acfba25
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ModuleListener.java
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.result;
+
+import com.android.compatibility.common.tradefed.testtype.IModuleDef;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.InputStreamSource;
+import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.TestSummary;
+
+import java.util.Map;
+
+/**
+ * Listener for Compatibility test info.
+ * <p>
+ * This listener wraps around the normal listener to convert from module name to module id.
+ */
+public class ModuleListener implements IModuleListener {
+
+ private IModuleDef mModule;
+ private ITestInvocationListener mListener;
+
+ /**
+ * @param module
+ * @param listener
+ */
+ public ModuleListener(IModuleDef module, ITestInvocationListener listener) {
+ mModule = module;
+ mListener = listener;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invocationStarted(IBuildInfo buildInfo) {
+ CLog.d("ModuleListener.invocationStarted(%s)", buildInfo.toString());
+ mListener.invocationStarted(buildInfo);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunStarted(String name, int numTests) {
+ CLog.d("ModuleListener.testRunStarted(%s, %d)", name, numTests);
+ mListener.testRunStarted(mModule.getId(), numTests);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testStarted(TestIdentifier test) {
+ CLog.d("ModuleListener.testStarted(%s)", test.toString());
+ mListener.testStarted(test);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+ CLog.d("ModuleListener.testEnded(%s, %s)", test.toString(), metrics.toString());
+ mListener.testEnded(test, metrics);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testIgnored(TestIdentifier test) {
+ CLog.d("ModuleListener.testIgnored(%s)", test.toString());
+ mListener.testIgnored(test);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testFailed(TestIdentifier test, String trace) {
+ CLog.d("ModuleListener.testFailed(%s, %s)", test.toString(), trace);
+ mListener.testFailed(test, trace);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testAssumptionFailure(TestIdentifier test, String trace) {
+ CLog.d("ModuleListener.testAssumptionFailure(%s, %s)", test.toString(), trace);
+ mListener.testAssumptionFailure(test, trace);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunStopped(long elapsedTime) {
+ CLog.d("ModuleListener.testRunStopped(%d)", elapsedTime);
+ mListener.testRunStopped(elapsedTime);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunEnded(long elapsedTime, Map<String, String> metrics) {
+ CLog.d("ModuleListener.testRunEnded(%d, %s)", elapsedTime, metrics.toString());
+ mListener.testRunEnded(elapsedTime, metrics);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunFailed(String id) {
+ CLog.d("ModuleListener.testRunFailed(%s)", id);
+ mListener.testRunFailed(mModule.getId());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public TestSummary getSummary() {
+ return mListener.getSummary();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invocationEnded(long elapsedTime) {
+ CLog.d("ModuleListener.invocationEnded(%d)", elapsedTime);
+ mListener.invocationEnded(elapsedTime);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invocationFailed(Throwable cause) {
+ CLog.d("ModuleListener.invocationFailed(%s)", cause.toString());
+ mListener.invocationFailed(cause);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testLog(String name, LogDataType type, InputStreamSource stream) {
+ CLog.d("ModuleListener.testLog(%s, %s, %s)", name, type.toString(), stream.toString());
+ mListener.testLog(name, type, stream);
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
new file mode 100644
index 0000000..0bfc41c
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
@@ -0,0 +1,488 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.result;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.compatibility.common.util.ICaseResult;
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.IModuleResult;
+import com.android.compatibility.common.util.ITestResult;
+import com.android.compatibility.common.util.InvocationResult;
+import com.android.compatibility.common.util.MetricsStore;
+import com.android.compatibility.common.util.ReportLog;
+import com.android.compatibility.common.util.ResultHandler;
+import com.android.compatibility.common.util.ResultUploader;
+import com.android.compatibility.common.util.TestStatus;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.ILogSaver;
+import com.android.tradefed.result.ILogSaverListener;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.ITestSummaryListener;
+import com.android.tradefed.result.InputStreamSource;
+import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.LogFile;
+import com.android.tradefed.result.LogFileSaver;
+import com.android.tradefed.result.TestSummary;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.StreamUtil;
+import com.android.tradefed.util.TimeUtil;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Reporter for Compatibility test results.
+ */
+@OptionClass(alias="result-reporter")
+public class ResultReporter implements ILogSaverListener, ITestInvocationListener,
+ ITestSummaryListener {
+
+ private static final String RESULT_KEY = "COMPATIBILITY_TEST_RESULT";
+ private static final String DEVICE_INFO_GENERIC = "DEVICE_INFO_GENERIC_";
+ private static final String[] RESULT_RESOURCES = {
+ "compatibility_result.css",
+ "compatibility_result.xsd",
+ "compatibility_result.xsl",
+ "logo.png",
+ "newrule_green.png"};
+
+ @Option(name = CompatibilityTest.RETRY_OPTION,
+ shortName = 'r',
+ description = "retry a previous session.",
+ importance = Importance.IF_UNSET)
+ private Integer mRetrySessionId = null;
+
+ @Option(name = "quiet-output", description = "Mute display of test results.")
+ private boolean mQuietOutput = false;
+
+ @Option(name = "result-server", description = "Server to publish test results.")
+ private String mResultServer;
+
+ @Option(name = "include-test-log-tags", description = "Include test log tags in report.")
+ private boolean mIncludeTestLogTags = false;
+
+ @Option(name = "use-log-saver", description = "Also saves generated result with log saver")
+ private boolean mUseLogSaver = false;
+
+ private String mDeviceSerial;
+
+ private boolean mInitialized;
+ private IInvocationResult mResult;
+ private File mResultDir = null;
+ private File mLogDir = null;
+ private long mStartTime;
+ private ResultUploader mUploader;
+ private String mReferenceUrl;
+ private IModuleResult mCurrentModuleResult;
+ private ICaseResult mCurrentCaseResult;
+ private ITestResult mCurrentResult;
+ private IBuildInfo mBuild;
+ private CompatibilityBuildHelper mBuildHelper;
+ private ILogSaver mLogSaver;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invocationStarted(IBuildInfo buildInfo) {
+ mInitialized = false;
+ mBuild = buildInfo;
+ mBuildHelper = new CompatibilityBuildHelper(mBuild);
+ mDeviceSerial = buildInfo.getDeviceSerial();
+ if (mDeviceSerial == null) {
+ mDeviceSerial = "unknown_device";
+ }
+ long time = System.currentTimeMillis();
+ String dirSuffix = getDirSuffix(time);
+ if (mRetrySessionId != null) {
+ Log.d(mDeviceSerial, String.format("Retrying session %d", mRetrySessionId));
+ List<IInvocationResult> results = null;
+ try {
+ results = ResultHandler.getResults(mBuildHelper.getResultsDir());
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ if (results != null && mRetrySessionId >= 0 && mRetrySessionId < results.size()) {
+ mResult = results.get(mRetrySessionId);
+ } else {
+ throw new IllegalArgumentException(
+ String.format("Could not find session %d",mRetrySessionId));
+ }
+ mStartTime = mResult.getStartTime();
+ mResultDir = mResult.getResultDir();
+ } else {
+ mStartTime = time;
+ try {
+ mResultDir = new File(mBuildHelper.getResultsDir(), dirSuffix);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ if (mResultDir != null && mResultDir.mkdirs()) {
+ logResult("Created result dir %s", mResultDir.getAbsolutePath());
+ } else {
+ throw new IllegalArgumentException(String.format("Could not create result dir %s",
+ mResultDir.getAbsolutePath()));
+ }
+ mResult = new InvocationResult(mStartTime, mResultDir);
+ }
+ mBuildHelper.setResultDir(mResultDir.getName());
+ mUploader = new ResultUploader(mResultServer, mBuildHelper.getSuiteName());
+ try {
+ mLogDir = new File(mBuildHelper.getLogsDir(), dirSuffix);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ if (mLogDir != null && mLogDir.mkdirs()) {
+ logResult("Created log dir %s", mLogDir.getAbsolutePath());
+ } else {
+ throw new IllegalArgumentException(String.format("Could not create log dir %s",
+ mLogDir.getAbsolutePath()));
+ }
+ mInitialized = true;
+ }
+
+ /**
+ * @return a {@link String} to use for directory suffixes created from the given time.
+ */
+ private String getDirSuffix(long time) {
+ return new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss").format(new Date(time));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunStarted(String id, int numTests) {
+ logResult("Starting %s with %d test%s", id, numTests, (numTests > 1) ? "s" : "");
+ mCurrentModuleResult = mResult.getOrCreateModule(id);
+ mResult.addDeviceSerial(mDeviceSerial);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testStarted(TestIdentifier test) {
+ mCurrentCaseResult = mCurrentModuleResult.getOrCreateResult(test.getClassName());
+ mCurrentResult = mCurrentCaseResult.getOrCreateResult(test.getTestName());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+ if (mCurrentResult.getResultStatus() == TestStatus.FAIL) {
+ // Test has already failed.
+ return;
+ }
+ // device test can have performance results in test metrics
+ String perfResult = metrics.get(RESULT_KEY);
+ ReportLog report = null;
+ if (perfResult != null) {
+ try {
+ report = ReportLog.parse(perfResult);
+ } catch (XmlPullParserException | IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ // host test should be checked into MetricsStore.
+ report = MetricsStore.removeResult(
+ mDeviceSerial, mCurrentModuleResult.getAbi(), test.toString());
+ }
+ mCurrentResult.passed(report);
+ logResult("%s passed", test);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testIgnored(TestIdentifier test) {
+ logResult("%s ignored", test);
+ // ignore
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testFailed(TestIdentifier test, String trace) {
+ mCurrentResult.failed(trace);
+ logResult("%s failed: %s", test, trace);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testAssumptionFailure(TestIdentifier test, String trace) {
+ mCurrentResult.failed(trace);
+ logResult("%s failed assumption: %s", test, trace);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunStopped(long elapsedTime) {
+ logResult("%s stopped after %s", mCurrentModuleResult.getId(),
+ TimeUtil.formatElapsedTime(elapsedTime));
+ // ignore
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunEnded(long elapsedTime, Map<String, String> metrics) {
+ // Check build attributes to add generic device info to report.
+ Map<String, String> buildAttributes = mBuild.getBuildAttributes();
+ for (Map.Entry<String, String> attributeEntry : buildAttributes.entrySet()) {
+ String key = attributeEntry.getKey();
+ String value = attributeEntry.getValue();
+ if (key.startsWith(DEVICE_INFO_GENERIC)) {
+ mResult.addBuildInfo(key.substring(DEVICE_INFO_GENERIC.length()), value);
+ }
+ }
+ mCurrentModuleResult.addRuntime(elapsedTime);
+ logResult("%s completed in %s. %d passed, %d failed, %d not executed",
+ mCurrentModuleResult.getId(),
+ TimeUtil.formatElapsedTime(elapsedTime),
+ mCurrentModuleResult.countResults(TestStatus.PASS),
+ mCurrentModuleResult.countResults(TestStatus.FAIL),
+ mCurrentModuleResult.countResults(TestStatus.NOT_EXECUTED));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunFailed(String id) {
+ logResult("%s failed to run", id);
+ // ignore
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public TestSummary getSummary() {
+ // ignore
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void putSummary(List<TestSummary> summaries) {
+ if (summaries.size() > 0) {
+ mReferenceUrl = summaries.get(0).getSummary().getString();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invocationEnded(long elapsedTime) {
+ if (mInitialized) {
+ logResult("Invocation completed in %s. %d passed, %d failed, %d not executed",
+ TimeUtil.formatElapsedTime(elapsedTime),
+ mResult.countResults(TestStatus.PASS),
+ mResult.countResults(TestStatus.FAIL),
+ mResult.countResults(TestStatus.NOT_EXECUTED));
+ try {
+ File resultFile = ResultHandler.writeResults(mBuildHelper.getSuiteName(),
+ mBuildHelper.getSuiteVersion(), mBuildHelper.getSuitePlan(), mResult,
+ mResultDir, mStartTime, elapsedTime + mStartTime, mReferenceUrl);
+ copyDynamicConfigFiles(mBuildHelper.getDynamicConfigFiles(), mResultDir);
+ copyFormattingFiles(mResultDir);
+ zipResults(mResultDir);
+ if (mUseLogSaver) {
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(resultFile);
+ mLogSaver.saveLogData("log-result", LogDataType.XML, fis);
+ } catch (IOException ioe) {
+ Log.e(mDeviceSerial, "error saving XML with log saver");
+ Log.e(mDeviceSerial, ioe);
+ } finally {
+ StreamUtil.close(fis);
+ }
+ }
+ if (mResultServer != null && !mResultServer.trim().isEmpty()) {
+ mUploader.uploadResult(resultFile, mReferenceUrl);
+ }
+ } catch (IOException | XmlPullParserException e) {
+ CLog.e(e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invocationFailed(Throwable cause) {
+ logResult("ResultReporter.invocationFailed(%s)", cause);
+ mInitialized = false;
+ // Clean up
+ mResultDir.delete();
+ mResultDir = null;
+ mLogDir.delete();
+ mLogDir = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testLog(String name, LogDataType type, InputStreamSource stream) {
+ try {
+ LogFileSaver saver = new LogFileSaver(mLogDir);
+ File logFile = saver.saveAndZipLogData(name, type, stream.createInputStream());
+ logResult("Saved logs for %s in %s", name, logFile.getAbsolutePath());
+ } catch (IOException e) {
+ logResult("Failed to write log for %s", name);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testLogSaved(String dataName, LogDataType dataType, InputStreamSource dataStream,
+ LogFile logFile) {
+ if (mIncludeTestLogTags && mCurrentResult != null
+ && dataName.startsWith(mCurrentResult.getFullName())) {
+ if (dataType == LogDataType.BUGREPORT) {
+ mCurrentResult.setBugReport(logFile.getUrl());
+ } else if (dataType == LogDataType.LOGCAT) {
+ mCurrentResult.setLog(logFile.getUrl());
+ } else if (dataType == LogDataType.PNG) {
+ mCurrentResult.setScreenshot(logFile.getUrl());
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setLogSaver(ILogSaver saver) {
+ mLogSaver = saver;
+ }
+
+ /**
+ * Copy the xml formatting files stored in this jar to the results directory
+ *
+ * @param resultsDir
+ */
+ static void copyFormattingFiles(File resultsDir) {
+ for (String resultFileName : RESULT_RESOURCES) {
+ InputStream configStream = ResultHandler.class.getResourceAsStream(
+ String.format("/report/%s", resultFileName));
+ if (configStream != null) {
+ File resultFile = new File(resultsDir, resultFileName);
+ try {
+ FileUtil.writeToFile(configStream, resultFile);
+ } catch (IOException e) {
+ Log.w(ResultReporter.class.getSimpleName(),
+ String.format("Failed to write %s to file", resultFileName));
+ }
+ } else {
+ Log.w(ResultReporter.class.getSimpleName(),
+ String.format("Failed to load %s from jar", resultFileName));
+ }
+ }
+ }
+
+ /**
+ * move the dynamic config files to the results directory
+ *
+ * @param configFiles
+ * @param resultsDir
+ */
+ static void copyDynamicConfigFiles(Map<String, File> configFiles, File resultsDir) {
+ if (configFiles.size() == 0) return;
+
+ File folder = new File(resultsDir, "config");
+ folder.mkdir();
+ for (String moduleName : configFiles.keySet()) {
+ File resultFile = new File(folder, moduleName+".dynamic");
+ try {
+ FileUtil.copyFile(configFiles.get(moduleName), resultFile);
+ FileUtil.deleteFile(configFiles.get(moduleName));
+ } catch (IOException e) {
+ Log.w(ResultReporter.class.getSimpleName(),
+ String.format("Failed to copy config file for %s to file", moduleName));
+ }
+ }
+ }
+
+ /**
+ * Zip the contents of the given results directory.
+ *
+ * @param resultsDir
+ */
+ @SuppressWarnings("deprecation")
+ private static void zipResults(File resultsDir) {
+ try {
+ // create a file in parent directory, with same name as resultsDir
+ File zipResultFile = new File(resultsDir.getParent(), String.format("%s.zip",
+ resultsDir.getName()));
+ FileUtil.createZip(resultsDir, zipResultFile);
+ } catch (IOException e) {
+ Log.w(ResultReporter.class.getSimpleName(),
+ String.format("Failed to create zip for %s", resultsDir.getName()));
+ }
+ }
+
+ /**
+ * @return the mResult
+ */
+ public IInvocationResult getResult() {
+ return mResult;
+ }
+
+ private void logResult(String format, Object... args) {
+ if (mQuietOutput) {
+ CLog.i(format, args);
+ } else {
+ Log.logAndDisplay(LogLevel.INFO, mDeviceSerial, String.format(format, args));
+ }
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstaller.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstaller.java
new file mode 100644
index 0000000..7773d7d
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstaller.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.targetprep.TestAppInstallSetup;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Installs specified APKs from Compatibility repository.
+ */
+@OptionClass(alias="apk-installer")
+public class ApkInstaller extends TestAppInstallSetup {
+
+ private CompatibilityBuildHelper mBuildHelper = null;
+
+ protected File getTestsDir(IBuildInfo buildInfo) throws FileNotFoundException {
+ if (mBuildHelper == null) {
+ mBuildHelper = new CompatibilityBuildHelper(buildInfo);
+ }
+ return mBuildHelper.getTestsDir();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected File getLocalPathForFilename(IBuildInfo buildInfo, String apkFileName)
+ throws TargetSetupError {
+ File apkFile = null;
+ try {
+ apkFile = new File(getTestsDir(buildInfo), apkFileName);
+ if (!apkFile.isFile()) {
+ throw new FileNotFoundException();
+ }
+ } catch (FileNotFoundException e) {
+ throw new TargetSetupError(String.format("%s not found", apkFileName), e);
+ }
+ return apkFile;
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
new file mode 100644
index 0000000..916e8ec
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.compatibility.common.tradefed.util.NoOpTestInvocationListener;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetCleaner;
+import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.testtype.AndroidJUnitTest;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Target preparer that instruments an APK.
+ */
+@OptionClass(alias="apk-instrumentation-preparer")
+public class ApkInstrumentationPreparer extends PreconditionPreparer implements ITargetCleaner {
+
+ @Option(name = "apk", description = "Name of the apk to instrument", mandatory = true)
+ protected String mApkFileName = null;
+
+ @Option(name = "package", description = "Name of the package", mandatory = true)
+ protected String mPackageName = null;
+
+ @Option(name = CompatibilityTest.INCLUDE_FILTER_OPTION,
+ description = "the include module filters to apply.",
+ importance = Importance.ALWAYS)
+ private List<String> mIncludeFilters = new ArrayList<>();
+
+ @Option(name = CompatibilityTest.EXCLUDE_FILTER_OPTION,
+ description = "the exclude module filters to apply.",
+ importance = Importance.ALWAYS)
+ private List<String> mExcludeFilters = new ArrayList<>();
+
+ public enum When {
+ BEFORE, AFTER, BOTH;
+ }
+
+ @Option(name = "when", description = "When to instrument the apk", mandatory = true)
+ protected When mWhen = null;
+
+ protected ConcurrentHashMap<TestIdentifier, Map<String, String>> testMetrics =
+ new ConcurrentHashMap<>();
+ private ConcurrentHashMap<TestIdentifier, String> testFailures = new ConcurrentHashMap<>();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+ if (mWhen == When.AFTER) {
+ return;
+ }
+ try {
+ if (!instrument(device, buildInfo)) {
+ throw new TargetSetupError("Not all target preparation steps completed");
+ }
+ } catch (FileNotFoundException e) {
+ throw new TargetSetupError("Couldn't find apk to instrument", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
+ throws DeviceNotAvailableException {
+ if (e instanceof DeviceNotAvailableException) {
+ return;
+ }
+ if (mWhen == When.BEFORE) {
+ return;
+ }
+ try {
+ instrument(device, buildInfo);
+ } catch (FileNotFoundException e1) {
+ CLog.e("Couldn't find apk to instrument");
+ CLog.e(e1);
+ }
+ }
+
+ private boolean instrument(ITestDevice device, IBuildInfo buildInfo)
+ throws DeviceNotAvailableException, FileNotFoundException {
+ ITestInvocationListener listener = new TargetPreparerListener();
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
+
+ File testsDir = buildHelper.getTestsDir();
+ File apkFile = new File(testsDir, mApkFileName);
+ if (!apkFile.exists()) {
+ throw new FileNotFoundException(String.format("%s not found", mApkFileName));
+ }
+
+ AndroidJUnitTest instrTest = new AndroidJUnitTest();
+ instrTest.setDevice(device);
+ instrTest.setInstallFile(apkFile);
+ instrTest.setPackageName(mPackageName);
+ instrTest.addAllIncludeFilters(mIncludeFilters);
+ instrTest.addAllExcludeFilters(mExcludeFilters);
+ instrTest.run(listener);
+ boolean success = true;
+ if (!testFailures.isEmpty()) {
+ for (TestIdentifier test : testFailures.keySet()) {
+ success = false;
+ String trace = testFailures.get(test);
+ CLog.e("Target preparation step %s failed.\n%s", test.getTestName(), trace);
+ }
+ }
+ return success;
+ }
+
+ public class TargetPreparerListener extends NoOpTestInvocationListener {
+
+ @Override
+ public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+ testMetrics.put(test, metrics);
+ }
+
+ @Override
+ public void testFailed(TestIdentifier test, String trace) {
+ testFailures.put(test, trace);
+ }
+
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkPreconditionCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkPreconditionCheck.java
new file mode 100644
index 0000000..0f0b6c2
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkPreconditionCheck.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.tradefed.config.OptionClass;
+
+/**
+ * Runs a precondition test by instrumenting an APK
+ */
+@OptionClass(alias="apk-precondition-check")
+public class ApkPreconditionCheck extends ApkInstrumentationPreparer {
+
+ public ApkPreconditionCheck() {
+ mWhen = When.BEFORE;
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
new file mode 100644
index 0000000..c178d9c
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Map;
+
+/**
+ * An {@link ApkInstrumentationPreparer} that collects device info.
+ */
+public class DeviceInfoCollector extends ApkInstrumentationPreparer {
+
+ private static String LOG_TAG = "DeviceInfoCollector";
+ private static String DEVICE_INFO_CLASS = "com.android.compatibility.common.deviceinfo";
+ private static String DEVICE_INFO_GENERIC = "DEVICE_INFO_GENERIC_";
+ private static String DEVICE_INFO_ERROR = "DEVICE_INFO_ERROR_";
+
+ @Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION, description =
+ "Whether device info collection should be skipped")
+ private boolean mSkipDeviceInfo = false;
+
+ @Option(name= "src-dir", description = "The directory to copy to the results dir")
+ private String mSrcDir;
+
+ @Option(name = "dest-dir", description = "The directory under the result to store the files")
+ private String mDestDir;
+
+ public DeviceInfoCollector() {
+ mWhen = When.BEFORE;
+ }
+
+ @Override
+ public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+ if (mSkipDeviceInfo) {
+ return;
+ }
+
+ run(device, buildInfo);
+
+ // Check test metrics for errors and copy generic device info results to build attribute.
+ for (Map.Entry<TestIdentifier, Map<String, String>> metricEntry : testMetrics.entrySet()) {
+ if (!metricEntry.getKey().getClassName().startsWith(DEVICE_INFO_CLASS)) {
+ continue;
+ }
+ for (Map.Entry<String, String> testEntry : metricEntry.getValue().entrySet()) {
+ String key = testEntry.getKey();
+ String value = testEntry.getValue();
+ if (key.startsWith(DEVICE_INFO_ERROR)) {
+ throw new TargetSetupError(String.format("[%s] %s", key, value));
+ }
+ if (key.startsWith(DEVICE_INFO_GENERIC)) {
+ buildInfo.addBuildAttribute(key, value);
+ }
+ }
+ }
+
+ getDeviceInfoFiles(device, buildInfo);
+ }
+
+ private void getDeviceInfoFiles(ITestDevice device, IBuildInfo buildInfo) {
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
+ try {
+ File resultDir = buildHelper.getResultDir();
+ if (mDestDir != null) {
+ resultDir = new File(resultDir, mDestDir);
+ }
+ resultDir.mkdirs();
+ if (!resultDir.isDirectory()) {
+ CLog.e(LOG_TAG, String.format("% is not a directory", resultDir.getAbsolutePath()));
+ return;
+ }
+ String resultPath = resultDir.getAbsolutePath();
+ pull(device, mSrcDir, resultPath);
+ } catch (FileNotFoundException fnfe) {
+ fnfe.printStackTrace();
+ }
+ }
+
+ private void pull(ITestDevice device, String src, String dest) {
+ String command = String.format("adb -s %s pull %s %s", device.getSerialNumber(), src, dest);
+ try {
+ Process p = Runtime.getRuntime().exec(new String[] {"/bin/bash", "-c", command});
+ if (p.waitFor() != 0) {
+ CLog.e(LOG_TAG, String.format("Failed to run %s", command));
+ }
+ } catch (Exception e) {
+ CLog.e(LOG_TAG, e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DynamicConfigPusher.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DynamicConfigPusher.java
new file mode 100644
index 0000000..8c455cd
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DynamicConfigPusher.java
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.util.DynamicConfig;
+import com.android.compatibility.common.util.DynamicConfigHandler;
+import com.android.ddmlib.Log;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetCleaner;
+import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.StreamUtil;
+
+import org.json.JSONException;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * Pushes dynamic config files from config repository
+ */
+@OptionClass(alias="dynamic-config-pusher")
+public class DynamicConfigPusher implements ITargetCleaner {
+ public enum TestTarget {
+ DEVICE,
+ HOST
+ }
+
+ private static final String LOG_TAG = DynamicConfigPusher.class.getSimpleName();
+
+ @Option(name = "cleanup", description = "Whether to clean up config files after test is done.")
+ private boolean mCleanup = true;
+
+ @Option(name="module-name", description = "Specify the module name")
+ private String mModuleName;
+
+ @Option(name = "target", description = "Specify the target, 'device' or 'host'")
+ private TestTarget mTarget;
+
+ @Option(name = "version-name", description = "Specify the version for override config")
+ private static String mVersion;
+
+
+ private String mFilePushed;
+
+ void setModuleName(String moduleName) {
+ mModuleName = moduleName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError, BuildError,
+ DeviceNotAvailableException {
+
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
+
+ File localConfigFile = null;
+ try {
+ localConfigFile = DynamicConfig.getConfigFile(buildHelper.getTestsDir(), mModuleName);
+ } catch (FileNotFoundException e) {
+ throw new TargetSetupError(
+ "Cannot get local dynamic config file from test directory", e);
+ }
+
+ String apfeConfigInJson = null;
+ String OriginUrl = buildHelper.getDynamicConfigUrl();
+
+ if (OriginUrl != null) {
+ try {
+ String requestUrl = OriginUrl
+ .replace("{module-name}", mModuleName).replace("{version-name}", mVersion);
+ java.net.URL request = new URL(requestUrl);
+ apfeConfigInJson = StreamUtil.getStringFromStream(request.openStream());
+ } catch (IOException e) {
+ LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG,
+ "Cannot download and parse json config from Url");
+ }
+ } else {
+ LogUtil.printLog(Log.LogLevel.INFO, LOG_TAG,
+ "Dynamic config override Url is not set");
+ }
+
+ File src = null;
+ try {
+ src = DynamicConfigHandler.getMergedDynamicConfigFile(
+ localConfigFile, apfeConfigInJson, mModuleName);
+ } catch (IOException | XmlPullParserException | JSONException e) {
+ throw new TargetSetupError("Cannot get merged dynamic config file", e);
+ }
+
+ switch (mTarget) {
+ case DEVICE:
+ String deviceDest = DynamicConfig.CONFIG_FOLDER_ON_DEVICE + src.getName();
+ if (!device.pushFile(src, deviceDest)) {
+ throw new TargetSetupError(String.format(
+ "Failed to push local '%s' to remote '%s'",
+ src.getAbsolutePath(), deviceDest));
+ } else {
+ mFilePushed = deviceDest;
+ buildHelper.addDynamicConfigFile(mModuleName, src);
+ }
+ break;
+
+ case HOST:
+ File storageDir = new File(DynamicConfig.CONFIG_FOLDER_ON_HOST);
+ if (!storageDir.exists()) storageDir.mkdir();
+ File hostDest = new File(DynamicConfig.CONFIG_FOLDER_ON_HOST + src.getName());
+ try {
+ FileUtil.copyFile(src, hostDest);
+ } catch (IOException e) {
+ throw new TargetSetupError(String.format("Failed to copy file from %s to %s",
+ src.getAbsolutePath(), hostDest.getAbsolutePath()), e);
+ }
+ mFilePushed = hostDest.getAbsolutePath();
+ buildHelper.addDynamicConfigFile(mModuleName, src);
+ break;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
+ throws DeviceNotAvailableException {
+ switch (mTarget) {
+ case DEVICE:
+ if (!(e instanceof DeviceNotAvailableException)
+ && mCleanup && mFilePushed != null) {
+ device.executeShellCommand("rm -r " + mFilePushed);
+ }
+ break;
+ case HOST:
+ new File(mFilePushed).delete();
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/FilePusher.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/FilePusher.java
new file mode 100644
index 0000000..70dc125
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/FilePusher.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.PushFilePreparer;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Pushes specified testing artifacts from Compatibility repository.
+ */
+@OptionClass(alias="file-pusher")
+public class FilePusher extends PushFilePreparer implements IAbiReceiver {
+
+ @Option(name = "append-bitness",
+ description = "Append the ABI's bitness to the filename.")
+ private boolean mAppendBitness = false;
+
+ private CompatibilityBuildHelper mBuildHelper = null;
+
+ private IAbi mAbi;
+
+ protected File getTestsDir(IBuildInfo buildInfo) throws FileNotFoundException {
+ if (mBuildHelper == null) {
+ mBuildHelper = new CompatibilityBuildHelper(buildInfo);
+ }
+ return mBuildHelper.getTestsDir();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public File resolveRelativeFilePath(IBuildInfo buildInfo, String fileName) {
+ try {
+ File f = new File(getTestsDir(buildInfo),
+ String.format("%s%s", fileName, mAppendBitness ? mAbi.getBitness() : ""));
+ CLog.logAndDisplay(LogLevel.INFO, "Copying from %s", f.getAbsolutePath());
+ return f;
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocationCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocationCheck.java
new file mode 100644
index 0000000..cea3136
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocationCheck.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+/**
+ * Checks that location is enabled for GPS or Network before running a compatibility test
+ */
+@OptionClass(alias="location-check")
+public class LocationCheck extends SettingsPreparer {
+
+ private static final String LOCATION_SETTING = "location_providers_allowed";
+
+ private static final String GPS = "gps";
+ private static final String NETWORK = "network";
+
+ private static final String GPS_FEATURE = "android.hardware.location.gps";
+ private static final String NETWORK_FEATURE = "android.hardware.location.network";
+
+
+ private boolean hasLocationFeature(ITestDevice device) throws DeviceNotAvailableException {
+ String adbFeatures = device.executeShellCommand("pm list features");
+ return (adbFeatures.contains(GPS_FEATURE) || adbFeatures.contains(NETWORK_FEATURE));
+ }
+
+ @Override
+ public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+
+ if (!hasLocationFeature(device)) {
+ return; // skip this precondition if required location feature is not present
+ }
+
+ mSettingName = LOCATION_SETTING;
+ mSettingType = SettingsPreparer.SettingType.SECURE;
+ mExpectedSettingValues.add(NETWORK);
+ mExpectedSettingValues.add(GPS);
+ mExpectedSettingValues.add(String.format("%s,%s", GPS, NETWORK));
+ mExpectedSettingValues.add(String.format("%s,%s", NETWORK, GPS));
+ mFailureMessage = "Location services must be enabled via GPS or Network in order to " +
+ "successfully run the test suite";
+ super.run(device, buildInfo);
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
new file mode 100644
index 0000000..5c94c27
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+/**
+ * An {@link ITargetPreparer} that performs checks and/or tasks to ensure the
+ * the device is ready to run the test suite.
+ */
+public abstract class PreconditionPreparer implements ITargetPreparer {
+
+ @Option(name = CompatibilityTest.SKIP_PRECONDITIONS_OPTION, description =
+ "Whether preconditions should be skipped")
+ private boolean mSkipPreconditions = false;
+
+ @Override
+ public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+ if (!mSkipPreconditions) {
+ run(device, buildInfo);
+ }
+ }
+
+ public abstract void run(ITestDevice device, IBuildInfo buildInfo)
+ throws TargetSetupError, BuildError, DeviceNotAvailableException;
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheck.java
new file mode 100644
index 0000000..5d2baa7
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheck.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.ddmlib.Log;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+/**
+ * Checks that a device property is as expected
+ */
+@OptionClass(alias="property-check")
+public class PropertyCheck extends PreconditionPreparer {
+
+ @Option(name = "property-name", description = "The name of the property to check",
+ mandatory = true)
+ protected String mPropertyName = null;
+
+ @Option(name = "expected-value", description = "The expected value of the property",
+ mandatory = true)
+ protected String mExpectedPropertyValue = null;
+
+ @Option(name = "throw-error",
+ description = "Whether to throw an error for an unexpected property value")
+ protected boolean mThrowError = false;
+
+ private static final String LOG_TAG = PropertyCheck.class.getSimpleName();
+
+ @Override
+ public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+ String propertyValue = device.getProperty(mPropertyName);
+ if (propertyValue == null) {
+ throw new TargetSetupError(String.format(
+ "Device property \"%s\" not found.", mPropertyName));
+ }
+
+ if (!mExpectedPropertyValue.equalsIgnoreCase(propertyValue)) {
+ String msg = String.format("Expected \"%s\" but found \"%s\" for property: %s",
+ mExpectedPropertyValue, propertyValue, mPropertyName);
+ // Handle unexpected property value with either exception or warning
+ if(mThrowError) {
+ throw new TargetSetupError(msg);
+ } else {
+ LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG, msg);
+ }
+ }
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ResultFilePuller.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ResultFilePuller.java
new file mode 100644
index 0000000..7b20997d
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ResultFilePuller.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetCleaner;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Pulls files from the device after a test run and puts them into the result folder.
+ */
+@OptionClass(alias="result-file-puller")
+public class ResultFilePuller implements ITargetCleaner {
+
+ private static final String LOG_TAG = ResultFilePuller.class.getSimpleName();
+
+ @Option(name="clear", description = "Whether to clear the src files and dirs before running the test")
+ private boolean mClearSrc = true;
+
+ @Option(name="src-file", description = "The file to copy to the results dir")
+ private List<String> mSrcFiles = new ArrayList<>();
+
+ @Option(name="src-dir", description = "The directory to copy to the results dir")
+ private List<String> mSrcDirs = new ArrayList<>();
+
+ @Option(name = "dest-dir", description = "The directory under the result to store the files")
+ private String mDestDir;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError, BuildError,
+ DeviceNotAvailableException {
+ if (mClearSrc) {
+ for (String file : mSrcFiles) {
+ delete(device, file);
+ }
+ for (String dir : mSrcDirs) {
+ delete(device, dir);
+ }
+ }
+ }
+
+ private void delete(ITestDevice device, String file) throws DeviceNotAvailableException {
+ device.executeShellCommand(String.format("rm -rf %s", file));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
+ throws DeviceNotAvailableException {
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
+ try {
+ File resultDir = buildHelper.getResultDir();
+ if (mDestDir != null) {
+ resultDir = new File(resultDir, mDestDir);
+ }
+ resultDir.mkdirs();
+ if (!resultDir.isDirectory()) {
+ CLog.e(LOG_TAG, String.format("% is not a directory", resultDir.getAbsolutePath()));
+ return;
+ }
+ String resultPath = resultDir.getAbsolutePath();
+ for (String file : mSrcFiles) {
+ pull(device, file, resultPath);
+ }
+ for (String dir : mSrcDirs) {
+ pull(device, dir, resultPath);
+ }
+ } catch (FileNotFoundException fnfe) {
+ fnfe.printStackTrace();
+ }
+ }
+
+ private void pull(ITestDevice device, String src, String dest) {
+ String command = String.format("adb -s %s pull %s %s", device.getSerialNumber(), src, dest);
+ try {
+ Process p = Runtime.getRuntime().exec(new String[] {"/bin/bash", "-c", command});
+ if (p.waitFor() != 0) {
+ CLog.e(LOG_TAG, String.format("Failed to run %s", command));
+ }
+ } catch (Exception e) {
+ CLog.e(LOG_TAG, e);
+ }
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java
new file mode 100644
index 0000000..f21ef39
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Checks that a given setting on the device is one of the given values
+ */
+@OptionClass(alias="settings-preparer")
+public class SettingsPreparer extends PreconditionPreparer {
+
+ public enum SettingType {
+ SECURE,
+ GLOBAL,
+ SYSTEM;
+ }
+
+ /* This option must be defined, but is not explicitly marked mandatory, as subclasses of
+ * the SettingsPreparer class can define mSettingName at runtime */
+ @Option(name = "device-setting", description = "The setting on the device to be checked")
+ protected String mSettingName = null;
+
+ /* This option must be defined, but is not explicitly marked mandatory, as subclasses of
+ * the SettingsPreparer class can define mSettingType at runtime */
+ @Option(name = "setting-type",
+ description = "If the setting is 'secure', 'global', or 'system'")
+ protected SettingType mSettingType = null;
+
+ @Option(name = "set-value", description = "The value to be set for the setting")
+ protected String mSetValue = null;
+
+ @Option(name = "expected-values", description = "The set of expected values of the setting")
+ protected List<String> mExpectedSettingValues = new ArrayList<String>();
+
+ @Option(name = "failure-message", description = "The text printed for an unexpected value")
+ protected String mFailureMessage = null;
+
+ @Override
+ public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+
+ if (mSettingName == null) {
+ throw new TargetSetupError("The \"device-setting\" option must be defined for the " +
+ "SettingsPreparer class");
+ }
+
+ if (mSettingType == null) {
+ throw new TargetSetupError("The \"setting-type\" option must be defined for the " +
+ "SettingsPreparer class");
+ }
+
+ /* At least one of the options "set-value" and "expected-values" must be set */
+ if (mSetValue == null && mExpectedSettingValues.isEmpty()) {
+ throw new TargetSetupError("At least one of the options \"set-value\" and " +
+ "\"expected-values\" must be set");
+ }
+
+ String shellCmdGet = (!mExpectedSettingValues.isEmpty()) ?
+ String.format("settings get %s %s", mSettingType, mSettingName) : "";
+ String shellCmdPut = (mSetValue != null) ?
+ String.format("settings put %s %s %s", mSettingType, mSettingName, mSetValue) : "";
+
+
+ /* Case 1: Both expected-values and set-value are given */
+ if (mSetValue != null && !mExpectedSettingValues.isEmpty()) {
+ // first ensure that the set-value given can be found in expected-values
+ if (!mExpectedSettingValues.contains(mSetValue)) {
+ throw new TargetSetupError(String.format(
+ "set-value for %s is %s, but value not found in expected-values: %s",
+ mSettingName, mSetValue, mExpectedSettingValues.toString()));
+ }
+ String currentSettingValue = device.executeShellCommand(shellCmdGet).trim();
+ // only change unexpected setting value
+ if (!mExpectedSettingValues.contains(currentSettingValue)) {
+ device.executeShellCommand(shellCmdPut);
+ }
+ return;
+ }
+
+ /* Case 2: Only set-value given */
+ if (mSetValue != null) {
+ device.executeShellCommand(shellCmdPut);
+ return;
+ }
+
+ /* Case 3: Only expected-values given */
+ String currentSettingValue = device.executeShellCommand(shellCmdGet).trim();
+ if (!mExpectedSettingValues.contains(currentSettingValue)) {
+ if (mFailureMessage == null) {
+ mFailureMessage = String.format(
+ "Device setting \"%s\" returned \"%s\", not found in %s",
+ mSettingName, currentSettingValue, mExpectedSettingValues.toString());
+ }
+ throw new TargetSetupError(mFailureMessage);
+ }
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/StayAwakePreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/StayAwakePreparer.java
new file mode 100644
index 0000000..9745179
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/StayAwakePreparer.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.util.Arrays;
+
+/**
+ * Modifies the 'Stay Awake' setting of the device, so that the device's screen stays on
+ * whenever charging via USB
+ */
+@OptionClass(alias="stay-awake-preparer")
+public class StayAwakePreparer extends SettingsPreparer {
+
+ private static final String STAY_AWAKE_SETTING = "stay_on_while_plugged_in";
+
+ /*
+ * Values that are appropriate for the "Stay Awake" setting while running compatibility tests:
+ * (the second bit must be 'on' to allow screen to stay awake while charging via USB)
+ * 2 - Stay awake while charging via USB
+ * 3 - Stay awake while changing via USB or AC
+ * 6 - Stay awake while charging via USB or Wireless
+ * 7 - Stay awake while charging via USB or AC or Wireless
+ */
+ private static final String[] STAY_AWAKE_VALUES = new String[] {"2", "3", "6", "7"};
+ private static final String DEFAULT_VALUE = "2";
+
+ @Override
+ public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+
+ mSettingName = STAY_AWAKE_SETTING;
+ mSettingType = SettingsPreparer.SettingType.GLOBAL;
+ mSetValue = DEFAULT_VALUE;
+ for (String value : STAY_AWAKE_VALUES) {
+ mExpectedSettingValues.add(value);
+ }
+ super.run(device, buildInfo);
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/TokenRequirement.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/TokenRequirement.java
new file mode 100644
index 0000000..54b6bc0
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/TokenRequirement.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An {@link ITargetPreparer} that allows a test module to specify tokens that a device must have
+ * to run the tests contained.
+ *
+ * A token is string that is required by a test module and given to a device by the user, they are
+ * used by the scheduler to ensure tests are scheduled on the correct devices. Eg if the user is
+ * sharding the innvocation across 10 devices, they will not want to put a SIM card in every device,
+ * instead they can use a single SIM card and use tokens to tell the scheduler which device should
+ * be used to run the SIM card tests.
+ */
+public class TokenRequirement implements ITargetPreparer {
+
+ @Option(name = "token", description = "The token a device must have to run this module")
+ private Set<String> mTokens = new HashSet<>();
+
+ @Override
+ public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+ throw new TargetSetupError("TokenRequirement is not expected to run");
+ }
+
+ /**
+ * @return the {@link Set} of tokens required by this module.
+ */
+ public Set<String> getTokens() {
+ return mTokens;
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java
new file mode 100644
index 0000000..0100969
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This preparer ensures that the device is connected to a network.
+ * The options "wifi-ssid" and "wifi-psk" allow users of the preparer to attempt connection
+ * to a network. If the options are provided, the preparer disconnects any existing network
+ * connection, and attempts to connect with the options provided.
+ *
+ * @throws TargetSetupError if device is not connected to a network and no options are given, or
+ * if the device fails to connect to the network specified in the options
+ */
+@OptionClass(alias="wifi-check")
+public class WifiCheck extends PreconditionPreparer {
+
+ private static final String WIFI_FEATURE = "android.hardware.wifi";
+
+ @Option(name = "wifi-ssid", description = "Name of the WiFi network with which to connect")
+ protected String mWifiSsid = null;
+
+ @Option(name = "wifi-psk",
+ description = "The WPA-PSK associated with the wifi-ssid option")
+ protected String mWifiPsk = null;
+
+ private boolean hasWifiFeature(ITestDevice device) throws DeviceNotAvailableException {
+ String pmFeatures = device.executeShellCommand("pm list features");
+ return pmFeatures.contains(WIFI_FEATURE);
+ }
+
+ @Override
+ public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+
+ if(!hasWifiFeature(device)) {
+ return; // skip this precondition check if device doesn't support wifi
+ }
+
+ if (mWifiSsid == null) { // no connection to create, check for existing connectivity
+ if (!device.checkConnectivity()) {
+ throw new TargetSetupError("Device has no network connection, no ssid provided");
+ }
+ } else { // network provided in options, attempt to create new connection
+ CLog.logAndDisplay(LogLevel.INFO, "Attempting connection to \"%s\"", mWifiSsid);
+ if (device.connectToWifiNetwork(mWifiSsid, mWifiPsk)) { // attempt connection
+ CLog.logAndDisplay(LogLevel.INFO, "Connection successful");
+ } else {
+ throw new TargetSetupError(String.format(
+ "Unable to connect to network \"%s\", some modules of CTS" +
+ "require an active network connection", mWifiSsid));
+ }
+ }
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/Abi.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/Abi.java
new file mode 100644
index 0000000..fab990e
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/Abi.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.tradefed.testtype.IAbi;
+
+/**
+ * A class representing an ABI.
+ *
+ * TODO(stuartscott): should be in TradeFed.
+ */
+public class Abi implements IAbi {
+
+ private final String mName;
+ private final String mBitness;
+
+ public Abi(String name, String bitness) {
+ mName = name;
+ mBitness = bitness;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getBitness() {
+ return mBitness;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return mName;
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
new file mode 100644
index 0000000..eff3006
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
@@ -0,0 +1,405 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.result.IInvocationResultRepo;
+import com.android.compatibility.common.tradefed.result.InvocationResultRepo;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.compatibility.common.util.ICaseResult;
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.IModuleResult;
+import com.android.compatibility.common.util.ITestResult;
+import com.android.compatibility.common.util.TestFilter;
+import com.android.compatibility.common.util.TestStatus;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.config.OptionCopier;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.IShardableTest;
+import com.android.tradefed.util.AbiFormatter;
+import com.android.tradefed.util.ArrayUtil;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A Test for running Compatibility Suites
+ */
+@OptionClass(alias = "compatibility")
+public class CompatibilityTest implements IDeviceTest, IShardableTest, IBuildReceiver {
+
+ public static final String INCLUDE_FILTER_OPTION = "include-filter";
+ public static final String EXCLUDE_FILTER_OPTION = "exclude-filter";
+ private static final String PLAN_OPTION = "plan";
+ private static final String MODULE_OPTION = "module";
+ private static final String TEST_OPTION = "test";
+ private static final String MODULE_ARG_OPTION = "module-arg";
+ private static final String TEST_ARG_OPTION = "test-arg";
+ public static final String RETRY_OPTION = "retry";
+ private static final String ABI_OPTION = "abi";
+ private static final String SHARD_OPTION = "shards";
+ public static final String SKIP_DEVICE_INFO_OPTION = "skip-device-info";
+ public static final String SKIP_PRECONDITIONS_OPTION = "skip-preconditions";
+ public static final String DEVICE_TOKEN_OPTION = "device-token";
+ private static final String URL = "dynamic-config-url";
+
+ private static final TestStatus[] RETRY_TEST_STATUS = new TestStatus[] {
+ TestStatus.FAIL,
+ TestStatus.NOT_EXECUTED
+ };
+
+ @Option(name = PLAN_OPTION,
+ description = "the test suite plan to run, such as \"everything\" or \"cts\"",
+ importance = Importance.ALWAYS)
+ private String mSuitePlan;
+
+ @Option(name = INCLUDE_FILTER_OPTION,
+ description = "the include module filters to apply.",
+ importance = Importance.ALWAYS)
+ private List<String> mIncludeFilters = new ArrayList<>();
+
+ @Option(name = EXCLUDE_FILTER_OPTION,
+ description = "the exclude module filters to apply.",
+ importance = Importance.ALWAYS)
+ private List<String> mExcludeFilters = new ArrayList<>();
+
+ @Option(name = MODULE_OPTION,
+ shortName = 'm',
+ description = "the test module to run.",
+ importance = Importance.IF_UNSET)
+ private String mModuleName = null;
+
+ @Option(name = TEST_OPTION,
+ shortName = 't',
+ description = "the test run.",
+ importance = Importance.IF_UNSET)
+ private String mTestName = null;
+
+ @Option(name = MODULE_ARG_OPTION,
+ description = "the arguments to pass to a module. The expected format is"
+ + "\"<module-name>:<arg-name>:<arg-value>\"",
+ importance = Importance.ALWAYS)
+ private List<String> mModuleArgs = new ArrayList<>();
+
+ @Option(name = TEST_ARG_OPTION,
+ description = "the arguments to pass to a test. The expected format is"
+ + "\"<test-class>:<arg-name>:<arg-value>\"",
+ importance = Importance.ALWAYS)
+ private List<String> mTestArgs = new ArrayList<>();
+
+ @Option(name = RETRY_OPTION,
+ shortName = 'r',
+ description = "retry a previous session.",
+ importance = Importance.IF_UNSET)
+ private Integer mRetrySessionId = null;
+
+ @Option(name = ABI_OPTION,
+ shortName = 'a',
+ description = "the abi to test.",
+ importance = Importance.IF_UNSET)
+ private String mAbiName = null;
+
+ @Option(name = SHARD_OPTION,
+ description = "split the modules up to run on multiple devices concurrently.")
+ private int mShards = 1;
+
+ @Option(name = URL,
+ description = "Specify the url for override config")
+ private String mURL;
+
+ @Option(name = SKIP_DEVICE_INFO_OPTION,
+ description = "Whether device info collection should be skipped")
+ private boolean mSkipDeviceInfo = false;
+
+ @Option(name = SKIP_PRECONDITIONS_OPTION,
+ description = "Whether preconditions should be skipped")
+ private boolean mSkipPreconditions = false;
+
+ @Option(name = DEVICE_TOKEN_OPTION,
+ description = "Holds the devices' tokens, used when scheduling tests that have"
+ + "prerequisits such as requiring a SIM card. Format is <serial>:<token>",
+ importance = Importance.ALWAYS)
+ private List<String> mDeviceTokens = new ArrayList<>();
+
+ @Option(name = "bugreport-on-failure",
+ description = "Take a bugreport on every test failure. " +
+ "Warning: can potentially use a lot of disk space.")
+ private boolean mBugReportOnFailure = false;
+
+ @Option(name = "logcat-on-failure",
+ description = "Take a logcat snapshot on every test failure.")
+ private boolean mLogcatOnFailure = false;
+
+ @Option(name = "screenshot-on-failure",
+ description = "Take a screenshot on every test failure.")
+ private boolean mScreenshotOnFailure = false;
+
+ private int mTotalShards;
+ private ITestDevice mDevice;
+ private IBuildInfo mBuild;
+ private CompatibilityBuildHelper mBuildHelper;
+
+ /**
+ * Create a new {@link CompatibilityTest} that will run the default list of
+ * modules.
+ */
+ public CompatibilityTest() {
+ this(1 /* totalShards */);
+ }
+
+ /**
+ * Create a new {@link CompatibilityTest} that will run a sublist of
+ * modules.
+ */
+ public CompatibilityTest(int totalShards) {
+ if (totalShards < 1) {
+ throw new IllegalArgumentException(
+ "Must be at least 1 shard. Given:" + totalShards);
+ }
+ mTotalShards = totalShards;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ITestDevice getDevice() {
+ return mDevice;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setDevice(ITestDevice device) {
+ mDevice = device;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mBuild = buildInfo;
+ mBuildHelper = new CompatibilityBuildHelper(mBuild);
+ mBuildHelper.init(mSuitePlan, mURL);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+ boolean isInitializer = false;
+ try {
+ IModuleRepo moduleRepo = ModuleRepo.getInstance();
+ // Synchronized so only one shard enters and sets up the moduleRepo. When the other
+ // shards enter after this, moduleRepo is already initialized so they dont do anything
+ synchronized (moduleRepo) {
+ if (!moduleRepo.isInitialized()) {
+ isInitializer = true;
+ setupFilters();
+ // Initialize the repository, {@link CompatibilityBuildHelper#getTestsDir} can
+ // throw a {@link FileNotFoundException}
+ moduleRepo.initialize(mTotalShards, mBuildHelper.getTestsDir(), getAbis(),
+ mDeviceTokens, mTestArgs, mModuleArgs, mIncludeFilters,
+ mExcludeFilters, mBuild);
+ }
+ }
+ // Get the tests to run in this shard
+ List<IModuleDef> modules = moduleRepo.getModules(getDevice().getSerialNumber());
+
+ listener = new FailureListener(listener, getDevice(), mBugReportOnFailure,
+ mLogcatOnFailure, mScreenshotOnFailure);
+ int moduleCount = modules.size();
+ CLog.logAndDisplay(LogLevel.INFO, "Starting %d module%s on %s", moduleCount,
+ (moduleCount > 1) ? "s" : "", mDevice.getSerialNumber());
+
+ // Set values and run preconditions
+ for (int i = 0; i < moduleCount; i++) {
+ IModuleDef module = modules.get(i);
+ module.setBuild(mBuild);
+ module.setDevice(mDevice);
+ module.prepare(mSkipPreconditions);
+ }
+ // Run the tests
+ for (int i = 0; i < moduleCount; i++) {
+ modules.get(i).run(listener);
+ }
+ } catch (DeviceNotAvailableException e) {
+ // Pass up
+ throw e;
+ } catch (FileNotFoundException | RuntimeException e) {
+ CLog.e(e);
+ } catch (Error e) {
+ CLog.e(e);
+ } finally {
+ if (isInitializer) {
+ ModuleRepo.tearDown();
+ }
+ }
+ }
+
+ /**
+ * Gets the set of ABIs supported by both Compatibility and the device under test
+ *
+ * @return The set of ABIs to run the tests on
+ * @throws DeviceNotAvailableException
+ */
+ Set<IAbi> getAbis() throws DeviceNotAvailableException {
+ Set<IAbi> abis = new HashSet<>();
+ for (String abi : AbiFormatter.getSupportedAbis(mDevice, "")) {
+ // Only test against ABIs supported by Compatibility, and if the
+ // --abi option was given, it must match.
+ if (AbiUtils.isAbiSupportedByCompatibility(abi)
+ && (mAbiName == null || mAbiName.equals(abi))) {
+ abis.add(new Abi(abi, AbiUtils.getBitness(abi)));
+ }
+ }
+ if (abis == null || abis.isEmpty()) {
+ if (mAbiName == null) {
+ throw new IllegalArgumentException("Could not get device's ABIs");
+ } else {
+ throw new IllegalArgumentException(String.format(
+ "Device %s doesn't support %s", mDevice.getSerialNumber(), mAbiName));
+ }
+ }
+ return abis;
+ }
+
+ /**
+ * Sets the include/exclude filters up based on if a module name was given or whether this is a
+ * retry run.
+ */
+ void setupFilters() {
+ if (mRetrySessionId != null) {
+ // We're retrying so clear the filters
+ mIncludeFilters.clear();
+ mExcludeFilters.clear();
+ mModuleName = null;
+ mTestName = null;
+ // Load the invocation result
+ IInvocationResultRepo repo;
+ IInvocationResult result = null;
+ try {
+ repo = new InvocationResultRepo(mBuildHelper.getResultsDir());
+ result = repo.getResult(mRetrySessionId);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ if (result == null) {
+ throw new IllegalArgumentException(String.format(
+ "Could not find session with id %d", mRetrySessionId));
+ }
+ // Append each test that failed or was not executed to the filters
+ for (IModuleResult module : result.getModules()) {
+ for (ICaseResult cr : module.getResults()) {
+ for (TestStatus status : RETRY_TEST_STATUS) {
+ for (ITestResult r : cr.getResults(status)) {
+ // Create the filter for the test to be run.
+ TestFilter filter = new TestFilter(
+ module.getAbi(), module.getName(), r.getFullName());
+ mIncludeFilters.add(filter.toString());
+ // Reset the result so that the test gets retried.
+ r.reset();
+ }
+ }
+ }
+ }
+ } else if (mModuleName != null) {
+ mIncludeFilters.clear();
+ try {
+ List<String> modules = ModuleRepo.getModuleNamesMatching(
+ mBuildHelper.getTestsDir(), mModuleName);
+ if (modules.size() == 0) {
+ throw new IllegalArgumentException(
+ String.format("No modules found matching %s", mModuleName));
+ } else if (modules.size() > 1) {
+ throw new IllegalArgumentException(String.format(
+ "Multiple modules found matching %s:\n%s\nWhich one did you mean?\n",
+ mModuleName, ArrayUtil.join("\n", modules)));
+ } else {
+ String module = modules.get(0);
+ mIncludeFilters.add(new TestFilter(mAbiName, module, mTestName).toString());
+ if (mTestName != null) {
+ // We're filtering it down to the lowest level, no need to give excludes
+ mExcludeFilters.clear();
+ } else {
+ // If we dont specify a test name, we only want to run this module with any
+ // previous exclusions as long as they dont exclude the whole module.
+ List<String> excludeFilters = new ArrayList<>();
+ for (String excludeFilter : mExcludeFilters) {
+ TestFilter filter = TestFilter.createFrom(excludeFilter);
+ String name = filter.getName();
+ // Add the filter if it applies to this module, and it has a test name
+ if (module.equals(name) && filter.getTest() != null) {
+ excludeFilters.add(excludeFilter);
+ }
+ }
+ mExcludeFilters = excludeFilters;
+ }
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ } else {
+ // If a module has an arg, assume it's included
+ for (String arg : mModuleArgs) {
+ mIncludeFilters.add(arg.split(":")[0]);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Collection<IRemoteTest> split() {
+ if (mShards <= 1) {
+ return null;
+ }
+
+ List<IRemoteTest> shardQueue = new LinkedList<>();
+ for (int i = 0; i < mShards; i++) {
+ CompatibilityTest test = new CompatibilityTest(mShards);
+ OptionCopier.copyOptionsNoThrow(this, test);
+ // Set the shard count because the copy option on the previous line
+ // copies over the mShard value
+ test.mShards = 0;
+ shardQueue.add(test);
+ }
+
+ return shardQueue;
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/FailureListener.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/FailureListener.java
new file mode 100644
index 0000000..c3509d1
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/FailureListener.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.InputStreamSource;
+import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.ResultForwarder;
+import com.android.tradefed.util.RunUtil;
+
+public class FailureListener extends ResultForwarder {
+
+ private static final int MAX_LOGCAT_BYTES = 500 * 1024; // 500K
+
+ private ITestDevice mDevice;
+ private boolean mBugReportOnFailure;
+ private boolean mLogcatOnFailure;
+ private boolean mScreenshotOnFailure;
+
+ public FailureListener(ITestInvocationListener listener, ITestDevice device,
+ boolean bugReportOnFailure, boolean logcatOnFailure, boolean screenshotOnFailure) {
+ super(listener);
+ mDevice = device;
+ mBugReportOnFailure = bugReportOnFailure;
+ mLogcatOnFailure = logcatOnFailure;
+ mScreenshotOnFailure = screenshotOnFailure;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testFailed(TestIdentifier test, String trace) {
+ super.testFailed(test, trace);
+ CLog.i("FailureListener.testFailed %s %b %b %b", test.toString(), mBugReportOnFailure, mLogcatOnFailure, mScreenshotOnFailure);
+ if (mBugReportOnFailure) {
+ InputStreamSource bugSource = mDevice.getBugreport();
+ super.testLog(String.format("%s-bugreport", test.toString()), LogDataType.BUGREPORT,
+ bugSource);
+ bugSource.cancel();
+ }
+ if (mLogcatOnFailure) {
+ // sleep 2s to ensure test failure stack trace makes it into logcat capture
+ RunUtil.getDefault().sleep(2 * 1000);
+ InputStreamSource logSource = mDevice.getLogcat(MAX_LOGCAT_BYTES);
+ super.testLog(String.format("%s-logcat", test.toString()), LogDataType.LOGCAT,
+ logSource);
+ logSource.cancel();
+ }
+ if (mScreenshotOnFailure) {
+ try {
+ InputStreamSource screenSource = mDevice.getScreenshot();
+ super.testLog(String.format("%s-screenshot", test.toString()), LogDataType.PNG,
+ screenSource);
+ screenSource.cancel();
+ } catch (DeviceNotAvailableException e) {
+ CLog.e(e);
+ CLog.e("Device %s became unavailable while capturing screenshot",
+ mDevice.getSerialNumber());
+ }
+ }
+ }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
new file mode 100644
index 0000000..931ed1f
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.IRuntimeHintProvider;
+
+import java.util.Set;
+
+/**
+ * Container for Compatibility test info.
+ */
+public interface IModuleDef extends Comparable<IModuleDef>, IBuildReceiver, IDeviceTest,
+ IRemoteTest, IRuntimeHintProvider {
+
+ /**
+ * @return The name of this module.
+ */
+ String getName();
+
+ /**
+ * @return a {@link String} to uniquely identify this module.
+ */
+ String getId();
+
+ /**
+ * @return the abi of this test module.
+ */
+ IAbi getAbi();
+
+ /**
+ * @return the {@link Set} of tokens a device must have in order to run this module.
+ */
+ Set<String> getTokens();
+
+ /**
+ * @return the {@link IRemoteTest} that runs the tests.
+ */
+ IRemoteTest getTest();
+
+ /**
+ * Adds a filter to include a specific test
+ *
+ * @param name the name of the test. Can be <package>, <package>.<class>,
+ * <package>.<class>#<method> or <native_name>
+ */
+ void addIncludeFilter(String name);
+
+ /**
+ * Adds a filter to exclude a specific test
+ *
+ * @param name the name of the test. Can be <package>, <package>.<class>,
+ * <package>.<class>#<method> or <native_name>
+ */
+ void addExcludeFilter(String name);
+
+ /**
+ * Runs the module's precondition checks and setup tasks.
+ */
+ void prepare(boolean skipPrep) throws DeviceNotAvailableException;
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleRepo.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleRepo.java
new file mode 100644
index 0000000..24e1dec
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleRepo.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.testtype.IAbi;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Interface for accessing tests from the Compatibility repository.
+ */
+public interface IModuleRepo {
+
+ /**
+ * @return true if this repository has been initialized.
+ */
+ boolean isInitialized();
+
+ /**
+ * Initializes the repository.
+ */
+ void initialize(int shards, File testsDir, Set<IAbi> abis, List<String> deviceTokens,
+ List<String> testArgs, List<String> moduleArgs, List<String> mIncludeFilters,
+ List<String> mExcludeFilters, IBuildInfo buildInfo);
+
+ /**
+ * @return a {@link Map} of all modules to run on the device referenced by the given serial.
+ */
+ List<IModuleDef> getModules(String serial);
+
+ /**
+ * @return the number of shards this repo is initialized for.
+ */
+ int getNumberOfShards();
+
+ /**
+ * @return the maximum number of modules a shard will run.
+ */
+ int getModulesPerShard();
+
+ /**
+ * @return the {@link Map} of device serials to tokens.
+ */
+ Map<String, Set<String>> getDeviceTokens();
+
+ /**
+ * @return the {@link Set} of device serials that have taken their workload.
+ */
+ Set<String> getSerials();
+
+ /**
+ * @return the small modules that don't have tokens but have not been assigned to a device.
+ */
+ List<IModuleDef> getSmallModules();
+
+ /**
+ * @return the medium modules that don't have tokens but have not been assigned to a device.
+ */
+ List<IModuleDef> getMediumModules();
+
+ /**
+ * @return the large modules that don't have tokens but have not been assigned to a device.
+ */
+ List<IModuleDef> getLargeModules();
+
+ /**
+ * @return the modules which have token and have not been assigned to a device.
+ */
+ List<IModuleDef> getTokenModules();
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/JarHostTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/JarHostTest.java
new file mode 100644
index 0000000..ba4c6c3
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/JarHostTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
+import com.android.tradefed.testtype.HostTest;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.IRuntimeHintProvider;
+import com.android.tradefed.util.TimeVal;
+
+import junit.framework.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Test runner for host-side JUnit tests.
+ */
+public class JarHostTest extends HostTest implements IAbiReceiver, IBuildReceiver,
+ IRuntimeHintProvider {
+
+ @Option(name="jar", description="The jars containing the JUnit test class to run.",
+ importance = Importance.IF_UNSET)
+ private Set<String> mJars = new HashSet<>();
+
+ @Option(name = "runtime-hint",
+ isTimeVal = true,
+ description="The hint about the test's runtime.")
+ private long mRuntimeHint = 60000;// 1 minute
+
+ private IAbi mAbi;
+ private IBuildInfo mBuild;
+ private CompatibilityBuildHelper mHelper;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo build) {
+ mBuild = build;
+ mHelper = new CompatibilityBuildHelper(build);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getRuntimeHint() {
+ return mRuntimeHint;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected List<Class<?>> getClasses() throws IllegalArgumentException {
+ List<Class<?>> classes = super.getClasses();
+ for (String jarName : mJars) {
+ JarFile jarFile = null;
+ try {
+ File file = new File(mHelper.getTestsDir(), jarName);
+ jarFile = new JarFile(file);
+ Enumeration<JarEntry> e = jarFile.entries();
+ URL[] urls = {
+ new URL(String.format("jar:file:%s!/", file.getAbsolutePath()))
+ };
+ URLClassLoader cl = URLClassLoader.newInstance(urls);
+
+ while (e.hasMoreElements()) {
+ JarEntry je = e.nextElement();
+ if (je.isDirectory() || !je.getName().endsWith(".class")
+ || je.getName().contains("$")) {
+ continue;
+ }
+ String className = getClassName(je.getName());
+ try {
+ Class<?> cls = cl.loadClass(className);
+ int modifiers = cls.getModifiers();
+ if ((IRemoteTest.class.isAssignableFrom(cls)
+ || Test.class.isAssignableFrom(cls))
+ && !Modifier.isStatic(modifiers)
+ && !Modifier.isPrivate(modifiers)
+ && !Modifier.isProtected(modifiers)
+ && !Modifier.isInterface(modifiers)
+ && !Modifier.isAbstract(modifiers)) {
+ classes.add(cls);
+ }
+ } catch (ClassNotFoundException cnfe) {
+ throw new IllegalArgumentException(
+ String.format("Cannot find test class %s", className));
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (jarFile != null) {
+ try {
+ jarFile.close();
+ } catch (IOException e) {
+ // Ignored
+ }
+ }
+ }
+ }
+ return classes;
+ }
+
+ private static String getClassName(String name) {
+ // -6 because of .class
+ return name.substring(0, name.length() - 6).replace('/', '.');
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Object loadObject(Class<?> classObj) throws IllegalArgumentException {
+ Object object = super.loadObject(classObj);
+ if (object instanceof IAbiReceiver) {
+ ((IAbiReceiver) object).setAbi(mAbi);
+ }
+ if (object instanceof IBuildReceiver) {
+ ((IBuildReceiver) object).setBuild(mBuild);
+ }
+ return object;
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
new file mode 100644
index 0000000..e24828d
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.compatibility.common.tradefed.result.IModuleListener;
+import com.android.compatibility.common.tradefed.result.ModuleListener;
+import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
+import com.android.compatibility.common.tradefed.targetprep.TokenRequirement;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.ConfigurationException;
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetCleaner;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.IRuntimeHintProvider;
+import com.android.tradefed.testtype.ITestFilterReceiver;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Container for Compatibility test module info.
+ */
+public class ModuleDef implements IModuleDef {
+
+ private final String mId;
+ private final String mName;
+ private final IAbi mAbi;
+ private final Set<String> mTokens = new HashSet<>();
+ private IRemoteTest mTest = null;
+ private List<ITargetPreparer> mPreconditions = new ArrayList<>();
+ private List<ITargetPreparer> mPreparers = new ArrayList<>();
+ private List<ITargetCleaner> mCleaners = new ArrayList<>();
+ private IBuildInfo mBuild;
+ private ITestDevice mDevice;
+ private List<String> mIncludeFilters = new ArrayList<>();
+ private List<String> mExcludeFilters = new ArrayList<>();
+
+ public ModuleDef(String name, IAbi abi, IRemoteTest test,
+ List<ITargetPreparer> preparers) {
+ mId = AbiUtils.createId(abi.getName(), name);
+ mName = name;
+ mAbi = abi;
+ mTest = test;
+ for (ITargetPreparer preparer : preparers) {
+ // Separate preconditions from target preparers.
+ if (preparer instanceof PreconditionPreparer) {
+ mPreconditions.add(preparer);
+ } else if (preparer instanceof TokenRequirement) {
+ mTokens.addAll(((TokenRequirement) preparer).getTokens());
+ } else {
+ mPreparers.add(preparer);
+ }
+ if (preparer instanceof ITargetCleaner) {
+ mCleaners.add((ITargetCleaner) preparer);
+ }
+ }
+ // Reverse cleaner order
+ Collections.reverse(mCleaners);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return mId;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IAbi getAbi() {
+ return mAbi;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<String> getTokens() {
+ return mTokens;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getRuntimeHint() {
+ if (mTest instanceof IRuntimeHintProvider) {
+ return ((IRuntimeHintProvider) mTest).getRuntimeHint();
+ }
+ return TimeUnit.MINUTES.toMillis(1); // Default 1 minute.
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IRemoteTest getTest() {
+ return mTest;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addIncludeFilter(String filter) {
+ mIncludeFilters.add(filter);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addExcludeFilter(String filter) {
+ mExcludeFilters.add(filter);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(IModuleDef moduleDef) {
+ return getName().compareTo(moduleDef.getName());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo build) {
+ mBuild = build;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ITestDevice getDevice() {
+ return mDevice;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setDevice(ITestDevice device) {
+ mDevice = device;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+ IModuleListener moduleListener = new ModuleListener(this, listener);
+
+ // Setup
+ for (ITargetPreparer preparer : mPreparers) {
+ CLog.d("Preparer: %s", preparer.getClass().getSimpleName());
+ if (preparer instanceof IAbiReceiver) {
+ ((IAbiReceiver) preparer).setAbi(mAbi);
+ }
+ try {
+ preparer.setUp(mDevice, mBuild);
+ } catch (BuildError e) {
+ // This should only happen for flashing new build
+ CLog.e("Unexpected BuildError from precondition: %s",
+ preparer.getClass().getCanonicalName());
+ } catch (TargetSetupError e) {
+ // log precondition class then rethrow & let caller handle
+ CLog.e("TargetSetupError in precondition: %s",
+ preparer.getClass().getCanonicalName());
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ CLog.d("Test: %s", mTest.getClass().getSimpleName());
+ if (mTest instanceof IAbiReceiver) {
+ ((IAbiReceiver) mTest).setAbi(mAbi);
+ }
+ if (mTest instanceof IBuildReceiver) {
+ ((IBuildReceiver) mTest).setBuild(mBuild);
+ }
+ if (mTest instanceof IDeviceTest) {
+ ((IDeviceTest) mTest).setDevice(mDevice);
+ }
+ if (mTest instanceof ITestFilterReceiver) {
+ ((ITestFilterReceiver) mTest).addAllIncludeFilters(mIncludeFilters);
+ ((ITestFilterReceiver) mTest).addAllExcludeFilters(mExcludeFilters);
+ }
+ mTest.run(moduleListener);
+
+ // Tear down
+ for (ITargetCleaner cleaner : mCleaners) {
+ CLog.d("Cleaner: %s", cleaner.getClass().getSimpleName());
+ cleaner.tearDown(mDevice, mBuild, null);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void prepare(boolean skipPrep) throws DeviceNotAvailableException {
+ for (ITargetPreparer preparer : mPreconditions) {
+ CLog.d("Preparer: %s", preparer.getClass().getSimpleName());
+ if (preparer instanceof IAbiReceiver) {
+ ((IAbiReceiver) preparer).setAbi(mAbi);
+ }
+ setOption(preparer, CompatibilityTest.SKIP_PRECONDITIONS_OPTION,
+ Boolean.toString(skipPrep));
+ try {
+ preparer.setUp(mDevice, mBuild);
+ } catch (BuildError e) {
+ // This should only happen for flashing new build
+ CLog.e("Unexpected BuildError from precondition: %s",
+ preparer.getClass().getCanonicalName());
+ } catch (TargetSetupError e) {
+ // log precondition class then rethrow & let caller handle
+ CLog.e("TargetSetupError in precondition: %s",
+ preparer.getClass().getCanonicalName());
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private void setOption(Object target, String option, String value) {
+ try {
+ OptionSetter setter = new OptionSetter(target);
+ setter.setOptionValue(option, value);
+ } catch (ConfigurationException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
new file mode 100644
index 0000000..5b6606c
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
@@ -0,0 +1,526 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.compatibility.common.util.TestFilter;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.ConfigurationException;
+import com.android.tradefed.config.ConfigurationFactory;
+import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.config.IConfigurationFactory;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.IShardableTest;
+import com.android.tradefed.util.TimeUtil;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Retrieves Compatibility test module definitions from the repository.
+ */
+public class ModuleRepo implements IModuleRepo {
+
+ private static final String CONFIG_EXT = ".config";
+ private static final long SMALL_TEST = TimeUnit.MINUTES.toMillis(2); // Small tests < 2mins
+ private static final long MEDIUM_TEST = TimeUnit.MINUTES.toMillis(10); // Medium tests < 10mins
+
+ static IModuleRepo sInstance;
+
+ private int mShards;
+ private int mModulesPerShard;
+ private int mSmallModulesPerShard;
+ private int mMediumModulesPerShard;
+ private int mLargeModulesPerShard;
+ private int mModuleCount = 0;
+ private Set<String> mSerials = new HashSet<>();
+ private Map<String, Set<String>> mDeviceTokens = new HashMap<>();
+ private Map<String, Map<String, String>> mTestArgs = new HashMap<>();
+ private Map<String, Map<String, String>> mModuleArgs = new HashMap<>();
+ private boolean mIncludeAll;
+ private Map<String, List<TestFilter>> mIncludeFilters = new HashMap<>();
+ private Map<String, List<TestFilter>> mExcludeFilters = new HashMap<>();
+ private IConfigurationFactory mConfigFactory = ConfigurationFactory.getInstance();
+
+ private volatile boolean mInitialized = false;
+
+ // Holds all the small tests waiting to be run.
+ private List<IModuleDef> mSmallModules = new ArrayList<>();
+ // Holds all the medium tests waiting to be run.
+ private List<IModuleDef> mMediumModules = new ArrayList<>();
+ // Holds all the large tests waiting to be run.
+ private List<IModuleDef> mLargeModules = new ArrayList<>();
+ // Holds all the tests with tokens waiting to be run. Meaning the DUT must have a specific token.
+ private List<IModuleDef> mTokenModules = new ArrayList<>();
+
+ public static IModuleRepo getInstance() {
+ if (sInstance == null) {
+ sInstance = new ModuleRepo();
+ }
+ return sInstance;
+ }
+
+ public static void tearDown() {
+ sInstance = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getNumberOfShards() {
+ return mShards;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getModulesPerShard() {
+ return mModulesPerShard;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Map<String, Set<String>> getDeviceTokens() {
+ return mDeviceTokens;
+ }
+
+ /**
+ * A {@link FilenameFilter} to find all modules in a directory who match the given pattern.
+ */
+ public static class NameFilter implements FilenameFilter {
+
+ private String mPattern;
+
+ public NameFilter(String pattern) {
+ mPattern = pattern;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.contains(mPattern) && name.endsWith(CONFIG_EXT);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<String> getSerials() {
+ return mSerials;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<IModuleDef> getSmallModules() {
+ return mSmallModules;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<IModuleDef> getMediumModules() {
+ return mMediumModules;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<IModuleDef> getLargeModules() {
+ return mLargeModules;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<IModuleDef> getTokenModules() {
+ return mTokenModules;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isInitialized() {
+ return mInitialized;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void initialize(int shards, File testsDir, Set<IAbi> abis, List<String> deviceTokens,
+ List<String> testArgs, List<String> moduleArgs, List<String> includeFilters,
+ List<String> excludeFilters, IBuildInfo buildInfo) {
+ mInitialized = true;
+ mShards = shards;
+ for (String line : deviceTokens) {
+ String[] parts = line.split(":");
+ if (parts.length == 2) {
+ String key = parts[0];
+ String value = parts[1];
+ Set<String> list = mDeviceTokens.get(key);
+ if (list == null) {
+ list = new HashSet<>();
+ mDeviceTokens.put(key, list);
+ }
+ list.add(value);
+ } else {
+ throw new IllegalArgumentException(
+ String.format("Could not parse device token: %s", line));
+ }
+ }
+ putArgs(testArgs, mTestArgs);
+ putArgs(moduleArgs, mModuleArgs);
+ mIncludeAll = includeFilters.isEmpty();
+ // Include all the inclusions
+ addFilters(includeFilters, mIncludeFilters, abis);
+ // Exclude all the exclusions
+ addFilters(excludeFilters, mExcludeFilters, abis);
+
+ File[] configFiles = testsDir.listFiles(new ConfigFilter());
+ for (File configFile : configFiles) {
+ final String name = configFile.getName().replace(CONFIG_EXT, "");
+ final String[] pathArg = new String[] { configFile.getAbsolutePath() };
+ try {
+ // Invokes parser to process the test module config file
+ // Need to generate a different config for each ABI as we cannot guarantee the
+ // configs are idempotent. This however means we parse the same file multiple times
+ for (IAbi abi : abis) {
+ IConfiguration config = mConfigFactory.createConfigurationFromArgs(pathArg);
+ String id = AbiUtils.createId(abi.getName(), name);
+ {
+ Map<String, String> args = new HashMap<>();
+ if (mModuleArgs.containsKey(name)) {
+ args.putAll(mModuleArgs.get(name));
+ }
+ if (mModuleArgs.containsKey(id)) {
+ args.putAll(mModuleArgs.get(id));
+ }
+ if (args != null && args.size() > 0) {
+ for (Entry<String, String> entry : args.entrySet()) {
+ config.injectOptionValue(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ List<IRemoteTest> tests = config.getTests();
+ for (IRemoteTest test : tests) {
+ String className = test.getClass().getName();
+ Map<String, String> args = new HashMap<>();
+ if (mTestArgs.containsKey(className)) {
+ args.putAll(mTestArgs.get(className));
+ }
+ if (args != null && args.size() > 0) {
+ for (Entry<String, String> entry : args.entrySet()) {
+ config.injectOptionValue(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ List<IRemoteTest> shardedTests = tests;
+ if (mShards > 1) {
+ shardedTests = splitShardableTests(tests, buildInfo);
+ }
+ for (IRemoteTest test : shardedTests) {
+ if (test instanceof IBuildReceiver) {
+ ((IBuildReceiver)test).setBuild(buildInfo);
+ }
+ addModuleDef(name, abi, test, pathArg);
+ }
+ }
+ } catch (ConfigurationException e) {
+ throw new RuntimeException(String.format("error parsing config file: %s",
+ configFile.getName()), e);
+ }
+ }
+ mModulesPerShard = mModuleCount / shards;
+ if (mModuleCount % shards != 0) {
+ mModulesPerShard++; // Round up
+ }
+ mSmallModulesPerShard = mSmallModules.size() / shards;
+ mMediumModulesPerShard = mMediumModules.size() / shards;
+ mLargeModulesPerShard = mLargeModules.size() / shards;
+ }
+
+ private static List<IRemoteTest> splitShardableTests(List<IRemoteTest> tests,
+ IBuildInfo buildInfo) {
+ ArrayList<IRemoteTest> shardedList = new ArrayList<>(tests.size());
+ for (IRemoteTest test : tests) {
+ if (test instanceof IShardableTest) {
+ if (test instanceof IBuildReceiver) {
+ ((IBuildReceiver)test).setBuild(buildInfo);
+ }
+ shardedList.addAll(((IShardableTest)test).split());
+ } else {
+ shardedList.add(test);
+ }
+ }
+ return shardedList;
+ }
+
+ private static void addFilters(List<String> stringFilters,
+ Map<String, List<TestFilter>> filters, Set<IAbi> abis) {
+ for (String filterString : stringFilters) {
+ TestFilter filter = TestFilter.createFrom(filterString);
+ String abi = filter.getAbi();
+ if (abi == null) {
+ for (IAbi a : abis) {
+ addFilter(a.getName(), filter, filters);
+ }
+ } else {
+ addFilter(abi, filter, filters);
+ }
+ }
+ }
+
+ private static void addFilter(String abi, TestFilter filter,
+ Map<String, List<TestFilter>> filters) {
+ getFilter(filters, AbiUtils.createId(abi, filter.getName())).add(filter);
+ }
+
+ private static List<TestFilter> getFilter(Map<String, List<TestFilter>> filters, String id) {
+ List<TestFilter> fs = filters.get(id);
+ if (fs == null) {
+ fs = new ArrayList<>();
+ filters.put(id, fs);
+ }
+ return fs;
+ }
+
+ private void addModuleDef(String name, IAbi abi, IRemoteTest test,
+ String[] configPaths) throws ConfigurationException {
+ // Invokes parser to process the test module config file
+ IConfiguration config = mConfigFactory.createConfigurationFromArgs(configPaths);
+ addModuleDef(new ModuleDef(name, abi, test, config.getTargetPreparers()));
+ }
+
+ private void addModuleDef(IModuleDef moduleDef) {
+ String id = moduleDef.getId();
+ boolean includeModule = mIncludeAll;
+ for (TestFilter include : getFilter(mIncludeFilters, id)) {
+ String test = include.getTest();
+ if (test != null) {
+ // We're including a subset of tests
+ moduleDef.addIncludeFilter(test);
+ }
+ includeModule = true;
+ }
+ for (TestFilter exclude : getFilter(mExcludeFilters, id)) {
+ String test = exclude.getTest();
+ if (test != null) {
+ // Excluding a subset of tests, so keep module but give filter
+ moduleDef.addExcludeFilter(test);
+ } else {
+ // Excluding all tests in the module so just remove the whole thing
+ includeModule = false;
+ }
+ }
+ if (includeModule) {
+ Set<String> tokens = moduleDef.getTokens();
+ if (tokens != null && !tokens.isEmpty()) {
+ mTokenModules.add(moduleDef);
+ } else if (moduleDef.getRuntimeHint() < SMALL_TEST) {
+ mSmallModules.add(moduleDef);
+ } else if (moduleDef.getRuntimeHint() < MEDIUM_TEST) {
+ mMediumModules.add(moduleDef);
+ } else {
+ mLargeModules.add(moduleDef);
+ }
+ mModuleCount++;
+ }
+ }
+
+ /**
+ * A {@link FilenameFilter} to find all the config files in a directory.
+ */
+ public static class ConfigFilter implements FilenameFilter {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(CONFIG_EXT);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized List<IModuleDef> getModules(String serial) {
+ Set<String> tokens = mDeviceTokens.get(serial);
+ List<IModuleDef> modules = new ArrayList<>(mModulesPerShard);
+ getModulesWithTokens(tokens, modules);
+ getModules(modules);
+ long estimatedTime = 0;
+ for (IModuleDef def : modules) {
+ estimatedTime += def.getRuntimeHint();
+ }
+ mSerials.add(serial);
+ if (mSerials.size() == mShards) {
+ // All shards have been given their workload.
+ if (!mTokenModules.isEmpty()) {
+ Set<String> deviceTokens = mDeviceTokens.keySet();
+ Set<String> moduleTokens = new HashSet<>();
+ for (IModuleDef module : mTokenModules) {
+ moduleTokens.addAll(module.getTokens());
+ }
+ StringBuilder sb = new StringBuilder("Not all modules could be scheduled.");
+ for (String token : moduleTokens) {
+ if (!deviceTokens.contains(token)) {
+ sb.append("\nNo devices found with token: ");
+ sb.append(token);
+ }
+ }
+ sb.append("\nDeclare device tokens with \"--device-token <serial>:<token>\"");
+ throw new IllegalArgumentException(sb.toString());
+ }
+ if (!mLargeModules.isEmpty()) {
+ throw new IllegalArgumentException("Couldn't schedule: " + mLargeModules);
+ }
+ if (!mMediumModules.isEmpty()) {
+ throw new IllegalArgumentException("Couldn't schedule: " + mMediumModules);
+ }
+ if (!mSmallModules.isEmpty()) {
+ throw new IllegalArgumentException("Couldn't schedule: " + mSmallModules);
+ }
+ }
+ Collections.sort(modules, new RuntimeHintComparator());
+ CLog.logAndDisplay(LogLevel.INFO, String.format(
+ "%s running %s modules, expected to complete in %s",
+ serial, modules.size(), TimeUtil.formatElapsedTime(estimatedTime)));
+ return modules;
+ }
+
+ /**
+ * Iterates through the remaining tests that require tokens and if the device has all the
+ * required tokens it will queue that module to run on that device, else the module gets put
+ * back into the list.
+ */
+ private void getModulesWithTokens(Set<String> tokens, List<IModuleDef> modules) {
+ if (tokens != null) {
+ List<IModuleDef> copy = mTokenModules;
+ mTokenModules = new ArrayList<>();
+ for (IModuleDef module : copy) {
+ // If a device has all the tokens required by the module then it can run it.
+ if (tokens.containsAll(module.getTokens())) {
+ modules.add(module);
+ } else {
+ mTokenModules.add(module);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds count modules that do not require tokens, to run on a device.
+ */
+ private void getModules(List<IModuleDef> modules) {
+ // Take the normal share of modules unless the device already has token modules.
+ takeModule(mSmallModules, modules, mSmallModulesPerShard - modules.size());
+ takeModule(mMediumModules, modules, mMediumModulesPerShard);
+ takeModule(mLargeModules, modules, mLargeModulesPerShard);
+ // If one bucket runs out, take from any of the others.
+ boolean success = true;
+ while (success && modules.size() < mModulesPerShard) {
+ // Take modules from the buckets until it has enough, or there are no more modules.
+ success = takeModule(mSmallModules, modules, 1)
+ || takeModule(mMediumModules, modules, 1)
+ || takeModule(mLargeModules, modules, 1);
+ }
+ }
+
+ /**
+ * Takes count modules from the first list and move it to the second.
+ */
+ private static boolean takeModule(
+ List<IModuleDef> source, List<IModuleDef> destination, int count) {
+ if (source.isEmpty()) {
+ return false;
+ }
+ if (count > source.size()) {
+ count = source.size();
+ }
+ for (int i = 0; i < count; i++) {
+ destination.add(source.remove(source.size() - 1));// Take from the end of the arraylist.
+ }
+ return true;
+ }
+
+ /**
+ * @return the {@link List} of modules whose name contains the given pattern.
+ */
+ public static List<String> getModuleNamesMatching(File directory, String pattern) {
+ String[] names = directory.list(new NameFilter(pattern));
+ List<String> modules = new ArrayList<String>(names.length);
+ for (String name : names) {
+ int index = name.indexOf(CONFIG_EXT);
+ if (index > 0) {
+ modules.add(name.substring(0, index));
+ }
+ }
+ return modules;
+ }
+
+ private static void putArgs(List<String> args, Map<String, Map<String, String>> argsMap) {
+ for (String arg : args) {
+ String[] parts = arg.split(":");
+ String target = parts[0];
+ String key = parts[1];
+ String value = parts[2];
+ Map<String, String> map = argsMap.get(target);
+ if (map == null) {
+ map = new HashMap<>();
+ argsMap.put(target, map);
+ }
+ map.put(key, value);
+ }
+ }
+
+ private static class RuntimeHintComparator implements Comparator<IModuleDef> {
+
+ @Override
+ public int compare(IModuleDef def1, IModuleDef def2) {
+ return (int) Math.signum(def2.getRuntimeHint() - def1.getRuntimeHint());
+ }
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/NoOpTestInvocationListener.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/NoOpTestInvocationListener.java
new file mode 100644
index 0000000..06f493d
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/NoOpTestInvocationListener.java
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.util;
+
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.ITestRunListener;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.result.InputStreamSource;
+import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.TestSummary;
+
+import java.util.Map;
+
+/**
+ * Implementation of ITestInvocationListener that does nothing or returns null for all methods.
+ * Extend this class to implement some, but not all methods of ITestInvocationListener.
+ */
+public class NoOpTestInvocationListener implements ITestInvocationListener {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invocationStarted(IBuildInfo buildInfo) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invocationEnded(long elapsedTime) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invocationFailed(Throwable cause) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public TestSummary getSummary() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunStarted(String runName, int testCount) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testStarted(TestIdentifier test) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testFailed(TestIdentifier test, String trace) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testAssumptionFailure(TestIdentifier test, String trace) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testIgnored(TestIdentifier test) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunFailed(String errorMessage) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunStopped(long elapsedTime) {}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunEnded(long elapsedTime, Map<String, String> runMetrics) {}
+
+}
diff --git a/common/host-side/tradefed/tests/Android.mk b/common/host-side/tradefed/tests/Android.mk
new file mode 100644
index 0000000..6d4a6cb
--- /dev/null
+++ b/common/host-side/tradefed/tests/Android.mk
@@ -0,0 +1,45 @@
+# 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.
+
+# Make a mock compatibility suite to test
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_JAVA_RESOURCE_DIRS := ../res
+
+LOCAL_SUITE_BUILD_NUMBER := 2
+LOCAL_SUITE_NAME := TESTS
+LOCAL_SUITE_FULLNAME := "Compatibility Tests"
+LOCAL_SUITE_VERSION := 1
+
+LOCAL_MODULE := compatibility-mock-tradefed
+
+include $(BUILD_COMPATIBILITY_SUITE)
+
+# Make the tests
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := compatibility-tradefed-tests
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := easymock
+
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt compatibility-mock-tradefed junit compatibility-host-util
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/common/host-side/tradefed/tests/run_tests.sh b/common/host-side/tradefed/tests/run_tests.sh
new file mode 100755
index 0000000..1d1940d
--- /dev/null
+++ b/common/host-side/tradefed/tests/run_tests.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# 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.
+
+CTS_DIR=$(dirname ${0})/../../../..
+source ${CTS_DIR}/test_defs.sh
+
+JARS="
+ compatibility-common-util-hostsidelib\
+ compatibility-common-util-tests\
+ compatibility-host-util\
+ compatibility-host-util-tests\
+ compatibility-mock-tradefed\
+ compatibility-tradefed-tests"
+
+run_tests "com.android.compatibility.common.tradefed.UnitTests" "${JARS}" "${@}"
+
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/TradefedTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/TradefedTest.java
deleted file mode 100644
index ab19369..0000000
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/TradefedTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.tradefed;
-
-import junit.framework.TestCase;
-
-public class TradefedTest extends TestCase {
-
- // TODO(stuartscott): Add tests when there is something to test.
-
-}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
new file mode 100644
index 0000000..318960c
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelperTest;
+import com.android.compatibility.common.tradefed.command.CompatibilityConsoleTest;
+import com.android.compatibility.common.tradefed.result.ResultReporterTest;
+import com.android.compatibility.common.tradefed.targetprep.PropertyCheckTest;
+import com.android.compatibility.common.tradefed.targetprep.SettingsPreparerTest;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityTestTest;
+import com.android.compatibility.common.tradefed.testtype.ModuleDefTest;
+import com.android.compatibility.common.tradefed.testtype.ModuleRepoTest;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * A test suite for all compatibility tradefed unit tests.
+ * <p/>
+ * All tests listed here should be self-contained, and do not require any external dependencies.
+ */
+public class UnitTests extends TestSuite {
+
+ public UnitTests() {
+ super();
+ addTestSuite(CompatibilityBuildHelperTest.class);
+ addTestSuite(CompatibilityConsoleTest.class);
+ addTestSuite(ResultReporterTest.class);
+ addTestSuite(CompatibilityTestTest.class);
+ addTestSuite(ModuleDefTest.class);
+ addTestSuite(ModuleRepoTest.class);
+ addTestSuite(PropertyCheckTest.class);
+ addTestSuite(SettingsPreparerTest.class);
+ }
+
+ public static Test suite() {
+ return new UnitTests();
+ }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelperTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelperTest.java
new file mode 100644
index 0000000..55d15dd
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelperTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.build;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.util.FileUtil;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+public class CompatibilityBuildHelperTest extends TestCase {
+
+ private static final String ROOT_PROPERTY = "TESTS_ROOT";
+ private static final String BUILD_NUMBER = "2";
+ private static final String SUITE_NAME = "TESTS";
+ private static final String SUITE_FULL_NAME = "Compatibility Tests";
+ private static final String SUITE_VERSION = "1";
+ private static final String SUITE_PLAN = "cts";
+ private static final String DYNAMIC_CONFIG_URL = "";
+ private static final String ROOT_DIR_NAME = "root";
+ private static final String BASE_DIR_NAME = "android-tests";
+ private static final String TESTCASES = "testcases";
+
+ private File mRoot = null;
+ private File mBase = null;
+ private File mTests = null;
+ private IBuildInfo mBuild;
+ private CompatibilityBuildHelper mHelper;
+
+ @Override
+ public void setUp() throws Exception {
+ mRoot = FileUtil.createTempDir(ROOT_DIR_NAME);
+ CompatibilityBuildProvider provider = new CompatibilityBuildProvider();
+ mBuild = provider.getBuild();
+ mHelper = new CompatibilityBuildHelper(mBuild);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ setProperty(null);
+ FileUtil.recursiveDelete(mRoot);
+ mRoot = null;
+ mBase = null;
+ mTests = null;
+ }
+
+ private void createDirStructure() {
+ mBase = new File(mRoot, BASE_DIR_NAME);
+ mBase.mkdirs();
+ mTests = new File(mBase, TESTCASES);
+ mTests.mkdirs();
+ }
+
+ public void testSuiteInfoLoad() throws Exception {
+ setProperty(mRoot.getAbsolutePath());
+ mHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ assertEquals("Incorrect suite build number", BUILD_NUMBER, mHelper.getSuiteBuild());
+ assertEquals("Incorrect suite name", SUITE_NAME, mHelper.getSuiteName());
+ assertEquals("Incorrect suite full name", SUITE_FULL_NAME, mHelper.getSuiteFullName());
+ assertEquals("Incorrect suite version", SUITE_VERSION, mHelper.getSuiteVersion());
+ }
+
+ public void testProperty() throws Exception {
+ setProperty(null);
+ CompatibilityBuildProvider provider = new CompatibilityBuildProvider();
+ CompatibilityBuildHelper helper = new CompatibilityBuildHelper(provider.getBuild());
+ try {
+ // Should fail with root unset
+ helper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ fail("Expected fail for unset root property");
+ } catch (IllegalArgumentException e) {
+ /* expected */
+ }
+ setProperty(mRoot.getAbsolutePath());
+ // Shouldn't fail with root set
+ helper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ }
+
+ public void testValidation() throws Exception {
+ setProperty(mRoot.getAbsolutePath());
+ mHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ try {
+ mHelper.getDir();
+ fail("Build helper validation succeeded on an invalid installation");
+ } catch (FileNotFoundException e) {
+ // Expected
+ }
+ createDirStructure();
+ try {
+ mHelper.getTestsDir();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ fail("Build helper validation failed on a valid installation");
+ }
+ }
+
+ public void testDirs() throws Exception {
+ setProperty(mRoot.getAbsolutePath());
+ mHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ createDirStructure();
+ assertNotNull(mRoot);
+ assertNotNull(mBuild);
+ assertNotNull(mHelper.getRootDir());
+ assertEquals("Incorrect root dir", mRoot.getAbsolutePath(),
+ mHelper.getRootDir().getAbsolutePath());
+ assertEquals("Incorrect base dir", mBase.getAbsolutePath(),
+ mHelper.getDir().getAbsolutePath());
+ assertEquals("Incorrect logs dir", new File(mBase, "logs").getAbsolutePath(),
+ mHelper.getLogsDir().getAbsolutePath());
+ assertEquals("Incorrect tests dir", mTests.getAbsolutePath(),
+ mHelper.getTestsDir().getAbsolutePath());
+ assertEquals("Incorrect results dir", new File(mBase, "results").getAbsolutePath(),
+ mHelper.getResultsDir().getAbsolutePath());
+ }
+
+ /**
+ * Sets the *_ROOT property of the build's installation location.
+ *
+ * @param value the value to set, or null to clear the property.
+ */
+ public static void setProperty(String value) {
+ if (value == null) {
+ System.clearProperty(ROOT_PROPERTY);
+ } else {
+ System.setProperty(ROOT_PROPERTY, value);
+ }
+ }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/command/CompatibilityConsoleTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/command/CompatibilityConsoleTest.java
new file mode 100644
index 0000000..55c1651
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/command/CompatibilityConsoleTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.command;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelperTest;
+
+import junit.framework.TestCase;
+
+public class CompatibilityConsoleTest extends TestCase {
+
+ @Override
+ public void setUp() throws Exception {
+ CompatibilityBuildHelperTest.setProperty("/tmp/foobar");
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ CompatibilityBuildHelperTest.setProperty(null);
+ }
+
+ public void testHelpExists() throws Exception {
+ CompatibilityConsole console = new CompatibilityConsole() {};
+ assertFalse("No help", console.getGenericHelpString(null).isEmpty());
+ }
+
+ public void testPromptExists() throws Exception {
+ CompatibilityConsole console = new CompatibilityConsole() {};
+ assertFalse("No prompt", console.getConsolePrompt().isEmpty());
+ }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
new file mode 100644
index 0000000..3fcf8b5
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.result;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.compatibility.common.util.ICaseResult;
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.IModuleResult;
+import com.android.compatibility.common.util.ITestResult;
+import com.android.compatibility.common.util.TestStatus;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.BuildInfo;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.util.FileUtil;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.HashMap;
+import java.util.List;
+
+public class ResultReporterTest extends TestCase {
+
+ private static final String ROOT_PROPERTY = "TESTS_ROOT";
+ private static final String BUILD_NUMBER = "2";
+ private static final String SUITE_PLAN = "cts";
+ private static final String DYNAMIC_CONFIG_URL = "";
+ private static final String ROOT_DIR_NAME = "root";
+ private static final String BASE_DIR_NAME = "android-tests";
+ private static final String TESTCASES = "testcases";
+ private static final String NAME = "ModuleName";
+ private static final String ABI = "mips64";
+ private static final String ID = AbiUtils.createId(ABI, NAME);
+ private static final String CLASS = "android.test.FoorBar";
+ private static final String METHOD_1 = "testBlah1";
+ private static final String METHOD_2 = "testBlah2";
+ private static final String METHOD_3 = "testBlah3";
+ private static final String TEST_1 = String.format("%s#%s", CLASS, METHOD_1);
+ private static final String TEST_2 = String.format("%s#%s", CLASS, METHOD_2);
+ private static final String TEST_3 = String.format("%s#%s", CLASS, METHOD_3);
+ private static final String STACK_TRACE = "Something small is not alright\n " +
+ "at four.big.insects.Marley.sing(Marley.java:10)";
+ private static final String RESULT_DIR = "result123";
+ private static final String[] FORMATTING_FILES = {
+ "compatibility_result.css",
+ "compatibility_result.xsd",
+ "compatibility_result.xsl",
+ "logo.png",
+ "newrule_green.png"};
+
+ private ResultReporter mReporter;
+ private IBuildInfo mBuildInfo;
+ private CompatibilityBuildHelper mBuildHelper;
+
+ private File mRoot = null;
+ private File mBase = null;
+ private File mTests = null;
+
+ @Override
+ public void setUp() throws Exception {
+ mReporter = new ResultReporter();
+ OptionSetter setter = new OptionSetter(mReporter);
+ setter.setOptionValue("quiet-output", "true");
+ mRoot = FileUtil.createTempDir(ROOT_DIR_NAME);
+ mBase = new File(mRoot, BASE_DIR_NAME);
+ mBase.mkdirs();
+ mTests = new File(mBase, TESTCASES);
+ mTests.mkdirs();
+ System.setProperty(ROOT_PROPERTY, mRoot.getAbsolutePath());
+ mBuildInfo = new BuildInfo(BUILD_NUMBER, "", "");
+ mBuildHelper = new CompatibilityBuildHelper(mBuildInfo);
+ mBuildHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mReporter = null;
+ FileUtil.recursiveDelete(mRoot);
+ }
+
+ public void testSetup() throws Exception {
+ mReporter.invocationStarted(mBuildInfo);
+ // Should have created a directory for the logs
+ File[] children = mBuildHelper.getLogsDir().listFiles();
+ assertTrue("Didn't create logs dir", children.length == 1 && children[0].isDirectory());
+ // Should have created a directory for the results
+ children = mBuildHelper.getResultsDir().listFiles();
+ assertTrue("Didn't create results dir", children.length == 1 && children[0].isDirectory());
+ mReporter.invocationEnded(10);
+ // Should have created a zip file
+ children = mBuildHelper.getResultsDir().listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ return pathname.getName().endsWith(".zip");
+ }
+ });
+ assertTrue("Didn't create results zip",
+ children.length == 1 && children[0].isFile() && children[0].length() > 0);
+ }
+
+ public void testResultReporting() throws Exception {
+ mReporter.invocationStarted(mBuildInfo);
+ mReporter.testRunStarted(ID, 2);
+ TestIdentifier test1 = new TestIdentifier(CLASS, METHOD_1);
+ mReporter.testStarted(test1);
+ mReporter.testEnded(test1, new HashMap<String, String>());
+ TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+ mReporter.testStarted(test2);
+ mReporter.testFailed(test2, STACK_TRACE);
+ TestIdentifier test3 = new TestIdentifier(CLASS, METHOD_3);
+ mReporter.testStarted(test3);
+ mReporter.testFailed(test3, STACK_TRACE);
+ mReporter.testRunEnded(10, new HashMap<String, String>());
+ mReporter.invocationEnded(10);
+ IInvocationResult result = mReporter.getResult();
+ assertEquals("Expected 1 pass", 1, result.countResults(TestStatus.PASS));
+ assertEquals("Expected 2 failures", 2, result.countResults(TestStatus.FAIL));
+ List<IModuleResult> modules = result.getModules();
+ assertEquals("Expected 1 module", 1, modules.size());
+ IModuleResult module = modules.get(0);
+ assertEquals("Incorrect ID", ID, module.getId());
+ List<ICaseResult> caseResults = module.getResults();
+ assertEquals("Expected 1 test case", 1, caseResults.size());
+ ICaseResult caseResult = caseResults.get(0);
+ List<ITestResult> testResults = caseResult.getResults();
+ assertEquals("Expected 3 tests", 3, testResults.size());
+ ITestResult result1 = caseResult.getResult(METHOD_1);
+ assertNotNull(String.format("Expected result for %s", TEST_1), result1);
+ assertEquals(String.format("Expected pass for %s", TEST_1), TestStatus.PASS,
+ result1.getResultStatus());
+ ITestResult result2 = caseResult.getResult(METHOD_2);
+ assertNotNull(String.format("Expected result for %s", TEST_2), result2);
+ assertEquals(String.format("Expected fail for %s", TEST_2), TestStatus.FAIL,
+ result2.getResultStatus());
+ ITestResult result3 = caseResult.getResult(METHOD_3);
+ assertNotNull(String.format("Expected result for %s", TEST_3), result3);
+ assertEquals(String.format("Expected fail for %s", TEST_3), TestStatus.FAIL,
+ result3.getResultStatus());
+ }
+
+ public void testCopyFormattingFiles() throws Exception {
+ File resultDir = new File(mBuildHelper.getResultsDir(), RESULT_DIR);
+ resultDir.mkdirs();
+ ResultReporter.copyFormattingFiles(resultDir);
+ for (String filename : FORMATTING_FILES) {
+ File file = new File(resultDir, filename);
+ assertTrue(String.format("%s (%s) was not created", filename, file.getAbsolutePath()),
+ file.exists() && file.isFile() && file.length() > 0);
+ }
+ }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheckTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheckTest.java
new file mode 100644
index 0000000..a309a47
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheckTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.tradefed.build.DeviceBuildInfo;
+import com.android.tradefed.build.IDeviceBuildInfo;
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+
+public class PropertyCheckTest extends TestCase {
+
+ private PropertyCheck mPropertyCheck;
+ private IDeviceBuildInfo mMockBuildInfo;
+ private ITestDevice mMockDevice;
+ private OptionSetter mOptionSetter;
+
+ private static final String PROPERTY = "ro.mock.property";
+ private static final String ACTUAL_VALUE = "mock_actual_value";
+ private static final String BAD_VALUE = "mock_bad_value";
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mPropertyCheck = new PropertyCheck();
+ mMockDevice = EasyMock.createMock(ITestDevice.class);
+ mMockBuildInfo = new DeviceBuildInfo("0", "", "");
+ mOptionSetter = new OptionSetter(mPropertyCheck);
+ EasyMock.expect(mMockDevice.getProperty(PROPERTY)).andReturn(ACTUAL_VALUE).anyTimes();
+ }
+
+ public void testWarningMatch() throws Exception {
+ mOptionSetter.setOptionValue("property-name", PROPERTY);
+ mOptionSetter.setOptionValue("expected-value", ACTUAL_VALUE);
+ mOptionSetter.setOptionValue("throw-error", "false");
+ EasyMock.replay(mMockDevice);
+ mPropertyCheck.run(mMockDevice, mMockBuildInfo); // no warnings or errors
+ }
+
+ public void testWarningMismatch() throws Exception {
+ mOptionSetter.setOptionValue("property-name", PROPERTY);
+ mOptionSetter.setOptionValue("expected-value", BAD_VALUE);
+ mOptionSetter.setOptionValue("throw-error", "false");
+ EasyMock.replay(mMockDevice);
+ mPropertyCheck.run(mMockDevice, mMockBuildInfo); // should only print a warning
+ }
+
+ public void testErrorMatch() throws Exception {
+ mOptionSetter.setOptionValue("property-name", PROPERTY);
+ mOptionSetter.setOptionValue("expected-value", ACTUAL_VALUE);
+ mOptionSetter.setOptionValue("throw-error", "true");
+ EasyMock.replay(mMockDevice);
+ mPropertyCheck.run(mMockDevice, mMockBuildInfo); // no warnings or errors
+ }
+
+ public void testErrorMismatch() throws Exception {
+ mOptionSetter.setOptionValue("property-name", PROPERTY);
+ mOptionSetter.setOptionValue("expected-value", BAD_VALUE);
+ mOptionSetter.setOptionValue("throw-error", "true");
+ EasyMock.replay(mMockDevice);
+ try {
+ mPropertyCheck.run(mMockDevice, mMockBuildInfo); // expecting TargetSetupError
+ fail("TargetSetupError expected");
+ } catch (TargetSetupError e) {
+ // Expected
+ }
+ }
+
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparerTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparerTest.java
new file mode 100644
index 0000000..739662e
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparerTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.tradefed.build.DeviceBuildInfo;
+import com.android.tradefed.build.BuildInfo;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+
+public class SettingsPreparerTest extends TestCase {
+
+ private SettingsPreparer mSettingsPreparer;
+ private IBuildInfo mMockBuildInfo;
+ private ITestDevice mMockDevice;
+ private OptionSetter mOptionSetter;
+
+ private static final String SHELL_CMD_GET = "settings get GLOBAL stay_on_while_plugged_in";
+ private static final String SHELL_CMD_PUT_7 = "settings put GLOBAL stay_on_while_plugged_in 7";
+ private static final String SHELL_CMD_PUT_8 = "settings put GLOBAL stay_on_while_plugged_in 8";
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mSettingsPreparer = new SettingsPreparer();
+ mMockDevice = EasyMock.createMock(ITestDevice.class);
+ mMockBuildInfo = new BuildInfo("0", "", "");
+ mOptionSetter = new OptionSetter(mSettingsPreparer);
+ mOptionSetter.setOptionValue("device-setting", "stay_on_while_plugged_in");
+ mOptionSetter.setOptionValue("setting-type", "global");
+ }
+
+ public void testCorrectOneExpected() throws Exception {
+ EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n3\n").once();
+ mOptionSetter.setOptionValue("expected-values", "3");
+ EasyMock.replay(mMockDevice);
+ mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+ }
+
+ public void testCorrectManyExpected() throws Exception {
+ EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n3\n").once();
+ mOptionSetter.setOptionValue("expected-values", "2");
+ mOptionSetter.setOptionValue("expected-values", "3");
+ mOptionSetter.setOptionValue("expected-values", "6");
+ mOptionSetter.setOptionValue("expected-values", "7");
+ EasyMock.replay(mMockDevice);
+ mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+ }
+
+ public void testIncorrectOneExpected() throws Exception {
+ EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n0\n").once();
+ mOptionSetter.setOptionValue("expected-values", "3");
+ EasyMock.replay(mMockDevice);
+ try {
+ mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+ fail("TargetSetupError expected");
+ } catch (TargetSetupError e) {
+ //Expected
+ }
+ }
+
+ public void testIncorrectManyExpected() throws Exception {
+ EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n0\n").once();
+ mOptionSetter.setOptionValue("expected-values", "2");
+ mOptionSetter.setOptionValue("expected-values", "3");
+ mOptionSetter.setOptionValue("expected-values", "6");
+ mOptionSetter.setOptionValue("expected-values", "7");
+ EasyMock.replay(mMockDevice);
+ try {
+ mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+ fail("TargetSetupError expected");
+ } catch (TargetSetupError e) {
+ //Expected
+ }
+ }
+
+ public void testCommandRun() throws Exception {
+ EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_PUT_7)).andReturn("\n");
+ mOptionSetter.setOptionValue("set-value", "7");
+ EasyMock.replay(mMockDevice);
+ mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+ }
+
+ public void testCommandRunWrongSetValue() throws Exception {
+ EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_PUT_8)).andReturn("\n");
+ mOptionSetter.setOptionValue("set-value", "8");
+ mOptionSetter.setOptionValue("expected-values", "7");
+ EasyMock.replay(mMockDevice);
+ try {
+ mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+ fail("TargetSetupError expected");
+ } catch (TargetSetupError e) {
+ //Expected
+ }
+ }
+
+ public void testIncorrectOneExpectedCommandRun() throws Exception {
+ EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n0\n").once();
+ EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_PUT_7)).andReturn("\n");
+ mOptionSetter.setOptionValue("set-value", "7");
+ mOptionSetter.setOptionValue("expected-values", "7");
+ }
+
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTestTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTestTest.java
new file mode 100644
index 0000000..ccab426
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTestTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.testtype;
+
+import junit.framework.TestCase;
+
+public class CompatibilityTestTest extends TestCase {
+
+ @Override
+ public void setUp() throws Exception {
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ }
+
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java
new file mode 100644
index 0000000..8714c1d
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.compatibility.common.tradefed.util.NoOpTestInvocationListener;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.ITestFilterReceiver;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ModuleDefTest extends TestCase {
+
+ private static final String NAME = "ModuleName";
+ private static final String ABI = "mips64";
+ private static final String ID = AbiUtils.createId(ABI, NAME);
+ private static final String CLASS = "android.test.FoorBar";
+ private static final String METHOD_1 = "testBlah1";
+ private static final String TEST_1 = String.format("%s#%s", CLASS, METHOD_1);
+
+ public void testAccessors() throws Exception {
+ IAbi abi = new Abi(ABI, "");
+ MockRemoteTest mockTest = new MockRemoteTest();
+ IModuleDef def = new ModuleDef(NAME, abi, mockTest, new ArrayList<ITargetPreparer>());
+ assertEquals("Incorrect ID", ID, def.getId());
+ assertEquals("Incorrect ABI", ABI, def.getAbi().getName());
+ assertEquals("Incorrect Name", NAME, def.getName());
+ }
+
+ public void testAddFilters() throws Exception {
+ IAbi abi = new Abi(ABI, "");
+ MockRemoteTest mockTest = new MockRemoteTest();
+ ModuleDef def = new ModuleDef(NAME, abi, mockTest, new ArrayList<ITargetPreparer>());
+ def.addIncludeFilter(CLASS);
+ def.addExcludeFilter(TEST_1);
+ MockListener mockListener = new MockListener();
+ def.run(mockListener);
+ assertEquals("Expected one include filter", 1, mockTest.mIncludeFilters.size());
+ assertEquals("Expected one exclude filter", 1, mockTest.mExcludeFilters.size());
+ assertEquals("Incorrect include filter", CLASS, mockTest.mIncludeFilters.get(0));
+ assertEquals("Incorrect exclude filter", TEST_1, mockTest.mExcludeFilters.get(0));
+ }
+
+ private class MockRemoteTest implements IRemoteTest, ITestFilterReceiver {
+
+ private final List<String> mIncludeFilters = new ArrayList<>();
+ private final List<String> mExcludeFilters = new ArrayList<>();
+
+ @Override
+ public void addIncludeFilter(String filter) {
+ mIncludeFilters.add(filter);
+ }
+
+ @Override
+ public void addAllIncludeFilters(List<String> filters) {
+ mIncludeFilters.addAll(filters);
+ }
+
+ @Override
+ public void addExcludeFilter(String filter) {
+ mExcludeFilters.add(filter);
+ }
+
+ @Override
+ public void addAllExcludeFilters(List<String> filters) {
+ mExcludeFilters.addAll(filters);
+ }
+
+ @Override
+ public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+ // Do nothing
+ }
+
+ }
+
+ private class MockListener extends NoOpTestInvocationListener {}
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java
new file mode 100644
index 0000000..4944f3a
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java
@@ -0,0 +1,247 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider;
+import com.android.compatibility.common.tradefed.testtype.ModuleRepo.ConfigFilter;
+import com.android.compatibility.common.tradefed.testtype.IModuleDef;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.IShardableTest;
+import com.android.tradefed.util.FileUtil;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class ModuleRepoTest extends TestCase {
+
+ private static final String TOKEN =
+ "<target_preparer class=\"com.android.compatibility.common.tradefed.targetprep.TokenRequirement\">\n"
+ + "<option name=\"token\" value=\"%s\" />\n"
+ + "</target_preparer>\n";
+ private static final String CONFIG =
+ "<configuration description=\"Auto Generated File\">\n" +
+ "%s" +
+ "<test class=\"com.android.compatibility.common.tradefed.testtype.%s\">\n" +
+ "<option name=\"module\" value=\"%s\" />" +
+ "</test>\n" +
+ "</configuration>";
+ private static final String FOOBAR_TOKEN = "foobar";
+ private static final String SERIAL1 = "abc";
+ private static final String SERIAL2 = "def";
+ private static final String SERIAL3 = "ghi";
+ private static final Set<String> SERIALS = new HashSet<>();
+ private static final Set<IAbi> ABIS = new HashSet<>();
+ private static final List<String> DEVICE_TOKENS = new ArrayList<>();
+ private static final List<String> TEST_ARGS= new ArrayList<>();
+ private static final List<String> MODULE_ARGS = new ArrayList<>();
+ private static final List<String> INCLUDES = new ArrayList<>();
+ private static final List<String> EXCLUDES = new ArrayList<>();
+ private static final Set<String> FILES = new HashSet<>();
+ private static final String FILENAME = "%s.config";
+ private static final String ABI_32 = "armeabi-v7a";
+ private static final String ABI_64 = "arm64-v8a";
+ private static final String MODULE_NAME_A = "FooModuleA";
+ private static final String MODULE_NAME_B = "FooModuleB";
+ private static final String MODULE_NAME_C = "FooModuleC";
+ private static final String ID_A_32 = AbiUtils.createId(ABI_32, MODULE_NAME_A);
+ private static final String ID_A_64 = AbiUtils.createId(ABI_64, MODULE_NAME_A);
+ private static final String ID_B_32 = AbiUtils.createId(ABI_32, MODULE_NAME_B);
+ private static final String ID_B_64 = AbiUtils.createId(ABI_64, MODULE_NAME_B);
+ private static final String ID_C_32 = AbiUtils.createId(ABI_32, MODULE_NAME_C);
+ private static final String ID_C_64 = AbiUtils.createId(ABI_64, MODULE_NAME_C);
+ private static final String TEST_ARG = TestStub.class.getName() + ":foo:bar";
+ private static final String MODULE_ARG = "%s:blah:foobar";
+ private static final String TEST_STUB = "TestStub"; // Trivial test stub
+ private static final String SHARDABLE_TEST_STUB = "ShardableTestStub"; // Shardable and IBuildReceiver
+ static {
+ SERIALS.add(SERIAL1);
+ SERIALS.add(SERIAL2);
+ SERIALS.add(SERIAL3);
+ ABIS.add(new Abi(ABI_32, "32"));
+ ABIS.add(new Abi(ABI_64, "64"));
+ DEVICE_TOKENS.add(String.format("%s:%s", SERIAL3, FOOBAR_TOKEN));
+ TEST_ARGS.add(TEST_ARG);
+ MODULE_ARGS.add(String.format(MODULE_ARG, MODULE_NAME_A));
+ MODULE_ARGS.add(String.format(MODULE_ARG, MODULE_NAME_B));
+ MODULE_ARGS.add(String.format(MODULE_ARG, MODULE_NAME_C));
+ FILES.add(String.format(FILENAME, MODULE_NAME_A));
+ FILES.add(String.format(FILENAME, MODULE_NAME_B));
+ FILES.add(String.format(FILENAME, MODULE_NAME_C));
+ }
+ private IModuleRepo mRepo;
+ private File mTestsDir;
+ private IBuildInfo mBuild;
+
+ @Override
+ public void setUp() throws Exception {
+ mTestsDir = setUpConfigs();
+ ModuleRepo.sInstance = null;// Clear the instance so it gets recreated.
+ mRepo = ModuleRepo.getInstance();
+ mBuild = new CompatibilityBuildProvider().getBuild();
+ }
+
+ private File setUpConfigs() throws IOException {
+ File testsDir = FileUtil.createNamedTempDir("testcases");
+ createConfig(testsDir, MODULE_NAME_A, null);
+ createConfig(testsDir, MODULE_NAME_B, null);
+ createConfig(testsDir, MODULE_NAME_C, FOOBAR_TOKEN);
+ return testsDir;
+ }
+
+ private void createConfig(File testsDir, String name, String token) throws IOException {
+ createConfig(testsDir, name, token, TEST_STUB);
+ }
+
+ private void createConfig(File testsDir, String name, String token, String moduleClass) throws IOException {
+ File config = new File(testsDir, String.format(FILENAME, name));
+ String preparer = "";
+ if (token != null) {
+ preparer = String.format(TOKEN, token);
+ }
+ FileUtil.writeToFile(String.format(CONFIG, preparer, moduleClass, name), config);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ tearDownConfigs(mTestsDir);
+ }
+
+ private void tearDownConfigs(File testsDir) {
+ FileUtil.recursiveDelete(testsDir);
+ }
+
+ public void testInitialization() throws Exception {
+ mRepo.initialize(3, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES,
+ EXCLUDES, mBuild);
+ assertTrue("Should be initialized", mRepo.isInitialized());
+ assertEquals("Wrong number of shards", 3, mRepo.getNumberOfShards());
+ assertEquals("Wrong number of modules per shard", 2, mRepo.getModulesPerShard());
+ Map<String, Set<String>> deviceTokens = mRepo.getDeviceTokens();
+ assertEquals("Wrong number of devices with tokens", 1, deviceTokens.size());
+ Set<String> tokens = deviceTokens.get(SERIAL3);
+ assertEquals("Wrong number of tokens", 1, tokens.size());
+ assertTrue("Unexpected device token", tokens.contains(FOOBAR_TOKEN));
+ assertEquals("Wrong number of modules", 0, mRepo.getLargeModules().size());
+ assertEquals("Wrong number of modules", 0, mRepo.getMediumModules().size());
+ assertEquals("Wrong number of modules", 4, mRepo.getSmallModules().size());
+ List<IModuleDef> tokenModules = mRepo.getTokenModules();
+ assertEquals("Wrong number of modules with tokens", 2, tokenModules.size());
+ List<IModuleDef> serial1Modules = mRepo.getModules(SERIAL1);
+ assertEquals("Wrong number of modules", 2, serial1Modules.size());
+ List<IModuleDef> serial2Modules = mRepo.getModules(SERIAL2);
+ assertEquals("Wrong number of modules", 2, serial2Modules.size());
+ List<IModuleDef> serial3Modules = mRepo.getModules(SERIAL3);
+ assertEquals("Wrong number of modules", 2, serial3Modules.size());
+ // Serial 3 should have the modules with tokens
+ for (IModuleDef module : serial3Modules) {
+ assertEquals("Wrong module", MODULE_NAME_C, module.getName());
+ }
+ Set<String> serials = mRepo.getSerials();
+ assertEquals("Wrong number of serials", 3, serials.size());
+ assertTrue("Unexpected device serial", serials.containsAll(SERIALS));
+ }
+
+ public void testConfigFilter() throws Exception {
+ File[] configFiles = mTestsDir.listFiles(new ConfigFilter());
+ assertEquals("Wrong number of config files found.", 3, configFiles.length);
+ for (File file : configFiles) {
+ assertTrue(String.format("Unrecognised file: %s", file.getAbsolutePath()),
+ FILES.contains(file.getName()));
+ }
+ }
+
+ public void testFiltering() throws Exception {
+ List<String> includeFilters = new ArrayList<>();
+ includeFilters.add(MODULE_NAME_A);
+ List<String> excludeFilters = new ArrayList<>();
+ excludeFilters.add(ID_A_32);
+ excludeFilters.add(MODULE_NAME_B);
+ mRepo.initialize(1, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, includeFilters,
+ excludeFilters, mBuild);
+ List<IModuleDef> modules = mRepo.getModules(SERIAL1);
+ assertEquals("Incorrect number of modules", 1, modules.size());
+ IModuleDef module = modules.get(0);
+ assertEquals("Incorrect ID", ID_A_64, module.getId());
+ checkArgs(module);
+ }
+
+ public void testParsing() throws Exception {
+ mRepo.initialize(1, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES,
+ EXCLUDES, mBuild);
+ List<IModuleDef> modules = mRepo.getModules(SERIAL3);
+ Set<String> idSet = new HashSet<>();
+ for (IModuleDef module : modules) {
+ idSet.add(module.getId());
+ }
+ assertEquals("Incorrect number of IDs", 6, idSet.size());
+ assertTrue("Missing ID_A_32", idSet.contains(ID_A_32));
+ assertTrue("Missing ID_A_64", idSet.contains(ID_A_64));
+ assertTrue("Missing ID_B_32", idSet.contains(ID_B_32));
+ assertTrue("Missing ID_B_64", idSet.contains(ID_B_64));
+ assertTrue("Missing ID_C_32", idSet.contains(ID_C_32));
+ assertTrue("Missing ID_C_64", idSet.contains(ID_C_64));
+ for (IModuleDef module : modules) {
+ checkArgs(module);
+ }
+ }
+
+ private void checkArgs(IModuleDef module) {
+ IRemoteTest test = module.getTest();
+ assertTrue("Incorrect test type", test instanceof TestStub);
+ TestStub stub = (TestStub) test;
+ assertEquals("Incorrect test arg", "bar", stub.mFoo);
+ assertEquals("Incorrect module arg", "foobar", stub.mBlah);
+ }
+
+ public void testSplit() throws Exception {
+ createConfig(mTestsDir, "sharder_1", null, SHARDABLE_TEST_STUB);
+ createConfig(mTestsDir, "sharder_2", null, SHARDABLE_TEST_STUB);
+ createConfig(mTestsDir, "sharder_3", null, SHARDABLE_TEST_STUB);
+ Set<IAbi> abis = new HashSet<>();
+ abis.add(new Abi(ABI_64, "64"));
+ ArrayList<String> emptyList = new ArrayList<>();
+
+ mRepo.initialize(3, mTestsDir, abis, DEVICE_TOKENS, emptyList, emptyList, emptyList,
+ emptyList, mBuild);
+
+ List<IModuleDef> modules = new ArrayList<>();
+ modules.addAll(mRepo.getLargeModules());
+ modules.addAll(mRepo.getMediumModules());
+ modules.addAll(mRepo.getSmallModules());
+ modules.addAll(mRepo.getTokenModules());
+
+ int shardableCount = 0;
+ for (IModuleDef def : modules) {
+ IRemoteTest test = def.getTest();
+ if (test instanceof IShardableTest) {
+ assertNotNull("Build not set", ((ShardableTestStub)test).mBuildInfo);
+ shardableCount++;
+ }
+ }
+ assertEquals("Shards wrong", 3*3, shardableCount);
+ }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ShardableTestStub.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ShardableTestStub.java
new file mode 100644
index 0000000..52a1aad
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ShardableTestStub.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.IShardableTest;
+
+import junit.framework.Assert;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class ShardableTestStub implements IRemoteTest, IShardableTest, IBuildReceiver {
+
+ @Option(name = "module")
+ String mModule;
+ @Option(name = "foo")
+ String mFoo;
+ @Option(name = "blah")
+ String mBlah;
+
+ public IBuildInfo mBuildInfo = null;
+
+ Collection<IRemoteTest> mShards;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mBuildInfo = buildInfo;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ @Override
+ public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+ // Do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Collection<IRemoteTest> split() {
+ Assert.assertNotNull(mBuildInfo);
+
+ mShards = new ArrayList<>();
+ for (int i = 0; i < 3; i++) {
+ mShards.add(new ShardableTestStub());
+ }
+ return mShards;
+ }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStub.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStub.java
new file mode 100644
index 0000000..8a6ab69
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStub.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.tradefed.testtype;
+
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IRemoteTest;
+
+public class TestStub implements IRemoteTest {
+
+ @Option(name = "module")
+ String mModule;
+ @Option(name = "foo")
+ String mFoo;
+ @Option(name = "blah")
+ String mBlah;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+ // Do nothing
+ }
+
+}
diff --git a/common/host-side/util/Android.mk b/common/host-side/util/Android.mk
new file mode 100644
index 0000000..8747cf8
--- /dev/null
+++ b/common/host-side/util/Android.mk
@@ -0,0 +1,31 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-common-util-hostsidelib
+
+LOCAL_JAVA_LIBRARIES := json-prebuilt
+
+LOCAL_MODULE := compatibility-host-util
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/DynamicConfigHandler.java b/common/host-side/util/src/com/android/compatibility/common/util/DynamicConfigHandler.java
new file mode 100644
index 0000000..b42faca
--- /dev/null
+++ b/common/host-side/util/src/com/android/compatibility/common/util/DynamicConfigHandler.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.util;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONTokener;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DynamicConfigHandler {
+
+ private static final String LOG_TAG = DynamicConfigHandler.class.getSimpleName();
+
+ // xml constant
+ private static final String NS = null; //representing null namespace
+ private static final String ENCODING = "UTF-8";
+
+ public static File getMergedDynamicConfigFile(File localConfigFile, String apfeConfigJson,
+ String moduleName) throws IOException, XmlPullParserException, JSONException {
+
+ DynamicConfig.Params localConfig = DynamicConfig.genParamsFromFile(localConfigFile);
+ DynamicConfig.Params apfeOverride = parseJsonToParam(apfeConfigJson);
+
+ localConfig.mDynamicParams.putAll(apfeOverride.mDynamicParams);
+ localConfig.mDynamicArrayParams.putAll(apfeOverride.mDynamicArrayParams);
+
+ File mergedConfigFile = storeMergedConfigFile(localConfig, moduleName);
+ return mergedConfigFile;
+ }
+
+ private static DynamicConfig.Params parseJsonToParam(String apfeConfigJson)
+ throws JSONException {
+ if (apfeConfigJson == null) return new DynamicConfig.Params();
+
+ Map<String, String> configMap = new HashMap<>();
+ Map<String, List<String>> configListMap = new HashMap<>();
+
+ JSONObject rootObj = new JSONObject(new JSONTokener(apfeConfigJson));
+ if (rootObj.has("config")) {
+ JSONArray configArr = rootObj.getJSONArray("config");
+ for (int i = 0; i < configArr.length(); i++) {
+ JSONObject config = configArr.getJSONObject(i);
+ configMap.put(config.getString("key"), config.getString("value"));
+ }
+ }
+ if (rootObj.has("configList")) {
+ JSONArray configListArr = rootObj.getJSONArray("configList");
+ for (int i = 0; i < configListArr.length(); i++) {
+ JSONObject configList = configListArr.getJSONObject(i);
+ String key = configList.getString("key");
+ List<String> values = new ArrayList<>();
+ JSONArray configListValuesArr = configList.getJSONArray("value");
+ for (int j = 0; j < configListValuesArr.length(); j++) {
+ values.add(configListValuesArr.getString(j));
+ }
+ configListMap.put(key, values);
+ }
+ }
+
+ DynamicConfig.Params param = new DynamicConfig.Params();
+ param.mDynamicParams = configMap;
+ param.mDynamicArrayParams = configListMap;
+ return param;
+ }
+
+ private static File storeMergedConfigFile(DynamicConfig.Params p, String moduleName)
+ throws XmlPullParserException, IOException {
+ XmlSerializer serializer = XmlPullParserFactory.newInstance().newSerializer();
+
+ File parentFolder = new File(DynamicConfig.CONFIG_FOLDER_ON_HOST);
+ if (!parentFolder.exists()) parentFolder.mkdir();
+ File folder = new File(DynamicConfig.MERGED_CONFIG_FILE_FOLDER);
+ if (!folder.exists()) folder.mkdir();
+ File mergedConfigFile = new File(folder, moduleName+".dynamic");
+ OutputStream stream = new FileOutputStream(mergedConfigFile);
+ serializer.setOutput(stream, ENCODING);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ serializer.startDocument(ENCODING, false);
+
+ serializer.startTag(NS, DynamicConfig.DYNAMIC_CONFIG_TAG);
+ for (String key : p.mDynamicParams.keySet()) {
+ serializer.startTag(NS, DynamicConfig.CONFIG_TAG);
+ serializer.attribute(NS, DynamicConfig.KEY_ATTR, key);
+ serializer.text(p.mDynamicParams.get(key));
+ serializer.endTag(NS, DynamicConfig.CONFIG_TAG);
+ }
+ for (String key : p.mDynamicArrayParams.keySet()) {
+ serializer.startTag(NS, DynamicConfig.CONFIG_LIST_TAG);
+ serializer.attribute(NS, DynamicConfig.KEY_ATTR, key);
+ for (String item: p.mDynamicArrayParams.get(key)) {
+ serializer.startTag(NS, DynamicConfig.ITEM_TAG);
+ serializer.text(item);
+ serializer.endTag(NS, DynamicConfig.ITEM_TAG);
+ }
+ serializer.endTag(NS, DynamicConfig.CONFIG_LIST_TAG);
+ }
+ serializer.endTag(NS, DynamicConfig.DYNAMIC_CONFIG_TAG);
+ serializer.endDocument();
+ return mergedConfigFile;
+ }
+}
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/DynamicConfigHostSide.java b/common/host-side/util/src/com/android/compatibility/common/util/DynamicConfigHostSide.java
new file mode 100644
index 0000000..ac69034
--- /dev/null
+++ b/common/host-side/util/src/com/android/compatibility/common/util/DynamicConfigHostSide.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.util;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Load dynamic config for device side test cases
+ */
+public class DynamicConfigHostSide extends DynamicConfig {
+ private static String LOG_TAG = DynamicConfigHostSide.class.getSimpleName();
+
+ public DynamicConfigHostSide(String moduleName) throws IOException, XmlPullParserException {
+ File configFile = getConfigFile(new File(CONFIG_FOLDER_ON_HOST), moduleName);
+ initConfigFromXml(configFile);
+ }
+}
diff --git a/common/util/src/com/android/compatibility/common/util/MetricsReportLog.java b/common/host-side/util/src/com/android/compatibility/common/util/MetricsReportLog.java
similarity index 100%
rename from common/util/src/com/android/compatibility/common/util/MetricsReportLog.java
rename to common/host-side/util/src/com/android/compatibility/common/util/MetricsReportLog.java
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/MetricsStore.java b/common/host-side/util/src/com/android/compatibility/common/util/MetricsStore.java
new file mode 100644
index 0000000..efe7182
--- /dev/null
+++ b/common/host-side/util/src/com/android/compatibility/common/util/MetricsStore.java
@@ -0,0 +1,61 @@
+/*
+ * 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
+ */
+
+package com.android.compatibility.common.util;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * A simple in-memory store for metrics results. This should be used for hostside metrics reporting.
+ */
+public class MetricsStore {
+
+ // needs concurrent version as there can be multiple client accessing this.
+ // But there is no additional protection for the same key as that should not happen.
+ private static final ConcurrentHashMap<String, ReportLog> mMap =
+ new ConcurrentHashMap<String, ReportLog>();
+
+ private MetricsStore() {}
+
+ /**
+ * Stores a result. Existing result with the same key will be replaced.
+ * Note that key is generated in the form of device_serial#class#method name.
+ * So there should be no concurrent test for the same (serial, class, method).
+ * @param deviceSerial
+ * @param abi
+ * @param classMethodName
+ * @param reportLog Contains the result to be stored
+ */
+ public static void storeResult(
+ String deviceSerial, String abi, String classMethodName, ReportLog reportLog) {
+ mMap.put(generateTestKey(deviceSerial, abi, classMethodName), reportLog);
+ }
+
+ /**
+ * retrieves a metric result for the given condition and remove it from the internal
+ * storage. If there is no result for the given condition, it will return null.
+ */
+ public static ReportLog removeResult(String deviceSerial, String abi, String classMethodName) {
+ return mMap.remove(generateTestKey(deviceSerial, abi, classMethodName));
+ }
+
+ /**
+ * @return test key in the form of device_serial#abi#class_name#method_name
+ */
+ private static String generateTestKey(String deviceSerial, String abi, String classMethodName) {
+ return String.format("%s#%s#%s", deviceSerial, abi, classMethodName);
+ }
+}
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/VersionCodes.java b/common/host-side/util/src/com/android/compatibility/common/util/VersionCodes.java
new file mode 100644
index 0000000..8f3c155
--- /dev/null
+++ b/common/host-side/util/src/com/android/compatibility/common/util/VersionCodes.java
@@ -0,0 +1,43 @@
+/*
+ * 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 com.android.compatibility.common.util;
+
+public class VersionCodes {
+ public static final int CUR_DEVELOPMENT = 10000;
+ public static final int BASE = 1;
+ public static final int BASE_1_1 = 2;
+ public static final int CUPCAKE = 3;
+ public static final int DONUT = 4;
+ public static final int ECLAIR = 5;
+ public static final int ECLAIR_0_1 = 6;
+ public static final int ECLAIR_MR1 = 7;
+ public static final int FROYO = 8;
+ public static final int GINGERBREAD = 9;
+ public static final int GINGERBREAD_MR1 = 10;
+ public static final int HONEYCOMB = 11;
+ public static final int HONEYCOMB_MR1 = 12;
+ public static final int HONEYCOMB_MR2 = 13;
+ public static final int ICE_CREAM_SANDWICH = 14;
+ public static final int ICE_CREAM_SANDWICH_MR1 = 15;
+ public static final int JELLY_BEAN = 16;
+ public static final int JELLY_BEAN_MR1 = 17;
+ public static final int JELLY_BEAN_MR2 = 18;
+ public static final int KITKAT = 19;
+ public static final int KITKAT_WATCH = 20;
+ public static final int LOLLIPOP = 21;
+ public static final int LOLLIPOP_MR1 = 22;
+ public static final int MNC = CUR_DEVELOPMENT;
+}
diff --git a/common/host-side/util/tests/Android.mk b/common/host-side/util/tests/Android.mk
new file mode 100644
index 0000000..a0e9a3b
--- /dev/null
+++ b/common/host-side/util/tests/Android.mk
@@ -0,0 +1,27 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := compatibility-host-util junit json-prebuilt
+
+LOCAL_MODULE := compatibility-host-util-tests
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/common/host-side/util/tests/run_tests.sh b/common/host-side/util/tests/run_tests.sh
new file mode 100755
index 0000000..d4513f9
--- /dev/null
+++ b/common/host-side/util/tests/run_tests.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# 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.
+
+# Helper script for running unit tests for compatibility libraries
+
+CTS_DIR=$(dirname ${0})/../../../..
+source ${CTS_DIR}/test_defs.sh
+
+JARS="
+ compatibility-common-util-hostsidelib\
+ compatibility-common-util-tests\
+ compatibility-host-util\
+ compatibility-host-util-tests\
+ compatibility-mock-tradefed\
+ compatibility-tradefed-tests"
+
+run_tests "com.android.compatibility.common.util.HostUnitTests" "${JARS}" "${@}"
+
diff --git a/common/host-side/util/tests/src/com/android/compatibility/common/util/DynamicConfigHandlerTest.java b/common/host-side/util/tests/src/com/android/compatibility/common/util/DynamicConfigHandlerTest.java
new file mode 100644
index 0000000..e2001fc
--- /dev/null
+++ b/common/host-side/util/tests/src/com/android/compatibility/common/util/DynamicConfigHandlerTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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
+ */
+
+package com.android.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Unit tests for {@link DynamicConfigHandler}
+ */
+public class DynamicConfigHandlerTest extends TestCase {
+
+ private static final String localConfig =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<DynamicConfig>\n" +
+ " <Config key=\"test-config-1\">test config 1</Config>\n" +
+ " <Config key=\"test-config-2\">test config 2</Config>\n" +
+ " <Config key=\"override-config-2\">test config 3</Config>\n" +
+ " <ConfigList key=\"config-list\">\n" +
+ " <Item>config0</Item>\n" +
+ " <Item>config1</Item>\n" +
+ " <Item>config2</Item>\n" +
+ " <Item>config3</Item>\n" +
+ " <Item>config4</Item>\n" +
+ " </ConfigList>\n" +
+ " <ConfigList key=\"override-config-list-2\">\n" +
+ " <Item>A</Item>\n" +
+ " <Item>B</Item>\n" +
+ " <Item>C</Item>\n" +
+ " <Item>D</Item>\n" +
+ " <Item>E</Item>\n" +
+ " </ConfigList>\n" +
+ "</DynamicConfig>\n";
+
+ private static final String overrideJson =
+ "{\n" +
+ " \"config\": [\n" +
+ " {\n" +
+ " \"key\": \"version\",\n" +
+ " \"value\": \"1.0\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"key\": \"suite\",\n" +
+ " \"value\": \"CTS_V2\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"key\": \"override-config-1\",\n" +
+ " \"value\": \"override-config-val-1\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"key\": \"override-config-2\",\n" +
+ " \"value\": \"override-config-val-2\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"configList\": [\n" +
+ " {\n" +
+ " \"key\": \"override-config-list-1\",\n" +
+ " \"value\": [\n" +
+ " \"override-config-list-val-1-1\",\n" +
+ " \"override-config-list-val-1-2\"\n" +
+ " ]\n" +
+ " },\n" +
+ " {\n" +
+ " \"key\": \"override-config-list-2\",\n" +
+ " \"value\": [\n" +
+ " \"override-config-list-val-2-1\"\n" +
+ " ]\n" +
+ " },\n" +
+ " {\n" +
+ " \"key\": \"override-config-list-3\",\n" +
+ " \"value\": []\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+
+ public void testDynamicConfigHandler() throws Exception {
+ String module = "test1";
+ File localConfigFile = createFileFromStr(localConfig, module);
+
+ File mergedFile = DynamicConfigHandler
+ .getMergedDynamicConfigFile(localConfigFile, overrideJson, module);
+
+ DynamicConfig.Params params = DynamicConfig.genParamsFromFile(mergedFile);
+
+ assertEquals("override-config-val-1", params.mDynamicParams.get("override-config-1"));
+ assertTrue(params.mDynamicArrayParams.get("override-config-list-1")
+ .contains("override-config-list-val-1-1"));
+ assertTrue(params.mDynamicArrayParams.get("override-config-list-1")
+ .contains("override-config-list-val-1-2"));
+ assertTrue(params.mDynamicArrayParams.get("override-config-list-3").size() == 0);
+
+ assertEquals("test config 1", params.mDynamicParams.get("test-config-1"));
+ assertTrue(params.mDynamicArrayParams.get("config-list").contains("config2"));
+
+ assertEquals("override-config-val-2", params.mDynamicParams.get("override-config-2"));
+ assertEquals(1, params.mDynamicArrayParams.get("override-config-list-2").size());
+ assertTrue(params.mDynamicArrayParams.get("override-config-list-2")
+ .contains("override-config-list-val-2-1"));
+ }
+
+
+ private File createFileFromStr(String configStr, String module) throws IOException {
+ File file = File.createTempFile(module, "dynamic");
+ FileOutputStream stream = null;
+ try {
+ stream = new FileOutputStream(file);
+ stream.write(configStr.getBytes());
+ stream.flush();
+ } finally {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ return file;
+ }
+}
diff --git a/common/host-side/util/tests/src/com/android/compatibility/common/util/HostUnitTests.java b/common/host-side/util/tests/src/com/android/compatibility/common/util/HostUnitTests.java
new file mode 100644
index 0000000..8cf1e3f
--- /dev/null
+++ b/common/host-side/util/tests/src/com/android/compatibility/common/util/HostUnitTests.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * A test suite for all host util unit tests.
+ * <p/>
+ * All tests listed here should be self-contained, and do not require any external dependencies.
+ */
+public class HostUnitTests extends TestSuite {
+
+ public HostUnitTests() {
+ super();
+ addTestSuite(DynamicConfigHandlerTest.class);
+ addTestSuite(MetricsStoreTest.class);
+ }
+
+ public static Test suite() {
+ return new HostUnitTests();
+ }
+}
\ No newline at end of file
diff --git a/common/util/tests/src/com/android/compatibility/common/util/MetricsStoreTest.java b/common/host-side/util/tests/src/com/android/compatibility/common/util/MetricsStoreTest.java
similarity index 100%
rename from common/util/tests/src/com/android/compatibility/common/util/MetricsStoreTest.java
rename to common/host-side/util/tests/src/com/android/compatibility/common/util/MetricsStoreTest.java
diff --git a/common/host-side/xml-plan-generator/Android.mk b/common/host-side/xml-plan-generator/Android.mk
deleted file mode 100644
index 53718e5..0000000
--- a/common/host-side/xml-plan-generator/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2014 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := compatibility-common-util-hostsidelib_v2
-
-LOCAL_STATIC_JAVA_LIBRARIES := vogarexpectlib
-
-LOCAL_JAR_MANIFEST := MANIFEST.mf
-
-LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
-
-LOCAL_MODULE := compatibility-xml-plan-generator_v2
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-###############################################################################
-# Build the tests
-###############################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, tests/src)
-
-LOCAL_JAVA_LIBRARIES := compatibility-tradefed_v2 compatibility-xml-plan-generator_v2 junit
-
-LOCAL_MODULE := compatibility-xml-plan-generator-tests_v2
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/common/host-side/xml-plan-generator/MANIFEST.mf b/common/host-side/xml-plan-generator/MANIFEST.mf
deleted file mode 100644
index 95aee0d..0000000
--- a/common/host-side/xml-plan-generator/MANIFEST.mf
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Main-Class: com.android.compatibility.common.xmlgenerator.XmlPlanGenerator
-Class-Path: compatibility-common-util-hostsidelib_v2.jar
diff --git a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/Test.java b/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/Test.java
deleted file mode 100644
index d3e1d88..0000000
--- a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/Test.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.xmlgenerator;
-
-public class Test {
-
- private final String mName;
-
- public Test(String name) {
- mName = name;
- }
-
- public String getName() {
- return mName;
- }
-}
diff --git a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/TestCase.java b/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/TestCase.java
deleted file mode 100644
index 65b4aa3..0000000
--- a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/TestCase.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.xmlgenerator;
-
-import java.util.ArrayList;
-
-public class TestCase {
-
- private final String mName;
- private final ArrayList<Test> mTests = new ArrayList<Test>();
-
- public TestCase(String name) {
- mName = name;
- }
-
- public void addTest(Test test) {
- mTests.add(test);
- }
-
- public String getName() {
- return mName;
- }
-
- public ArrayList<Test> getTests() {
- return mTests;
- }
-}
diff --git a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/TestListParser.java b/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/TestListParser.java
deleted file mode 100644
index 6880440..0000000
--- a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/TestListParser.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.xmlgenerator;
-
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Scanner;
-
-/**
- * Parser of test lists in the form;
- *
- * suite:android.sample
- * case:SampleTest
- * test:testA
- * test:testB
- * suite:android.sample.ui
- * case:SampleUiTest
- * test:testA
- * test:testB
- */
-public class TestListParser {
-
- private TestListParser() {}
-
- public static HashMap<String, TestSuite> parse(InputStream input) {
- final HashMap<String, TestSuite> suites = new HashMap<String, TestSuite>();
- TestSuite currentSuite = null;
- TestCase currentCase = null;
- Scanner in = null;
- try {
- in = new Scanner(input);
- while (in.hasNextLine()) {
- final String line = in.nextLine();
- final String[] parts = line.split(":");
- if (parts.length != 2) {
- throw new RuntimeException("Invalid Format: " + line);
- }
- final String key = parts[0];
- final String value = parts[1];
- if (currentSuite == null) {
- if (!"suite".equals(key)) {
- throw new RuntimeException("TestSuite Expected");
- }
- final String[] names = value.split("\\.");
- for (int i = 0; i < names.length; i++) {
- final String name = names[i];
- if (currentSuite != null) {
- if (currentSuite.hasTestSuite(name)) {
- currentSuite = currentSuite.getTestSuite(name);
- } else {
- final TestSuite newSuite = new TestSuite(name);
- currentSuite.addTestSuite(newSuite);
- currentSuite = newSuite;
- }
- } else if (suites.containsKey(name)) {
- currentSuite = suites.get(name);
- } else {
- currentSuite = new TestSuite(name);
- suites.put(name, currentSuite);
- }
- }
- } else if (currentCase == null) {
- if (!"case".equals(key)) {
- throw new RuntimeException("TestCase Expected");
- }
- currentCase = new TestCase(value);
- currentSuite.addTestCase(currentCase);
- } else {
- if (!"test".equals(key)) {
- throw new RuntimeException("Test Expected");
- }
- currentCase.addTest(new Test(value));
- }
- }
- } finally {
- if (in != null) {
- in.close();
- }
- }
- return suites;
- }
-}
diff --git a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/TestSuite.java b/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/TestSuite.java
deleted file mode 100644
index db4fd07c..0000000
--- a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/TestSuite.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.xmlgenerator;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public class TestSuite {
-
- private final String mName;
- private final HashMap<String, TestSuite> mTestSuites = new HashMap<String, TestSuite>();
- private final ArrayList<TestCase> mTestCases = new ArrayList<TestCase>();
-
- public TestSuite(String name) {
- mName = name;
- }
-
- public boolean hasTestSuite(String name) {
- return mTestSuites.containsKey(name);
- }
-
- public TestSuite getTestSuite(String name) {
- return mTestSuites.get(name);
- }
-
- public void addTestSuite(TestSuite testSuite) {
- mTestSuites.put(testSuite.getName(), testSuite);
- }
-
- public void addTestCase(TestCase testCase) {
- mTestCases.add(testCase);
- }
-
- public String getName() {
- return mName;
- }
-
- public HashMap<String, TestSuite> getTestSuites() {
- return mTestSuites;
- }
-
- public ArrayList<TestCase> getTestCases() {
- return mTestCases;
- }
-}
diff --git a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/XmlPlanGenerator.java b/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/XmlPlanGenerator.java
deleted file mode 100644
index efb53d5..0000000
--- a/common/host-side/xml-plan-generator/src/com/android/compatibility/common/xmlgenerator/XmlPlanGenerator.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.xmlgenerator;
-
-import com.android.compatibility.common.util.KeyValueArgsParser;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-import vogar.ExpectationStore;
-import vogar.ModeId;
-import vogar.Result;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-
-import javax.xml.parsers.DocumentBuilderFactory;
-
-/**
- * Passes the scanner output and outputs an xml description of the tests.
- */
-public class XmlPlanGenerator {
-
- private final ExpectationStore mExpectations;
- private final String mAppNameSpace;
- private final String mAppPackageName;
- private final String mName;
- private final String mRunner;
- private final String mTargetBinaryName;
- private final String mTargetNameSpace;
- private final String mJarPath;
- private final String mTestType;
- private final String mOutput;
-
- private XmlPlanGenerator(ExpectationStore expectations, String appNameSpace,
- String appPackageName, String name, String runner, String targetBinaryName,
- String targetNameSpace, String jarPath, String testType, String output) {
- mExpectations = expectations;
- mAppNameSpace = appNameSpace;
- mAppPackageName = appPackageName;
- mName = name;
- mRunner = runner;
- mTargetBinaryName = targetBinaryName;
- mTargetNameSpace = targetNameSpace;
- mJarPath = jarPath;
- mTestType = testType;
- mOutput = output;
- }
-
- private void writePackageXml() throws IOException {
- OutputStream out = System.out;
- if (mOutput != null) {
- out = new FileOutputStream(mOutput);
- }
- PrintWriter writer = null;
- try {
- writer = new PrintWriter(out);
- writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
- writeTestPackage(writer);
- } finally {
- if (writer != null) {
- writer.close();
- }
- }
- }
-
- private void writeTestPackage(PrintWriter writer) {
- writer.append("<TestPackage");
- if (mAppNameSpace != null) {
- writer.append(" appNameSpace=\"").append(mAppNameSpace).append("\"");
- }
-
- writer.append(" appPackageName=\"").append(mAppPackageName).append("\"");
- writer.append(" name=\"").append(mName).append("\"");
-
- if (mRunner != null) {
- writer.append(" runner=\"").append(mRunner).append("\"");
- }
-
- if (mAppNameSpace != null && mTargetNameSpace != null
- && !mAppNameSpace.equals(mTargetNameSpace)) {
- writer.append(" targetBinaryName=\"").append(mTargetBinaryName).append("\"");
- writer.append(" targetNameSpace=\"").append(mTargetNameSpace).append("\"");
- }
-
- if (mTestType != null && !mTestType.isEmpty()) {
- writer.append(" testType=\"").append(mTestType).append("\"");
- }
-
- if (mJarPath != null) {
- writer.append(" jarPath=\"").append(mJarPath).append("\"");
- }
-
- writer.println(" version=\"1.0\">");
-
- final HashMap<String, TestSuite> suites = TestListParser.parse(System.in);
- if (suites.isEmpty()) {
- throw new RuntimeException("No TestSuites Found");
- }
- writeTestSuites(writer, suites, "");
- writer.println("</TestPackage>");
- }
-
- private void writeTestSuites(PrintWriter writer, HashMap<String, TestSuite> suites, String name) {
- for (String suiteName : suites.keySet()) {
- final TestSuite suite = suites.get(suiteName);
- writer.append("<TestSuite name=\"").append(suiteName).println("\">");
- final String fullname = name + suiteName + ".";
- writeTestSuites(writer, suite.getTestSuites(), fullname);
- writeTestCases(writer, suite.getTestCases(), fullname);
- writer.println("</TestSuite>");
- }
- }
-
- private void writeTestCases(PrintWriter writer, ArrayList<TestCase> cases, String name) {
- for (TestCase testCase : cases) {
- final String caseName = testCase.getName();
- writer.append("<TestCase name=\"").append(caseName).println("\">");
- final String fullname = name + caseName;
- writeTests(writer, testCase.getTests(), fullname);
- writer.println("</TestCase>");
- }
- }
-
- private void writeTests(PrintWriter writer, ArrayList<Test> tests, String name) {
- if (tests.isEmpty()) {
- throw new RuntimeException("No Tests Found");
- }
- for (Test test : tests) {
- final String testName = test.getName();
- writer.append("<Test name=\"").append(testName).append("\"");
- final String fullname = name + "#" + testName;
- if (isKnownFailure(mExpectations, fullname)) {
- writer.append(" expectation=\"failure\"");
- }
- writer.println(" />");
- }
- }
-
- public static boolean isKnownFailure(ExpectationStore store, String fullname) {
- return store != null && store.get(fullname).getResult() != Result.SUCCESS;
- }
-
- public static void main(String[] args) throws Exception {
- final HashMap<String, String> argsMap = KeyValueArgsParser.parse(args);
- final String packageName = argsMap.get("-p");
- final String name = argsMap.get("-n");
- final String testType = argsMap.get("-t");
- final String jarPath = argsMap.get("-j");
- final String instrumentation = argsMap.get("-i");
- final String manifest = argsMap.get("-m");
- final String expectations = argsMap.get("-e");
- final String output = argsMap.get("-o");
- String appNameSpace = argsMap.get("-a");
- String targetNameSpace = argsMap.get("-r");
- if (packageName == null || name == null) {
- usage(args);
- }
- String runner = null;
- if (manifest != null) {
- Document m = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(manifest);
- Element elem = m.getDocumentElement();
- appNameSpace = elem.getAttribute("package");
- runner = getElementAttribute(elem, "instrumentation", "android:name");
- targetNameSpace = getElementAttribute(elem, "instrumentation", "android:targetPackage");
- }
-
- final HashSet<File> expectationFiles = new HashSet<File>();
- if (expectations != null) {
- expectationFiles.add(new File(expectations));
- }
- final ExpectationStore store = ExpectationStore.parse(expectationFiles, ModeId.DEVICE);
- XmlPlanGenerator generator = new XmlPlanGenerator(store, appNameSpace, packageName, name,
- runner, instrumentation, targetNameSpace, jarPath, testType, output);
- generator.writePackageXml();
- }
-
- private static String getElementAttribute(Element parent, String elem, String name) {
- NodeList nodeList = parent.getElementsByTagName(elem);
- if (nodeList.getLength() > 0) {
- Element element = (Element) nodeList.item(0);
- return element.getAttribute(name);
- }
- return null;
- }
-
- private static void usage(String[] args) {
- System.err.println("Arguments: " + Arrays.toString(args));
- System.err.println("Usage: compatibility-xml-plan-generator -p PACKAGE_NAME -n NAME" +
- "[-t TEST_TYPE] [-j JAR_PATH] [-i INSTRUMENTATION] [-m MANIFEST] [-e EXPECTATIONS]" +
- "[-o OUTPUT]");
- System.exit(1);
- }
-}
diff --git a/common/host-side/xml-plan-generator/tests/src/com/android/compatibility/common/xmlgenerator/XmlPlanGeneratorTest.java b/common/host-side/xml-plan-generator/tests/src/com/android/compatibility/common/xmlgenerator/XmlPlanGeneratorTest.java
deleted file mode 100644
index 082af17..0000000
--- a/common/host-side/xml-plan-generator/tests/src/com/android/compatibility/common/xmlgenerator/XmlPlanGeneratorTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.compatibility.common.xmlgenerator;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayInputStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Scanner;
-
-public class XmlPlanGeneratorTest extends TestCase {
-
- private static final String JAR = "out/host/linux-x86/framework/compatibility-xml-plan-generator_v2.jar";
- private static final String PACKAGE_NAME = "com.android.test";
- private static final String NAME = "ValidTest";
- private static final String VALID_RESULT =
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
- "<TestPackage appPackageName=\"com.android.test\" name=\"ValidTest\" version=\"1.0\">" +
- "<TestSuite name=\"com\">" +
- "<TestSuite name=\"android\">" +
- "<TestSuite name=\"test\">" +
- "<TestCase name=\"ValidTest\">" +
- "<Test name=\"testA\" />" +
- "</TestCase>" +
- "</TestSuite>" +
- "</TestSuite>" +
- "</TestSuite>" +
- "</TestPackage>";
-
- private static final String VALID =
- "suite:com.android.test\n" +
- "case:ValidTest\n" +
- "test:testA\n";
-
- private static final String INVALID_A = "";
-
- private static final String INVALID_B =
- "suite:com.android.test\n" +
- "case:InvalidTest\n";
-
- private static final String INVALID_C =
- "uh oh";
-
- private static final String INVALID_D =
- "test:testA\n" +
- "case:InvalidTest\n" +
- "suite:com.android.test\n";
-
- private static final String INVALID_E =
- "suite:com.android.test\n" +
- "test:testA\n" +
- "case:InvalidTest\n";
-
- public void testValid() throws Exception {
- assertEquals(VALID_RESULT, runGenerator(VALID));
- }
-
- public void testInvalidA() throws Exception {
- assertNull(runGenerator(INVALID_A));
- }
-
- public void testInvalidB() throws Exception {
- assertNull(runGenerator(INVALID_B));
- }
-
- public void testTestListParserInvalidFormat() throws Exception {
- runTestListParser(INVALID_C);
- }
-
- public void testTestListParserSuiteExpected() throws Exception {
- runTestListParser(INVALID_D);
- }
-
- public void testTestListParserCaseExpected() throws Exception {
- runTestListParser(INVALID_E);
- }
-
- private static String runGenerator(String input) throws Exception {
- ArrayList<String> args = new ArrayList<String>();
- args.add("java");
- args.add("-jar");
- args.add(JAR);
- args.add("-p");
- args.add(PACKAGE_NAME);
- args.add("-n");
- args.add(NAME);
-
- final Process p = new ProcessBuilder(args).start();
- final PrintWriter out = new PrintWriter(p.getOutputStream());
- out.print(input);
- out.flush();
- out.close();
- final StringBuilder output = new StringBuilder();
- final Scanner in = new Scanner(p.getInputStream());
- while (in.hasNextLine()) {
- output.append(in.nextLine());
- }
- int ret = p.waitFor();
- if (ret == 0) {
- return output.toString();
- }
- return null;
- }
-
- private static void runTestListParser(String input) throws Exception {
- try {
- final ByteArrayInputStream in = new ByteArrayInputStream(input.getBytes());
- final HashMap<String, TestSuite> suites = TestListParser.parse(in);
- fail();
- } catch (RuntimeException e) {}
- }
-}
diff --git a/common/util/Android.mk b/common/util/Android.mk
index 84ced65..d011636 100644
--- a/common/util/Android.mk
+++ b/common/util/Android.mk
@@ -24,7 +24,7 @@
LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := compatibility-common-util-devicesidelib_v2
+LOCAL_MODULE := compatibility-common-util-devicesidelib
LOCAL_SDK_VERSION := current
@@ -40,27 +40,10 @@
LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := compatibility-common-util-hostsidelib_v2
+LOCAL_MODULE := compatibility-common-util-hostsidelib
-LOCAL_STATIC_JAVA_LIBRARIES := kxml2-2.3.0
+LOCAL_STATIC_JAVA_LIBRARIES := junit kxml2-2.3.0
include $(BUILD_HOST_JAVA_LIBRARY)
-###############################################################################
-# Build the tests
-###############################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, tests/src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- junit \
- kxml2-2.3.0 \
- compatibility-common-util-hostsidelib_v2
-
-LOCAL_MODULE := compatibility-common-util-tests_v2
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_JAVA_LIBRARY)
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/common/util/run_unit_tests.sh b/common/util/run_unit_tests.sh
deleted file mode 100755
index 04a6745..0000000
--- a/common/util/run_unit_tests.sh
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-# Copyright (C) 2012 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.
-
-# helper script for running the cts common unit tests
-
-checkFile() {
- if [ ! -f "$1" ]; then
- echo "Unable to locate $1"
- exit
- fi;
-}
-
-# check if in Android build env
-if [ ! -z ${ANDROID_BUILD_TOP} ]; then
- HOST=`uname`
- if [ "$HOST" == "Linux" ]; then
- OS="linux-x86"
- elif [ "$HOST" == "Darwin" ]; then
- OS="darwin-x86"
- else
- echo "Unrecognized OS"
- exit
- fi;
-fi;
-
-JAR_DIR=${ANDROID_BUILD_TOP}/out/host/$OS/framework
-JARS="tradefed-prebuilt.jar compatibility-common-util-hostsidelib_v2.jar compatibility-common-util-tests_v2.jar"
-
-for JAR in $JARS; do
- checkFile ${JAR_DIR}/${JAR}
- JAR_PATH=${JAR_PATH}:${JAR_DIR}/${JAR}
-done
-
-java $RDBG_FLAG \
- -cp ${JAR_PATH} com.android.tradefed.command.Console run singleCommand host -n --class com.android.compatibility.common.util.UnitTests "$@"
-
diff --git a/common/util/src/com/android/compatibility/common/util/AbiUtils.java b/common/util/src/com/android/compatibility/common/util/AbiUtils.java
new file mode 100644
index 0000000..ef42a00
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/AbiUtils.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2014 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 com.android.compatibility.common.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Utility class for handling device ABIs
+ */
+public class AbiUtils {
+
+ /**
+ * The set of 32Bit ABIs.
+ */
+ private static final Set<String> ABIS_32BIT = new HashSet<String>();
+
+ /**
+ * The set of 64Bit ABIs.
+ */
+ private static final Set<String> ABIS_64BIT = new HashSet<String>();
+
+ /**
+ * The set of ARM ABIs.
+ */
+ private static final Set<String> ARM_ABIS = new HashSet<String>();
+
+ /**
+ * The set of Intel ABIs.
+ */
+ private static final Set<String> INTEL_ABIS = new HashSet<String>();
+
+ /**
+ * The set of Mips ABIs.
+ */
+ private static final Set<String> MIPS_ABIS = new HashSet<String>();
+
+ /**
+ * The set of ABI names which Compatibility supports.
+ */
+ private static final Set<String> ABIS_SUPPORTED_BY_COMPATIBILITY = new HashSet<String>();
+
+ /**
+ * The map of architecture to ABI.
+ */
+ private static final Map<String, Set<String>> ARCH_TO_ABIS = new HashMap<String, Set<String>>();
+ static {
+ ABIS_32BIT.add("armeabi-v7a");
+ ABIS_32BIT.add("x86");
+ ABIS_32BIT.add("mips");
+
+ ABIS_64BIT.add("arm64-v8a");
+ ABIS_64BIT.add("x86_64");
+ ABIS_64BIT.add("mips64");
+
+ ARM_ABIS.add("armeabi-v7a");
+ ARM_ABIS.add("arm64-v8a");
+
+ INTEL_ABIS.add("x86");
+ INTEL_ABIS.add("x86_64");
+
+ MIPS_ABIS.add("mips");
+ MIPS_ABIS.add("mips64");
+
+ ARCH_TO_ABIS.put("arm", ARM_ABIS);
+ ARCH_TO_ABIS.put("arm64", ARM_ABIS);
+ ARCH_TO_ABIS.put("x86", INTEL_ABIS);
+ ARCH_TO_ABIS.put("x86_64", INTEL_ABIS);
+ ARCH_TO_ABIS.put("mips", MIPS_ABIS);
+ ARCH_TO_ABIS.put("mips64", MIPS_ABIS);
+
+ ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(ARM_ABIS);
+ ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(INTEL_ABIS);
+ ABIS_SUPPORTED_BY_COMPATIBILITY.addAll(MIPS_ABIS);
+ }
+
+ /**
+ * Private constructor to avoid instantiation.
+ */
+ private AbiUtils() {}
+
+ /**
+ * Returns the set of ABIs associated with the given architecture.
+ * @param arch The architecture to look up.
+ * @return a new Set containing the ABIs.
+ */
+ public static Set<String> getAbisForArch(String arch) {
+ if (arch == null || arch.isEmpty() || !ARCH_TO_ABIS.containsKey(arch)) {
+ return getAbisSupportedByCompatibility();
+ }
+ return new HashSet<String>(ARCH_TO_ABIS.get(arch));
+ }
+
+ /**
+ * Returns the set of ABIs supported by Compatibility.
+ * @return a new Set containing the supported ABIs.
+ */
+ public static Set<String> getAbisSupportedByCompatibility() {
+ return new HashSet<String>(ABIS_SUPPORTED_BY_COMPATIBILITY);
+ }
+
+ /**
+ * @param abi The ABI name to test.
+ * @return true if the given ABI is supported by Compatibility.
+ */
+ public static boolean isAbiSupportedByCompatibility(String abi) {
+ return ABIS_SUPPORTED_BY_COMPATIBILITY.contains(abi);
+ }
+
+ /**
+ * Creates a flag for the given ABI.
+ * @param abi the ABI to create the flag for.
+ * @return a string which can be add to a command sent to ADB.
+ */
+ public static String createAbiFlag(String abi) {
+ if (abi == null || abi.isEmpty() || !isAbiSupportedByCompatibility(abi)) {
+ return "";
+ }
+ return String.format("--abi %s ", abi);
+ }
+
+ /**
+ * Creates a unique id from the given ABI and name.
+ * @param abi The ABI to use.
+ * @param name The name to use.
+ * @return a string which uniquely identifies a run.
+ */
+ public static String createId(String abi, String name) {
+ return String.format("%s %s", abi, name);
+ }
+
+ /**
+ * Parses a unique id into the ABI and name.
+ * @param id The id to parse.
+ * @return a string array containing the ABI and name.
+ */
+ public static String[] parseId(String id) {
+ if (id == null || !id.contains(" ")) {
+ return new String[] {"", ""};
+ }
+ return id.split(" ");
+ }
+
+ /**
+ * @return the test name portion of the test id.
+ * e.g. armeabi-v7a android.mytest = android.mytest
+ */
+ public static String parseTestName(String id) {
+ return parseId(id)[1];
+ }
+
+ /**
+ * @return the abi portion of the test id.
+ * e.g. armeabi-v7a android.mytest = armeabi-v7a
+ */
+ public static String parseAbi(String id) {
+ return parseId(id)[0];
+ }
+
+ /**
+ * @param name The name of the ABI.
+ * @return The bitness of the ABI with the given name
+ */
+ public static String getBitness(String name) {
+ return ABIS_32BIT.contains(name) ? "32" : "64";
+ }
+
+ /**
+ * @param unsupportedAbiDescription A comma separated string containing abis.
+ * @return A List of Strings containing valid ABIs.
+ */
+ public static Set<String> parseAbiList(String unsupportedAbiDescription) {
+ Set<String> abiSet = new HashSet<>();
+ String[] descSegments = unsupportedAbiDescription.split(":");
+ if (descSegments.length == 2) {
+ for (String abi : descSegments[1].split(",")) {
+ String trimmedAbi = abi.trim();
+ if (isAbiSupportedByCompatibility(trimmedAbi)) {
+ abiSet.add(trimmedAbi);
+ }
+ }
+ }
+ return abiSet;
+ }
+}
diff --git a/common/util/src/com/android/compatibility/common/util/CaseResult.java b/common/util/src/com/android/compatibility/common/util/CaseResult.java
new file mode 100644
index 0000000..e16ad1f
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/CaseResult.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Data structure for a Compatibility test case result.
+ */
+public class CaseResult implements ICaseResult {
+
+ private String mName;
+
+ private Map<String, ITestResult> mResults = new HashMap<>();
+
+ /**
+ * Creates a {@link CaseResult} for the given name, eg <package-name>.<class-name>
+ */
+ public CaseResult(String name) {
+ mName = name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ITestResult getOrCreateResult(String testName) {
+ ITestResult result = mResults.get(testName);
+ if (result == null) {
+ result = new TestResult(this, testName);
+ mResults.put(testName, result);
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ITestResult getResult(String testName) {
+ return mResults.get(testName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<ITestResult> getResults(TestStatus status) {
+ List<ITestResult> results = new ArrayList<>();
+ for (ITestResult result : mResults.values()) {
+ if (result.getResultStatus() == status) {
+ results.add(result);
+ }
+ }
+ return results;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<ITestResult> getResults() {
+ ArrayList<ITestResult> results = new ArrayList<>(mResults.values());
+ Collections.sort(results);
+ return results;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int countResults(TestStatus status) {
+ int total = 0;
+ for (ITestResult result : mResults.values()) {
+ if (result.getResultStatus() == status) {
+ total++;
+ }
+ }
+ return total;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(ICaseResult another) {
+ return getName().compareTo(another.getName());
+ }
+
+}
\ No newline at end of file
diff --git a/common/util/src/com/android/compatibility/common/util/DynamicConfig.java b/common/util/src/com/android/compatibility/common/util/DynamicConfig.java
new file mode 100644
index 0000000..a0b1d5e
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/DynamicConfig.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.util;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Load dynamic config for test cases
+ */
+public class DynamicConfig {
+ public final static String MODULE_NAME = "module-name";
+
+ //XML constant
+ public static final String NS = null;
+ public static final String DYNAMIC_CONFIG_TAG = "DynamicConfig";
+ public static final String CONFIG_TAG = "Config";
+ public static final String CONFIG_LIST_TAG = "ConfigList";
+ public static final String ITEM_TAG = "Item";
+ public static final String KEY_ATTR = "key";
+
+ public final static String CONFIG_FOLDER_ON_DEVICE = "/sdcard/dynamic-config-files/";
+ public final static String CONFIG_FOLDER_ON_HOST =
+ System.getProperty("java.io.tmpdir") + "/dynamic-config-files/";
+ public final static String MERGED_CONFIG_FILE_FOLDER =
+ System.getProperty("java.io.tmpdir") + "/dynamic-config-files/merged";
+
+
+ protected Params params;
+
+ protected void initConfigFromXml(File file) throws XmlPullParserException, IOException {
+ params = genParamsFromFile(file);
+ }
+
+ public String getConfig(String key) {
+ return params.mDynamicParams.get(key);
+ }
+
+ public List<String> getConfigList(String key) {
+ return params.mDynamicArrayParams.get(key);
+ }
+
+ public static File getConfigFile(File configFolder, String moduleName)
+ throws FileNotFoundException {
+ File config = new File(configFolder, String.format("%s.dynamic", moduleName));
+ if (!config.exists()) {
+ throw new FileNotFoundException(String.format("Cannot find %s.dynamic", moduleName));
+ }
+ return config;
+ }
+
+ public static class Params {
+ public Map<String, String> mDynamicParams = new HashMap<>();
+ public Map<String, List<String>> mDynamicArrayParams = new HashMap<>();
+ }
+
+ public static Params genParamsFromFile(File file) throws XmlPullParserException, IOException {
+ Params param = new Params();
+
+ XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setInput(new InputStreamReader(new FileInputStream(file)));
+
+ parser.nextTag();
+ parser.require(XmlPullParser.START_TAG, NS, DYNAMIC_CONFIG_TAG);
+
+ while (parser.nextTag() == XmlPullParser.START_TAG) {
+ if (parser.getName().equals(CONFIG_TAG)) {
+ String key = parser.getAttributeValue(NS, KEY_ATTR);
+ String value = parser.nextText();
+ parser.require(XmlPullParser.END_TAG, NS, CONFIG_TAG);
+ if (key != null && !key.isEmpty()) {
+ param.mDynamicParams.put(key, value);
+ }
+ } else {
+ List<String> arrayValue = new ArrayList<>();
+ parser.require(XmlPullParser.START_TAG, NS, CONFIG_LIST_TAG);
+ String key = parser.getAttributeValue(NS, KEY_ATTR);
+ while (parser.nextTag() == XmlPullParser.START_TAG) {
+ parser.require(XmlPullParser.START_TAG, NS, ITEM_TAG);
+ arrayValue.add(parser.nextText());
+ parser.require(XmlPullParser.END_TAG, NS, ITEM_TAG);
+ }
+ parser.require(XmlPullParser.END_TAG, NS, CONFIG_LIST_TAG);
+ if (key != null && !key.isEmpty()) {
+ param.mDynamicArrayParams.put(key, arrayValue);
+ }
+ }
+ }
+ parser.require(XmlPullParser.END_TAG, NS, DYNAMIC_CONFIG_TAG);
+ return param;
+ }
+}
diff --git a/common/util/src/com/android/compatibility/common/util/ICaseResult.java b/common/util/src/com/android/compatibility/common/util/ICaseResult.java
new file mode 100644
index 0000000..99e646a
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/ICaseResult.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+import java.util.List;
+
+/**
+ * Data structure for a Compatibility test case result.
+ */
+public interface ICaseResult extends Comparable<ICaseResult> {
+
+ String getName();
+
+ /**
+ * Gets a {@link ITestResult} for the given test, creating it if it doesn't exist.
+ *
+ * @param testName the name of the test eg <method-name>
+ * @return the {@link ITestResult} or <code>null</code>
+ */
+ ITestResult getOrCreateResult(String testName);
+
+ /**
+ * Gets the {@link ITestResult} for given test.
+ *
+ * @param testName the name of the test eg <method-name>
+ * @return the {@link ITestResult} or <code>null</code>
+ */
+ ITestResult getResult(String testName);
+
+ /**
+ * Gets all results sorted by name.
+ */
+ List<ITestResult> getResults();
+
+ /**
+ * Gets all results which have the given status.
+ */
+ List<ITestResult> getResults(TestStatus status);
+
+ /**
+ * Counts the number of results which have the given status.
+ */
+ int countResults(TestStatus status);
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/IInvocationResult.java b/common/util/src/com/android/compatibility/common/util/IInvocationResult.java
new file mode 100644
index 0000000..c1e5d28
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/IInvocationResult.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Interface for a the result of a single Compatibility invocation.
+ */
+public interface IInvocationResult {
+
+ /**
+ * @return the starting timestamp.
+ */
+ long getStartTime();
+
+ /**
+ * @param time the starting timestamp
+ */
+ void setStartTime(long time);
+
+ /**
+ * Count the number of results with given status.
+ */
+ int countResults(TestStatus result);
+
+ /**
+ * @param plan the plan associated with this result.
+ */
+ void setTestPlan(String plan);
+
+ /**
+ * @return the test plan associated with this result.
+ */
+ String getTestPlan();
+
+ /**
+ * Adds the given device serial to the result.
+ */
+ void addDeviceSerial(String serial);
+
+ /**
+ * @return the device serials associated with result.
+ */
+ Set<String> getDeviceSerials();
+
+ /**
+ * @return the {@link IModuleResult} for the given id, creating one if it doesn't exist
+ */
+ IModuleResult getOrCreateModule(String id);
+
+ /**
+ * @return the {@link IModuleResult}s sorted by id.
+ */
+ List<IModuleResult> getModules();
+
+ /**
+ * @return the directory containing this result.
+ */
+ File getResultDir();
+
+ /**
+ * Adds the given build info to the result.
+ */
+ void addBuildInfo(String key, String value);
+
+ /**
+ * Gets the {@link Map} of build info collected.
+ */
+ Map<String, String> getBuildInfo();
+}
diff --git a/common/util/src/com/android/compatibility/common/util/IModuleResult.java b/common/util/src/com/android/compatibility/common/util/IModuleResult.java
new file mode 100644
index 0000000..6d4efa1
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/IModuleResult.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+import java.util.List;
+
+/**
+ * Data structure for a Compatibility test module result.
+ */
+public interface IModuleResult extends Comparable<IModuleResult> {
+
+ String getId();
+
+ String getName();
+
+ String getAbi();
+
+ void addRuntime(long elapsedTime);
+
+ long getRuntime();
+
+ /**
+ * Gets a {@link ICaseResult} for the given testcase, creating it if it doesn't exist.
+ *
+ * @param caseName the name of the testcase eg <package-name><class-name>
+ * @return the {@link ICaseResult} or <code>null</code>
+ */
+ ICaseResult getOrCreateResult(String caseName);
+
+ /**
+ * Gets the {@link ICaseResult} result for given testcase.
+ *
+ * @param caseName the name of the testcase eg <package-name><class-name>
+ * @return the {@link ITestResult} or <code>null</code>
+ */
+ ICaseResult getResult(String caseName);
+
+ /**
+ * Gets all results sorted by name.
+ */
+ List<ICaseResult> getResults();
+
+ /**
+ * Counts the number of results which have the given status.
+ */
+ int countResults(TestStatus status);
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/ITestResult.java b/common/util/src/com/android/compatibility/common/util/ITestResult.java
new file mode 100644
index 0000000..f27cf48
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/ITestResult.java
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+/**
+ * Represents a single test result.
+ */
+public interface ITestResult extends Comparable<ITestResult> {
+
+ /**
+ * @return The name of this test result.
+ */
+ String getName();
+
+ /**
+ * @return The full name of this test result, ie
+ * <package-name>.<class-name>#<method-name>
+ */
+ String getFullName();
+
+ /**
+ * @return The {@link TestStatus} of this result.
+ */
+ TestStatus getResultStatus();
+
+ /**
+ * Sets the {@link TestStatus} of the result and updates the end time of the test.
+ *
+ * @param status The {@link TestStatus} of this result.
+ */
+ void setResultStatus(TestStatus status);
+
+ /**
+ * @return The failure message to display
+ */
+ String getMessage();
+
+ /**
+ * @param message The message to display which describes the failure
+ */
+ void setMessage(String message);
+
+ /**
+ * @return The stack trace generated by the failure
+ */
+ String getStackTrace();
+
+ /**
+ * @param stackTrace the stack trace generated by the failure.
+ */
+ void setStackTrace(String stackTrace);
+
+ /**
+ * @return the metrics report.
+ */
+ ReportLog getReportLog();
+
+ /**
+ * @param report the metrics report.
+ */
+ void setReportLog(ReportLog report);
+
+ /**
+ * @return the path of the bug report generated of the failure.
+ */
+ String getBugReport();
+
+ /**
+ * @param path the path of the bug report generated of the failure.
+ */
+ void setBugReport(String path);
+
+ /**
+ * @return the path of the log file generated of the failure.
+ */
+ String getLog();
+
+ /**
+ * @param path the path of the log file generated of the failure.
+ */
+ void setLog(String path);
+
+ /**
+ * @return the path of the screenshot file generated of the failure.
+ */
+ String getScreenshot();
+
+ /**
+ * @param path the path of the screenshot file generated of the failure.
+ */
+ void setScreenshot(String path);
+
+ /**
+ * Report the test as a failure.
+ *
+ * @param trace the stacktrace of the failure.
+ */
+ void failed(String trace);
+
+ /**
+ * Report that the test has completed.
+ *
+ * @param report A report generated by the test, or null.
+ */
+ void passed(ReportLog report);
+
+ /**
+ * Resets the result.
+ */
+ void reset();
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/InvocationResult.java b/common/util/src/com/android/compatibility/common/util/InvocationResult.java
new file mode 100644
index 0000000..b499bc1
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/InvocationResult.java
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Data structure for the detailed Compatibility test results.
+ */
+public class InvocationResult implements IInvocationResult {
+
+ private long mTimestamp;
+ private Map<String, IModuleResult> mModuleResults = new LinkedHashMap<>();
+ private Map<String, String> mBuildInfo = new HashMap<>();
+ private Set<String> mSerials = new HashSet<>();
+ private String mTestPlan;
+ private File mResultDir;
+
+ /**
+ * @param resultDir
+ */
+ public InvocationResult(File resultDir) {
+ this(System.currentTimeMillis(), resultDir);
+ }
+
+ /**
+ * @param timestamp
+ * @param resultDir
+ */
+ public InvocationResult(long timestamp, File resultDir) {
+ setStartTime(timestamp);
+ mResultDir = resultDir;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<IModuleResult> getModules() {
+ ArrayList<IModuleResult> modules = new ArrayList<>(mModuleResults.values());
+ Collections.sort(modules);
+ return modules;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int countResults(TestStatus result) {
+ int total = 0;
+ for (IModuleResult m : mModuleResults.values()) {
+ total += m.countResults(result);
+ }
+ return total;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IModuleResult getOrCreateModule(String id) {
+ IModuleResult moduleResult = mModuleResults.get(id);
+ if (moduleResult == null) {
+ moduleResult = new ModuleResult(id);
+ mModuleResults.put(id, moduleResult);
+ }
+ return moduleResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addBuildInfo(String key, String value) {
+ mBuildInfo.put(key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Map<String, String> getBuildInfo() {
+ return mBuildInfo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setStartTime(long time) {
+ mTimestamp = time;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getStartTime() {
+ return mTimestamp;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setTestPlan(String plan) {
+ mTestPlan = plan;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getTestPlan() {
+ return mTestPlan;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addDeviceSerial(String serial) {
+ mSerials.add(serial);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<String> getDeviceSerials() {
+ return mSerials;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public File getResultDir() {
+ return mResultDir;
+ }
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/MeasureRun.java b/common/util/src/com/android/compatibility/common/util/MeasureRun.java
index d58b8d438..2b8905f 100644
--- a/common/util/src/com/android/compatibility/common/util/MeasureRun.java
+++ b/common/util/src/com/android/compatibility/common/util/MeasureRun.java
@@ -25,7 +25,7 @@
*/
public void prepare(int i) throws Exception {
// default empty implementation
- };
+ }
abstract public void run(int i) throws Exception;
}
diff --git a/common/util/src/com/android/compatibility/common/util/MetricsStore.java b/common/util/src/com/android/compatibility/common/util/MetricsStore.java
deleted file mode 100644
index 9eeb94a..0000000
--- a/common/util/src/com/android/compatibility/common/util/MetricsStore.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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
- */
-
-package com.android.compatibility.common.util;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * A simple in-memory store for metrics results. This should be used for hostside metrics reporting.
- */
-public class MetricsStore {
-
- // needs concurrent version as there can be multiple client accessing this.
- // But there is no additional protection for the same key as that should not happen.
- private static final ConcurrentHashMap<String, ReportLog> mMap =
- new ConcurrentHashMap<String, ReportLog>();
-
- /**
- * Stores a result. Existing result with the same key will be replaced.
- * Note that key is generated in the form of device_serial#class#method name.
- * So there should be no concurrent test for the same (serial, class, method).
- * @param deviceSerial
- * @param abi
- * @param classMethodName
- * @param reportLog Contains the result to be stored
- */
- public static void storeResult(
- String deviceSerial, String abi, String classMethodName, ReportLog reportLog) {
- mMap.put(generateTestKey(deviceSerial, abi, classMethodName), reportLog);
- }
-
- /**
- * retrieves a metric result for the given condition and remove it from the internal
- * storage. If there is no result for the given condition, it will return null.
- */
- public static ReportLog removeResult(String deviceSerial, String abi, String classMethodName) {
- return mMap.remove(generateTestKey(deviceSerial, abi, classMethodName));
- }
-
- /**
- * @return test key in the form of device_serial#abi#class_name#method_name
- */
- private static String generateTestKey(String deviceSerial, String abi, String classMethodName) {
- return String.format("%s#%s#%s", deviceSerial, abi, classMethodName);
- }
-}
diff --git a/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java b/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java
index 0e2b004..0f4b597 100644
--- a/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java
+++ b/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java
@@ -21,6 +21,7 @@
import java.io.IOException;
import java.util.List;
+//TODO(stuartscott): Delete file for v2, ReportLog can serialize itself.
/**
* Serialize Metric data from {@link ReportLog} into compatibility report friendly XML
*/
@@ -36,26 +37,26 @@
if (reportLog == null) {
return;
}
- ReportLog.Result summary = reportLog.getSummary();
- List<ReportLog.Result> detailedMetrics = reportLog.getDetailedMetrics();
+ ReportLog.Metric summary = reportLog.getSummary();
+ List<ReportLog.Metric> detailedMetrics = reportLog.getDetailedMetrics();
// <Summary message="Average" scoreType="lower_better" unit="ms">195.2</Summary>
if (summary != null) {
mXmlSerializer.startTag(null, "Summary");
mXmlSerializer.attribute(null, "message", summary.getMessage());
- mXmlSerializer.attribute(null, "scoreType", summary.getType().getXmlString());
- mXmlSerializer.attribute(null, "unit", summary.getUnit().getXmlString());
+ mXmlSerializer.attribute(null, "scoreType", summary.getType().toReportString());
+ mXmlSerializer.attribute(null, "unit", summary.getUnit().toReportString());
mXmlSerializer.text(Double.toString(summary.getValues()[0]));
mXmlSerializer.endTag(null, "Summary");
}
if (!detailedMetrics.isEmpty()) {
mXmlSerializer.startTag(null, "Details");
- for (ReportLog.Result result : detailedMetrics) {
+ for (ReportLog.Metric result : detailedMetrics) {
mXmlSerializer.startTag(null, "ValueArray");
- mXmlSerializer.attribute(null, "source", result.getLocation());
+ mXmlSerializer.attribute(null, "source", result.getSource());
mXmlSerializer.attribute(null, "message", result.getMessage());
- mXmlSerializer.attribute(null, "scoreType", result.getType().getXmlString());
- mXmlSerializer.attribute(null, "unit", result.getUnit().getXmlString());
+ mXmlSerializer.attribute(null, "scoreType", result.getType().toReportString());
+ mXmlSerializer.attribute(null, "unit", result.getUnit().toReportString());
for (double value : result.getValues()) {
mXmlSerializer.startTag(null, "Value");
@@ -67,4 +68,4 @@
mXmlSerializer.endTag(null, "Details");
}
}
-}
+}
\ No newline at end of file
diff --git a/common/util/src/com/android/compatibility/common/util/ModuleResult.java b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
new file mode 100644
index 0000000..1f277f7
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Data structure for a Compatibility test module result.
+ */
+public class ModuleResult implements IModuleResult {
+
+ private String mId;
+ private long mRuntime = 0;
+
+ private Map<String, ICaseResult> mResults = new HashMap<>();
+
+ /**
+ * Creates a {@link ModuleResult} for the given id, created with
+ * {@link AbiUtils#createId(String, String)}
+ */
+ public ModuleResult(String id) {
+ mId = id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return AbiUtils.parseTestName(mId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getAbi() {
+ return AbiUtils.parseAbi(mId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addRuntime(long elapsedTime) {
+ mRuntime += elapsedTime;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getRuntime() {
+ return mRuntime;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ICaseResult getOrCreateResult(String caseName) {
+ ICaseResult result = mResults.get(caseName);
+ if (result == null) {
+ result = new CaseResult(caseName);
+ mResults.put(caseName, result);
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ICaseResult getResult(String caseName) {
+ return mResults.get(caseName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<ICaseResult> getResults() {
+ ArrayList<ICaseResult> results = new ArrayList<>(mResults.values());
+ Collections.sort(results);
+ return results;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int countResults(TestStatus status) {
+ int total = 0;
+ for (ICaseResult result : mResults.values()) {
+ total += result.countResults(status);
+ }
+ return total;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(IModuleResult another) {
+ return getId().compareTo(another.getId());
+ }
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/MultipartForm.java b/common/util/src/com/android/compatibility/common/util/MultipartForm.java
new file mode 100644
index 0000000..4ae7860
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/MultipartForm.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2011 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 com.android.compatibility.common.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Builds a multipart form and submits it. */
+class MultipartForm {
+
+ private static final String FORM_DATA_BOUNDARY = "C75I55u3R3p0r73r";
+
+ /* package */ final String mServerUrl;
+ /* package */ final Map<String, String> mFormValues = new HashMap<String, String>();
+ /* package */ String mName;
+ /* package */ String mFileName;
+ /* package */ byte[] mData;
+
+ /**
+ * Creates a new multi-part form with the given serverUrl.
+ */
+ public MultipartForm(String serverUrl) {
+ mServerUrl = serverUrl;
+ }
+
+ /**
+ * Adds a key value attribute to the form.
+ *
+ * @param name the name of the attribute.
+ * @param value the attribute's value.
+ * @return the {@link MultipartForm} for easy chaining.
+ */
+ public MultipartForm addFormValue(String name, String value) {
+ mFormValues.put(name, value);
+ return this;
+ }
+
+ /**
+ * Adds the file as the payload of the form.
+ *
+ * @param name The name of attribute
+ * @param fileName The file's name
+ * @param data The file's data
+ * @return the {@link MultipartForm} for easy chaining.
+ */
+ public MultipartForm addFormFile(String name, String fileName, byte[] data) {
+ mName = name;
+ mFileName = fileName;
+ mData = data;
+ return this;
+ }
+
+ /**
+ * Submits the form to the server url.
+ *
+ * This will handle a redirection from the server.
+ *
+ * @throws IOException
+ */
+ public void submit() throws IOException {
+ String redirectUrl = submitForm(mServerUrl);
+ if (redirectUrl != null) {
+ submitForm(redirectUrl);
+ }
+ }
+
+ /**
+ * @param serverUrl to post the data to
+ * @return a url if the server redirected to another url
+ * @throws IOException
+ */
+ private String submitForm(String serverUrl) throws IOException {
+ HttpURLConnection connection = null;
+ try {
+ URL url = new URL(serverUrl);
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setInstanceFollowRedirects(false);
+ connection.setRequestMethod("POST");
+ connection.setDoOutput(true);
+ connection.setRequestProperty("Content-Type",
+ "multipart/form-data; boundary=" + FORM_DATA_BOUNDARY);
+
+ byte[] body = getContentBody();
+ connection.setRequestProperty("Content-Length", Integer.toString(body.length));
+
+ OutputStream output = connection.getOutputStream();
+ try {
+ output.write(body);
+ } finally {
+ output.close();
+ }
+
+ // Open the stream to get a response. Otherwise request will be cancelled.
+ InputStream input = connection.getInputStream();
+ input.close();
+
+ if (connection.getResponseCode() == 302) {
+ return connection.getHeaderField("Location");
+ }
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+
+ return null;
+ }
+
+ /* package */ byte[] getContentBody() throws IOException {
+ ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(byteOutput));
+ writer.println();
+
+ for (Map.Entry<String, String> formValue : mFormValues.entrySet()) {
+ writeFormField(writer, formValue.getKey(), formValue.getValue());
+ }
+
+ if (mData != null) {
+ writeFormFileHeader(writer, mName, mFileName);
+ writer.flush(); // Must flush here before writing to the byte stream!
+ byteOutput.write(mData);
+ writer.println();
+ }
+ writer.append("--").append(FORM_DATA_BOUNDARY).println("--");
+ writer.flush();
+ writer.close();
+ return byteOutput.toByteArray();
+ }
+
+ private void writeFormField(PrintWriter writer, String name, String value) {
+ writer.append("--").println(FORM_DATA_BOUNDARY);
+ writer.append("Content-Disposition: form-data; name=\"").append(name).println("\"");
+ writer.println();
+ writer.println(value);
+ }
+
+ private void writeFormFileHeader(PrintWriter writer, String name, String fileName) {
+ writer.append("--").println(FORM_DATA_BOUNDARY);
+ writer.append("Content-Disposition: form-data; name=\"").append(name);
+ writer.append("\"; filename=\"").append(fileName).println("\"");
+ writer.println("Content-Type: application/x-gzip");
+ writer.println("Content-Transfer-Encoding: binary");
+ writer.println();
+ }
+}
diff --git a/common/util/src/com/android/compatibility/common/util/ReportLog.java b/common/util/src/com/android/compatibility/common/util/ReportLog.java
index 7209ac8..445bbd4 100644
--- a/common/util/src/com/android/compatibility/common/util/ReportLog.java
+++ b/common/util/src/com/android/compatibility/common/util/ReportLog.java
@@ -16,66 +16,93 @@
package com.android.compatibility.common.util;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-import java.util.StringTokenizer;
-import java.util.regex.Pattern;
/**
* Utility class to add results to the report.
*/
public class ReportLog implements Serializable {
- private static final String LOG_SEPARATOR = "+++";
- private static final String SUMMARY_SEPARATOR = "++++";
- private static final String LOG_ELEM_SEPARATOR = "|";
- private static final String EMPTY_CHAR = " ";
- private Result mSummary;
- private final List<Result> mDetails = new ArrayList<Result>();
+ private static final String ENCODING = "UTF-8";
+ private static final String TYPE = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer";
- static class Result implements Serializable {
- private String mLocation;
+ // XML constants
+ private static final String DETAIL_TAG = "Detail";
+ private static final String METRIC_TAG = "Metric";
+ private static final String MESSAGE_ATTR = "message";
+ private static final String SCORETYPE_ATTR = "score_type";
+ private static final String SCOREUNIT_ATTR = "score_unit";
+ private static final String SOURCE_ATTR = "source";
+ private static final String SUMMARY_TAG = "Summary";
+ private static final String VALUE_TAG = "Value";
+
+ private Metric mSummary;
+ private final List<Metric> mDetails = new ArrayList<>();
+
+ public static class Metric implements Serializable {
+ private static final int MAX_SOURCE_LENGTH = 200;
+ private static final int MAX_MESSAGE_LENGTH = 200;
+ private static final int MAX_NUM_VALUES = 1000;
+ private String mSource;
private String mMessage;
private double[] mValues;
private ResultType mType;
private ResultUnit mUnit;
- private Double mTarget;
-
- private Result(String location, String message, double[] values,
- ResultType type, ResultUnit unit) {
- this(location, message, values, null /*target*/, type, unit);
+ Metric(String source, String message, double value, ResultType type, ResultUnit unit) {
+ this(source, message, new double[] { value }, type, unit);
}
/**
- * Creates a result object to be included in the report. Each object has a message
+ * Creates a metric array to be included in the report. Each object has a message
* describing its values and enums to interpret them. In addition, each result also includes
* class, method and line number information about the test which added this result which is
* collected by looking at the stack trace.
*
* @param message A string describing the values
* @param values An array of the values
- * @param target Nullable. The target value.
* @param type Represents how to interpret the values (eg. A lower score is better)
* @param unit Represents the unit in which the values are (eg. Milliseconds)
*/
- private Result(String location, String message, double[] values,
- Double target, ResultType type, ResultUnit unit) {
- mLocation = location;
- mMessage = message;
- mValues = values;
+ Metric(String source, String message, double[] values, ResultType type, ResultUnit unit) {
+ int sourceLength = source.length();
+ if (sourceLength > MAX_SOURCE_LENGTH) {
+ // Substring to the end
+ mSource = source.substring(sourceLength - MAX_SOURCE_LENGTH);
+ } else {
+ mSource = source;
+ }
+ int messageLength = message.length();
+ if (messageLength > MAX_MESSAGE_LENGTH) {
+ // Substring from the start
+ mMessage = message.substring(0, MAX_MESSAGE_LENGTH);
+ } else {
+ mMessage = message;
+ }
+ int valuesLength = values.length;
+ if (valuesLength > MAX_NUM_VALUES) {
+ // Subarray from the start
+ mValues = Arrays.copyOf(values, MAX_NUM_VALUES);
+ } else {
+ mValues = values;
+ }
mType = type;
mUnit = unit;
- mTarget = target;
}
- public double getTarget() {
- return mTarget;
- }
-
- public String getLocation() {
- return mLocation;
+ public String getSource() {
+ return mSource;
}
public String getMessage() {
@@ -94,137 +121,212 @@
return mUnit;
}
- /**
- * Format:
- * location|message|target|type|unit|value[s], target can be " " if there is no target set.
- * log for array = classMethodName:line_number|message|unit|type|space separated values
- */
- String toEncodedString() {
- StringBuilder builder = new StringBuilder()
- .append(mLocation)
- .append(LOG_ELEM_SEPARATOR)
- .append(mMessage)
- .append(LOG_ELEM_SEPARATOR)
- .append(mTarget != null ? mTarget : EMPTY_CHAR)
- .append(LOG_ELEM_SEPARATOR)
- .append(mType.name())
- .append(LOG_ELEM_SEPARATOR)
- .append(mUnit.name())
- .append(LOG_ELEM_SEPARATOR);
- for (double value : mValues) {
- builder.append(value).append(" ");
+ void serialize(XmlSerializer serializer)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ serializer.startTag(null, METRIC_TAG);
+ serializer.attribute(null, SOURCE_ATTR, getSource());
+ serializer.attribute(null, MESSAGE_ATTR, getMessage());
+ serializer.attribute(null, SCORETYPE_ATTR, getType().toReportString());
+ serializer.attribute(null, SCOREUNIT_ATTR, getUnit().toReportString());
+ for (double d : getValues()) {
+ serializer.startTag(null, VALUE_TAG);
+ serializer.text(Double.toString(d));
+ serializer.endTag(null, VALUE_TAG);
}
- return builder.toString();
+ serializer.endTag(null, METRIC_TAG);
}
- static Result fromEncodedString(String encodedString) {
- String[] elems = encodedString.split(Pattern.quote(LOG_ELEM_SEPARATOR));
- if (elems.length < 5) {
- return null;
+ static Metric parse(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ parser.require(XmlPullParser.START_TAG, null, METRIC_TAG);
+ String source = parser.getAttributeValue(null, SOURCE_ATTR);
+ String message = parser.getAttributeValue(null, MESSAGE_ATTR);
+ ResultType type = ResultType.parseReportString(
+ parser.getAttributeValue(null, SCORETYPE_ATTR));
+ ResultUnit unit = ResultUnit.parseReportString(
+ parser.getAttributeValue(null, SCOREUNIT_ATTR));
+ List<String> valuesList = new ArrayList<>();
+ while (parser.nextTag() == XmlPullParser.START_TAG) {
+ parser.require(XmlPullParser.START_TAG, null, VALUE_TAG);
+ valuesList.add(parser.nextText());
+ parser.require(XmlPullParser.END_TAG, null, VALUE_TAG);
}
-
- String[] valueStrArray = elems[5].split(" ");
- double[] valueArray = new double[valueStrArray.length];
- for (int i = 0; i < valueStrArray.length; i++) {
- valueArray[i] = Double.parseDouble(valueStrArray[i]);
+ int length = valuesList.size();
+ double[] values = new double[length];
+ for (int i = 0; i < length; i++) {
+ values[i] = Double.parseDouble(valuesList.get(i));
}
- return new Result(
- elems[0], /*location*/
- elems[1], /*message*/
- valueArray, /*values*/
- elems[2].equals(EMPTY_CHAR) ? null : Double.parseDouble(elems[2]), /*target*/
- ResultType.valueOf(elems[3]), /*type*/
- ResultUnit.valueOf(elems[4]) /*unit*/);
+ parser.require(XmlPullParser.END_TAG, null, METRIC_TAG);
+ return new Metric(source, message, values, type, unit);
}
}
/**
- * Adds an array of values to the report.
+ * @param elem
+ */
+ /* package */ void addMetric(Metric elem) {
+ mDetails.add(elem);
+ }
+
+ /**
+ * Adds an array of metrics to the report.
+ *
+ * NOTE: messages over {@value Metric#MAX_MESSAGE_LENGTH} chars will be trimmed.
+ * NOTE: arrays with length over {@value Metric#MAX_NUM_VALUES} will be truncated.
*/
public void addValues(String message, double[] values, ResultType type, ResultUnit unit) {
- mDetails.add(new Result(Stacktrace.getTestCallerClassMethodNameLineNumber(),
+ addMetric(new Metric(Stacktrace.getTestCallerClassMethodNameLineNumber(),
message, values, type, unit));
}
/**
- * Adds an array of values to the report.
+ * Adds an array of metrics to the report.
+ *
+ * NOTE: sources over {@value Metric#MAX_SOURCE_LENGTH} chars will be trimmed.
+ * NOTE: messages over {@value Metric#MAX_MESSAGE_LENGTH} chars will be trimmed.
+ * NOTE: arrays with length over {@value Metric#MAX_NUM_VALUES} will be truncated.
*/
- public void addValues(
- String message, double[] values, ResultType type, ResultUnit unit, String location) {
- mDetails.add(new Result(location, message, values, type, unit));
+ public void addValues(String source, String message, double[] values, ResultType type,
+ ResultUnit unit) {
+ addMetric(new Metric(source, message, values, type, unit));
}
/**
- * Adds a value to the report.
+ * Adds a metric to the report.
+ *
+ * NOTE: messages over {@value Metric#MAX_MESSAGE_LENGTH} chars will be trimmed.
*/
public void addValue(String message, double value, ResultType type, ResultUnit unit) {
- mDetails.add(new Result(Stacktrace.getTestCallerClassMethodNameLineNumber(), message,
- new double[] {value}, type, unit));
+ addMetric(new Metric(Stacktrace.getTestCallerClassMethodNameLineNumber(), message,
+ value, type, unit));
}
/**
- * Adds a value to the report.
+ * Adds a metric to the report.
+ *
+ * NOTE: sources over {@value Metric#MAX_SOURCE_LENGTH} chars will be trimmed.
+ * NOTE: messages over {@value Metric#MAX_MESSAGE_LENGTH} chars will be trimmed.
*/
- public void addValue(String message, double value, ResultType type,
- ResultUnit unit, String location) {
- mDetails.add(new Result(location, message, new double[] {value}, type, unit));
+ public void addValue(String source, String message, double value, ResultType type,
+ ResultUnit unit) {
+ addMetric(new Metric(source, message, value, type, unit));
+ }
+
+ /**
+ * @param elem
+ */
+ /* package */ void setSummary(Metric elem) {
+ mSummary = elem;
}
/**
* Sets the summary of the report.
+ *
+ * NOTE: messages over {@value Metric#MAX_MESSAGE_LENGTH} chars will be trimmed.
*/
public void setSummary(String message, double value, ResultType type, ResultUnit unit) {
- mSummary = new Result(Stacktrace.getTestCallerClassMethodNameLineNumber(),
- message, new double[] {value}, type, unit);
+ setSummary(new Metric(Stacktrace.getTestCallerClassMethodNameLineNumber(),
+ message, value, type, unit));
}
- public Result getSummary() {
+ public Metric getSummary() {
return mSummary;
}
- public List<Result> getDetailedMetrics() {
- return new ArrayList<Result>(mDetails);
+ public List<Metric> getDetailedMetrics() {
+ return new ArrayList<Metric>(mDetails);
}
/**
- * Parse a String encoded {@link com.android.compatibility.common.util.ReportLog}
+ * Serializes a given {@link ReportLog} to a String.
+ * @throws XmlPullParserException
+ * @throws IOException
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
*/
- public static ReportLog fromEncodedString(String encodedString) {
- ReportLog reportLog = new ReportLog();
- StringTokenizer tok = new StringTokenizer(encodedString, SUMMARY_SEPARATOR);
- if (tok.hasMoreTokens()) {
- // Extract the summary
- reportLog.mSummary = Result.fromEncodedString(tok.nextToken());
+ public static String serialize(ReportLog reportlog) throws XmlPullParserException,
+ IllegalArgumentException, IllegalStateException, IOException {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ XmlSerializer serializer = XmlPullParserFactory.newInstance(TYPE, null).newSerializer();
+ serializer.setOutput(byteArrayOutputStream, ENCODING);
+ serializer.startDocument(ENCODING, true);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ serialize(serializer, reportlog);
+ serializer.endDocument();
+ return byteArrayOutputStream.toString(ENCODING);
+ }
+
+ /**
+ * Serializes a given {@link ReportLog} to XML.
+ * @param serializer
+ * @param reportLog
+ * @throws IOException
+ */
+ public static void serialize(XmlSerializer serializer, ReportLog reportLog)
+ throws IOException {
+ if (reportLog == null) {
+ throw new IllegalArgumentException("Metrics reports was null");
}
- if (tok.hasMoreTokens()) {
- // Extract the detailed results
- StringTokenizer detailedTok = new StringTokenizer(tok.nextToken(), LOG_SEPARATOR);
- while (detailedTok.hasMoreTokens()) {
- reportLog.mDetails.add(Result.fromEncodedString(detailedTok.nextToken()));
+ Metric summary = reportLog.getSummary();
+ List<Metric> detailedMetrics = reportLog.getDetailedMetrics();
+ if (summary == null) {
+ throw new IllegalArgumentException("Metrics reports must have a summary");
+ }
+ serializer.startTag(null, SUMMARY_TAG);
+ summary.serialize(serializer);
+ serializer.endTag(null, SUMMARY_TAG);
+
+ if (!detailedMetrics.isEmpty()) {
+ serializer.startTag(null, DETAIL_TAG);
+ for (Metric elem : detailedMetrics) {
+ elem.serialize(serializer);
}
+ serializer.endTag(null, DETAIL_TAG);
}
- return reportLog;
}
/**
- * @return a String representation of this report or null if not collected
+ * Parses a {@link ReportLog} from the given string.
+ * @throws XmlPullParserException
+ * @throws IOException
*/
- protected String toEncodedString() {
- if ((mSummary == null) && mDetails.isEmpty()) {
- // just return empty string
- return null;
+ public static ReportLog parse(String result) throws XmlPullParserException, IOException {
+ if (result == null || result.trim().isEmpty()) {
+ throw new IllegalArgumentException("Metrics string was empty");
}
- StringBuilder builder = new StringBuilder();
- builder.append(mSummary.toEncodedString());
- builder.append(SUMMARY_SEPARATOR);
- for (Result result : mDetails) {
- builder.append(result.toEncodedString());
- builder.append(LOG_SEPARATOR);
- }
- // delete the last separator
- if (builder.length() >= LOG_SEPARATOR.length()) {
- builder.delete(builder.length() - LOG_SEPARATOR.length(), builder.length());
- }
- return builder.toString();
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ XmlPullParser parser = factory.newPullParser();
+ parser.setInput(new ByteArrayInputStream(result.getBytes(ENCODING)), ENCODING);
+ parser.nextTag();
+ return parse(parser);
}
+
+ /**
+ * Parses a {@link ReportLog} from the given XML parser.
+ * @param parser
+ * @throws IOException
+ * @throws XmlPullParserException
+ */
+ public static ReportLog parse(XmlPullParser parser) throws XmlPullParserException, IOException {
+ parser.require(XmlPullParser.START_TAG, null, SUMMARY_TAG);
+ parser.nextTag();
+ ReportLog report = new ReportLog();
+ report.setSummary(Metric.parse(parser));
+ parser.nextTag();
+ parser.require(XmlPullParser.END_TAG, null, SUMMARY_TAG);
+ try {
+ parser.nextTag();
+ } catch (XmlPullParserException e) {
+ // Report doesn't have any details, it's ok
+ return report;
+ }
+ if (parser.getName().equals(DETAIL_TAG)) {
+ while (parser.nextTag() == XmlPullParser.START_TAG) {
+ report.addMetric(Metric.parse(parser));
+ }
+ parser.require(XmlPullParser.END_TAG, null, DETAIL_TAG);
+ }
+ return report;
+ }
+
}
diff --git a/common/util/src/com/android/compatibility/common/util/ResultHandler.java b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
new file mode 100644
index 0000000..c4fcfc6
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Handles conversion of results to/from files.
+ */
+public class ResultHandler {
+
+ private static final String ENCODING = "UTF-8";
+ private static final String TYPE = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer";
+ private static final String NS = null;
+ private static final String RESULT_FILE_VERSION = "5.0";
+ /* package */ static final String TEST_RESULT_FILE_NAME = "test_result.xml";
+
+ // XML constants
+ private static final String ABI_ATTR = "abi";
+ private static final String BUGREPORT_TAG = "BugReport";
+ private static final String BUILD_TAG = "Build";
+ private static final String CASE_TAG = "TestCase";
+ private static final String DEVICES_ATTR = "devices";
+ private static final String END_TIME_ATTR = "end";
+ private static final String FAILED_ATTR = "failed";
+ private static final String FAILURE_TAG = "Failure";
+ private static final String HOST_NAME_ATTR = "host_name";
+ private static final String JAVA_VENDOR_ATTR = "java_vendor";
+ private static final String JAVA_VERSION_ATTR = "java_version";
+ private static final String LOGCAT_TAG = "Logcat";
+ private static final String MESSAGE_ATTR = "message";
+ private static final String MODULE_TAG = "Module";
+ private static final String NAME_ATTR = "name";
+ private static final String NOT_EXECUTED_ATTR = "not_executed";
+ private static final String OS_ARCH_ATTR = "os_arch";
+ private static final String OS_NAME_ATTR = "os_name";
+ private static final String OS_VERSION_ATTR = "os_version";
+ private static final String PASS_ATTR = "pass";
+ private static final String REPORT_VERSION_ATTR = "report_version";
+ private static final String REFERENCE_URL_ATTR = "reference_url";
+ private static final String RESULT_ATTR = "result";
+ private static final String RESULT_TAG = "Result";
+ private static final String RUNTIME_ATTR = "runtime";
+ private static final String SCREENSHOT_TAG = "Screenshot";
+ private static final String STACK_TAG = "StackTrace";
+ private static final String START_TIME_ATTR = "start";
+ private static final String SUITE_NAME_ATTR = "suite_name";
+ private static final String SUITE_PLAN_ATTR = "suite_plan";
+ private static final String SUITE_VERSION_ATTR = "suite_version";
+ private static final String SUMMARY_TAG = "Summary";
+ private static final String TEST_TAG = "Test";
+
+ /**
+ * @param resultsDir
+ */
+ public static List<IInvocationResult> getResults(File resultsDir) {
+ List<IInvocationResult> results = new ArrayList<>();
+ File[] files = resultsDir.listFiles();
+ if (files == null || files.length == 0) {
+ // No results, just return the empty list
+ return results;
+ }
+ for (File resultDir : files) {
+ if (!resultDir.isDirectory()) {
+ continue;
+ }
+ try {
+ File resultFile = new File(resultDir, TEST_RESULT_FILE_NAME);
+ if (!resultFile.exists()) {
+ continue;
+ }
+ IInvocationResult invocation = new InvocationResult(resultDir);
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ XmlPullParser parser = factory.newPullParser();
+ parser.setInput(new FileReader(resultFile));
+ parser.nextTag();
+ parser.require(XmlPullParser.START_TAG, NS, RESULT_TAG);
+ invocation.setStartTime(Long.valueOf(
+ parser.getAttributeValue(NS, START_TIME_ATTR)));
+ invocation.setTestPlan(parser.getAttributeValue(NS, SUITE_PLAN_ATTR));
+ String deviceList = parser.getAttributeValue(NS, DEVICES_ATTR);
+ for (String device : deviceList.split(",")) {
+ invocation.addDeviceSerial(device);
+ }
+ parser.nextTag();
+ parser.require(XmlPullParser.START_TAG, NS, BUILD_TAG);
+ // TODO(stuartscott): may want to reload these incase the retry was done with
+ // --skip-device-info flag
+ parser.nextTag();
+ parser.require(XmlPullParser.END_TAG, NS, BUILD_TAG);
+ parser.nextTag();
+ parser.require(XmlPullParser.START_TAG, NS, SUMMARY_TAG);
+ parser.nextTag();
+ parser.require(XmlPullParser.END_TAG, NS, SUMMARY_TAG);
+ while (parser.nextTag() == XmlPullParser.START_TAG) {
+ parser.require(XmlPullParser.START_TAG, NS, MODULE_TAG);
+ String name = parser.getAttributeValue(NS, NAME_ATTR);
+ String abi = parser.getAttributeValue(NS, ABI_ATTR);
+ String id = AbiUtils.createId(abi, name);
+ IModuleResult module = invocation.getOrCreateModule(id);
+ while (parser.nextTag() == XmlPullParser.START_TAG) {
+ parser.require(XmlPullParser.START_TAG, NS, CASE_TAG);
+ String caseName = parser.getAttributeValue(NS, NAME_ATTR);
+ ICaseResult testCase = module.getOrCreateResult(caseName);
+ while (parser.nextTag() == XmlPullParser.START_TAG) {
+ parser.require(XmlPullParser.START_TAG, NS, TEST_TAG);
+ String testName = parser.getAttributeValue(NS, NAME_ATTR);
+ ITestResult test = testCase.getOrCreateResult(testName);
+ String result = parser.getAttributeValue(NS, RESULT_ATTR);
+ test.setResultStatus(TestStatus.getStatus(result));
+ if (parser.nextTag() == XmlPullParser.START_TAG) {
+ if (parser.getName().equals(FAILURE_TAG)) {
+ test.setMessage(parser.getAttributeValue(NS, MESSAGE_ATTR));
+ if (parser.nextTag() == XmlPullParser.START_TAG) {
+ parser.require(XmlPullParser.START_TAG, NS, STACK_TAG);
+ test.setStackTrace(parser.nextText());
+ parser.require(XmlPullParser.END_TAG, NS, STACK_TAG);
+ parser.nextTag();
+ }
+ parser.require(XmlPullParser.END_TAG, NS, FAILURE_TAG);
+ parser.nextTag();
+ } else if (parser.getName().equals(BUGREPORT_TAG)) {
+ test.setBugReport(parser.nextText());
+ parser.nextTag();
+ } else if (parser.getName().equals(LOGCAT_TAG)) {
+ test.setLog(parser.nextText());
+ parser.nextTag();
+ } else if (parser.getName().equals(SCREENSHOT_TAG)) {
+ test.setScreenshot(parser.nextText());
+ parser.nextTag();
+ } else {
+ test.setReportLog(ReportLog.parse(parser));
+ parser.nextTag();
+ }
+ }
+ parser.require(XmlPullParser.END_TAG, NS, TEST_TAG);
+ }
+ parser.require(XmlPullParser.END_TAG, NS, CASE_TAG);
+ }
+ parser.require(XmlPullParser.END_TAG, NS, MODULE_TAG);
+ }
+ parser.require(XmlPullParser.END_TAG, NS, RESULT_TAG);
+ results.add(invocation);
+ } catch (XmlPullParserException e) {
+ e.printStackTrace();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return results;
+ }
+
+ /**
+ * @param result
+ * @param resultDir
+ * @param startTime
+ * @param referenceUrl A nullable string that can contain a URL to a related data
+ * @return The result file created.
+ * @throws IOException
+ * @throws XmlPullParserException
+ */
+ public static File writeResults(String suiteName, String suiteVersion, String suitePlan,
+ IInvocationResult result, File resultDir, long startTime, long endTime,
+ String referenceUrl) throws IOException, XmlPullParserException {
+ int passed = result.countResults(TestStatus.PASS);
+ int failed = result.countResults(TestStatus.FAIL);
+ int notExecuted = result.countResults(TestStatus.NOT_EXECUTED);
+ File resultFile = new File(resultDir, TEST_RESULT_FILE_NAME);
+ OutputStream stream = new FileOutputStream(resultFile);
+ XmlSerializer serializer = XmlPullParserFactory.newInstance(TYPE, null).newSerializer();
+ serializer.setOutput(stream, ENCODING);
+ serializer.startDocument(ENCODING, false);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ serializer.processingInstruction(
+ "xml-stylesheet type=\"text/xsl\" href=\"compatibility-result.xsl\"");
+ serializer.startTag(NS, RESULT_TAG);
+ serializer.attribute(NS, START_TIME_ATTR, String.valueOf(startTime));
+ serializer.attribute(NS, END_TIME_ATTR, String.valueOf(endTime));
+ serializer.attribute(NS, SUITE_NAME_ATTR, suiteName);
+ serializer.attribute(NS, SUITE_VERSION_ATTR, suiteVersion);
+ serializer.attribute(NS, SUITE_PLAN_ATTR, suitePlan);
+ serializer.attribute(NS, REPORT_VERSION_ATTR, RESULT_FILE_VERSION);
+ if (referenceUrl != null) {
+ serializer.attribute(NS, REFERENCE_URL_ATTR, referenceUrl);
+ }
+
+ // Device Info
+ Set<String> devices = result.getDeviceSerials();
+ StringBuilder deviceList = new StringBuilder();
+ boolean first = true;
+ for (String device : devices) {
+ if (first) {
+ first = false;
+ } else {
+ deviceList.append(",");
+ }
+ deviceList.append(device);
+ }
+ serializer.attribute(NS, DEVICES_ATTR, deviceList.toString());
+
+ // Host Info
+ String hostName = "";
+ try {
+ hostName = InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException ignored) {}
+ serializer.attribute(NS, HOST_NAME_ATTR, hostName);
+ serializer.attribute(NS, OS_NAME_ATTR, System.getProperty("os.name"));
+ serializer.attribute(NS, OS_VERSION_ATTR, System.getProperty("os.version"));
+ serializer.attribute(NS, OS_ARCH_ATTR, System.getProperty("os.arch"));
+ serializer.attribute(NS, JAVA_VENDOR_ATTR, System.getProperty("java.vendor"));
+ serializer.attribute(NS, JAVA_VERSION_ATTR, System.getProperty("java.version"));
+
+ // Build Info
+ serializer.startTag(NS, BUILD_TAG);
+ for (Entry<String, String> entry : result.getBuildInfo().entrySet()) {
+ serializer.attribute(NS, entry.getKey(), entry.getValue());
+ }
+ serializer.endTag(NS, BUILD_TAG);
+
+ // Summary
+ serializer.startTag(NS, SUMMARY_TAG);
+ serializer.attribute(NS, PASS_ATTR, Integer.toString(passed));
+ serializer.attribute(NS, FAILED_ATTR, Integer.toString(failed));
+ serializer.attribute(NS, NOT_EXECUTED_ATTR, Integer.toString(notExecuted));
+ serializer.endTag(NS, SUMMARY_TAG);
+
+ // Results
+ for (IModuleResult module : result.getModules()) {
+ serializer.startTag(NS, MODULE_TAG);
+ serializer.attribute(NS, NAME_ATTR, module.getName());
+ serializer.attribute(NS, ABI_ATTR, module.getAbi());
+ serializer.attribute(NS, RUNTIME_ATTR, String.valueOf(module.getRuntime()));
+ for (ICaseResult cr : module.getResults()) {
+ serializer.startTag(NS, CASE_TAG);
+ serializer.attribute(NS, NAME_ATTR, cr.getName());
+ for (ITestResult r : cr.getResults()) {
+ serializer.startTag(NS, TEST_TAG);
+ serializer.attribute(NS, RESULT_ATTR, r.getResultStatus().getValue());
+ serializer.attribute(NS, NAME_ATTR, r.getName());
+ String message = r.getMessage();
+ if (message != null) {
+ serializer.startTag(NS, FAILURE_TAG);
+ serializer.attribute(NS, MESSAGE_ATTR, message);
+ String stackTrace = r.getStackTrace();
+ if (stackTrace != null) {
+ serializer.startTag(NS, STACK_TAG);
+ serializer.text(stackTrace);
+ serializer.endTag(NS, STACK_TAG);
+ }
+ serializer.endTag(NS, FAILURE_TAG);
+ }
+ String bugreport = r.getBugReport();
+ if (bugreport != null) {
+ serializer.startTag(NS, BUGREPORT_TAG);
+ serializer.text(bugreport);
+ serializer.endTag(NS, BUGREPORT_TAG);
+ }
+ String logcat = r.getLog();
+ if (logcat != null) {
+ serializer.startTag(NS, LOGCAT_TAG);
+ serializer.text(logcat);
+ serializer.endTag(NS, LOGCAT_TAG);
+ }
+ String screenshot = r.getScreenshot();
+ if (screenshot != null) {
+ serializer.startTag(NS, SCREENSHOT_TAG);
+ serializer.text(screenshot);
+ serializer.endTag(NS, SCREENSHOT_TAG);
+ }
+ ReportLog report = r.getReportLog();
+ if (report != null) {
+ ReportLog.serialize(serializer, report);
+ }
+ serializer.endTag(NS, TEST_TAG);
+ }
+ serializer.endTag(NS, CASE_TAG);
+ }
+ serializer.endTag(NS, MODULE_TAG);
+ }
+ serializer.endDocument();
+ return resultFile;
+ }
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/ResultType.java b/common/util/src/com/android/compatibility/common/util/ResultType.java
index 779c6d0..9d0a5fa 100644
--- a/common/util/src/com/android/compatibility/common/util/ResultType.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultType.java
@@ -30,9 +30,16 @@
WARNING;
/**
- * Return string used in the XML report
+ * @return a string to be used in the report.
*/
- public String getXmlString() {
+ public String toReportString() {
return name().toLowerCase();
}
+
+ /**
+ * Returns a {@link ResultType} given a string from the report.
+ */
+ public static ResultType parseReportString(String value) {
+ return ResultType.valueOf(value.toUpperCase());
+ }
}
diff --git a/common/util/src/com/android/compatibility/common/util/ResultUnit.java b/common/util/src/com/android/compatibility/common/util/ResultUnit.java
index f38ddae..5b082f9 100644
--- a/common/util/src/com/android/compatibility/common/util/ResultUnit.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultUnit.java
@@ -40,10 +40,16 @@
SCORE;
/**
- * Return string used in the XML report
+ * @return a string to be used in the report.
*/
- public String getXmlString() {
+ public String toReportString() {
return name().toLowerCase();
}
-}
+ /**
+ * Returns a {@link ResultUnit} given a string from the report.
+ */
+ public static ResultUnit parseReportString(String value) {
+ return ResultUnit.valueOf(value.toUpperCase());
+ }
+}
diff --git a/common/util/src/com/android/compatibility/common/util/ResultUploader.java b/common/util/src/com/android/compatibility/common/util/ResultUploader.java
new file mode 100644
index 0000000..ff8d156
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/ResultUploader.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * Uploads a result through a HTTP POST multipart/form-data request containing
+ * the test result XML.
+ */
+public class ResultUploader {
+
+ private static final int RESULT_XML_BYTES = 500 * 1024;
+
+ /* package */ MultipartForm mMultipartForm;
+
+ public ResultUploader(String serverUrl, String suiteName) {
+ mMultipartForm = new MultipartForm(serverUrl).addFormValue("suite", suiteName);
+ }
+
+ /**
+ * Uploads the given file to the server.
+ *
+ * @param reportFile The file to upload.
+ * @param referenceUrl A reference url to use.
+ * @throws IOException
+ */
+ public void uploadResult(File reportFile, String referenceUrl) throws IOException {
+ InputStream input = new FileInputStream(reportFile);
+ try {
+ byte[] data = getBytes(input);
+ mMultipartForm.addFormFile("result-xml", "test-result.xml.gz", data);
+ if (referenceUrl == null || referenceUrl.trim().isEmpty()) {
+ mMultipartForm.addFormValue("reference-url", referenceUrl);
+ }
+ mMultipartForm.submit();
+ } finally {
+ input.close();
+ }
+ }
+
+ private static byte[] getBytes(InputStream input) throws IOException {
+ ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(RESULT_XML_BYTES);
+ GZIPOutputStream gzipOutput = new GZIPOutputStream(byteOutput);
+ byte[] buffer = new byte[1024];
+ int count;
+ while ((count = input.read(buffer)) > 0) {
+ gzipOutput.write(buffer, 0, count);
+ }
+ gzipOutput.close();
+ return byteOutput.toByteArray();
+ }
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/Stat.java b/common/util/src/com/android/compatibility/common/util/Stat.java
index 8bf9bf7..9748440 100644
--- a/common/util/src/com/android/compatibility/common/util/Stat.java
+++ b/common/util/src/com/android/compatibility/common/util/Stat.java
@@ -22,6 +22,10 @@
* Utilities for doing statistics
*/
public class Stat {
+ /**
+ * Private constructor for static class.
+ */
+ private Stat() {}
/**
* Collection of statistical propertirs like average, max, min, and stddev
@@ -48,10 +52,8 @@
double average = data[0];
double min = data[0];
double max = data[0];
- double eX2 = data[0] * data[0]; // will become E[X^2]
for (int i = 1; i < data.length; i++) {
average += data[i];
- eX2 += data[i] * data[i];
if (data[i] > max) {
max = data[i];
}
@@ -60,9 +62,13 @@
}
}
average /= data.length;
- eX2 /= data.length;
- // stddev = sqrt(E[X^2] - (E[X])^2)
- double stddev = Math.sqrt(eX2 - average * average);
+ double sumOfSquares = 0.0;
+ for (int i = 0; i < data.length; i++) {
+ double diff = average - data[i];
+ sumOfSquares += diff * diff;
+ }
+ double variance = sumOfSquares / (data.length - 1);
+ double stddev = Math.sqrt(variance);
return new StatResult(average, min, max, stddev, data.length);
}
@@ -84,37 +90,16 @@
double thresholdMin = median * (1.0 - rejectionThreshold);
double thresholdMax = median * (1.0 + rejectionThreshold);
- double average = 0.0;
- double min = median;
- double max = median;
- double eX2 = 0.0; // will become E[X^2]
- int validDataCounter = 0;
+ double[] validData = new double[data.length];
+ int index = 0;
for (int i = 0; i < data.length; i++) {
if ((data[i] > thresholdMin) && (data[i] < thresholdMax)) {
- validDataCounter++;
- average += data[i];
- eX2 += data[i] * data[i];
- if (data[i] > max) {
- max = data[i];
- }
- if (data[i] < min) {
- min = data[i];
- }
+ validData[index] = data[i];
+ index++;
}
// TODO report rejected data
}
- double stddev;
- if (validDataCounter > 0) {
- average /= validDataCounter;
- eX2 /= validDataCounter;
- // stddev = sqrt(E[X^2] - (E[X])^2)
- stddev = Math.sqrt(eX2 - average * average);
- } else { // both median is showing too much diff
- average = median;
- stddev = 0; // don't care
- }
-
- return new StatResult(average, min, max, stddev, validDataCounter);
+ return getStat(Arrays.copyOf(validData, index));
}
/**
@@ -159,7 +144,6 @@
* timeInSec with 0 value will be changed to small value to prevent divide by zero.
* @param change total change of quality for the given duration timeInMSec.
* @param timeInMSec
- * @return
*/
public static double calcRatePerSec(double change, double timeInMSec) {
if (timeInMSec == 0) {
@@ -185,4 +169,14 @@
return result;
}
+ /**
+ * Get the value of the 95th percentile using nearest rank algorithm.
+ */
+ public static double get95PercentileValue(double[] values) {
+ Arrays.sort(values);
+ // zero-based array index
+ int index = (int) Math.round(values.length * 0.95 + .5) - 1;
+ return values[index];
+ }
+
}
diff --git a/common/util/src/com/android/compatibility/common/util/TestFilter.java b/common/util/src/com/android/compatibility/common/util/TestFilter.java
new file mode 100644
index 0000000..78b68cf
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/TestFilter.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+/**
+ * Represents a filter for including and excluding tests.
+ */
+public class TestFilter {
+
+ private final String mAbi;
+ private final String mName;
+ private final String mTest;
+
+ /**
+ * Builds a new {@link TestFilter} from the given string. Filters can be in one of four forms,
+ * the instance will be initialized as;
+ * -"name" -> abi = null, name = "name", test = null
+ * -"name" "test" -> abi = null, name = "name", test = "test"
+ * -"abi" "name" -> abi = "abi", name = "name", test = null
+ * -"abi" "name" test" -> abi = "abi", name = "name", test = "test"
+ *
+ * @param filter the filter to parse
+ * @return the {@link TestFilter}
+ */
+ public static TestFilter createFrom(String filter) {
+ String[] parts = filter.split(" ");
+ String abi = null, name = null, test = null;
+ // Either:
+ // <name>
+ // <name> <test>
+ // <abi> <name>
+ // <abi> <name> <test>
+ if (parts.length == 1) {
+ name = parts[0];
+ } else if (parts.length == 2) {
+ if (AbiUtils.isAbiSupportedByCompatibility(parts[0])) {
+ abi = parts[0];
+ name = parts[1];
+ } else {
+ name = parts[0];
+ test = parts[1];
+ }
+ } else if (parts.length == 3){
+ abi = parts[0];
+ name = parts[1];
+ test = parts[2];
+ } else {
+ throw new IllegalArgumentException(String.format("Could not parse filter: %s", filter));
+ }
+ return new TestFilter(abi, name, test);
+ }
+
+ /**
+ * Creates a new {@link TestFilter} from the given parts.
+ *
+ * @param abi The ABI must be supported {@link AbiUtils#isAbiSupportedByCompatibility(String)}
+ * @param name The module's name
+ * @param test The test's identifier eg <package>.<class>#<method>
+ */
+ public TestFilter(String abi, String name, String test) {
+ mAbi = abi;
+ mName = name;
+ mTest = test;
+ }
+
+ /**
+ * Returns a String representation of this filter. This function is the inverse of
+ * {@link TestFilter#createFrom(String)}.
+ *
+ * For a valid filter f;
+ * <pre>
+ * {@code
+ * new TestFilter(f).toString().equals(f)
+ * }
+ * </pre>
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (mAbi != null) {
+ sb.append(mAbi);
+ sb.append(" ");
+ }
+ if (mName != null) {
+ sb.append(mName);
+ }
+ if (mTest != null) {
+ sb.append(" ");
+ sb.append(mTest);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * @return the abi of this filter, or null if not specified.
+ */
+ public String getAbi() {
+ return mAbi;
+ }
+
+ /**
+ * @return the module name of this filter, or null if not specified.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * @return the test identifier of this filter, or null if not specified.
+ */
+ public String getTest() {
+ return mTest;
+ }
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/TestResult.java b/common/util/src/com/android/compatibility/common/util/TestResult.java
new file mode 100644
index 0000000..03aaca29
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/TestResult.java
@@ -0,0 +1,233 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+/**
+ * Represents a single test result.
+ */
+public class TestResult implements ITestResult {
+
+ private final ICaseResult mParent;
+ private final String mTestName;
+ private TestStatus mResult;
+ private String mMessage;
+ private String mStackTrace;
+ private ReportLog mReport;
+ private String mBugReport;
+ private String mLog;
+ private String mScreenshot;
+
+ /**
+ * Create a {@link TestResult} for the given test name.
+ */
+ public TestResult(ICaseResult parent, String name) {
+ mParent = parent;
+ mTestName = name;
+ reset();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return mTestName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getFullName() {
+ return String.format("%s#%s", mParent.getName(), getName());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public TestStatus getResultStatus() {
+ return mResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setResultStatus(TestStatus status) {
+ mResult = status;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getMessage() {
+ return mMessage;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setMessage(String message) {
+ mMessage = message;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getStackTrace() {
+ return mStackTrace;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setStackTrace(String stackTrace) {
+ mStackTrace = sanitizeStackTrace(stackTrace);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ReportLog getReportLog() {
+ return mReport;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setReportLog(ReportLog report) {
+ mReport = report;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getBugReport() {
+ return mBugReport;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBugReport(String path) {
+ mBugReport = path;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getLog() {
+ return mLog;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setLog(String path) {
+ mLog = path;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getScreenshot() {
+ return mScreenshot;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setScreenshot(String path) {
+ mScreenshot = path;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void failed(String trace) {
+ setResultStatus(TestStatus.FAIL);
+ int index = trace.indexOf('\n');
+ if (index < 0) {
+ // Trace is a single line, just set the message to be the same as the stacktrace.
+ setMessage(trace);
+ } else {
+ setMessage(trace.substring(0, index));
+ }
+ setStackTrace(trace);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void passed(ReportLog report) {
+ if (!getResultStatus().equals(TestStatus.FAIL)) {
+ setResultStatus(TestStatus.PASS);
+ if (report != null) {
+ setReportLog(report);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void reset() {
+ mResult = TestStatus.NOT_EXECUTED;
+ mMessage = null;
+ mStackTrace = null;
+ mReport = null;
+ mBugReport = null;
+ mLog = null;
+ mScreenshot = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(ITestResult another) {
+ return getName().compareTo(another.getName());
+ }
+
+ /**
+ * Strip out any invalid XML characters that might cause the report to be unviewable.
+ * http://www.w3.org/TR/REC-xml/#dt-character
+ */
+ static String sanitizeStackTrace(String trace) {
+ if (trace != null) {
+ return trace.replaceAll("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD]", "");
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/TestStatus.java b/common/util/src/com/android/compatibility/common/util/TestStatus.java
new file mode 100644
index 0000000..766e4d2
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/TestStatus.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+/**
+ * An enum of possible test statuses.
+ */
+public enum TestStatus {
+ PASS("pass"),
+ FAIL("fail"),
+ NOT_EXECUTED("not_executed");
+
+ private String mValue;
+
+ private TestStatus(String storedValue) {
+ mValue = storedValue;
+ }
+
+ /**
+ * Get the String representation of this test status that should be stored in
+ * xml
+ */
+ public String getValue() {
+ return mValue;
+ }
+
+ /**
+ * Find the {@link TestStatus} corresponding to given string value
+ * <p/>
+ * Performs a case insensitive search
+ *
+ * @param value
+ * @return the {@link TestStatus} or <code>null</code> if it could not be found
+ */
+ static TestStatus getStatus(String value) {
+ for (TestStatus status : TestStatus.values()) {
+ if (value.compareToIgnoreCase(status.getValue()) == 0) {
+ return status;
+ }
+ }
+ return null;
+ }
+}
diff --git a/common/util/src/com/android/compatibility/common/util/TestSuiteFilter.java b/common/util/src/com/android/compatibility/common/util/TestSuiteFilter.java
new file mode 100644
index 0000000..e498c17
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/TestSuiteFilter.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.util;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+
+public class TestSuiteFilter {
+
+ private TestSuiteFilter() {}
+
+ public static TestSuite createSuite(List<Class<?>> classes, Set<String> includes,
+ Set<String> excludes) {
+ return new FilterableTestSuite(classes, includes, excludes);
+ }
+
+ /**
+ * A {@link TestSuite} that can filter which tests run, given the include and exclude filters.
+ *
+ * This had to be private inner class because the test runner would find it and think it was a
+ * suite of tests, but it has no tests in it, causing a crash.
+ */
+ private static class FilterableTestSuite extends TestSuite {
+
+ private Set<String> mIncludes;
+ private Set<String> mExcludes;
+
+ public FilterableTestSuite(List<Class<?>> classes, Set<String> includes,
+ Set<String> excludes) {
+ super(classes.toArray(new Class<?>[classes.size()]));
+ mIncludes = includes;
+ mExcludes = excludes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int countTestCases() {
+ return countTests(this);
+ }
+
+ private int countTests(Test test) {
+ if (test instanceof TestSuite) {
+ // If the test is a suite it could contain multiple tests, these need to be split
+ // out into separate tests so they can be filtered
+ TestSuite suite = (TestSuite) test;
+ Enumeration<Test> enumerator = suite.tests();
+ int count = 0;
+ while (enumerator.hasMoreElements()) {
+ count += countTests(enumerator.nextElement());
+ }
+ return count;
+ } else if (shouldRun(test)) {
+ return 1;
+ }
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void runTest(Test test, TestResult result) {
+ runTests(test, result);
+ }
+
+ private void runTests(Test test, TestResult result) {
+ if (test instanceof TestSuite) {
+ // If the test is a suite it could contain multiple tests, these need to be split
+ // out into separate tests so they can be filtered
+ TestSuite suite = (TestSuite) test;
+ Enumeration<Test> enumerator = suite.tests();
+ while (enumerator.hasMoreElements()) {
+ runTests(enumerator.nextElement(), result);
+ }
+ } else if (shouldRun(test)) {
+ test.run(result);
+ }
+ }
+
+ private boolean shouldRun(Test test) {
+ String fullName = test.toString();
+ String[] parts = fullName.split("[\\(\\)]");
+ String className = parts[1];
+ String methodName = String.format("%s#%s", className, parts[0]);
+ int index = className.lastIndexOf('.');
+ String packageName = index < 0 ? "" : className.substring(0, index);
+
+ if (mExcludes.contains(packageName)) {
+ // Skip package because it was excluded
+ return false;
+ }
+ if (mExcludes.contains(className)) {
+ // Skip class because it was excluded
+ return false;
+ }
+ if (mExcludes.contains(methodName)) {
+ // Skip method because it was excluded
+ return false;
+ }
+ return mIncludes.isEmpty()
+ || mIncludes.contains(methodName)
+ || mIncludes.contains(className)
+ || mIncludes.contains(packageName);
+ }
+ }
+}
diff --git a/common/util/tests/Android.mk b/common/util/tests/Android.mk
new file mode 100644
index 0000000..0e0af50
--- /dev/null
+++ b/common/util/tests/Android.mk
@@ -0,0 +1,27 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := junit kxml2-2.3.0 tradefed-prebuilt compatibility-common-util-hostsidelib
+
+LOCAL_MODULE := compatibility-common-util-tests
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/common/util/tests/run_tests.sh b/common/util/tests/run_tests.sh
new file mode 100755
index 0000000..0045014
--- /dev/null
+++ b/common/util/tests/run_tests.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# 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.
+
+CTS_DIR=$(dirname ${0})/../../..
+source ${CTS_DIR}/test_defs.sh
+
+JARS="
+ compatibility-common-util-hostsidelib\
+ compatibility-common-util-tests\
+ compatibility-host-util\
+ compatibility-host-util-tests\
+ compatibility-mock-tradefed\
+ compatibility-tradefed-tests"
+
+run_tests "com.android.compatibility.common.util.UnitTests" "${JARS}" "${@}"
+
diff --git a/common/util/tests/src/com/android/compatibility/common/util/AbiUtilsTest.java b/common/util/tests/src/com/android/compatibility/common/util/AbiUtilsTest.java
new file mode 100644
index 0000000..567da54
--- /dev/null
+++ b/common/util/tests/src/com/android/compatibility/common/util/AbiUtilsTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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
+ */
+
+package com.android.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link AbiUtils}
+ */
+public class AbiUtilsTest extends TestCase {
+
+ private static final String MODULE_NAME = "ModuleName";
+ private static final String ABI_NAME = "mips64";
+ private static final String ABI_FLAG = "--abi mips64 ";
+ private static final String ABI_ID = "mips64 ModuleName";
+
+ public void testCreateAbiFlag() {
+ String flag = AbiUtils.createAbiFlag(ABI_NAME);
+ assertEquals("Incorrect flag created", ABI_FLAG, flag);
+ }
+
+ public void testCreateId() {
+ String id = AbiUtils.createId(ABI_NAME, MODULE_NAME);
+ assertEquals("Incorrect id created", ABI_ID, id);
+ }
+
+ public void testParseId() {
+ String[] parts = AbiUtils.parseId(ABI_ID);
+ assertEquals("Wrong size array", 2, parts.length);
+ assertEquals("Wrong abi name", ABI_NAME, parts[0]);
+ assertEquals("Wrong module name", MODULE_NAME, parts[1]);
+ }
+
+ public void testParseName() {
+ String name = AbiUtils.parseTestName(ABI_ID);
+ assertEquals("Incorrect module name", MODULE_NAME, name);
+ }
+
+ public void testParseAbi() {
+ String abi = AbiUtils.parseAbi(ABI_ID);
+ assertEquals("Incorrect abi name", ABI_NAME, abi);
+ }
+
+}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/CaseResultTest.java b/common/util/tests/src/com/android/compatibility/common/util/CaseResultTest.java
new file mode 100644
index 0000000..ae29597
--- /dev/null
+++ b/common/util/tests/src/com/android/compatibility/common/util/CaseResultTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link CaseResult}
+ */
+public class CaseResultTest extends TestCase {
+
+ private static final String CLASS = "android.test.FoorBar";
+ private static final String METHOD_1 = "testBlah1";
+ private static final String METHOD_2 = "testBlah2";
+ private static final String METHOD_3 = "testBlah3";
+ private static final String MESSAGE = "Something small is not alright";
+ private static final String STACK_TRACE = "Something small is not alright\n " +
+ "at four.big.insects.Marley.sing(Marley.java:10)";
+ private CaseResult mResult;
+
+ @Override
+ public void setUp() throws Exception {
+ mResult = new CaseResult(CLASS);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mResult = null;
+ }
+
+ public void testAccessors() throws Exception {
+ assertEquals("Incorrect case name", CLASS, mResult.getName());
+ }
+
+ public void testResultCreation() throws Exception {
+ ITestResult testResult = mResult.getOrCreateResult(METHOD_1);
+ // Should create one
+ assertEquals("Expected one result", 1, mResult.getResults().size());
+ assertTrue("Expected test result", mResult.getResults().contains(testResult));
+ // Should not create another one
+ ITestResult testResult2 = mResult.getOrCreateResult(METHOD_1);
+ assertEquals("Expected the same result", testResult, testResult2);
+ assertEquals("Expected one result", 1, mResult.getResults().size());
+ }
+
+ public void testResultReporting() throws Exception {
+ ITestResult testResult = mResult.getOrCreateResult(METHOD_1);
+ testResult.failed(STACK_TRACE);
+ assertEquals("Expected status to be set", TestStatus.FAIL, testResult.getResultStatus());
+ assertEquals("Expected message to be set", MESSAGE, testResult.getMessage());
+ assertEquals("Expected stack to be set", STACK_TRACE, testResult.getStackTrace());
+ testResult = mResult.getOrCreateResult(METHOD_2);
+ testResult.passed(null);
+ assertEquals("Expected status to be set", TestStatus.PASS, testResult.getResultStatus());
+ assertEquals("Expected two results", 2, mResult.getResults().size());
+ }
+
+ public void testCountResults() throws Exception {
+ mResult.getOrCreateResult(METHOD_1).failed(STACK_TRACE);
+ mResult.getOrCreateResult(METHOD_2).failed(STACK_TRACE);
+ mResult.getOrCreateResult(METHOD_3).passed(null);
+ assertEquals("Expected two failures", 2, mResult.countResults(TestStatus.FAIL));
+ assertEquals("Expected one pass", 1, mResult.countResults(TestStatus.PASS));
+ }
+}
\ No newline at end of file
diff --git a/common/util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java b/common/util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java
new file mode 100644
index 0000000..6d6ba2d
--- /dev/null
+++ b/common/util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Unit tests for {@link DynamicConfig}
+ */
+public class DynamicConfigTest extends TestCase {
+ private static final String correctConfig =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<DynamicConfig>\n" +
+ " <Config key=\"test-config-1\">test config 1</Config>\n" +
+ " <Config key=\"test-config-2\">testconfig2</Config>\n" +
+ " <ConfigList key=\"config-list\">\n" +
+ " <Item>config0</Item>\n" +
+ " <Item>config1</Item>\n" +
+ " <Item>config2</Item>\n" +
+ " <Item>config3</Item>\n" +
+ " <Item>config4</Item>\n" +
+ " </ConfigList>\n" +
+ " <ConfigList key=\"config-list-2\">\n" +
+ " <Item>A</Item>\n" +
+ " <Item>B</Item>\n" +
+ " <Item>C</Item>\n" +
+ " <Item>D</Item>\n" +
+ " <Item>E</Item>\n" +
+ " </ConfigList>\n" +
+ "</DynamicConfig>\n";
+
+ private static final String configWrongNodeName =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<DynamicCsonfig>\n" + //The node name DynamicConfig is intentionally mistyped
+ " <Config key=\"test-config-1\">test config 1</Config>\n" +
+ " <Config key=\"test-config-2\">testconfig2</Config>\n" +
+ " <ConfigList key=\"config-list\">\n" +
+ " <Item>Nevermore</Item>\n" +
+ " <Item>Puck</Item>\n" +
+ " <Item>Zeus</Item>\n" +
+ " <Item>Earth Shaker</Item>\n" +
+ " <Item>Vengeful Spirit</Item>\n" +
+ " </ConfigList>\n" +
+ " <ConfigList key=\"config-list-2\">\n" +
+ " <Item>A</Item>\n" +
+ " <Item>B</Item>\n" +
+ " <Item>C</Item>\n" +
+ " <Item>D</Item>\n" +
+ " <Item>E</Item>\n" +
+ " </ConfigList>\n" +
+ "</DynamicConfig>\n";
+
+ public void testCorrectConfig() throws Exception {
+ DynamicConfig config = new DynamicConfig();
+ File file = createFileFromStr(correctConfig);
+ config.initConfigFromXml(file);
+
+ assertEquals("Wrong Config", config.getConfig("test-config-1"), "test config 1");
+ assertEquals("Wrong Config", config.getConfig("test-config-2"), "testconfig2");
+ assertEquals("Wrong Config List", config.getConfigList("config-list").get(0), "config0");
+ assertEquals("Wrong Config List", config.getConfigList("config-list").get(2), "config2");
+ assertEquals("Wrong Config List", config.getConfigList("config-list-2").get(2), "C");
+ }
+
+ public void testConfigWithWrongNodeName() throws Exception {
+ DynamicConfig config = new DynamicConfig();
+ File file = createFileFromStr(configWrongNodeName);
+
+ try {
+ config.initConfigFromXml(file);
+ fail("Cannot detect error when config file has wrong node name");
+ } catch (XmlPullParserException e) {
+ //expected
+ }
+ }
+
+ private File createFileFromStr(String configStr) throws IOException {
+ File file = File.createTempFile("test", "dynamic");
+ FileOutputStream stream = new FileOutputStream(file);
+ stream.write(configStr.getBytes());
+ stream.flush();
+ return file;
+ }
+}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java b/common/util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java
index 05e69d8..c6f3ec1 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java
@@ -24,6 +24,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+//TODO(stuartscott): Delete file for v2, ReportLog can serialize itself.
/**
* Unit tests for {@link MetricsXmlSerializer}
*/
@@ -32,8 +33,7 @@
static class LocalReportLog extends ReportLog {}
private static final double[] VALUES = new double[] {1, 11, 21, 1211, 111221};
private static final String HEADER = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>";
- private static final String EXPECTED_XML =
- HEADER
+ private static final String EXPECTED_XML = HEADER
+ "<Summary message=\"Sample\" scoreType=\"higher_better\" unit=\"byte\">1.0</Summary>"
+ "<Details>"
+ "<ValueArray source=\"com.android.compatibility.common.util."
@@ -89,4 +89,4 @@
assertEquals(EXPECTED_XML, mByteArrayOutputStream.toString("utf-8"));
}
-}
+}
\ No newline at end of file
diff --git a/common/util/tests/src/com/android/compatibility/common/util/ModuleResultTest.java b/common/util/tests/src/com/android/compatibility/common/util/ModuleResultTest.java
new file mode 100644
index 0000000..2239ac8
--- /dev/null
+++ b/common/util/tests/src/com/android/compatibility/common/util/ModuleResultTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link ModuleResult}
+ */
+public class ModuleResultTest extends TestCase {
+
+ private static final String NAME = "ModuleName";
+ private static final String ABI = "mips64";
+ private static final String ID = AbiUtils.createId(ABI, NAME);
+ private static final String CLASS = "android.test.FoorBar";
+ private static final String METHOD_1 = "testBlah1";
+ private static final String METHOD_2 = "testBlah2";
+ private static final String METHOD_3 = "testBlah3";
+ private static final String STACK_TRACE = "Something small is not alright\n " +
+ "at four.big.insects.Marley.sing(Marley.java:10)";
+ private ModuleResult mResult;
+
+ @Override
+ public void setUp() throws Exception {
+ mResult = new ModuleResult(ID);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mResult = null;
+ }
+
+ public void testAccessors() throws Exception {
+ assertEquals("Incorrect module ID", ID, mResult.getId());
+ assertEquals("Incorrect module ABI", ABI, mResult.getAbi());
+ assertEquals("Incorrect module name", NAME, mResult.getName());
+ }
+
+ public void testResultCreation() throws Exception {
+ ICaseResult caseResult = mResult.getOrCreateResult(CLASS);
+ // Should create one
+ assertEquals("Expected one result", 1, mResult.getResults().size());
+ assertTrue("Expected test result", mResult.getResults().contains(caseResult));
+ // Should not create another one
+ ICaseResult caseResult2 = mResult.getOrCreateResult(CLASS);
+ assertEquals("Expected the same result", caseResult, caseResult2);
+ assertEquals("Expected one result", 1, mResult.getResults().size());
+ }
+
+ public void testCountResults() throws Exception {
+ ICaseResult testCase = mResult.getOrCreateResult(CLASS);
+ testCase.getOrCreateResult(METHOD_1).failed(STACK_TRACE);
+ testCase.getOrCreateResult(METHOD_2).failed(STACK_TRACE);
+ testCase.getOrCreateResult(METHOD_3).passed(null);
+ assertEquals("Expected two failures", 2, mResult.countResults(TestStatus.FAIL));
+ assertEquals("Expected one pass", 1, mResult.countResults(TestStatus.PASS));
+ }
+}
\ No newline at end of file
diff --git a/common/util/tests/src/com/android/compatibility/common/util/MultipartFormTest.java b/common/util/tests/src/com/android/compatibility/common/util/MultipartFormTest.java
new file mode 100644
index 0000000..dd96308
--- /dev/null
+++ b/common/util/tests/src/com/android/compatibility/common/util/MultipartFormTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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
+ */
+
+package com.android.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link MultipartForm}
+ */
+public class MultipartFormTest extends TestCase {
+
+ private static final String SERVER_URL = "http://127.0.0.1:5555";
+ private static final byte[] ZIP_ARRAY = {
+ 0xa, 0x2d, 0x2d, 0x43, 0x37, 0x35, 0x49, 0x35, 0x35, 0x75, 0x33, 0x52, 0x33, 0x70, 0x30,
+ 0x72, 0x37, 0x33, 0x72, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69,
+ 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x3b, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22,
+ 0x66, 0x6f, 0x6f, 0x22, 0xa, 0xa, 0x62, 0x61, 0x72, 0xa, 0x2d, 0x2d, 0x43, 0x37, 0x35,
+ 0x49, 0x35, 0x35, 0x75, 0x33, 0x52, 0x33, 0x70, 0x30, 0x72, 0x37, 0x33, 0x72, 0xa, 0x43,
+ 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74,
+ 0x61, 0x3b, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x68, 0x22,
+ 0x3b, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x62, 0x6c,
+ 0x61, 0x68, 0x2e, 0x78, 0x6d, 0x6c, 0x2e, 0x67, 0x7a, 0x22, 0xa, 0x43, 0x6f, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c,
+ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x67, 0x7a, 0x69, 0x70, 0xa,
+ 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66,
+ 0x65, 0x72, 0x2d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x62,
+ 0x69, 0x6e, 0x61, 0x72, 0x79, 0xa, 0xa, 0x62, 0x6c, 0x61, 0x68, 0xa, 0x2d, 0x2d, 0x43,
+ 0x37, 0x35, 0x49, 0x35, 0x35, 0x75, 0x33, 0x52, 0x33, 0x70, 0x30, 0x72, 0x37, 0x33,
+ 0x72, 0x2d, 0x2d, 0xa,
+ };
+
+ public void testContentBody() throws Exception {
+ MultipartForm form = new MultipartForm(SERVER_URL);
+ form.addFormValue("foo", "bar");
+ form.addFormFile("blah", "blah.xml.gz", "blah".getBytes());
+ byte[] data = form.getContentBody();
+ assertTrue("No data", data.length > 0);
+ assertTrue("Wrong data", Arrays.equals(ZIP_ARRAY, data));
+ }
+}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/ReportLogTest.java b/common/util/tests/src/com/android/compatibility/common/util/ReportLogTest.java
index a5f3306..0b4a639 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/ReportLogTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/ReportLogTest.java
@@ -16,8 +16,13 @@
package com.android.compatibility.common.util;
+import com.android.compatibility.common.util.ReportLog.Metric;
+
import junit.framework.TestCase;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.util.List;
import java.util.Arrays;
/**
@@ -25,44 +30,164 @@
*/
public class ReportLogTest extends TestCase {
- private static final double[] VALUES = new double[] {1, 11, 21, 1211, 111221};
+ private static final String SOURCE = "Source";
+ private static final String MESSAGE = "Message";
+ private static final double[] VALUES = new double[] {.1, 124, 4736, 835.683, 98, 395};
+ private static final String HEADER_XML =
+ "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>";
+ private static final String SUMMARY_XML =
+ HEADER_XML + "\r\n" +
+ "<Summary>\r\n" +
+ " <Metric source=\"com.android.compatibility.common.util.ReportLogTest#%s\" message=\"Sample\" score_type=\"higher_better\" score_unit=\"byte\">\r\n" +
+ " <Value>1.0</Value>\r\n" +
+ " </Metric>\r\n" +
+ "</Summary>";
+ private static final String DETAIL_XML =
+ "<Detail>\r\n" +
+ " <Metric source=\"com.android.compatibility.common.util.ReportLogTest#%s\" message=\"Details\" score_type=\"neutral\" score_unit=\"fps\">\r\n" +
+ " <Value>0.1</Value>\r\n" +
+ " <Value>124.0</Value>\r\n" +
+ " <Value>4736.0</Value>\r\n" +
+ " <Value>835.683</Value>\r\n" +
+ " <Value>98.0</Value>\r\n" +
+ " <Value>395.0</Value>\r\n" +
+ " </Metric>\r\n" +
+ "</Detail>";
+ private static final String FULL_XML = SUMMARY_XML + "\r\n" + DETAIL_XML;
- private static final String EXPECTED_ENCODED_REPORT_LOG =
- "com.android.compatibility.common.util.ReportLogTest#testEncodeDecode:44|" +
- "Sample Summary| |HIGHER_BETTER|BYTE|1.0 ++++" +
- "com.android.compatibility.common.util.ReportLogTest#testEncodeDecode:45|" +
- "Details| |NEUTRAL|FPS|1.0 11.0 21.0 1211.0 111221.0 ";
- private ReportLog reportLog;
+ private ReportLog mReportLog;
@Override
protected void setUp() throws Exception {
- this.reportLog = new ReportLog();
+ mReportLog = new ReportLog();
}
- public void testEncodeDecode() {
-
- reportLog.setSummary("Sample Summary", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
- reportLog.addValues("Details", VALUES, ResultType.NEUTRAL, ResultUnit.FPS);
-
- String encodedReportLog = reportLog.toEncodedString();
- assertEquals(EXPECTED_ENCODED_REPORT_LOG, encodedReportLog);
-
- ReportLog decodedReportLog = ReportLog.fromEncodedString(encodedReportLog);
- ReportLog.Result summary = reportLog.getSummary();
- assertEquals("Sample Summary", summary.getMessage());
- assertFalse(summary.getLocation().isEmpty());
- assertEquals(ResultType.HIGHER_BETTER, summary.getType());
- assertEquals(ResultUnit.BYTE, summary.getUnit());
- assertTrue(Arrays.equals(new double[] {1.0}, summary.getValues()));
-
- assertEquals(1, decodedReportLog.getDetailedMetrics().size());
- ReportLog.Result detail = decodedReportLog.getDetailedMetrics().get(0);
- assertEquals("Details", detail.getMessage());
- assertFalse(detail.getLocation().isEmpty());
- assertEquals(ResultType.NEUTRAL, detail.getType());
- assertEquals(ResultUnit.FPS, detail.getUnit());
- assertTrue(Arrays.equals(VALUES, detail.getValues()));
-
- assertEquals(encodedReportLog, decodedReportLog.toEncodedString());
+ public void testSerialize_null() throws Exception {
+ try {
+ ReportLog.serialize(null);
+ fail("Expected IllegalArgumentException when serializing an empty report");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
}
+
+ public void testSerialize_noData() throws Exception {
+ try {
+ ReportLog.serialize(mReportLog);
+ fail("Expected IllegalArgumentException when serializing an empty report");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+ }
+
+ public void testSerialize_summaryOnly() throws Exception {
+ mReportLog.setSummary("Sample", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+ assertEquals(String.format(SUMMARY_XML, "testSerialize_summaryOnly:84"),
+ ReportLog.serialize(mReportLog));
+ }
+
+ public void testSerialize_detailOnly() throws Exception {
+ mReportLog.addValues("Details", VALUES, ResultType.NEUTRAL, ResultUnit.FPS);
+ try {
+ ReportLog.serialize(mReportLog);
+ fail("Expected IllegalArgumentException when serializing report without summary");
+ } catch(IllegalArgumentException e) {
+ // Expected
+ }
+ }
+
+ public void testSerialize_full() throws Exception {
+ mReportLog.setSummary("Sample", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+ mReportLog.addValues("Details", VALUES, ResultType.NEUTRAL, ResultUnit.FPS);
+ assertEquals(String.format(FULL_XML, "testSerialize_full:100", "testSerialize_full:101"),
+ ReportLog.serialize(mReportLog));
+ }
+
+ public void testParse_null() throws Exception {
+ try {
+ ReportLog.parse((String) null);
+ fail("Expected IllegalArgumentException when passing a null report");
+ } catch(IllegalArgumentException e) {
+ // Expected
+ }
+ }
+
+ public void testParse_noData() throws Exception {
+ try {
+ ReportLog.parse(HEADER_XML);
+ fail("Expected XmlPullParserException when passing a report with no content");
+ } catch(XmlPullParserException e) {
+ // Expected
+ }
+ }
+
+ public void testParse_summaryOnly() throws Exception {
+ ReportLog report = ReportLog.parse(String.format(SUMMARY_XML, "testParse_summaryOnly:125"));
+ assertNotNull(report);
+ assertEquals("Sample", report.getSummary().getMessage());
+ }
+
+ public void testParse_detailOnly() throws Exception {
+ try {
+ ReportLog.parse(String.format(DETAIL_XML, "testParse_detailOnly:132"));
+ fail("Expected XmlPullParserException when serializing report without summary");
+ } catch (XmlPullParserException e) {
+ // Expected
+ }
+ }
+
+ public void testParse_full() throws Exception {
+ ReportLog report = ReportLog.parse(String.format(FULL_XML, "testParse_full:140",
+ "testParse_full:138"));
+ assertNotNull(report);
+ assertEquals("Sample", report.getSummary().getMessage());
+ List<Metric> details = report.getDetailedMetrics();
+ assertEquals(1, details.size());
+ assertEquals("Details", details.get(0).getMessage());
+ }
+
+ public void testLimits_source() throws Exception {
+ // Should pass with a short source.
+ Metric metric = new Metric(SOURCE, MESSAGE, 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+ assertEquals("Expected message to be ok", SOURCE, metric.getSource());
+ // Make a long source.
+ StringBuilder sb = new StringBuilder();
+ // 40 x "Source" = 240 character string
+ for (int i = 0; i < 40; i++) sb.append(SOURCE);
+ String source = sb.toString();
+ // Should be trimmed because source is too long.
+ metric = new Metric(source, MESSAGE, 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+ assertEquals("Expected source to be trimmed", source.substring(source.length() - 200),
+ metric.getSource());
+ }
+
+ public void testLimits_message() throws Exception {
+ // Should pass with a short message.
+ Metric metric = new Metric(SOURCE, MESSAGE, 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+ assertEquals("Expected message to be ok", MESSAGE, metric.getMessage());
+ // Make a long message.
+ StringBuilder sb = new StringBuilder();
+ // 40 x "Message" = 280 character string
+ for (int i = 0; i < 40; i++) sb.append(MESSAGE);
+ String message = sb.toString();
+ // Should be trimmed because message is too long.
+ metric = new Metric(SOURCE, message, 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+ assertEquals("Expected message to be trimmed", message.substring(0, 200),
+ metric.getMessage());
+ }
+
+ public void testLimits_values() throws Exception {
+ // Should pass with a small array.
+ Metric metric = new Metric(SOURCE, MESSAGE, VALUES, ResultType.HIGHER_BETTER,
+ ResultUnit.BYTE);
+ assertTrue("Expected values to be ok", Arrays.equals(VALUES, metric.getValues()));
+ // Make a big array.
+ double[] values = new double[1001];
+ for (int i = 0; i < values.length; i++) values[i] = i;
+ // Should be trimmed because array is too big.
+ metric = new Metric(SOURCE, MESSAGE, values, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
+ assertTrue("Expected values to be trimmed", Arrays.equals(Arrays.copyOf(values, 1000),
+ metric.getValues()));
+ }
+
}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
new file mode 100644
index 0000000..be3c109
--- /dev/null
+++ b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
@@ -0,0 +1,321 @@
+/*
+ * 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
+ */
+package com.android.compatibility.common.util;
+
+import com.android.tradefed.util.FileUtil;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Unit tests for {@link ResultHandler}
+ */
+public class ResultHandlerTest extends TestCase {
+
+ private static final String SUITE_NAME = "CTS";
+ private static final String SUITE_VERSION = "5.0";
+ private static final String SUITE_PLAN = "cts";
+ private static final String REPORT_VERSION = "5.0";
+ private static final String OS_NAME = System.getProperty("os.name");
+ private static final String OS_VERSION = System.getProperty("os.version");
+ private static final String OS_ARCH = System.getProperty("os.arch");
+ private static final String JAVA_VENDOR = System.getProperty("java.vendor");
+ private static final String JAVA_VERSION = System.getProperty("java.version");
+ private static final String NAME_A = "ModuleA";
+ private static final String NAME_B = "ModuleB";
+ private static final String ABI = "mips64";
+ private static final String ID_A = AbiUtils.createId(ABI, NAME_A);
+ private static final String ID_B = AbiUtils.createId(ABI, NAME_B);
+ private static final String DEVICE_A = "device123";
+ private static final String DEVICE_B = "device456";
+ private static final String DEVICES = "device456,device123";
+ private static final String CLASS_A = "android.test.Foor";
+ private static final String CLASS_B = "android.test.Bar";
+ private static final String METHOD_1 = "testBlah1";
+ private static final String METHOD_2 = "testBlah2";
+ private static final String METHOD_3 = "testBlah3";
+ private static final String METHOD_4 = "testBlah4";
+ private static final String SUMMARY_SOURCE = String.format("%s#%s:20", CLASS_B, METHOD_4);
+ private static final String DETAILS_SOURCE = String.format("%s#%s:18", CLASS_B, METHOD_4);
+ private static final String SUMMARY_MESSAGE = "Headline";
+ private static final double SUMMARY_VALUE = 9001;
+ private static final String DETAILS_MESSAGE = "Deats";
+ private static final double DETAILS_VALUE_1 = 14;
+ private static final double DETAILS_VALUE_2 = 18;
+ private static final double DETAILS_VALUE_3 = 17;
+ private static final String MESSAGE = "Something small is not alright";
+ private static final String STACK_TRACE = "Something small is not alright\n " +
+ "at four.big.insects.Marley.sing(Marley.java:10)";
+ private static final long START_MS = 1431586801000L;
+ private static final long END_MS = 1431673199000L;
+ private static final String REFERENCE_URL="http://android.com";
+ private static final String JOIN = "%s%s";
+ private static final String XML_BASE =
+ "<?xml version='1.0' encoding='UTF-8' standalone='no' ?>" +
+ "<?xml-stylesheet type=\"text/xsl\" href=\"compatibility_result.xsl\"?>\n" +
+ "<Result start=\"%d\" end=\"%d\" suite_name=\"%s\" suite_version=\"%s\" " +
+ "suite_plan=\"%s\" report_version=\"%s\" devices=\"%s\" host_name=\"%s\"" +
+ "os_name=\"%s\" os_version=\"%s\" os_arch=\"%s\" java_vendor=\"%s\"" +
+ "java_version=\"%s\" reference_url=\"%s\">\n" +
+ "%s%s%s" +
+ "</Result>";
+ private static final String XML_DEVICE_INFO =
+ " <Build build_fingerprint=\"%s\" />\n";
+ private static final String XML_SUMMARY =
+ " <Summary pass=\"%d\" failed=\"%d\" not_executed=\"%d\" />\n";
+ private static final String XML_MODULE =
+ " <Module name=\"%s\" abi=\"%s\" device=\"%s\">\n" +
+ "%s" +
+ " </Module>\n";
+ private static final String XML_CASE =
+ " <TestCase name=\"%s\">\n" +
+ "%s" +
+ " </TestCase>\n";
+ private static final String XML_TEST_PASS =
+ " <Test result=\"pass\" name=\"%s\"/>\n";
+ private static final String XML_TEST_NOT_EXECUTED =
+ " <Test result=\"not_executed\" name=\"%s\"/>\n";
+ private static final String XML_TEST_FAIL =
+ " <Test result=\"fail\" name=\"%s\">\n" +
+ " <Failure message=\"%s\">\n" +
+ " <StackTrace>%s</StackTrace>\n" +
+ " </Failure>\n" +
+ " </Test>\n";
+ private static final String XML_TEST_RESULT =
+ " <Test result=\"pass\" name=\"%s\">\n" +
+ " <Summary>\n" +
+ " <Metric source=\"%s\" message=\"%s\" score_type=\"%s\" score_unit=\"%s\">\n" +
+ " <Value>%s</Value>\n" +
+ " </Metric>\n" +
+ " </Summary>\n" +
+ " <Detail>\n" +
+ " <Metric source=\"%s\" message=\"%s\" score_type=\"%s\" score_unit=\"%s\">\n" +
+ " <Value>%s</Value>\n" +
+ " <Value>%s</Value>\n" +
+ " <Value>%s</Value>\n" +
+ " </Metric>\n" +
+ " </Detail>\n" +
+ " </Test>\n";
+ private File resultsDir = null;
+ private File resultDir = null;
+
+ @Override
+ public void setUp() throws Exception {
+ resultsDir = FileUtil.createTempDir("results");
+ resultDir = FileUtil.createTempDir("12345", resultsDir);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (resultsDir != null) {
+ FileUtil.recursiveDelete(resultsDir);
+ }
+ }
+
+ public void testSerialization() throws Exception {
+ IInvocationResult result = new InvocationResult(resultDir);
+ result.setStartTime(START_MS);
+ result.setTestPlan(SUITE_PLAN);
+ result.addDeviceSerial(DEVICE_A);
+ result.addDeviceSerial(DEVICE_B);
+ IModuleResult moduleA = result.getOrCreateModule(ID_A);
+ ICaseResult moduleACase = moduleA.getOrCreateResult(CLASS_A);
+ ITestResult moduleATest1 = moduleACase.getOrCreateResult(METHOD_1);
+ moduleATest1.setResultStatus(TestStatus.PASS);
+ ITestResult moduleATest2 = moduleACase.getOrCreateResult(METHOD_2);
+ moduleATest2.setResultStatus(TestStatus.NOT_EXECUTED);
+
+ IModuleResult moduleB = result.getOrCreateModule(ID_B);
+ ICaseResult moduleBCase = moduleB.getOrCreateResult(CLASS_B);
+ ITestResult moduleBTest3 = moduleBCase.getOrCreateResult(METHOD_3);
+ moduleBTest3.setResultStatus(TestStatus.FAIL);
+ moduleBTest3.setMessage(MESSAGE);
+ moduleBTest3.setStackTrace(STACK_TRACE);
+ ITestResult moduleBTest4 = moduleBCase.getOrCreateResult(METHOD_4);
+ moduleBTest4.setResultStatus(TestStatus.PASS);
+ ReportLog report = new ReportLog();
+ ReportLog.Metric summary = new ReportLog.Metric(SUMMARY_SOURCE, SUMMARY_MESSAGE,
+ SUMMARY_VALUE, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
+ report.setSummary(summary);
+ ReportLog.Metric details = new ReportLog.Metric(DETAILS_SOURCE, DETAILS_MESSAGE,
+ new double[] {DETAILS_VALUE_1, DETAILS_VALUE_2, DETAILS_VALUE_3},
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addMetric(details);
+ moduleBTest4.setReportLog(report);
+
+ // Serialize to file
+ ResultHandler.writeResults(SUITE_NAME, SUITE_VERSION, SUITE_PLAN, result, resultDir,
+ START_MS, END_MS, REFERENCE_URL);
+
+ // Parse the results and assert correctness
+ checkResult(ResultHandler.getResults(resultsDir), resultDir);
+ }
+
+ public void testParsing() throws Exception {
+ File resultsDir = null;
+ FileWriter writer = null;
+ try {
+ resultsDir = FileUtil.createTempDir("results");
+ File resultDir = FileUtil.createTempDir("12345", resultsDir);
+ // Create the result file
+ File resultFile = new File(resultDir, ResultHandler.TEST_RESULT_FILE_NAME);
+ writer = new FileWriter(resultFile);
+ String deviceInfo = String.format(XML_DEVICE_INFO, DEVICE_A);
+ String summary = String.format(XML_SUMMARY, 2, 1, 1);
+ String moduleATest1 = String.format(XML_TEST_PASS, METHOD_1);
+ String moduleATest2 = String.format(XML_TEST_NOT_EXECUTED, METHOD_2);
+ String moduleATests = String.format(JOIN, moduleATest1, moduleATest2);
+ String moduleACases = String.format(XML_CASE, CLASS_A, moduleATests);
+ String moduleA = String.format(XML_MODULE, NAME_A, ABI, DEVICE_A, moduleACases);
+ String moduleBTest3 = String.format(XML_TEST_FAIL, METHOD_3, MESSAGE, STACK_TRACE);
+ String moduleBTest4 = String.format(XML_TEST_RESULT, METHOD_4,
+ SUMMARY_SOURCE, SUMMARY_MESSAGE, ResultType.HIGHER_BETTER.toReportString(),
+ ResultUnit.SCORE.toReportString(), Double.toString(SUMMARY_VALUE),
+ DETAILS_SOURCE, DETAILS_MESSAGE, ResultType.LOWER_BETTER.toReportString(),
+ ResultUnit.MS.toReportString(), Double.toString(DETAILS_VALUE_1),
+ Double.toString(DETAILS_VALUE_2), Double.toString(DETAILS_VALUE_3));
+ String moduleBTests = String.format(JOIN, moduleBTest3, moduleBTest4);
+ String moduleBCases = String.format(XML_CASE, CLASS_B, moduleBTests);
+ String moduleB = String.format(XML_MODULE, NAME_B, ABI, DEVICE_B, moduleBCases);
+ String modules = String.format(JOIN, moduleA, moduleB);
+ String hostName = "";
+ try {
+ hostName = InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException ignored) {}
+ String output = String.format(XML_BASE, START_MS, END_MS, SUITE_NAME, SUITE_VERSION,
+ SUITE_PLAN, REPORT_VERSION, DEVICES, hostName, OS_NAME, OS_VERSION, OS_ARCH,
+ JAVA_VENDOR, JAVA_VERSION, REFERENCE_URL, deviceInfo, summary, modules);
+ writer.write(output);
+ writer.flush();
+
+ // Parse the results and assert correctness
+ checkResult(ResultHandler.getResults(resultsDir), resultDir);
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+
+ private void checkResult(List<IInvocationResult> results, File resultDir) throws Exception {
+ assertEquals("Expected 1 result", 1, results.size());
+ IInvocationResult result = results.get(0);
+ assertEquals("Expected 2 passes", 2, result.countResults(TestStatus.PASS));
+ assertEquals("Expected 1 failure", 1, result.countResults(TestStatus.FAIL));
+ assertEquals("Expected 1 not executed", 1, result.countResults(TestStatus.NOT_EXECUTED));
+ Set<String> serials = result.getDeviceSerials();
+ assertTrue("Missing device", serials.contains(DEVICE_A));
+ assertTrue("Missing device", serials.contains(DEVICE_B));
+ assertEquals("Expected 2 devices", 2, serials.size());
+ assertTrue("Incorrect devices", serials.contains(DEVICE_A) && serials.contains(DEVICE_B));
+ assertEquals("Incorrect result dir", resultDir.getAbsolutePath(),
+ result.getResultDir().getAbsolutePath());
+ assertEquals("Incorrect start time", START_MS, result.getStartTime());
+ assertEquals("Incorrect test plan", SUITE_PLAN, result.getTestPlan());
+
+ List<IModuleResult> modules = result.getModules();
+ assertEquals("Expected 2 modules", 2, modules.size());
+
+ IModuleResult moduleA = modules.get(0);
+ assertEquals("Expected 1 pass", 1, moduleA.countResults(TestStatus.PASS));
+ assertEquals("Expected 0 failures", 0, moduleA.countResults(TestStatus.FAIL));
+ assertEquals("Expected 1 not executed", 1, moduleA.countResults(TestStatus.NOT_EXECUTED));
+ assertEquals("Incorrect ABI", ABI, moduleA.getAbi());
+ assertEquals("Incorrect name", NAME_A, moduleA.getName());
+ assertEquals("Incorrect ID", ID_A, moduleA.getId());
+ List<ICaseResult> moduleACases = moduleA.getResults();
+ assertEquals("Expected 1 test case", 1, moduleACases.size());
+ ICaseResult moduleACase = moduleACases.get(0);
+ assertEquals("Incorrect name", CLASS_A, moduleACase.getName());
+ List<ITestResult> moduleAResults = moduleACase.getResults();
+ assertEquals("Expected 2 results", 2, moduleAResults.size());
+ ITestResult moduleATest1 = moduleAResults.get(0);
+ assertEquals("Incorrect name", METHOD_1, moduleATest1.getName());
+ assertEquals("Incorrect result", TestStatus.PASS, moduleATest1.getResultStatus());
+ assertNull("Unexpected bugreport", moduleATest1.getBugReport());
+ assertNull("Unexpected log", moduleATest1.getLog());
+ assertNull("Unexpected screenshot", moduleATest1.getScreenshot());
+ assertNull("Unexpected message", moduleATest1.getMessage());
+ assertNull("Unexpected stack trace", moduleATest1.getStackTrace());
+ assertNull("Unexpected report", moduleATest1.getReportLog());
+ ITestResult moduleATest2 = moduleAResults.get(1);
+ assertEquals("Incorrect name", METHOD_2, moduleATest2.getName());
+ assertEquals("Incorrect result", TestStatus.NOT_EXECUTED, moduleATest2.getResultStatus());
+ assertNull("Unexpected bugreport", moduleATest2.getBugReport());
+ assertNull("Unexpected log", moduleATest2.getLog());
+ assertNull("Unexpected screenshot", moduleATest2.getScreenshot());
+ assertNull("Unexpected message", moduleATest2.getMessage());
+ assertNull("Unexpected stack trace", moduleATest2.getStackTrace());
+ assertNull("Unexpected report", moduleATest2.getReportLog());
+
+ IModuleResult moduleB = modules.get(1);
+ assertEquals("Expected 1 pass", 1, moduleB.countResults(TestStatus.PASS));
+ assertEquals("Expected 1 failure", 1, moduleB.countResults(TestStatus.FAIL));
+ assertEquals("Expected 0 not executed", 0, moduleB.countResults(TestStatus.NOT_EXECUTED));
+ assertEquals("Incorrect ABI", ABI, moduleB.getAbi());
+ assertEquals("Incorrect name", NAME_B, moduleB.getName());
+ assertEquals("Incorrect ID", ID_B, moduleB.getId());
+ List<ICaseResult> moduleBCases = moduleB.getResults();
+ assertEquals("Expected 1 test case", 1, moduleBCases.size());
+ ICaseResult moduleBCase = moduleBCases.get(0);
+ assertEquals("Incorrect name", CLASS_B, moduleBCase.getName());
+ List<ITestResult> moduleBResults = moduleBCase.getResults();
+ assertEquals("Expected 2 results", 2, moduleBResults.size());
+ ITestResult moduleBTest3 = moduleBResults.get(0);
+ assertEquals("Incorrect name", METHOD_3, moduleBTest3.getName());
+ assertEquals("Incorrect result", TestStatus.FAIL, moduleBTest3.getResultStatus());
+ assertNull("Unexpected bugreport", moduleBTest3.getBugReport());
+ assertNull("Unexpected log", moduleBTest3.getLog());
+ assertNull("Unexpected screenshot", moduleBTest3.getScreenshot());
+ assertEquals("Incorrect message", MESSAGE, moduleBTest3.getMessage());
+ assertEquals("Incorrect stack trace", STACK_TRACE, moduleBTest3.getStackTrace());
+ assertNull("Unexpected report", moduleBTest3.getReportLog());
+ ITestResult moduleBTest4 = moduleBResults.get(1);
+ assertEquals("Incorrect name", METHOD_4, moduleBTest4.getName());
+ assertEquals("Incorrect result", TestStatus.PASS, moduleBTest4.getResultStatus());
+ assertNull("Unexpected bugreport", moduleBTest4.getBugReport());
+ assertNull("Unexpected log", moduleBTest4.getLog());
+ assertNull("Unexpected screenshot", moduleBTest4.getScreenshot());
+ assertNull("Unexpected message", moduleBTest4.getMessage());
+ assertNull("Unexpected stack trace", moduleBTest4.getStackTrace());
+ ReportLog report = moduleBTest4.getReportLog();
+ assertNotNull("Expected report", report);
+ ReportLog.Metric summary = report.getSummary();
+ assertNotNull("Expected report summary", summary);
+ assertEquals("Incorrect source", SUMMARY_SOURCE, summary.getSource());
+ assertEquals("Incorrect message", SUMMARY_MESSAGE, summary.getMessage());
+ assertEquals("Incorrect type", ResultType.HIGHER_BETTER, summary.getType());
+ assertEquals("Incorrect unit", ResultUnit.SCORE, summary.getUnit());
+ assertTrue("Incorrect values", Arrays.equals(new double[] { SUMMARY_VALUE },
+ summary.getValues()));
+ List<ReportLog.Metric> details = report.getDetailedMetrics();
+ assertEquals("Expected 1 report detail", 1, details.size());
+ ReportLog.Metric detail = details.get(0);
+ assertEquals("Incorrect source", DETAILS_SOURCE, detail.getSource());
+ assertEquals("Incorrect message", DETAILS_MESSAGE, detail.getMessage());
+ assertEquals("Incorrect type", ResultType.LOWER_BETTER, detail.getType());
+ assertEquals("Incorrect unit", ResultUnit.MS, detail.getUnit());
+ assertTrue("Incorrect values", Arrays.equals(new double[] { DETAILS_VALUE_1,
+ DETAILS_VALUE_2, DETAILS_VALUE_3 }, detail.getValues()));
+ }
+}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/StatTest.java b/common/util/tests/src/com/android/compatibility/common/util/StatTest.java
new file mode 100644
index 0000000..6e53d48
--- /dev/null
+++ b/common/util/tests/src/com/android/compatibility/common/util/StatTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 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 com.android.compatibility.common.util;
+
+import com.android.compatibility.common.util.Stat;
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for the {@link Stat} class.
+ */
+public class StatTest extends TestCase {
+
+ /**
+ * Test {@link Stat#get95PercentileValue(double[])}.
+ */
+ public void testGet95PercentileValue() {
+ double[] values = new double[100];
+ for (int i = 0; i < 100; i++) {
+ values[i] = i;
+ }
+ assertEquals(95, (int) Stat.get95PercentileValue(values));
+
+ values = new double[1000];
+ for (int i = 0; i < 1000; i++) {
+ values[i] = i;
+ }
+ assertEquals(950, (int) Stat.get95PercentileValue(values));
+
+ values = new double[100];
+ for (int i = 0; i < 100; i++) {
+ values[i] = i * i;
+ }
+ assertEquals(95 * 95, (int) Stat.get95PercentileValue(values));
+ }
+
+ /**
+ * Test {@link Stat#getAverage(double[])}.
+ */
+ public void testGetAverage() {
+ double[] values = new double[]{0, 1, 2, 3, 4};
+ double average = Stat.getAverage(values);
+ assertEquals(2.0, average, 0.00001);
+
+ values = new double[]{1, 2, 3, 4, 5};
+ average = Stat.getAverage(values);
+ assertEquals(3.0, average, 0.00001);
+
+ values = new double[]{0, 1, 4, 9, 16};
+ average = Stat.getAverage(values);
+ assertEquals(6.0, average, 0.00001);
+ }
+
+ /**
+ * Test standard deviation.
+ */
+ public void testGetStandardDeviation() {
+ double[] values = new double[]{0, 1, 2, 3, 4};
+ double stddev = Stat.getStat(values).mStddev;
+ assertEquals(Math.sqrt(2.5), stddev, 0.00001);
+
+ values = new double[]{1, 2, 3, 4, 5};
+ stddev = Stat.getStat(values).mStddev;
+ assertEquals(Math.sqrt(2.5), stddev, 0.00001);
+
+ values = new double[]{0, 2, 4, 6, 8};
+ stddev = Stat.getStat(values).mStddev;
+ assertEquals(Math.sqrt(10.0), stddev, 0.00001);
+ }
+
+
+}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/TestFilterTest.java b/common/util/tests/src/com/android/compatibility/common/util/TestFilterTest.java
new file mode 100644
index 0000000..bc1091bb
--- /dev/null
+++ b/common/util/tests/src/com/android/compatibility/common/util/TestFilterTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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
+ */
+
+package com.android.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link TestFilter}
+ */
+public class TestFilterTest extends TestCase {
+
+ private static final String NAME = "ModuleName";
+ private static final String ABI = "mips64";
+ private static final String TEST = "com.android.foobar.Blah#testAllTheThings";
+ private static final String NAME_FILTER = String.format("%s", NAME);
+ private static final String ABI_NAME_FILTER = String.format("%s %s", ABI, NAME);
+ private static final String NAME_TEST_FILTER = String.format("%s %s", NAME, TEST);
+ private static final String FULL_FILTER = String.format("%s %s %s", ABI, NAME, TEST);
+
+ public void testParseNameFilter() {
+ TestFilter filter = TestFilter.createFrom(NAME_FILTER);
+ assertNull("Incorrect abi", filter.getAbi());
+ assertEquals("Incorrect name", NAME, filter.getName());
+ assertNull("Incorrect test", filter.getTest());
+ }
+
+ public void testParseAbiNameFilter() {
+ TestFilter filter = TestFilter.createFrom(ABI_NAME_FILTER);
+ assertEquals("Incorrect abi", ABI, filter.getAbi());
+ assertEquals("Incorrect name", NAME, filter.getName());
+ assertNull("Incorrect test", filter.getTest());
+ }
+
+ public void testParseNameTestFilter() {
+ TestFilter filter = TestFilter.createFrom(NAME_TEST_FILTER);
+ assertNull("Incorrect abi", filter.getAbi());
+ assertEquals("Incorrect name", NAME, filter.getName());
+ assertEquals("Incorrect test", TEST, filter.getTest());
+ }
+
+ public void testParseFullFilter() {
+ TestFilter filter = TestFilter.createFrom(FULL_FILTER);
+ assertEquals("Incorrect abi", ABI, filter.getAbi());
+ assertEquals("Incorrect name", NAME, filter.getName());
+ assertEquals("Incorrect test", TEST, filter.getTest());
+ }
+
+ public void testCreateNameFilter() {
+ TestFilter filter = new TestFilter(null, NAME, null);
+ assertEquals("Incorrect filter", NAME_FILTER, filter.toString());
+ }
+
+ public void testCreateAbiNameFilter() {
+ TestFilter filter = new TestFilter(ABI, NAME, null);
+ assertEquals("Incorrect filter", ABI_NAME_FILTER, filter.toString());
+ }
+
+ public void testCreateNameTestFilter() {
+ TestFilter filter = new TestFilter(null, NAME, TEST);
+ assertEquals("Incorrect filter", NAME_TEST_FILTER, filter.toString());
+ }
+
+ public void testCreateFullFilter() {
+ TestFilter filter = new TestFilter(ABI, NAME, TEST);
+ assertEquals("Incorrect filter", FULL_FILTER, filter.toString());
+ }
+
+}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/TestResultTest.java b/common/util/tests/src/com/android/compatibility/common/util/TestResultTest.java
new file mode 100644
index 0000000..5e4431e
--- /dev/null
+++ b/common/util/tests/src/com/android/compatibility/common/util/TestResultTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.common.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link TestResult}
+ */
+public class TestResultTest extends TestCase {
+
+ private static final String CLASS = "android.test.FoorBar";
+ private static final String METHOD_1 = "testBlah1";
+ private static final String TEST_1 = String.format("%s#%s", CLASS, METHOD_1);
+ private CaseResult mCase;
+ private TestResult mResult;
+
+ @Override
+ public void setUp() throws Exception {
+ mCase = new CaseResult(CLASS);
+ mResult = new TestResult(mCase, METHOD_1);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mResult = null;
+ }
+
+ public void testAccessors() throws Exception {
+ assertEquals("Incorrect test name", METHOD_1, mResult.getName());
+ assertEquals("Incorrect full name", TEST_1, mResult.getFullName());
+ }
+
+}
\ No newline at end of file
diff --git a/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java b/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java
index 348c680..967b8a8 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -11,23 +11,36 @@
* 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
+ * limitations under the License.
*/
-
package com.android.compatibility.common.util;
+import junit.framework.Test;
import junit.framework.TestSuite;
/**
- * A {@link TestSuite} for the common.util package.
+ * A test suite for all util unit tests.
+ * <p/>
+ * All tests listed here should be self-contained, and do not require any external dependencies.
*/
public class UnitTests extends TestSuite {
public UnitTests() {
super();
-
- addTestSuite(MetricsStoreTest.class);
+ addTestSuite(AbiUtilsTest.class);
+ addTestSuite(CaseResultTest.class);
+ addTestSuite(DynamicConfigTest.class);
addTestSuite(MetricsXmlSerializerTest.class);
+ addTestSuite(ModuleResultTest.class);
+ addTestSuite(MultipartFormTest.class);
addTestSuite(ReportLogTest.class);
+ addTestSuite(StatTest.class);
+ addTestSuite(TestFilterTest.class);
+ addTestSuite(TestResultTest.class);
+ addTestSuite(ResultHandlerTest.class);
}
-}
+
+ public static Test suite() {
+ return new UnitTests();
+ }
+}
\ No newline at end of file
diff --git a/hostsidetests/aadb/Android.mk b/hostsidetests/aadb/Android.mk
index b9551d1..c7651ba 100644
--- a/hostsidetests/aadb/Android.mk
+++ b/hostsidetests/aadb/Android.mk
@@ -19,12 +19,16 @@
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE := CtsAdbTests
+# Adb test cases, but name 'aadb' ensures adb tests run before all other modules depending on adb
+LOCAL_MODULE := CtsAadbHostTestCases
LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
LOCAL_CTS_TEST_PACKAGE := android.aadb
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
# Build the test APKs using their own makefiles
diff --git a/hostsidetests/aadb/AndroidTest.xml b/hostsidetests/aadb/AndroidTest.xml
new file mode 100644
index 0000000..cfba81e
--- /dev/null
+++ b/hostsidetests/aadb/AndroidTest.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<configuration description="Config for the CTS aadb host tests">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest">
+ <option name="jar" value="CtsAadbHostTestCases.jar" />
+ <option name="runtime-hint" value="5m30s" />
+ </test>
+</configuration>
diff --git a/hostsidetests/aadb/src/android/aadb/cts/TestDeviceFuncTest.java b/hostsidetests/aadb/src/android/aadb/cts/TestDeviceFuncTest.java
new file mode 100644
index 0000000..ddc3e82
--- /dev/null
+++ b/hostsidetests/aadb/src/android/aadb/cts/TestDeviceFuncTest.java
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2013 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.aadb.cts;
+
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.IFileEntry;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.InputStreamSource;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.util.CommandStatus;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.RunUtil;
+import com.android.tradefed.util.StreamUtil;
+
+import java.awt.image.BufferedImage;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.TimeZone;
+
+import javax.imageio.ImageIO;
+
+/**
+ * Functional tests for adb connection
+ * <p/>
+ * Requires a physical device to be connected.
+ */
+public class TestDeviceFuncTest extends DeviceTestCase {
+
+ private static final String LOG_TAG = "TestDeviceFuncTest";
+ private ITestDevice mTestDevice;
+ /** Expect bugreports to be at least a meg. */
+ private static final int mMinBugreportBytes = 1024 * 1024;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestDevice = getDevice();
+ }
+
+ /**
+ * Simple testcase to ensure that the grabbing a bugreport from a real TestDevice works.
+ */
+ public void testBugreport() throws Exception {
+ String data = StreamUtil.getStringFromStream(
+ mTestDevice.getBugreport().createInputStream());
+ assertTrue(String.format("Expected at least %d characters; only saw %d", mMinBugreportBytes,
+ data.length()), data.length() >= mMinBugreportBytes);
+ // TODO: check the captured report more extensively, perhaps using loganalysis
+ }
+
+ /**
+ * Simple normal case test for
+ * {@link TestDevice#executeShellCommand(String)}.
+ * <p/>
+ * Do a 'shell ls' command, and verify /data and /system are listed in result.
+ */
+ public void testExecuteShellCommand() throws IOException, DeviceNotAvailableException {
+ Log.i(LOG_TAG, "testExecuteShellCommand");
+ assertSimpleShellCommand();
+ }
+
+ /**
+ * Verify that a simple {@link TestDevice#executeShellCommand(String)} command is successful.
+ */
+ private void assertSimpleShellCommand() throws DeviceNotAvailableException {
+ // Check for expected contents of device's root directory
+ final String output = mTestDevice.executeShellCommand("ls /");
+ assertTrue(output.contains("data"));
+ assertTrue(output.contains("system"));
+ }
+
+
+ /**
+ * Push and then pull a file from device, and verify contents are as expected.
+ */
+ public void testPushPull_normal() throws IOException, DeviceNotAvailableException {
+ Log.i(LOG_TAG, "testPushPull");
+ File tmpFile = null;
+ File tmpDestFile = null;
+ String deviceFilePath = null;
+
+ try {
+ tmpFile = createTempTestFile(null);
+ String externalStorePath = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
+ assertNotNull(externalStorePath);
+ deviceFilePath = String.format("%s/%s", externalStorePath, "tmp_testPushPull.txt");
+ // ensure file does not already exist
+ mTestDevice.executeShellCommand(String.format("rm %s", deviceFilePath));
+ assertFalse(String.format("%s exists", deviceFilePath),
+ mTestDevice.doesFileExist(deviceFilePath));
+
+ assertTrue(mTestDevice.pushFile(tmpFile, deviceFilePath));
+ assertTrue(mTestDevice.doesFileExist(deviceFilePath));
+ tmpDestFile = FileUtil.createTempFile("tmp", "txt");
+ assertTrue(mTestDevice.pullFile(deviceFilePath, tmpDestFile));
+ assertTrue(compareFiles(tmpFile, tmpDestFile));
+ } finally {
+ if (tmpDestFile != null) {
+ tmpDestFile.delete();
+ }
+ if (deviceFilePath != null) {
+ mTestDevice.executeShellCommand(String.format("rm %s", deviceFilePath));
+ }
+ }
+ }
+
+ /**
+ * Push and then pull a file from device, and verify contents are as expected.
+ * <p />
+ * This variant of the test uses "${EXTERNAL_STORAGE}" in the pathname.
+ */
+ public void testPushPull_extStorageVariable() throws IOException, DeviceNotAvailableException {
+ Log.i(LOG_TAG, "testPushPull");
+ File tmpFile = null;
+ File tmpDestFile = null;
+ File tmpDestFile2 = null;
+ String deviceFilePath = null;
+ final String filename = "tmp_testPushPull.txt";
+
+ try {
+ tmpFile = createTempTestFile(null);
+ String externalStorePath = "${EXTERNAL_STORAGE}";
+ assertNotNull(externalStorePath);
+ deviceFilePath = String.format("%s/%s", externalStorePath, filename);
+ // ensure file does not already exist
+ mTestDevice.executeShellCommand(String.format("rm %s", deviceFilePath));
+ assertFalse(String.format("%s exists", deviceFilePath),
+ mTestDevice.doesFileExist(deviceFilePath));
+
+ assertTrue(mTestDevice.pushFile(tmpFile, deviceFilePath));
+ assertTrue(mTestDevice.doesFileExist(deviceFilePath));
+ tmpDestFile = FileUtil.createTempFile("tmp", "txt");
+ assertTrue(mTestDevice.pullFile(deviceFilePath, tmpDestFile));
+ assertTrue(compareFiles(tmpFile, tmpDestFile));
+
+ tmpDestFile2 = mTestDevice.pullFileFromExternal(filename);
+ assertNotNull(tmpDestFile2);
+ assertTrue(compareFiles(tmpFile, tmpDestFile2));
+ } finally {
+ if (tmpDestFile != null) {
+ tmpDestFile.delete();
+ }
+ if (tmpDestFile2 != null) {
+ tmpDestFile2.delete();
+ }
+ if (deviceFilePath != null) {
+ mTestDevice.executeShellCommand(String.format("rm %s", deviceFilePath));
+ }
+ }
+ }
+
+ /**
+ * Test pulling a file from device that does not exist.
+ * <p/>
+ * Expect {@link TestDevice#pullFile(String)} to return <code>false</code>
+ */
+ public void testPull_noexist() throws IOException, DeviceNotAvailableException {
+ Log.i(LOG_TAG, "testPull_noexist");
+
+ // make sure the root path is valid
+ String externalStorePath = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
+ assertNotNull(externalStorePath);
+ String deviceFilePath = String.format("%s/%s", externalStorePath, "thisfiledoesntexist");
+ assertFalse(String.format("%s exists", deviceFilePath),
+ mTestDevice.doesFileExist(deviceFilePath));
+ assertNull(mTestDevice.pullFile(deviceFilePath));
+ }
+
+ private File createTempTestFile(File dir) throws IOException {
+ File tmpFile = null;
+ try {
+ final String fileContents = "this is the test file contents";
+ tmpFile = FileUtil.createTempFile("tmp", ".txt", dir);
+ FileUtil.writeToFile(fileContents, tmpFile);
+ return tmpFile;
+ } catch (IOException e) {
+ if (tmpFile != null) {
+ tmpFile.delete();
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Utility method to do byte-wise content comparison of two files.
+ */
+ private boolean compareFiles(File file1, File file2) throws IOException {
+ BufferedInputStream stream1 = null;
+ BufferedInputStream stream2 = null;
+
+ try {
+ stream1 = new BufferedInputStream(new FileInputStream(file1));
+ stream2 = new BufferedInputStream(new FileInputStream(file2));
+ boolean eof = false;
+ while (!eof) {
+ int byte1 = stream1.read();
+ int byte2 = stream2.read();
+ if (byte1 != byte2) {
+ return false;
+ }
+ eof = byte1 == -1;
+ }
+ return true;
+ } finally {
+ if (stream1 != null) {
+ stream1.close();
+ }
+ if (stream2 != null) {
+ stream2.close();
+ }
+ }
+ }
+
+ /**
+ * Test syncing a single file using {@link TestDevice#syncFiles(File, String)}.
+ */
+ public void testSyncFiles_normal() throws Exception {
+ doTestSyncFiles(mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE));
+ }
+
+ /**
+ * Test syncing a single file using {@link TestDevice#syncFiles(File, String)}.
+ * <p />
+ * This variant of the test uses "${EXTERNAL_STORAGE}" in the pathname.
+ */
+ public void testSyncFiles_extStorageVariable() throws Exception {
+ doTestSyncFiles("${EXTERNAL_STORAGE}");
+ }
+
+ /**
+ * Test syncing a single file using {@link TestDevice#syncFiles(File, String)}.
+ */
+ public void doTestSyncFiles(String externalStorePath) throws Exception {
+ String expectedDeviceFilePath = null;
+
+ // create temp dir with one temp file
+ File tmpDir = FileUtil.createTempDir("tmp");
+ try {
+ File tmpFile = createTempTestFile(tmpDir);
+ // set last modified to 10 minutes ago
+ tmpFile.setLastModified(System.currentTimeMillis() - 10*60*1000);
+ assertNotNull(externalStorePath);
+ expectedDeviceFilePath = String.format("%s/%s/%s", externalStorePath,
+ tmpDir.getName(), tmpFile.getName());
+
+ assertTrue(mTestDevice.syncFiles(tmpDir, externalStorePath));
+ assertTrue(mTestDevice.doesFileExist(expectedDeviceFilePath));
+
+ // get 'ls -l' attributes of file which includes timestamp
+ String origTmpFileStamp = mTestDevice.executeShellCommand(String.format("ls -l %s",
+ expectedDeviceFilePath));
+ // now create another file and verify that is synced
+ File tmpFile2 = createTempTestFile(tmpDir);
+ tmpFile2.setLastModified(System.currentTimeMillis() - 10*60*1000);
+ assertTrue(mTestDevice.syncFiles(tmpDir, externalStorePath));
+ String expectedDeviceFilePath2 = String.format("%s/%s/%s", externalStorePath,
+ tmpDir.getName(), tmpFile2.getName());
+ assertTrue(mTestDevice.doesFileExist(expectedDeviceFilePath2));
+
+ // verify 1st file timestamp did not change
+ String unchangedTmpFileStamp = mTestDevice.executeShellCommand(String.format("ls -l %s",
+ expectedDeviceFilePath));
+ assertEquals(origTmpFileStamp, unchangedTmpFileStamp);
+
+ // now modify 1st file and verify it does change remotely
+ String testString = "blah";
+ FileOutputStream stream = new FileOutputStream(tmpFile);
+ stream.write(testString.getBytes());
+ stream.close();
+
+ // adjust 1st file's last-modified timestamp according to persist.sys.timezone
+ String deviceTimezone = mTestDevice.getProperty("persist.sys.timezone");
+ if (deviceTimezone != null) {
+ TimeZone tz = TimeZone.getTimeZone(deviceTimezone);
+ long timestamp = tmpFile.lastModified() + tz.getRawOffset();
+ if (tz.observesDaylightTime()) {
+ timestamp += tz.getDSTSavings();
+ }
+ tmpFile.setLastModified(timestamp);
+ }
+
+ assertTrue(mTestDevice.syncFiles(tmpDir, externalStorePath));
+ String tmpFileContents = mTestDevice.executeShellCommand(String.format("cat %s",
+ expectedDeviceFilePath));
+ assertTrue(tmpFileContents.contains(testString));
+ } finally {
+ if (expectedDeviceFilePath != null && externalStorePath != null) {
+ // note that expectedDeviceFilePath has externalStorePath prepended at definition
+ mTestDevice.executeShellCommand(String.format("rm -r %s", expectedDeviceFilePath));
+ }
+ FileUtil.recursiveDelete(tmpDir);
+ }
+ }
+
+ /**
+ * Test pushing a directory
+ */
+ public void testPushDir() throws IOException, DeviceNotAvailableException {
+ String expectedDeviceFilePath = null;
+ String externalStorePath = null;
+ File rootDir = FileUtil.createTempDir("tmp");
+ // create temp dir with one temp file
+ try {
+ File tmpDir = FileUtil.createTempDir("tmp", rootDir);
+ File tmpFile = createTempTestFile(tmpDir);
+ externalStorePath = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
+ assertNotNull(externalStorePath);
+ expectedDeviceFilePath = String.format("%s/%s/%s", externalStorePath,
+ tmpDir.getName(), tmpFile.getName());
+
+ assertTrue(mTestDevice.pushDir(rootDir, externalStorePath));
+ assertTrue(mTestDevice.doesFileExist(expectedDeviceFilePath));
+
+ } finally {
+ if (expectedDeviceFilePath != null && externalStorePath != null) {
+ mTestDevice.executeShellCommand(String.format("rm -r %s/%s", externalStorePath,
+ expectedDeviceFilePath));
+ }
+ FileUtil.recursiveDelete(rootDir);
+ }
+ }
+
+ /**
+ * Basic test for {@link TestDevice#getScreenshot()}.
+ * <p/>
+ * Grab a screenshot and perform a cursory size check to ensure its valid.
+ */
+ public void testGetScreenshot() throws DeviceNotAvailableException, IOException {
+ InputStreamSource source = getDevice().getScreenshot();
+ assertNotNull(source);
+ InputStream inputStream = source.createInputStream();
+ try {
+ BufferedImage screenshotImage = ImageIO.read(inputStream);
+ CLog.i(LOG_TAG, "testGetScreenshot w=%d, h=%d",
+ screenshotImage.getWidth(), screenshotImage.getHeight());
+ assertTrue(screenshotImage.getWidth() > 0);
+ assertTrue(screenshotImage.getHeight() > 0);
+ } finally {
+ StreamUtil.cancel(source);
+ StreamUtil.close(inputStream);
+ }
+ }
+
+ /**
+ * Basic test for {@link TestDevice#getLogcat(long)}.
+ * <p/>
+ * Dumps a bunch of messages to logcat, calls getLogcat(), and verifies size of capture file is
+ * equal to provided data.
+ */
+ public void testGetLogcat_size() throws DeviceNotAvailableException, IOException {
+ CLog.i(LOG_TAG, "testGetLogcat_size");
+ for (int i = 0; i < 100; i++) {
+ getDevice().executeShellCommand(String.format("log testGetLogcat_size log dump %d", i));
+ }
+ boolean passed = false;
+ int retry = 0;
+ while (!passed) {
+ // sleep a small amount of time to ensure last log message makes it into capture
+ RunUtil.getDefault().sleep(10);
+ InputStreamSource source = getDevice().getLogcat(100 * 1024);
+ assertNotNull(source);
+ File tmpTxtFile = FileUtil.createTempFile("logcat", ".txt");
+ try {
+ FileUtil.writeToFile(source.createInputStream(), tmpTxtFile);
+ CLog.i("Created file at %s", tmpTxtFile.getAbsolutePath());
+ // ensure last log message is present in log
+ String s = FileUtil.readStringFromFile(tmpTxtFile);
+ if (s.contains("testGetLogcat_size log dump 99")) {
+ passed = true;
+ }
+ } finally {
+ FileUtil.deleteFile(tmpTxtFile);
+ source.cancel();
+ }
+ retry++;
+ if ((retry > 100) && !passed) {
+ fail("last log message is not in captured logcat");
+ }
+ }
+ }
+}
diff --git a/hostsidetests/aadb/src/android/aadb/cts/TestDeviceStressTest.java b/hostsidetests/aadb/src/android/aadb/cts/TestDeviceStressTest.java
new file mode 100644
index 0000000..f5872a7
--- /dev/null
+++ b/hostsidetests/aadb/src/android/aadb/cts/TestDeviceStressTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2013 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.aadb.cts;
+
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.util.FileUtil;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Long running functional tests for {@link TestDevice} that verify an operation can be run
+ * many times in sequence
+ * <p/>
+ * Requires a physical device to be connected.
+ */
+public class TestDeviceStressTest extends DeviceTestCase {
+
+ private int mIterations = 25;
+
+ private static final String LOG_TAG = "TestDeviceStressTest";
+ private static final int TEST_FILE_COUNT= 200;
+ private ITestDevice mTestDevice;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestDevice = getDevice();
+ }
+
+ private File createTempTestFiles() throws IOException {
+ File tmpDir = null;
+ File tmpFile = null;
+
+ tmpDir = FileUtil.createTempDir("testDir");
+
+ final String fileContents = "this is the test file contents";
+ for (int i = 0; i < TEST_FILE_COUNT; i++) {
+ tmpFile = FileUtil.createTempFile(String.format("tmp_%d", i), ".txt", tmpDir);
+ FileUtil.writeToFile(fileContents, tmpFile);
+ }
+ return tmpDir;
+
+ }
+
+ /**
+ * Stress test to push a folder which contains 200 text file to device
+ * internal storage.
+ */
+ public void testPushFolderWithManyFiles() throws IOException, DeviceNotAvailableException {
+ File tmpDir = null;
+ String deviceFilePath = null;
+ String externalStorePath = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
+ assertNotNull(externalStorePath);
+ deviceFilePath = String.format("%s/%s", externalStorePath, "testDir");
+
+ // start the stress test
+ try {
+ // Create the test folder and make sure the test folder doesn't exist in
+ // device before the test start.
+ tmpDir = createTempTestFiles();
+ for (int i = 0; i < mIterations; i++) {
+ mTestDevice.executeShellCommand(String.format("rm -r %s", deviceFilePath));
+ assertFalse(String.format("%s exists", deviceFilePath),
+ mTestDevice.doesFileExist(deviceFilePath));
+ assertTrue(mTestDevice.pushDir(tmpDir, deviceFilePath));
+ assertTrue(mTestDevice.doesFileExist(deviceFilePath));
+ }
+ } finally {
+ if (tmpDir != null) {
+ FileUtil.recursiveDelete(tmpDir);
+ }
+ mTestDevice.executeShellCommand(String.format("rm -r %s", deviceFilePath));
+ assertFalse(String.format("%s exists", deviceFilePath),
+ mTestDevice.doesFileExist(deviceFilePath));
+ }
+ }
+}
diff --git a/hostsidetests/aadb/src/com/android/cts/aadb/TestDeviceFuncTest.java b/hostsidetests/aadb/src/com/android/cts/aadb/TestDeviceFuncTest.java
deleted file mode 100644
index b0fb1fb..0000000
--- a/hostsidetests/aadb/src/com/android/cts/aadb/TestDeviceFuncTest.java
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.aadb;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.IFileEntry;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.util.CommandStatus;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.RunUtil;
-import com.android.tradefed.util.StreamUtil;
-
-import java.awt.image.BufferedImage;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.util.TimeZone;
-
-import javax.imageio.ImageIO;
-
-/**
- * Functional tests for adb connection
- * <p/>
- * Requires a physical device to be connected.
- */
-public class TestDeviceFuncTest extends DeviceTestCase {
-
- private static final String LOG_TAG = "TestDeviceFuncTest";
- private ITestDevice mTestDevice;
- /** Expect bugreports to be at least a meg. */
- private static final int mMinBugreportBytes = 1024 * 1024;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mTestDevice = getDevice();
- }
-
- /**
- * Simple testcase to ensure that the grabbing a bugreport from a real TestDevice works.
- */
- public void testBugreport() throws Exception {
- String data = StreamUtil.getStringFromStream(
- mTestDevice.getBugreport().createInputStream());
- assertTrue(String.format("Expected at least %d characters; only saw %d", mMinBugreportBytes,
- data.length()), data.length() >= mMinBugreportBytes);
- // TODO: check the captured report more extensively, perhaps using loganalysis
- }
-
- /**
- * Simple normal case test for
- * {@link TestDevice#executeShellCommand(String)}.
- * <p/>
- * Do a 'shell ls' command, and verify /data and /system are listed in result.
- */
- public void testExecuteShellCommand() throws IOException, DeviceNotAvailableException {
- Log.i(LOG_TAG, "testExecuteShellCommand");
- assertSimpleShellCommand();
- }
-
- /**
- * Verify that a simple {@link TestDevice#executeShellCommand(String)} command is successful.
- */
- private void assertSimpleShellCommand() throws DeviceNotAvailableException {
- // Check for expected contents of device's root directory
- final String output = mTestDevice.executeShellCommand("ls /");
- assertTrue(output.contains("data"));
- assertTrue(output.contains("system"));
- }
-
-
- /**
- * Push and then pull a file from device, and verify contents are as expected.
- */
- public void testPushPull_normal() throws IOException, DeviceNotAvailableException {
- Log.i(LOG_TAG, "testPushPull");
- File tmpFile = null;
- File tmpDestFile = null;
- String deviceFilePath = null;
-
- try {
- tmpFile = createTempTestFile(null);
- String externalStorePath = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- assertNotNull(externalStorePath);
- deviceFilePath = String.format("%s/%s", externalStorePath, "tmp_testPushPull.txt");
- // ensure file does not already exist
- mTestDevice.executeShellCommand(String.format("rm %s", deviceFilePath));
- assertFalse(String.format("%s exists", deviceFilePath),
- mTestDevice.doesFileExist(deviceFilePath));
-
- assertTrue(mTestDevice.pushFile(tmpFile, deviceFilePath));
- assertTrue(mTestDevice.doesFileExist(deviceFilePath));
- tmpDestFile = FileUtil.createTempFile("tmp", "txt");
- assertTrue(mTestDevice.pullFile(deviceFilePath, tmpDestFile));
- assertTrue(compareFiles(tmpFile, tmpDestFile));
- } finally {
- if (tmpDestFile != null) {
- tmpDestFile.delete();
- }
- if (deviceFilePath != null) {
- mTestDevice.executeShellCommand(String.format("rm %s", deviceFilePath));
- }
- }
- }
-
- /**
- * Push and then pull a file from device, and verify contents are as expected.
- * <p />
- * This variant of the test uses "${EXTERNAL_STORAGE}" in the pathname.
- */
- public void testPushPull_extStorageVariable() throws IOException, DeviceNotAvailableException {
- Log.i(LOG_TAG, "testPushPull");
- File tmpFile = null;
- File tmpDestFile = null;
- File tmpDestFile2 = null;
- String deviceFilePath = null;
- final String filename = "tmp_testPushPull.txt";
-
- try {
- tmpFile = createTempTestFile(null);
- String externalStorePath = "${EXTERNAL_STORAGE}";
- assertNotNull(externalStorePath);
- deviceFilePath = String.format("%s/%s", externalStorePath, filename);
- // ensure file does not already exist
- mTestDevice.executeShellCommand(String.format("rm %s", deviceFilePath));
- assertFalse(String.format("%s exists", deviceFilePath),
- mTestDevice.doesFileExist(deviceFilePath));
-
- assertTrue(mTestDevice.pushFile(tmpFile, deviceFilePath));
- assertTrue(mTestDevice.doesFileExist(deviceFilePath));
- tmpDestFile = FileUtil.createTempFile("tmp", "txt");
- assertTrue(mTestDevice.pullFile(deviceFilePath, tmpDestFile));
- assertTrue(compareFiles(tmpFile, tmpDestFile));
-
- tmpDestFile2 = mTestDevice.pullFileFromExternal(filename);
- assertNotNull(tmpDestFile2);
- assertTrue(compareFiles(tmpFile, tmpDestFile2));
- } finally {
- if (tmpDestFile != null) {
- tmpDestFile.delete();
- }
- if (tmpDestFile2 != null) {
- tmpDestFile2.delete();
- }
- if (deviceFilePath != null) {
- mTestDevice.executeShellCommand(String.format("rm %s", deviceFilePath));
- }
- }
- }
-
- /**
- * Test pulling a file from device that does not exist.
- * <p/>
- * Expect {@link TestDevice#pullFile(String)} to return <code>false</code>
- */
- public void testPull_noexist() throws IOException, DeviceNotAvailableException {
- Log.i(LOG_TAG, "testPull_noexist");
-
- // make sure the root path is valid
- String externalStorePath = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- assertNotNull(externalStorePath);
- String deviceFilePath = String.format("%s/%s", externalStorePath, "thisfiledoesntexist");
- assertFalse(String.format("%s exists", deviceFilePath),
- mTestDevice.doesFileExist(deviceFilePath));
- assertNull(mTestDevice.pullFile(deviceFilePath));
- }
-
- private File createTempTestFile(File dir) throws IOException {
- File tmpFile = null;
- try {
- final String fileContents = "this is the test file contents";
- tmpFile = FileUtil.createTempFile("tmp", ".txt", dir);
- FileUtil.writeToFile(fileContents, tmpFile);
- return tmpFile;
- } catch (IOException e) {
- if (tmpFile != null) {
- tmpFile.delete();
- }
- throw e;
- }
- }
-
- /**
- * Utility method to do byte-wise content comparison of two files.
- */
- private boolean compareFiles(File file1, File file2) throws IOException {
- BufferedInputStream stream1 = null;
- BufferedInputStream stream2 = null;
-
- try {
- stream1 = new BufferedInputStream(new FileInputStream(file1));
- stream2 = new BufferedInputStream(new FileInputStream(file2));
- boolean eof = false;
- while (!eof) {
- int byte1 = stream1.read();
- int byte2 = stream2.read();
- if (byte1 != byte2) {
- return false;
- }
- eof = byte1 == -1;
- }
- return true;
- } finally {
- if (stream1 != null) {
- stream1.close();
- }
- if (stream2 != null) {
- stream2.close();
- }
- }
- }
-
- /**
- * Test syncing a single file using {@link TestDevice#syncFiles(File, String)}.
- */
- public void testSyncFiles_normal() throws Exception {
- doTestSyncFiles(mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE));
- }
-
- /**
- * Test syncing a single file using {@link TestDevice#syncFiles(File, String)}.
- * <p />
- * This variant of the test uses "${EXTERNAL_STORAGE}" in the pathname.
- */
- public void testSyncFiles_extStorageVariable() throws Exception {
- doTestSyncFiles("${EXTERNAL_STORAGE}");
- }
-
- /**
- * Test syncing a single file using {@link TestDevice#syncFiles(File, String)}.
- */
- public void doTestSyncFiles(String externalStorePath) throws Exception {
- String expectedDeviceFilePath = null;
-
- // create temp dir with one temp file
- File tmpDir = FileUtil.createTempDir("tmp");
- try {
- File tmpFile = createTempTestFile(tmpDir);
- // set last modified to 10 minutes ago
- tmpFile.setLastModified(System.currentTimeMillis() - 10*60*1000);
- assertNotNull(externalStorePath);
- expectedDeviceFilePath = String.format("%s/%s/%s", externalStorePath,
- tmpDir.getName(), tmpFile.getName());
-
- assertTrue(mTestDevice.syncFiles(tmpDir, externalStorePath));
- assertTrue(mTestDevice.doesFileExist(expectedDeviceFilePath));
-
- // get 'ls -l' attributes of file which includes timestamp
- String origTmpFileStamp = mTestDevice.executeShellCommand(String.format("ls -l %s",
- expectedDeviceFilePath));
- // now create another file and verify that is synced
- File tmpFile2 = createTempTestFile(tmpDir);
- tmpFile2.setLastModified(System.currentTimeMillis() - 10*60*1000);
- assertTrue(mTestDevice.syncFiles(tmpDir, externalStorePath));
- String expectedDeviceFilePath2 = String.format("%s/%s/%s", externalStorePath,
- tmpDir.getName(), tmpFile2.getName());
- assertTrue(mTestDevice.doesFileExist(expectedDeviceFilePath2));
-
- // verify 1st file timestamp did not change
- String unchangedTmpFileStamp = mTestDevice.executeShellCommand(String.format("ls -l %s",
- expectedDeviceFilePath));
- assertEquals(origTmpFileStamp, unchangedTmpFileStamp);
-
- // now modify 1st file and verify it does change remotely
- String testString = "blah";
- FileOutputStream stream = new FileOutputStream(tmpFile);
- stream.write(testString.getBytes());
- stream.close();
-
- // adjust 1st file's last-modified timestamp according to persist.sys.timezone
- String deviceTimezone = mTestDevice.getProperty("persist.sys.timezone");
- if (deviceTimezone != null) {
- TimeZone tz = TimeZone.getTimeZone(deviceTimezone);
- long timestamp = tmpFile.lastModified() + tz.getRawOffset();
- if (tz.observesDaylightTime()) {
- timestamp += tz.getDSTSavings();
- }
- tmpFile.setLastModified(timestamp);
- }
-
- assertTrue(mTestDevice.syncFiles(tmpDir, externalStorePath));
- String tmpFileContents = mTestDevice.executeShellCommand(String.format("cat %s",
- expectedDeviceFilePath));
- assertTrue(tmpFileContents.contains(testString));
- } finally {
- if (expectedDeviceFilePath != null && externalStorePath != null) {
- // note that expectedDeviceFilePath has externalStorePath prepended at definition
- mTestDevice.executeShellCommand(String.format("rm -r %s", expectedDeviceFilePath));
- }
- FileUtil.recursiveDelete(tmpDir);
- }
- }
-
- /**
- * Test pushing a directory
- */
- public void testPushDir() throws IOException, DeviceNotAvailableException {
- String expectedDeviceFilePath = null;
- String externalStorePath = null;
- File rootDir = FileUtil.createTempDir("tmp");
- // create temp dir with one temp file
- try {
- File tmpDir = FileUtil.createTempDir("tmp", rootDir);
- File tmpFile = createTempTestFile(tmpDir);
- externalStorePath = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- assertNotNull(externalStorePath);
- expectedDeviceFilePath = String.format("%s/%s/%s", externalStorePath,
- tmpDir.getName(), tmpFile.getName());
-
- assertTrue(mTestDevice.pushDir(rootDir, externalStorePath));
- assertTrue(mTestDevice.doesFileExist(expectedDeviceFilePath));
-
- } finally {
- if (expectedDeviceFilePath != null && externalStorePath != null) {
- mTestDevice.executeShellCommand(String.format("rm -r %s/%s", externalStorePath,
- expectedDeviceFilePath));
- }
- FileUtil.recursiveDelete(rootDir);
- }
- }
-
- /**
- * Basic test for {@link TestDevice#getScreenshot()}.
- * <p/>
- * Grab a screenshot and perform a cursory size check to ensure its valid.
- */
- public void testGetScreenshot() throws DeviceNotAvailableException, IOException {
- InputStreamSource source = getDevice().getScreenshot();
- assertNotNull(source);
- InputStream inputStream = source.createInputStream();
- try {
- BufferedImage screenshotImage = ImageIO.read(inputStream);
- CLog.i(LOG_TAG, "testGetScreenshot w=%d, h=%d",
- screenshotImage.getWidth(), screenshotImage.getHeight());
- assertTrue(screenshotImage.getWidth() > 0);
- assertTrue(screenshotImage.getHeight() > 0);
- } finally {
- StreamUtil.cancel(source);
- StreamUtil.close(inputStream);
- }
- }
-
- /**
- * Basic test for {@link TestDevice#getLogcat(long)}.
- * <p/>
- * Dumps a bunch of messages to logcat, calls getLogcat(), and verifies size of capture file is
- * equal to provided data.
- */
- public void testGetLogcat_size() throws DeviceNotAvailableException, IOException {
- CLog.i(LOG_TAG, "testGetLogcat_size");
- for (int i = 0; i < 100; i++) {
- getDevice().executeShellCommand(String.format("log testGetLogcat_size log dump %d", i));
- }
- boolean passed = false;
- int retry = 0;
- while (!passed) {
- // sleep a small amount of time to ensure last log message makes it into capture
- RunUtil.getDefault().sleep(10);
- InputStreamSource source = getDevice().getLogcat(100 * 1024);
- assertNotNull(source);
- File tmpTxtFile = FileUtil.createTempFile("logcat", ".txt");
- try {
- FileUtil.writeToFile(source.createInputStream(), tmpTxtFile);
- CLog.i("Created file at %s", tmpTxtFile.getAbsolutePath());
- // ensure last log message is present in log
- String s = FileUtil.readStringFromFile(tmpTxtFile);
- if (s.contains("testGetLogcat_size log dump 99")) {
- passed = true;
- }
- } finally {
- FileUtil.deleteFile(tmpTxtFile);
- source.cancel();
- }
- retry++;
- if ((retry > 100) && !passed) {
- fail("last log message is not in captured logcat");
- }
- }
- }
-}
diff --git a/hostsidetests/aadb/src/com/android/cts/aadb/TestDeviceStressTest.java b/hostsidetests/aadb/src/com/android/cts/aadb/TestDeviceStressTest.java
deleted file mode 100644
index 2c6fcef..0000000
--- a/hostsidetests/aadb/src/com/android/cts/aadb/TestDeviceStressTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.aadb;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.util.FileUtil;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Long running functional tests for {@link TestDevice} that verify an operation can be run
- * many times in sequence
- * <p/>
- * Requires a physical device to be connected.
- */
-public class TestDeviceStressTest extends DeviceTestCase {
-
- private int mIterations = 25;
-
- private static final String LOG_TAG = "TestDeviceStressTest";
- private static final int TEST_FILE_COUNT= 200;
- private ITestDevice mTestDevice;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mTestDevice = getDevice();
- }
-
- private File createTempTestFiles() throws IOException {
- File tmpDir = null;
- File tmpFile = null;
-
- tmpDir = FileUtil.createTempDir("testDir");
-
- final String fileContents = "this is the test file contents";
- for (int i = 0; i < TEST_FILE_COUNT; i++) {
- tmpFile = FileUtil.createTempFile(String.format("tmp_%d", i), ".txt", tmpDir);
- FileUtil.writeToFile(fileContents, tmpFile);
- }
- return tmpDir;
-
- }
-
- /**
- * Stress test to push a folder which contains 200 text file to device
- * internal storage.
- */
- public void testPushFolderWithManyFiles() throws IOException, DeviceNotAvailableException {
- File tmpDir = null;
- String deviceFilePath = null;
- String externalStorePath = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- assertNotNull(externalStorePath);
- deviceFilePath = String.format("%s/%s", externalStorePath, "testDir");
-
- // start the stress test
- try {
- // Create the test folder and make sure the test folder doesn't exist in
- // device before the test start.
- tmpDir = createTempTestFiles();
- for (int i = 0; i < mIterations; i++) {
- mTestDevice.executeShellCommand(String.format("rm -r %s", deviceFilePath));
- assertFalse(String.format("%s exists", deviceFilePath),
- mTestDevice.doesFileExist(deviceFilePath));
- assertTrue(mTestDevice.pushDir(tmpDir, deviceFilePath));
- assertTrue(mTestDevice.doesFileExist(deviceFilePath));
- }
- } finally {
- if (tmpDir != null) {
- FileUtil.recursiveDelete(tmpDir);
- }
- mTestDevice.executeShellCommand(String.format("rm -r %s", deviceFilePath));
- assertFalse(String.format("%s exists", deviceFilePath),
- mTestDevice.doesFileExist(deviceFilePath));
- }
- }
-}
diff --git a/hostsidetests/appsecurity/Android.mk b/hostsidetests/appsecurity/Android.mk
index 61f9a4d..55fe0d9 100644
--- a/hostsidetests/appsecurity/Android.mk
+++ b/hostsidetests/appsecurity/Android.mk
@@ -19,11 +19,16 @@
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE := CtsAppSecurityTests
+LOCAL_MODULE := CtsAppSecurityHostTestCases
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed_v2 compatibility-host-util tradefed-prebuilt
-LOCAL_CTS_TEST_PACKAGE := android.tests.appsecurity
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
+
+LOCAL_CTS_TEST_PACKAGE := android.appsecurity
+
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/appsecurity/AndroidTest.xml b/hostsidetests/appsecurity/AndroidTest.xml
new file mode 100644
index 0000000..d1989e6
--- /dev/null
+++ b/hostsidetests/appsecurity/AndroidTest.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<configuration description="Config for the CTS App Security host tests">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsAppSecurityHostTestCases.jar" />
+ <option name="runtime-hint" value="20m" />
+ </test>
+</configuration>
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
new file mode 100644
index 0000000..d8c2134
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -0,0 +1,351 @@
+/*
+ * 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.
+ */
+
+package android.appsecurity.cts;
+
+import static android.appsecurity.cts.SplitTests.ABI_TO_APK;
+import static android.appsecurity.cts.SplitTests.APK;
+import static android.appsecurity.cts.SplitTests.APK_mdpi;
+import static android.appsecurity.cts.SplitTests.APK_xxhdpi;
+import static android.appsecurity.cts.SplitTests.CLASS;
+import static android.appsecurity.cts.SplitTests.PKG;
+
+import android.appsecurity.cts.SplitTests.BaseInstallMultiple;
+import com.android.cts.migration.MigrationHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.util.Arrays;
+
+/**
+ * Set of tests that verify behavior of adopted storage media, if supported.
+ */
+public class AdoptableHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+ private IAbi mAbi;
+ private IBuildInfo mCtsBuild;
+
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ assertNotNull(mAbi);
+ assertNotNull(mCtsBuild);
+
+ getDevice().uninstallPackage(PKG);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ getDevice().uninstallPackage(PKG);
+ }
+
+ public void testApps() throws Exception {
+ if (!hasAdoptable()) return;
+ final String diskId = getAdoptionDisk();
+ try {
+ final String abi = mAbi.getName();
+ final String apk = ABI_TO_APK.get(abi);
+ assertNotNull("Failed to find APK for ABI " + abi, apk);
+
+ // Install simple app on internal
+ new InstallMultiple().useNaturalAbi().addApk(APK).addApk(apk).run();
+ runDeviceTests(PKG, CLASS, "testDataInternal");
+ runDeviceTests(PKG, CLASS, "testDataWrite");
+ runDeviceTests(PKG, CLASS, "testDataRead");
+ runDeviceTests(PKG, CLASS, "testNative");
+
+ // Adopt that disk!
+ assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
+ final LocalVolumeInfo vol = getAdoptionVolume();
+
+ // Move app and verify
+ assertSuccess(getDevice().executeShellCommand(
+ "pm move-package " + PKG + " " + vol.uuid));
+ runDeviceTests(PKG, CLASS, "testDataNotInternal");
+ runDeviceTests(PKG, CLASS, "testDataRead");
+ runDeviceTests(PKG, CLASS, "testNative");
+
+ // Unmount, remount and verify
+ getDevice().executeShellCommand("sm unmount " + vol.volId);
+ getDevice().executeShellCommand("sm mount " + vol.volId);
+ runDeviceTests(PKG, CLASS, "testDataNotInternal");
+ runDeviceTests(PKG, CLASS, "testDataRead");
+ runDeviceTests(PKG, CLASS, "testNative");
+
+ // Move app back and verify
+ assertSuccess(getDevice().executeShellCommand("pm move-package " + PKG + " internal"));
+ runDeviceTests(PKG, CLASS, "testDataInternal");
+ runDeviceTests(PKG, CLASS, "testDataRead");
+ runDeviceTests(PKG, CLASS, "testNative");
+
+ // Un-adopt volume and app should still be fine
+ getDevice().executeShellCommand("sm partition " + diskId + " public");
+ runDeviceTests(PKG, CLASS, "testDataInternal");
+ runDeviceTests(PKG, CLASS, "testDataRead");
+ runDeviceTests(PKG, CLASS, "testNative");
+
+ } finally {
+ cleanUp(diskId);
+ }
+ }
+
+ public void testPrimaryStorage() throws Exception {
+ if (!hasAdoptable()) return;
+ final String diskId = getAdoptionDisk();
+ try {
+ final String originalVol = getDevice()
+ .executeShellCommand("sm get-primary-storage-uuid").trim();
+
+ if ("null".equals(originalVol)) {
+ verifyPrimaryInternal(diskId);
+ } else if ("primary_physical".equals(originalVol)) {
+ verifyPrimaryPhysical(diskId);
+ }
+ } finally {
+ cleanUp(diskId);
+ }
+ }
+
+ private void verifyPrimaryInternal(String diskId) throws Exception {
+ // Write some data to shared storage
+ new InstallMultiple().addApk(APK).run();
+ runDeviceTests(PKG, CLASS, "testPrimaryOnSameVolume");
+ runDeviceTests(PKG, CLASS, "testPrimaryInternal");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataWrite");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+
+ // Adopt that disk!
+ assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
+ final LocalVolumeInfo vol = getAdoptionVolume();
+
+ // Move storage there and verify that data went along for ride
+ assertSuccess(getDevice().executeShellCommand("pm move-primary-storage " + vol.uuid));
+ runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+
+ // Unmount and verify
+ getDevice().executeShellCommand("sm unmount " + vol.volId);
+ runDeviceTests(PKG, CLASS, "testPrimaryUnmounted");
+ getDevice().executeShellCommand("sm mount " + vol.volId);
+ runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+
+ // Move app and verify backing storage volume is same
+ assertSuccess(getDevice().executeShellCommand("pm move-package " + PKG + " " + vol.uuid));
+ runDeviceTests(PKG, CLASS, "testPrimaryOnSameVolume");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+
+ // And move back to internal
+ assertSuccess(getDevice().executeShellCommand("pm move-primary-storage internal"));
+ runDeviceTests(PKG, CLASS, "testPrimaryInternal");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+
+ assertSuccess(getDevice().executeShellCommand("pm move-package " + PKG + " internal"));
+ runDeviceTests(PKG, CLASS, "testPrimaryOnSameVolume");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+ }
+
+ private void verifyPrimaryPhysical(String diskId) throws Exception {
+ // Write some data to shared storage
+ new InstallMultiple().addApk(APK).run();
+ runDeviceTests(PKG, CLASS, "testPrimaryPhysical");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataWrite");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+
+ // Adopt that disk!
+ assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
+ final LocalVolumeInfo vol = getAdoptionVolume();
+
+ // Move primary storage there, but since we just nuked primary physical
+ // the storage device will be empty
+ assertSuccess(getDevice().executeShellCommand("pm move-primary-storage " + vol.uuid));
+ runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataWrite");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+
+ // Unmount and verify
+ getDevice().executeShellCommand("sm unmount " + vol.volId);
+ runDeviceTests(PKG, CLASS, "testPrimaryUnmounted");
+ getDevice().executeShellCommand("sm mount " + vol.volId);
+ runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+
+ // And move to internal
+ assertSuccess(getDevice().executeShellCommand("pm move-primary-storage internal"));
+ runDeviceTests(PKG, CLASS, "testPrimaryOnSameVolume");
+ runDeviceTests(PKG, CLASS, "testPrimaryInternal");
+ runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
+ }
+
+ /**
+ * Verify that we can install both new and inherited packages directly on
+ * adopted volumes.
+ */
+ public void testPackageInstaller() throws Exception {
+ if (!hasAdoptable()) return;
+ final String diskId = getAdoptionDisk();
+ try {
+ assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
+ final LocalVolumeInfo vol = getAdoptionVolume();
+
+ // Install directly onto adopted volume
+ new InstallMultiple().locationAuto().forceUuid(vol.uuid)
+ .addApk(APK).addApk(APK_mdpi).run();
+ runDeviceTests(PKG, CLASS, "testDataNotInternal");
+ runDeviceTests(PKG, CLASS, "testDensityBest1");
+
+ // Now splice in an additional split which offers better resources
+ new InstallMultiple().locationAuto().inheritFrom(PKG)
+ .addApk(APK_xxhdpi).run();
+ runDeviceTests(PKG, CLASS, "testDataNotInternal");
+ runDeviceTests(PKG, CLASS, "testDensityBest2");
+
+ } finally {
+ cleanUp(diskId);
+ }
+ }
+
+ /**
+ * Verify behavior when changes occur while adopted device is ejected and
+ * returned at a later time.
+ */
+ public void testEjected() throws Exception {
+ if (!hasAdoptable()) return;
+ final String diskId = getAdoptionDisk();
+ try {
+ assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
+ final LocalVolumeInfo vol = getAdoptionVolume();
+
+ // Install directly onto adopted volume, and write data there
+ new InstallMultiple().locationAuto().forceUuid(vol.uuid).addApk(APK).run();
+ runDeviceTests(PKG, CLASS, "testDataNotInternal");
+ runDeviceTests(PKG, CLASS, "testDataWrite");
+ runDeviceTests(PKG, CLASS, "testDataRead");
+
+ // Now unmount and uninstall; leaving stale package on adopted volume
+ getDevice().executeShellCommand("sm unmount " + vol.volId);
+ getDevice().uninstallPackage(PKG);
+
+ // Install second copy on internal, but don't write anything
+ new InstallMultiple().locationInternalOnly().addApk(APK).run();
+ runDeviceTests(PKG, CLASS, "testDataInternal");
+
+ // Kick through a remount cycle, which should purge the adopted app
+ getDevice().executeShellCommand("sm mount " + vol.volId);
+ runDeviceTests(PKG, CLASS, "testDataInternal");
+ try {
+ runDeviceTests(PKG, CLASS, "testDataRead");
+ fail("Unexpected data from adopted volume picked up");
+ } catch (AssertionError expected) {
+ }
+ getDevice().executeShellCommand("sm unmount " + vol.volId);
+
+ // Uninstall the internal copy and remount; we should have no record of app
+ getDevice().uninstallPackage(PKG);
+ getDevice().executeShellCommand("sm mount " + vol.volId);
+
+ assertEmpty(getDevice().executeShellCommand("pm list packages " + PKG));
+ } finally {
+ cleanUp(diskId);
+ }
+ }
+
+ private boolean hasAdoptable() throws Exception {
+ return Boolean.parseBoolean(getDevice().executeShellCommand("sm has-adoptable").trim());
+ }
+
+ private String getAdoptionDisk() throws Exception {
+ final String disks = getDevice().executeShellCommand("sm list-disks adoptable");
+ if (disks == null || disks.length() == 0) {
+ throw new AssertionError("Devices that claim to support adoptable storage must have "
+ + "adoptable media inserted during CTS to verify correct behavior");
+ }
+ return disks.split("\n")[0].trim();
+ }
+
+ private LocalVolumeInfo getAdoptionVolume() throws Exception {
+ String[] lines = null;
+ int attempt = 0;
+ while (attempt++ < 15) {
+ lines = getDevice().executeShellCommand("sm list-volumes private").split("\n");
+ for (String line : lines) {
+ final LocalVolumeInfo info = new LocalVolumeInfo(line.trim());
+ if (!"private".equals(info.volId) && "mounted".equals(info.state)) {
+ return info;
+ }
+ }
+ Thread.sleep(1000);
+ }
+ throw new AssertionError("Expected private volume; found " + Arrays.toString(lines));
+ }
+
+ private void cleanUp(String diskId) throws Exception {
+ getDevice().executeShellCommand("sm partition " + diskId + " public");
+ getDevice().executeShellCommand("sm forget all");
+ }
+
+ private void runDeviceTests(String packageName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+ }
+
+ private static void assertSuccess(String str) {
+ if (str == null || !str.startsWith("Success")) {
+ throw new AssertionError("Expected success string but found " + str);
+ }
+ }
+
+ private static void assertEmpty(String str) {
+ if (str != null && str.trim().length() > 0) {
+ throw new AssertionError("Expected empty string but found " + str);
+ }
+ }
+
+ private static class LocalVolumeInfo {
+ public String volId;
+ public String state;
+ public String uuid;
+
+ public LocalVolumeInfo(String line) {
+ final String[] split = line.split(" ");
+ volId = split[0];
+ state = split[1];
+ uuid = split[2];
+ }
+ }
+
+ private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
+ public InstallMultiple() {
+ super(getDevice(), mCtsBuild, mAbi);
+ }
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
new file mode 100644
index 0000000..00acdf5
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
@@ -0,0 +1,300 @@
+/*
+ * 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.appsecurity.cts;
+
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.cts.migration.MigrationHelper;
+import com.android.ddmlib.Log;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Set of tests that verify various security checks involving multiple apps are
+ * properly enforced.
+ */
+public class AppSecurityTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+
+ // testSharedUidDifferentCerts constants
+ private static final String SHARED_UI_APK = "CtsSharedUidInstall.apk";
+ private static final String SHARED_UI_PKG = "com.android.cts.shareuidinstall";
+ private static final String SHARED_UI_DIFF_CERT_APK = "CtsSharedUidInstallDiffCert.apk";
+ private static final String SHARED_UI_DIFF_CERT_PKG =
+ "com.android.cts.shareuidinstalldiffcert";
+
+ // testAppUpgradeDifferentCerts constants
+ private static final String SIMPLE_APP_APK = "CtsSimpleAppInstall.apk";
+ private static final String SIMPLE_APP_PKG = "com.android.cts.simpleappinstall";
+ private static final String SIMPLE_APP_DIFF_CERT_APK = "CtsSimpleAppInstallDiffCert.apk";
+
+ // testAppFailAccessPrivateData constants
+ private static final String APP_WITH_DATA_APK = "CtsAppWithData.apk";
+ private static final String APP_WITH_DATA_PKG = "com.android.cts.appwithdata";
+ private static final String APP_WITH_DATA_CLASS =
+ "com.android.cts.appwithdata.CreatePrivateDataTest";
+ private static final String APP_WITH_DATA_CREATE_METHOD =
+ "testCreatePrivateData";
+ private static final String APP_WITH_DATA_CHECK_NOEXIST_METHOD =
+ "testEnsurePrivateDataNotExist";
+ private static final String APP_ACCESS_DATA_APK = "CtsAppAccessData.apk";
+ private static final String APP_ACCESS_DATA_PKG = "com.android.cts.appaccessdata";
+
+ // testInstrumentationDiffCert constants
+ private static final String TARGET_INSTRUMENT_APK = "CtsTargetInstrumentationApp.apk";
+ private static final String TARGET_INSTRUMENT_PKG = "com.android.cts.targetinstrumentationapp";
+ private static final String INSTRUMENT_DIFF_CERT_APK = "CtsInstrumentationAppDiffCert.apk";
+ private static final String INSTRUMENT_DIFF_CERT_PKG =
+ "com.android.cts.instrumentationdiffcertapp";
+
+ // testPermissionDiffCert constants
+ private static final String DECLARE_PERMISSION_APK = "CtsPermissionDeclareApp.apk";
+ private static final String DECLARE_PERMISSION_PKG = "com.android.cts.permissiondeclareapp";
+ private static final String DECLARE_PERMISSION_COMPAT_APK = "CtsPermissionDeclareAppCompat.apk";
+ private static final String DECLARE_PERMISSION_COMPAT_PKG = "com.android.cts.permissiondeclareappcompat";
+
+ private static final String PERMISSION_DIFF_CERT_APK = "CtsUsePermissionDiffCert.apk";
+ private static final String PERMISSION_DIFF_CERT_PKG =
+ "com.android.cts.usespermissiondiffcertapp";
+
+ private static final String LOG_TAG = "AppSecurityTests";
+
+ private IAbi mAbi;
+ private IBuildInfo mCtsBuild;
+
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ private File getTestAppFile(String fileName) throws FileNotFoundException {
+ return MigrationHelper.getTestFile(mCtsBuild, fileName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // ensure build has been set before test is run
+ assertNotNull(mCtsBuild);
+ }
+
+ /**
+ * Test that an app that declares the same shared uid as an existing app, cannot be installed
+ * if it is signed with a different certificate.
+ */
+ public void testSharedUidDifferentCerts() throws Exception {
+ Log.i(LOG_TAG, "installing apks with shared uid, but different certs");
+ try {
+ // cleanup test apps that might be installed from previous partial test run
+ getDevice().uninstallPackage(SHARED_UI_PKG);
+ getDevice().uninstallPackage(SHARED_UI_DIFF_CERT_PKG);
+
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ String installResult = getDevice().installPackage(getTestAppFile(SHARED_UI_APK),
+ false, options);
+ assertNull(String.format("failed to install shared uid app, Reason: %s", installResult),
+ installResult);
+ installResult = getDevice().installPackage(getTestAppFile(SHARED_UI_DIFF_CERT_APK),
+ false, options);
+ assertNotNull("shared uid app with different cert than existing app installed " +
+ "successfully", installResult);
+ assertEquals("INSTALL_FAILED_SHARED_USER_INCOMPATIBLE",
+ installResult.substring(0, installResult.indexOf(':')));
+ } finally {
+ getDevice().uninstallPackage(SHARED_UI_PKG);
+ getDevice().uninstallPackage(SHARED_UI_DIFF_CERT_PKG);
+ }
+ }
+
+ /**
+ * Test that an app update cannot be installed over an existing app if it has a different
+ * certificate.
+ */
+ public void testAppUpgradeDifferentCerts() throws Exception {
+ Log.i(LOG_TAG, "installing app upgrade with different certs");
+ try {
+ // cleanup test app that might be installed from previous partial test run
+ getDevice().uninstallPackage(SIMPLE_APP_PKG);
+
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ String installResult = getDevice().installPackage(getTestAppFile(SIMPLE_APP_APK),
+ false, options);
+ assertNull(String.format("failed to install simple app. Reason: %s", installResult),
+ installResult);
+ installResult = getDevice().installPackage(getTestAppFile(SIMPLE_APP_DIFF_CERT_APK),
+ true /* reinstall */, options);
+ assertNotNull("app upgrade with different cert than existing app installed " +
+ "successfully", installResult);
+ assertEquals("INSTALL_FAILED_UPDATE_INCOMPATIBLE",
+ installResult.substring(0, installResult.indexOf(':')));
+ } finally {
+ getDevice().uninstallPackage(SIMPLE_APP_PKG);
+ }
+ }
+
+ /**
+ * Test that an app cannot access another app's private data.
+ */
+ public void testAppFailAccessPrivateData() throws Exception {
+ Log.i(LOG_TAG, "installing app that attempts to access another app's private data");
+ try {
+ // cleanup test app that might be installed from previous partial test run
+ getDevice().uninstallPackage(APP_WITH_DATA_PKG);
+ getDevice().uninstallPackage(APP_ACCESS_DATA_PKG);
+
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ String installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
+ false, options);
+ assertNull(String.format("failed to install app with data. Reason: %s", installResult),
+ installResult);
+ // run appwithdata's tests to create private data
+ runDeviceTests(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD);
+
+ installResult = getDevice().installPackage(getTestAppFile(APP_ACCESS_DATA_APK),
+ false, options);
+ assertNull(String.format("failed to install app access data. Reason: %s",
+ installResult), installResult);
+ // run appaccessdata's tests which attempt to access appwithdata's private data
+ runDeviceTests(APP_ACCESS_DATA_PKG);
+ } finally {
+ getDevice().uninstallPackage(APP_WITH_DATA_PKG);
+ getDevice().uninstallPackage(APP_ACCESS_DATA_PKG);
+ }
+ }
+
+ /**
+ * Test that uninstall of an app removes its private data.
+ */
+ public void testUninstallRemovesData() throws Exception {
+ Log.i(LOG_TAG, "Uninstalling app, verifying data is removed.");
+ try {
+ // cleanup test app that might be installed from previous partial test run
+ getDevice().uninstallPackage(APP_WITH_DATA_PKG);
+
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ String installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
+ false, options);
+ assertNull(String.format("failed to install app with data. Reason: %s", installResult),
+ installResult);
+ // run appwithdata's tests to create private data
+ runDeviceTests(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD);
+
+ getDevice().uninstallPackage(APP_WITH_DATA_PKG);
+
+ installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
+ false, options);
+ assertNull(String.format("failed to install app with data second time. Reason: %s",
+ installResult), installResult);
+ // run appwithdata's 'check if file exists' test
+ runDeviceTests(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS,
+ APP_WITH_DATA_CHECK_NOEXIST_METHOD);
+ } finally {
+ getDevice().uninstallPackage(APP_WITH_DATA_PKG);
+ }
+ }
+
+ /**
+ * Test that an app cannot instrument another app that is signed with different certificate.
+ */
+ public void testInstrumentationDiffCert() throws Exception {
+ Log.i(LOG_TAG, "installing app that attempts to instrument another app");
+ try {
+ // cleanup test app that might be installed from previous partial test run
+ getDevice().uninstallPackage(TARGET_INSTRUMENT_PKG);
+ getDevice().uninstallPackage(INSTRUMENT_DIFF_CERT_PKG);
+
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ String installResult = getDevice().installPackage(
+ getTestAppFile(TARGET_INSTRUMENT_APK), false, options);
+ assertNull(String.format("failed to install target instrumentation app. Reason: %s",
+ installResult), installResult);
+
+ // the app will install, but will get error at runtime when starting instrumentation
+ installResult = getDevice().installPackage(getTestAppFile(INSTRUMENT_DIFF_CERT_APK),
+ false, options);
+ assertNull(String.format(
+ "failed to install instrumentation app with diff cert. Reason: %s",
+ installResult), installResult);
+ // run INSTRUMENT_DIFF_CERT_PKG tests
+ // this test will attempt to call startInstrumentation directly and verify
+ // SecurityException is thrown
+ runDeviceTests(INSTRUMENT_DIFF_CERT_PKG);
+ } finally {
+ getDevice().uninstallPackage(TARGET_INSTRUMENT_PKG);
+ getDevice().uninstallPackage(INSTRUMENT_DIFF_CERT_PKG);
+ }
+ }
+
+ /**
+ * Test that an app cannot use a signature-enforced permission if it is signed with a different
+ * certificate than the app that declared the permission.
+ */
+ public void testPermissionDiffCert() throws Exception {
+ Log.i(LOG_TAG, "installing app that attempts to use permission of another app");
+ try {
+ // cleanup test app that might be installed from previous partial test run
+ getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
+ getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
+ getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);
+
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ String installResult = getDevice().installPackage(
+ getTestAppFile(DECLARE_PERMISSION_APK), false, options);
+ assertNull(String.format("failed to install declare permission app. Reason: %s",
+ installResult), installResult);
+
+ installResult = getDevice().installPackage(
+ getTestAppFile(DECLARE_PERMISSION_COMPAT_APK), false, options);
+ assertNull(String.format("failed to install declare permission compat app. Reason: %s",
+ installResult), installResult);
+
+ // the app will install, but will get error at runtime
+ installResult = getDevice().installPackage(getTestAppFile(PERMISSION_DIFF_CERT_APK),
+ false, options);
+ assertNull(String.format("failed to install permission app with diff cert. Reason: %s",
+ installResult), installResult);
+ // run PERMISSION_DIFF_CERT_PKG tests which try to access the permission
+ runDeviceTests(PERMISSION_DIFF_CERT_PKG);
+ } finally {
+ getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
+ getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
+ getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);
+ }
+ }
+
+ private void runDeviceTests(String packageName) throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName);
+ }
+
+ private void runDeviceTests(String packageName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
new file mode 100644
index 0000000..300aa3a
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 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.appsecurity.cts;
+
+import com.android.cts.migration.MigrationHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+/**
+ * Set of tests that verify behavior of
+ * {@link android.provider.DocumentsContract} and related intents.
+ */
+public class DocumentsTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+ private static final String PROVIDER_PKG = "com.android.cts.documentprovider";
+ private static final String PROVIDER_APK = "CtsDocumentProvider.apk";
+
+ private static final String CLIENT_PKG = "com.android.cts.documentclient";
+ private static final String CLIENT_APK = "CtsDocumentClient.apk";
+
+ private IAbi mAbi;
+ private IBuildInfo mCtsBuild;
+
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ assertNotNull(mAbi);
+ assertNotNull(mCtsBuild);
+
+ getDevice().uninstallPackage(PROVIDER_PKG);
+ getDevice().uninstallPackage(CLIENT_PKG);
+
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, PROVIDER_APK), false));
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, CLIENT_APK), false));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ getDevice().uninstallPackage(PROVIDER_PKG);
+ getDevice().uninstallPackage(CLIENT_PKG);
+ }
+
+ public void testOpenSimple() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenSimple");
+ }
+
+ public void testCreateNew() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateNew");
+ }
+
+ public void testCreateExisting() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateExisting");
+ }
+
+ public void testTree() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTree");
+ }
+
+ public void testGetContent() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testGetContent");
+ }
+
+ public void runDeviceTests(String packageName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
new file mode 100644
index 0000000..c49340e
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -0,0 +1,256 @@
+/*
+ * 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.
+ */
+
+package android.appsecurity.cts;
+
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.cts.migration.MigrationHelper;
+import com.android.ddmlib.Log;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Set of tests that verify behavior of external storage devices.
+ */
+public class ExternalStorageHostTest extends DeviceTestCase
+ implements IAbiReceiver, IBuildReceiver {
+ private static final String TAG = "ExternalStorageHostTest";
+
+ private static final String COMMON_CLASS =
+ "com.android.cts.externalstorageapp.CommonExternalStorageTest";
+
+ private static final String NONE_APK = "CtsExternalStorageApp.apk";
+ private static final String NONE_PKG = "com.android.cts.externalstorageapp";
+ private static final String NONE_CLASS = ".ExternalStorageTest";
+ private static final String READ_APK = "CtsReadExternalStorageApp.apk";
+ private static final String READ_PKG = "com.android.cts.readexternalstorageapp";
+ private static final String READ_CLASS = ".ReadExternalStorageTest";
+ private static final String WRITE_APK = "CtsWriteExternalStorageApp.apk";
+ private static final String WRITE_PKG = "com.android.cts.writeexternalstorageapp";
+ private static final String WRITE_CLASS = ".WriteExternalStorageTest";
+ private static final String MULTIUSER_APK = "CtsMultiUserStorageApp.apk";
+ private static final String MULTIUSER_PKG = "com.android.cts.multiuserstorageapp";
+ private static final String MULTIUSER_CLASS = ".MultiUserStorageTest";
+
+ private IAbi mAbi;
+ private IBuildInfo mCtsBuild;
+
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ private File getTestAppFile(String fileName) throws FileNotFoundException {
+ return MigrationHelper.getTestFile(mCtsBuild, fileName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ assertNotNull(mAbi);
+ assertNotNull(mCtsBuild);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Verify that app with no external storage permissions works correctly.
+ */
+ public void testExternalStorageNone() throws Exception {
+ final int[] users = createUsersForTest();
+ try {
+ wipePrimaryExternalStorage();
+
+ getDevice().uninstallPackage(NONE_PKG);
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
+
+ for (int user : users) {
+ runDeviceTests(NONE_PKG, COMMON_CLASS, user);
+ runDeviceTests(NONE_PKG, NONE_CLASS, user);
+ }
+ } finally {
+ getDevice().uninstallPackage(NONE_PKG);
+ removeUsersForTest(users);
+ }
+ }
+
+ /**
+ * Verify that app with
+ * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} works
+ * correctly.
+ */
+ public void testExternalStorageRead() throws Exception {
+ final int[] users = createUsersForTest();
+ try {
+ wipePrimaryExternalStorage();
+
+ getDevice().uninstallPackage(READ_PKG);
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
+
+ for (int user : users) {
+ runDeviceTests(READ_PKG, COMMON_CLASS, user);
+ runDeviceTests(READ_PKG, READ_CLASS, user);
+ }
+ } finally {
+ getDevice().uninstallPackage(READ_PKG);
+ removeUsersForTest(users);
+ }
+ }
+
+ /**
+ * Verify that app with
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} works
+ * correctly.
+ */
+ public void testExternalStorageWrite() throws Exception {
+ final int[] users = createUsersForTest();
+ try {
+ wipePrimaryExternalStorage();
+
+ getDevice().uninstallPackage(WRITE_PKG);
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
+
+ for (int user : users) {
+ runDeviceTests(WRITE_PKG, COMMON_CLASS, user);
+ runDeviceTests(WRITE_PKG, WRITE_CLASS, user);
+ }
+ } finally {
+ getDevice().uninstallPackage(WRITE_PKG);
+ removeUsersForTest(users);
+ }
+ }
+
+ /**
+ * Verify that app with WRITE_EXTERNAL can leave gifts in external storage
+ * directories belonging to other apps, and those apps can read.
+ */
+ public void testExternalStorageGifts() throws Exception {
+ final int[] users = createUsersForTest();
+ try {
+ wipePrimaryExternalStorage();
+
+ getDevice().uninstallPackage(NONE_PKG);
+ getDevice().uninstallPackage(READ_PKG);
+ getDevice().uninstallPackage(WRITE_PKG);
+ final String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+
+ // We purposefully delay the installation of the reading apps to
+ // verify that the daemon correctly invalidates any caches.
+ assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
+ for (int user : users) {
+ runDeviceTests(WRITE_PKG, ".WriteGiftTest", user);
+ }
+
+ assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
+ assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
+ for (int user : users) {
+ runDeviceTests(READ_PKG, ".ReadGiftTest", user);
+ runDeviceTests(NONE_PKG, ".GiftTest", user);
+ }
+ } finally {
+ getDevice().uninstallPackage(NONE_PKG);
+ getDevice().uninstallPackage(READ_PKG);
+ getDevice().uninstallPackage(WRITE_PKG);
+ removeUsersForTest(users);
+ }
+ }
+
+ /**
+ * Test multi-user emulated storage environment, ensuring that each user has
+ * isolated storage.
+ */
+ public void testMultiUserStorageIsolated() throws Exception {
+ final int[] users = createUsersForTest();
+ try {
+ if (users.length == 1) {
+ Log.d(TAG, "Single user device; skipping isolated storage tests");
+ return;
+ }
+
+ final int owner = users[0];
+ final int secondary = users[1];
+
+ // Install our test app
+ getDevice().uninstallPackage(MULTIUSER_PKG);
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ final String installResult = getDevice()
+ .installPackage(getTestAppFile(MULTIUSER_APK), false, options);
+ assertNull("Failed to install: " + installResult, installResult);
+
+ // Clear data from previous tests
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testCleanIsolatedStorage", owner);
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testCleanIsolatedStorage", secondary);
+
+ // Have both users try writing into isolated storage
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testWriteIsolatedStorage", owner);
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testWriteIsolatedStorage", secondary);
+
+ // Verify they both have isolated view of storage
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", owner);
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", secondary);
+
+ // Verify they can't poke at each other
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", owner);
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", secondary);
+ } finally {
+ getDevice().uninstallPackage(MULTIUSER_PKG);
+ removeUsersForTest(users);
+ }
+ }
+
+ private void wipePrimaryExternalStorage() throws DeviceNotAvailableException {
+ getDevice().executeShellCommand("rm -rf /sdcard/Android");
+ getDevice().executeShellCommand("rm -rf /sdcard/DCIM");
+ getDevice().executeShellCommand("rm -rf /sdcard/MUST_*");
+ }
+
+ private int[] createUsersForTest() throws DeviceNotAvailableException {
+ return Utils.createUsersForTest(getDevice());
+ }
+
+ private void removeUsersForTest(int[] users) throws DeviceNotAvailableException {
+ Utils.removeUsersForTest(getDevice(), users);
+ }
+
+ private void runDeviceTests(String packageName, String testClassName, int userId)
+ throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, userId);
+ }
+
+ private void runDeviceTests(String packageName, String testClassName, String testMethodName,
+ int userId) throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName, userId);
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
new file mode 100644
index 0000000..53a54dd
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
@@ -0,0 +1,515 @@
+/*
+ * Copyright (C) 2014 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.appsecurity.cts;
+
+import com.android.cts.migration.MigrationHelper;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Map;
+
+/**
+ * Tests for Keyset based features.
+ */
+public class KeySetHostTest extends DeviceTestCase implements IBuildReceiver {
+
+ private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+
+ /* package with device-side tests */
+ private static final String KEYSET_TEST_PKG = "com.android.cts.keysets.testapp";
+ private static final String KEYSET_TEST_APP_APK = "CtsKeySetTestApp.apk";
+
+ /* plain test apks with different signing and upgrade keysets */
+ private static final String KEYSET_PKG = "com.android.cts.keysets";
+ private static final String A_SIGNED_NO_UPGRADE =
+ "CtsKeySetSigningAUpgradeNone.apk";
+ private static final String A_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningAUpgradeA.apk";
+ private static final String A_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningAUpgradeB.apk";
+ private static final String A_SIGNED_A_OR_B_UPGRADE =
+ "CtsKeySetSigningAUpgradeAOrB.apk";
+ private static final String B_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningBUpgradeA.apk";
+ private static final String B_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningBUpgradeB.apk";
+ private static final String A_AND_B_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningAAndBUpgradeA.apk";
+ private static final String A_AND_B_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningAAndBUpgradeB.apk";
+ private static final String A_AND_C_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningAAndCUpgradeB.apk";
+ private static final String SHARED_USR_A_SIGNED_B_UPGRADE =
+ "CtsKeySetSharedUserSigningAUpgradeB.apk";
+ private static final String SHARED_USR_B_SIGNED_B_UPGRADE =
+ "CtsKeySetSharedUserSigningBUpgradeB.apk";
+ private static final String A_SIGNED_BAD_B_B_UPGRADE =
+ "CtsKeySetSigningABadUpgradeB.apk";
+ private static final String C_SIGNED_BAD_A_AB_UPGRADE =
+ "CtsKeySetSigningCBadAUpgradeAB.apk";
+ private static final String A_SIGNED_NO_B_B_UPGRADE =
+ "CtsKeySetSigningANoDefUpgradeB.apk";
+ private static final String A_SIGNED_EC_A_UPGRADE =
+ "CtsKeySetSigningAUpgradeEcA.apk";
+ private static final String EC_A_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningEcAUpgradeA.apk";
+
+ /* package which defines the KEYSET_PERM_NAME signature permission */
+ private static final String KEYSET_PERM_DEF_PKG =
+ "com.android.cts.keysets_permdef";
+
+ /* The apks defining and using the permission have both A and B as upgrade keys */
+ private static final String PERM_DEF_A_SIGNED =
+ "CtsKeySetPermDefSigningA.apk";
+ private static final String PERM_DEF_B_SIGNED =
+ "CtsKeySetPermDefSigningB.apk";
+ private static final String PERM_USE_A_SIGNED =
+ "CtsKeySetPermUseSigningA.apk";
+ private static final String PERM_USE_B_SIGNED =
+ "CtsKeySetPermUseSigningB.apk";
+
+ private static final String PERM_TEST_CLASS =
+ "com.android.cts.keysets.KeySetPermissionsTest";
+
+ private static final String LOG_TAG = "AppsecurityHostTests";
+
+ private File getTestAppFile(String fileName) throws FileNotFoundException {
+ return MigrationHelper.getTestFile(mCtsBuild, fileName);
+ }
+
+ /**
+ * Helper method that checks that all tests in given result passed, and attempts to generate
+ * a meaningful error message if they failed.
+ *
+ * @param result
+ */
+ private void assertDeviceTestsPass(TestRunResult result) {
+ assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
+ result.getName(), result.getRunFailureMessage()), result.isRunFailure());
+
+ if (result.hasFailedTests()) {
+
+ /* build a meaningful error message */
+ StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+ for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ result.getTestResults().entrySet()) {
+ if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ fail(errorBuilder.toString());
+ }
+ }
+
+ /**
+ * Helper method that checks that all tests in given result passed, and attempts to generate
+ * a meaningful error message if they failed.
+ *
+ * @param result
+ */
+ private void assertDeviceTestsFail(String msg, TestRunResult result) {
+ assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
+ result.getName(), result.getRunFailureMessage()), result.isRunFailure());
+
+ if (!result.hasFailedTests()) {
+ fail(msg);
+ }
+ }
+
+ /**
+ * Helper method that will run the specified packages tests on device.
+ *
+ * @param pkgName Android application package for tests
+ * @return <code>true</code> if all tests passed.
+ * @throws DeviceNotAvailableException if connection to device was lost.
+ */
+ private boolean runDeviceTests(String pkgName) throws DeviceNotAvailableException {
+ return runDeviceTests(pkgName, null, null);
+ }
+
+ /**
+ * Helper method that will run the specified packages tests on device.
+ *
+ * @param pkgName Android application package for tests
+ * @return <code>true</code> if all tests passed.
+ * @throws DeviceNotAvailableException if connection to device was lost.
+ */
+ private boolean runDeviceTests(String pkgName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ TestRunResult runResult = doRunTests(pkgName, testClassName, testMethodName);
+ return !runResult.hasFailedTests();
+ }
+
+ /**
+ * Helper method to run tests and return the listener that collected the results.
+ *
+ * @param pkgName Android application package for tests
+ * @return the {@link TestRunResult}
+ * @throws DeviceNotAvailableException if connection to device was lost.
+ */
+ private TestRunResult doRunTests(String pkgName, String testClassName,
+ String testMethodName) throws DeviceNotAvailableException {
+
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName,
+ RUNNER, getDevice().getIDevice());
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ }
+ CollectingTestListener listener = new CollectingTestListener();
+ getDevice().runInstrumentationTests(testRunner, listener);
+ return listener.getCurrentRunResults();
+ }
+
+ /**
+ * Helper method which installs a package and an upgrade to it.
+ *
+ * @param pkgName - package name of apk.
+ * @param firstApk - first apk to install
+ * @param secondApk - apk to which we attempt to upgrade
+ * @param expectedResult - null if successful, otherwise expected error.
+ */
+ private String testPackageUpgrade(String pkgName, String firstApk,
+ String secondApk) throws Exception {
+ String installResult;
+ try {
+
+ /* cleanup test apps that might be installed from previous partial test run */
+ mDevice.uninstallPackage(pkgName);
+
+ installResult = mDevice.installPackage(getTestAppFile(firstApk),
+ false);
+ /* we should always succeed on first-install */
+ assertNull(String.format("failed to install %s, Reason: %s", pkgName,
+ installResult), installResult);
+
+ /* attempt to install upgrade */
+ installResult = mDevice.installPackage(getTestAppFile(secondApk),
+ true);
+ } finally {
+ mDevice.uninstallPackage(pkgName);
+ }
+ return installResult;
+ }
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ private IBuildInfo mCtsBuild;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+ assertNotNull(mCtsBuild);
+ }
+
+ /**
+ * Tests for KeySet based key rotation
+ */
+
+ /*
+ * Check if an apk which does not specify an upgrade-key-set may be upgraded
+ * to an apk which does.
+ */
+ public void testNoKSToUpgradeKS() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_NO_UPGRADE, A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from no specified upgrade-key-set"
+ + "to version with specified upgrade-key-set, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk which does specify an upgrade-key-set may be upgraded
+ * to an apk which does not.
+ */
+ public void testUpgradeKSToNoKS() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_NO_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from specified upgrade-key-set"
+ + "to version without specified upgrade-key-set, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by a key other than the upgrade keyset can update
+ * an app
+ */
+ public void testUpgradeKSWithWrongKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, B_SIGNED_A_UPGRADE);
+ assertNotNull("upgrade to improperly signed app succeeded!", installResult);
+ }
+
+ /*
+ * Check if an apk signed by its signing key, which is not an upgrade key,
+ * can upgrade an app.
+ */
+ public void testUpgradeKSWithWrongSigningKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, A_SIGNED_B_UPGRADE);
+ assertNotNull("upgrade to improperly signed app succeeded!",
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by its upgrade key, which is not its signing key,
+ * can upgrade an app.
+ */
+ public void testUpgradeKSWithUpgradeKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, B_SIGNED_B_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by its upgrade key, which is its signing key, can
+ * upgrade an app.
+ */
+ public void testUpgradeKSWithSigningUpgradeKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by multiple keys, one of which is its upgrade key,
+ * can upgrade an app.
+ */
+ public void testMultipleUpgradeKSWithUpgradeKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE,
+ A_AND_B_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by multiple keys, its signing keys,
+ * but none of which is an upgrade key, can upgrade an app.
+ */
+ public void testMultipleUpgradeKSWithSigningKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_AND_C_SIGNED_B_UPGRADE,
+ A_AND_C_SIGNED_B_UPGRADE);
+ assertNotNull("upgrade to improperly signed app succeeded!", installResult);
+ }
+
+ /*
+ * Check if an apk which defines multiple (two) upgrade keysets is
+ * upgrade-able by either.
+ */
+ public void testUpgradeKSWithMultipleUpgradeKeySetsFirstKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
+ A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to one signed by first upgrade keyset key-a, Reason: %s", installResult),
+ installResult);
+ installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
+ B_SIGNED_B_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to one signed by second upgrade keyset key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /**
+ * Helper method which installs a package defining a permission and a package
+ * using the permission, and then rotates the signing keys for one of them.
+ * A device-side test is then used to ascertain whether or not the permission
+ * was appropriately gained or lost.
+ *
+ * @param permDefApk - apk to install which defines the sig-permissoin
+ * @param permUseApk - apk to install which declares it uses the permission
+ * @param upgradeApk - apk to install which upgrades one of the first two
+ * @param hasPermBeforeUpgrade - whether we expect the consuming app to have
+ * the permission before the upgrade takes place.
+ * @param hasPermAfterUpgrade - whether we expect the consuming app to have
+ * the permission after the upgrade takes place.
+ */
+ private void testKeyRotationPerm(String permDefApk, String permUseApk,
+ String upgradeApk, boolean hasPermBeforeUpgrade,
+ boolean hasPermAfterUpgrade) throws Exception {
+ try {
+
+ /* cleanup test apps that might be installed from previous partial test run */
+ mDevice.uninstallPackage(KEYSET_PKG);
+ mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
+ mDevice.uninstallPackage(KEYSET_TEST_PKG);
+
+ /* install PERM_DEF, KEYSET_APP and KEYSET_TEST_APP */
+ String installResult = mDevice.installPackage(
+ getTestAppFile(permDefApk), false);
+ assertNull(String.format("failed to install keyset perm-def app, Reason: %s",
+ installResult), installResult);
+ installResult = getDevice().installPackage(
+ getTestAppFile(permUseApk), false);
+ assertNull(String.format("failed to install keyset test app. Reason: %s",
+ installResult), installResult);
+ installResult = getDevice().installPackage(
+ getTestAppFile(KEYSET_TEST_APP_APK), false);
+ assertNull(String.format("failed to install keyset test app. Reason: %s",
+ installResult), installResult);
+
+ /* verify package does have perm */
+ TestRunResult result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
+ "testHasPerm");
+ if (hasPermBeforeUpgrade) {
+ assertDeviceTestsPass(result);
+ } else {
+ assertDeviceTestsFail(" has permission permission it should not have.", result);
+ }
+
+ /* rotate keys */
+ installResult = mDevice.installPackage(getTestAppFile(upgradeApk),
+ true);
+ result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
+ "testHasPerm");
+ if (hasPermAfterUpgrade) {
+ assertDeviceTestsPass(result);
+ } else {
+ assertDeviceTestsFail(KEYSET_PKG + " has permission it should not have.", result);
+ }
+ } finally {
+ mDevice.uninstallPackage(KEYSET_PKG);
+ mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
+ mDevice.uninstallPackage(KEYSET_TEST_PKG);
+ }
+ }
+
+ /*
+ * Check if an apk gains signature-level permission after changing to a new
+ * signature, for which a permission should be granted.
+ */
+ public void testUpgradeSigPermGained() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_USE_A_SIGNED,
+ false, true);
+ }
+
+ /*
+ * Check if an apk loses signature-level permission after changing to a new
+ * signature, from one for which a permission was previously granted.
+ */
+ public void testUpgradeSigPermLost() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_USE_B_SIGNED,
+ true, false);
+ }
+
+ /*
+ * Check if an apk gains signature-level permission after the app defining
+ * it rotates to the same signature.
+ */
+ public void testUpgradeDefinerSigPermGained() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_DEF_B_SIGNED,
+ false, true);
+ }
+
+ /*
+ * Check if an apk loses signature-level permission after the app defining
+ * it rotates to a different signature.
+ */
+ public void testUpgradeDefinerSigPermLost() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_DEF_B_SIGNED,
+ true, false);
+ }
+
+ /*
+ * Check if an apk which indicates it uses a sharedUserId and defines an
+ * upgrade keyset is allowed to rotate to that keyset.
+ */
+ public void testUpgradeSharedUser() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, SHARED_USR_A_SIGNED_B_UPGRADE,
+ SHARED_USR_B_SIGNED_B_UPGRADE);
+ assertNotNull("upgrade allowed for app with shareduserid!", installResult);
+ }
+
+ /*
+ * Check that an apk with an upgrade key represented by a bad public key
+ * fails to install.
+ */
+ public void testBadUpgradeBadPubKey() throws Exception {
+ mDevice.uninstallPackage(KEYSET_PKG);
+ String installResult = mDevice.installPackage(getTestAppFile(A_SIGNED_BAD_B_B_UPGRADE),
+ false);
+ assertNotNull("Installation of apk with upgrade key referring to a bad public key succeeded!",
+ installResult);
+ }
+
+ /*
+ * Check that an apk with an upgrade keyset that includes a bad public key fails to install.
+ */
+ public void testBadUpgradeMissingPubKey() throws Exception {
+ mDevice.uninstallPackage(KEYSET_PKG);
+ String installResult = mDevice.installPackage(getTestAppFile(C_SIGNED_BAD_A_AB_UPGRADE),
+ false);
+ assertNotNull("Installation of apk with upgrade key referring to a bad public key succeeded!",
+ installResult);
+ }
+
+ /*
+ * Check that an apk with an upgrade key that has no corresponding public key fails to install.
+ */
+ public void testBadUpgradeNoPubKey() throws Exception {
+ mDevice.uninstallPackage(KEYSET_PKG);
+ String installResult = mDevice.installPackage(getTestAppFile(A_SIGNED_NO_B_B_UPGRADE),
+ false);
+ assertNotNull("Installation of apk with upgrade key referring to a bad public key succeeded!",
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by RSA pub key can upgrade to apk signed by EC key.
+ */
+ public void testUpgradeKSRsaToEC() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_EC_A_UPGRADE,
+ EC_A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by RSA key"
+ + "to version signed by EC upgrade-key-set, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by EC pub key can upgrade to apk signed by RSA key.
+ */
+ public void testUpgradeKSECToRSA() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, EC_A_SIGNED_A_UPGRADE,
+ A_SIGNED_EC_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by EC key"
+ + "to version signed by RSA upgrade-key-set, Reason: %s", installResult),
+ installResult);
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
new file mode 100644
index 0000000..6c5e4a5
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+package android.appsecurity.cts;
+
+import com.android.cts.migration.MigrationHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+/**
+ * Set of tests that verify behavior of runtime permissions, including both
+ * dynamic granting and behavior of legacy apps.
+ */
+public class PermissionsHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+ private static final String PKG = "com.android.cts.usepermission";
+
+ private static final String APK = "CtsUsePermissionApp.apk";
+ private static final String APK_COMPAT = "CtsUsePermissionAppCompat.apk";
+
+ private IAbi mAbi;
+ private IBuildInfo mCtsBuild;
+
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ assertNotNull(mAbi);
+ assertNotNull(mCtsBuild);
+
+ getDevice().uninstallPackage(PKG);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ getDevice().uninstallPackage(PKG);
+ }
+
+ public void testFail() throws Exception {
+ // Sanity check that remote failure is host failure
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+ try {
+ runDeviceTests(PKG, ".UsePermissionTest", "testFail");
+ fail("Expected remote failure");
+ } catch (AssertionError expected) {
+ }
+ }
+
+ public void testKill() throws Exception {
+ // Sanity check that remote kill is host failure
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+ try {
+ runDeviceTests(PKG, ".UsePermissionTest", "testKill");
+ fail("Expected remote failure");
+ } catch (AssertionError expected) {
+ }
+ }
+
+ public void testDefault() throws Exception {
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+ runDeviceTests(PKG, ".UsePermissionTest", "testDefault");
+ }
+
+ public void testGranted() throws Exception {
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+ grantPermission(PKG, "android.permission.READ_EXTERNAL_STORAGE");
+ grantPermission(PKG, "android.permission.WRITE_EXTERNAL_STORAGE");
+ runDeviceTests(PKG, ".UsePermissionTest", "testGranted");
+ }
+
+ public void testInteractiveGrant() throws Exception {
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+ runDeviceTests(PKG, ".UsePermissionTest", "testInteractiveGrant");
+ }
+
+ public void testRuntimeGroupGrantSpecificity() throws Exception {
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+ runDeviceTests(PKG, ".UsePermissionTest", "testRuntimeGroupGrantSpecificity");
+ }
+
+ public void testRuntimeGroupGrantExpansion() throws Exception {
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+ runDeviceTests(PKG, ".UsePermissionTest", "testRuntimeGroupGrantExpansion");
+ }
+
+ public void testCompatDefault() throws Exception {
+ assertNull(getDevice().installPackage(MigrationHelper.getTestFile(mCtsBuild, APK_COMPAT),
+ false, false));
+ runDeviceTests(PKG, ".UsePermissionCompatTest", "testCompatDefault");
+ }
+
+ public void testCompatRevoked() throws Exception {
+ assertNull(getDevice().installPackage(MigrationHelper.getTestFile(mCtsBuild, APK_COMPAT),
+ false, false));
+ setAppOps(PKG, "android:read_external_storage", "deny");
+ setAppOps(PKG, "android:write_external_storage", "deny");
+ runDeviceTests(PKG, ".UsePermissionCompatTest", "testCompatRevoked");
+ }
+
+ private void runDeviceTests(String packageName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+ }
+
+ private void grantPermission(String pkg, String permission) throws Exception {
+ assertEmpty(getDevice().executeShellCommand("pm grant " + pkg + " " + permission));
+ }
+
+ private void revokePermission(String pkg, String permission) throws Exception {
+ assertEmpty(getDevice().executeShellCommand("pm revoke " + pkg + " " + permission));
+ }
+
+ private void setAppOps(String pkg, String op, String mode) throws Exception {
+ assertEmpty(getDevice().executeShellCommand("appops set " + pkg + " " + op + " " + mode));
+ }
+
+ private static void assertEmpty(String str) {
+ if (str == null || str.length() == 0) {
+ return;
+ } else {
+ fail("Expected empty string but found " + str);
+ }
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
new file mode 100644
index 0000000..a2ef1f3
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2014 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.appsecurity.cts;
+
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.cts.migration.MigrationHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Tests that verify installing of various split APKs from host side.
+ */
+public class SplitTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+ static final String PKG = "com.android.cts.splitapp";
+ static final String CLASS = ".SplitAppTest";
+
+ static final String APK = "CtsSplitApp.apk";
+
+ static final String APK_mdpi = "CtsSplitApp_mdpi-v4.apk";
+ static final String APK_hdpi = "CtsSplitApp_hdpi-v4.apk";
+ static final String APK_xhdpi = "CtsSplitApp_xhdpi-v4.apk";
+ static final String APK_xxhdpi = "CtsSplitApp_xxhdpi-v4.apk";
+
+ private static final String APK_v7 = "CtsSplitApp_v7.apk";
+ private static final String APK_fr = "CtsSplitApp_fr.apk";
+ private static final String APK_de = "CtsSplitApp_de.apk";
+
+ private static final String APK_x86 = "CtsSplitApp_x86.apk";
+ private static final String APK_x86_64 = "CtsSplitApp_x86_64.apk";
+ private static final String APK_armeabi_v7a = "CtsSplitApp_armeabi-v7a.apk";
+ private static final String APK_armeabi = "CtsSplitApp_armeabi.apk";
+ private static final String APK_arm64_v8a = "CtsSplitApp_arm64-v8a.apk";
+ private static final String APK_mips64 = "CtsSplitApp_mips64.apk";
+ private static final String APK_mips = "CtsSplitApp_mips.apk";
+
+ private static final String APK_DIFF_REVISION = "CtsSplitAppDiffRevision.apk";
+ private static final String APK_DIFF_REVISION_v7 = "CtsSplitAppDiffRevision_v7.apk";
+
+ private static final String APK_DIFF_VERSION = "CtsSplitAppDiffVersion.apk";
+ private static final String APK_DIFF_VERSION_v7 = "CtsSplitAppDiffVersion_v7.apk";
+
+ private static final String APK_DIFF_CERT = "CtsSplitAppDiffCert.apk";
+ private static final String APK_DIFF_CERT_v7 = "CtsSplitAppDiffCert_v7.apk";
+
+ private static final String APK_FEATURE = "CtsSplitAppFeature.apk";
+ private static final String APK_FEATURE_v7 = "CtsSplitAppFeature_v7.apk";
+
+ static final HashMap<String, String> ABI_TO_APK = new HashMap<>();
+
+ static {
+ ABI_TO_APK.put("x86", APK_x86);
+ ABI_TO_APK.put("x86_64", APK_x86_64);
+ ABI_TO_APK.put("armeabi-v7a", APK_armeabi_v7a);
+ ABI_TO_APK.put("armeabi", APK_armeabi);
+ ABI_TO_APK.put("arm64-v8a", APK_arm64_v8a);
+ ABI_TO_APK.put("mips64", APK_mips64);
+ ABI_TO_APK.put("mips", APK_mips);
+ }
+
+ private IAbi mAbi;
+ private IBuildInfo mCtsBuild;
+
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ assertNotNull(mAbi);
+ assertNotNull(mCtsBuild);
+
+ getDevice().uninstallPackage(PKG);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ getDevice().uninstallPackage(PKG);
+ }
+
+ public void testSingleBase() throws Exception {
+ new InstallMultiple().addApk(APK).run();
+ runDeviceTests(PKG, CLASS, "testSingleBase");
+ }
+
+ public void testDensitySingle() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
+ runDeviceTests(PKG, CLASS, "testDensitySingle");
+ }
+
+ public void testDensityAll() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_mdpi).addApk(APK_hdpi).addApk(APK_xhdpi)
+ .addApk(APK_xxhdpi).run();
+ runDeviceTests(PKG, CLASS, "testDensityAll");
+ }
+
+ /**
+ * Install first with low-resolution resources, then add a split that offers
+ * higher-resolution resources.
+ */
+ public void testDensityBest() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
+ runDeviceTests(PKG, CLASS, "testDensityBest1");
+
+ // Now splice in an additional split which offers better resources
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_xxhdpi).run();
+ runDeviceTests(PKG, CLASS, "testDensityBest2");
+ }
+
+ /**
+ * Verify that an API-based split can change enabled/disabled state of
+ * manifest elements.
+ */
+ public void testApi() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_v7).run();
+ runDeviceTests(PKG, CLASS, "testApi");
+ }
+
+ public void testLocale() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_de).addApk(APK_fr).run();
+ runDeviceTests(PKG, CLASS, "testLocale");
+ }
+
+ /**
+ * Install test app with <em>single</em> split that exactly matches the
+ * currently active ABI. This also explicitly forces ABI when installing.
+ */
+ public void testNativeSingle() throws Exception {
+ final String abi = mAbi.getName();
+ final String apk = ABI_TO_APK.get(abi);
+ assertNotNull("Failed to find APK for ABI " + abi, apk);
+
+ new InstallMultiple().addApk(APK).addApk(apk).run();
+ runDeviceTests(PKG, CLASS, "testNative");
+ }
+
+ /**
+ * Install test app with <em>single</em> split that exactly matches the
+ * currently active ABI. This variant <em>does not</em> force the ABI when
+ * installing, instead exercising the system's ability to choose the ABI
+ * through inspection of the installed app.
+ */
+ public void testNativeSingleNatural() throws Exception {
+ final String abi = mAbi.getName();
+ final String apk = ABI_TO_APK.get(abi);
+ assertNotNull("Failed to find APK for ABI " + abi, apk);
+
+ new InstallMultiple().useNaturalAbi().addApk(APK).addApk(apk).run();
+ runDeviceTests(PKG, CLASS, "testNative");
+ }
+
+ /**
+ * Install test app with <em>all</em> possible ABI splits. This also
+ * explicitly forces ABI when installing.
+ */
+ public void testNativeAll() throws Exception {
+ final InstallMultiple inst = new InstallMultiple().addApk(APK);
+ for (String apk : ABI_TO_APK.values()) {
+ inst.addApk(apk);
+ }
+ inst.run();
+ runDeviceTests(PKG, CLASS, "testNative");
+ }
+
+ /**
+ * Install test app with <em>all</em> possible ABI splits. This variant
+ * <em>does not</em> force the ABI when installing, instead exercising the
+ * system's ability to choose the ABI through inspection of the installed
+ * app.
+ */
+ public void testNativeAllNatural() throws Exception {
+ final InstallMultiple inst = new InstallMultiple().useNaturalAbi().addApk(APK);
+ for (String apk : ABI_TO_APK.values()) {
+ inst.addApk(apk);
+ }
+ inst.run();
+ runDeviceTests(PKG, CLASS, "testNative");
+ }
+
+ public void testDuplicateBase() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK).runExpectingFailure();
+ }
+
+ public void testDuplicateSplit() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_v7).addApk(APK_v7).runExpectingFailure();
+ }
+
+ public void testDiffCert() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
+ }
+
+ public void testDiffCertInherit() throws Exception {
+ new InstallMultiple().addApk(APK).run();
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
+ }
+
+ public void testDiffVersion() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
+ }
+
+ public void testDiffVersionInherit() throws Exception {
+ new InstallMultiple().addApk(APK).run();
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
+ }
+
+ public void testDiffRevision() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_DIFF_REVISION_v7).run();
+ runDeviceTests(PKG, CLASS, "testRevision0_12");
+ }
+
+ public void testDiffRevisionInheritBase() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_v7).run();
+ runDeviceTests(PKG, CLASS, "testRevision0_0");
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION_v7).run();
+ runDeviceTests(PKG, CLASS, "testRevision0_12");
+ }
+
+ public void testDiffRevisionInheritSplit() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_v7).run();
+ runDeviceTests(PKG, CLASS, "testRevision0_0");
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION).run();
+ runDeviceTests(PKG, CLASS, "testRevision12_0");
+ }
+
+ public void testDiffRevisionDowngrade() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_DIFF_REVISION_v7).run();
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_v7).runExpectingFailure();
+ }
+
+ public void testFeatureBase() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_FEATURE).run();
+ runDeviceTests(PKG, CLASS, "testFeatureBase");
+ }
+
+ public void testFeatureApi() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_FEATURE).addApk(APK_FEATURE_v7).run();
+ runDeviceTests(PKG, CLASS, "testFeatureApi");
+ }
+
+ public void testInheritUpdatedBase() throws Exception {
+ // TODO: flesh out this test
+ }
+
+ public void testInheritUpdatedSplit() throws Exception {
+ // TODO: flesh out this test
+ }
+
+ /**
+ * Verify that installing a new version of app wipes code cache.
+ */
+ public void testClearCodeCache() throws Exception {
+ new InstallMultiple().addApk(APK).run();
+ runDeviceTests(PKG, CLASS, "testCodeCacheWrite");
+ new InstallMultiple().addArg("-r").addApk(APK_DIFF_VERSION).run();
+ runDeviceTests(PKG, CLASS, "testCodeCacheRead");
+ }
+
+ private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
+ public InstallMultiple() {
+ super(getDevice(), mCtsBuild, mAbi);
+ }
+ }
+
+ public static class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
+ private final ITestDevice mDevice;
+ private final IBuildInfo mBuild;
+ private final IAbi mAbi;
+
+ private final List<String> mArgs = new ArrayList<>();
+ private final List<File> mApks = new ArrayList<>();
+ private boolean mUseNaturalAbi;
+
+ public BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo, IAbi abi) {
+ mDevice = device;
+ mBuild = buildInfo;
+ mAbi = abi;
+ addArg("-g");
+ }
+
+ T addArg(String arg) {
+ mArgs.add(arg);
+ return (T) this;
+ }
+
+ T addApk(String apk) throws FileNotFoundException {
+ mApks.add(MigrationHelper.getTestFile(mBuild, apk));
+ return (T) this;
+ }
+
+ T inheritFrom(String packageName) {
+ addArg("-r");
+ addArg("-p " + packageName);
+ return (T) this;
+ }
+
+ T useNaturalAbi() {
+ mUseNaturalAbi = true;
+ return (T) this;
+ }
+
+ T locationAuto() {
+ addArg("--install-location 0");
+ return (T) this;
+ }
+
+ T locationInternalOnly() {
+ addArg("--install-location 1");
+ return (T) this;
+ }
+
+ T locationPreferExternal() {
+ addArg("--install-location 2");
+ return (T) this;
+ }
+
+ T forceUuid(String uuid) {
+ addArg("--force-uuid " + uuid);
+ return (T) this;
+ }
+
+ void run() throws DeviceNotAvailableException {
+ run(true);
+ }
+
+ void runExpectingFailure() throws DeviceNotAvailableException {
+ run(false);
+ }
+
+ private void run(boolean expectingSuccess) throws DeviceNotAvailableException {
+ final ITestDevice device = mDevice;
+
+ // Create an install session
+ final StringBuilder cmd = new StringBuilder();
+ cmd.append("pm install-create");
+ for (String arg : mArgs) {
+ cmd.append(' ').append(arg);
+ }
+ if (!mUseNaturalAbi) {
+ cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
+ }
+
+ String result = device.executeShellCommand(cmd.toString());
+ assertTrue(result, result.startsWith("Success"));
+
+ final int start = result.lastIndexOf("[");
+ final int end = result.lastIndexOf("]");
+ int sessionId = -1;
+ try {
+ if (start != -1 && end != -1 && start < end) {
+ sessionId = Integer.parseInt(result.substring(start + 1, end));
+ }
+ } catch (NumberFormatException e) {
+ }
+ if (sessionId == -1) {
+ throw new IllegalStateException("Failed to create install session: " + result);
+ }
+
+ // Push our files into session. Ideally we'd use stdin streaming,
+ // but ddmlib doesn't support it yet.
+ for (int i = 0; i < mApks.size(); i++) {
+ final File apk = mApks.get(i);
+ final String remotePath = "/data/local/tmp/" + i + "_" + apk.getName();
+ if (!device.pushFile(apk, remotePath)) {
+ throw new IllegalStateException("Failed to push " + apk);
+ }
+
+ cmd.setLength(0);
+ cmd.append("pm install-write");
+ cmd.append(' ').append(sessionId);
+ cmd.append(' ').append(i + "_" + apk.getName());
+ cmd.append(' ').append(remotePath);
+
+ result = device.executeShellCommand(cmd.toString());
+ assertTrue(result, result.startsWith("Success"));
+ }
+
+ // Everything staged; let's pull trigger
+ cmd.setLength(0);
+ cmd.append("pm install-commit");
+ cmd.append(' ').append(sessionId);
+
+ result = device.executeShellCommand(cmd.toString());
+ if (expectingSuccess) {
+ assertTrue(result, result.startsWith("Success"));
+ } else {
+ assertFalse(result, result.startsWith("Success"));
+ }
+ }
+ }
+
+ public void runDeviceTests(String packageName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
new file mode 100644
index 0000000..7048074
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 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.appsecurity.cts;
+
+import com.android.ddmlib.Log;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+
+import java.util.Map;
+
+public class Utils {
+ private static final String TAG = "AppSecurity";
+
+ public static final int USER_OWNER = 0;
+
+ public static void runDeviceTests(ITestDevice device, String packageName)
+ throws DeviceNotAvailableException {
+ runDeviceTests(device, packageName, null, null, USER_OWNER);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, int userId)
+ throws DeviceNotAvailableException {
+ runDeviceTests(device, packageName, null, null, userId);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName)
+ throws DeviceNotAvailableException {
+ runDeviceTests(device, packageName, testClassName, null, USER_OWNER);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+ int userId) throws DeviceNotAvailableException {
+ runDeviceTests(device, packageName, testClassName, null, userId);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+ String testMethodName) throws DeviceNotAvailableException {
+ runDeviceTests(device, packageName, testClassName, testMethodName, USER_OWNER);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+ String testMethodName, int userId) throws DeviceNotAvailableException {
+ if (testClassName != null && testClassName.startsWith(".")) {
+ testClassName = packageName + testClassName;
+ }
+
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName,
+ "android.support.test.runner.AndroidJUnitRunner", device.getIDevice());
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ } else if (testClassName != null) {
+ testRunner.setClassName(testClassName);
+ }
+
+ if (userId != USER_OWNER) {
+ // TODO: move this to RemoteAndroidTestRunner once it supports users
+ testRunner.addInstrumentationArg("hack_key", "hack_value --user " + userId);
+ }
+
+ final CollectingTestListener listener = new CollectingTestListener();
+ device.runInstrumentationTests(testRunner, listener);
+
+ final TestRunResult result = listener.getCurrentRunResults();
+ if (result.isRunFailure()) {
+ throw new AssertionError("Failed to successfully run device tests for "
+ + result.getName() + ": " + result.getRunFailureMessage());
+ }
+
+ if (result.hasFailedTests()) {
+ // build a meaningful error message
+ StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+ for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ result.getTestResults().entrySet()) {
+ if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ throw new AssertionError(errorBuilder.toString());
+ }
+ }
+
+ private static boolean isMultiUserSupportedOnDevice(ITestDevice device)
+ throws DeviceNotAvailableException {
+ // TODO: move this to ITestDevice once it supports users
+ final String output = device.executeShellCommand("pm get-max-users");
+ try {
+ return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim()) > 1;
+ } catch (NumberFormatException e) {
+ throw new AssertionError("Failed to parse result: " + output);
+ }
+ }
+
+ /**
+ * Return set of users that test should be run for, creating a secondary
+ * user if the device supports it. Always call
+ * {@link #removeUsersForTest(ITestDevice, int[])} when finished.
+ */
+ public static int[] createUsersForTest(ITestDevice device) throws DeviceNotAvailableException {
+ if (isMultiUserSupportedOnDevice(device)) {
+ return new int[] { USER_OWNER, createUserOnDevice(device) };
+ } else {
+ Log.d(TAG, "Single user device; skipping isolated storage tests");
+ return new int[] { USER_OWNER };
+ }
+ }
+
+ public static void removeUsersForTest(ITestDevice device, int[] users)
+ throws DeviceNotAvailableException {
+ for (int user : users) {
+ if (user != USER_OWNER) {
+ removeUserOnDevice(device, user);
+ }
+ }
+ }
+
+ private static int createUserOnDevice(ITestDevice device) throws DeviceNotAvailableException {
+ // TODO: move this to ITestDevice once it supports users
+ final String name = "CTS_" + System.currentTimeMillis();
+ final String output = device.executeShellCommand("pm create-user " + name);
+ if (output.startsWith("Success")) {
+ try {
+ final int userId = Integer.parseInt(
+ output.substring(output.lastIndexOf(" ")).trim());
+ device.executeShellCommand("am start-user " + userId);
+ return userId;
+ } catch (NumberFormatException e) {
+ throw new AssertionError("Failed to parse result: " + output);
+ }
+ } else {
+ throw new AssertionError("Failed to create user: " + output);
+ }
+ }
+
+ private static void removeUserOnDevice(ITestDevice device, int userId)
+ throws DeviceNotAvailableException {
+ // TODO: move this to ITestDevice once it supports users
+ final String output = device.executeShellCommand("pm remove-user " + userId);
+ if (output.startsWith("Error")) {
+ throw new AssertionError("Failed to remove user: " + output);
+ }
+ }
+
+}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AdoptableHostTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AdoptableHostTest.java
deleted file mode 100644
index 2ae2e10..0000000
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AdoptableHostTest.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.appsecurity;
-
-import static com.android.cts.appsecurity.SplitTests.ABI_TO_APK;
-import static com.android.cts.appsecurity.SplitTests.APK;
-import static com.android.cts.appsecurity.SplitTests.APK_mdpi;
-import static com.android.cts.appsecurity.SplitTests.APK_xxhdpi;
-import static com.android.cts.appsecurity.SplitTests.CLASS;
-import static com.android.cts.appsecurity.SplitTests.PKG;
-
-import com.android.cts.appsecurity.SplitTests.BaseInstallMultiple;
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.util.Arrays;
-
-/**
- * Set of tests that verify behavior of adopted storage media, if supported.
- */
-public class AdoptableHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
- private IAbi mAbi;
- private CtsBuildHelper mCtsBuild;
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- assertNotNull(mAbi);
- assertNotNull(mCtsBuild);
-
- getDevice().uninstallPackage(PKG);
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- getDevice().uninstallPackage(PKG);
- }
-
- public void testApps() throws Exception {
- if (!hasAdoptable()) return;
- final String diskId = getAdoptionDisk();
- try {
- final String abi = mAbi.getName();
- final String apk = ABI_TO_APK.get(abi);
- assertNotNull("Failed to find APK for ABI " + abi, apk);
-
- // Install simple app on internal
- new InstallMultiple().useNaturalAbi().addApk(APK).addApk(apk).run();
- runDeviceTests(PKG, CLASS, "testDataInternal");
- runDeviceTests(PKG, CLASS, "testDataWrite");
- runDeviceTests(PKG, CLASS, "testDataRead");
- runDeviceTests(PKG, CLASS, "testNative");
-
- // Adopt that disk!
- assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
- final LocalVolumeInfo vol = getAdoptionVolume();
-
- // Move app and verify
- assertSuccess(getDevice().executeShellCommand("pm move-package " + PKG + " " + vol.uuid));
- runDeviceTests(PKG, CLASS, "testDataNotInternal");
- runDeviceTests(PKG, CLASS, "testDataRead");
- runDeviceTests(PKG, CLASS, "testNative");
-
- // Unmount, remount and verify
- getDevice().executeShellCommand("sm unmount " + vol.volId);
- getDevice().executeShellCommand("sm mount " + vol.volId);
- runDeviceTests(PKG, CLASS, "testDataNotInternal");
- runDeviceTests(PKG, CLASS, "testDataRead");
- runDeviceTests(PKG, CLASS, "testNative");
-
- // Move app back and verify
- assertSuccess(getDevice().executeShellCommand("pm move-package " + PKG + " internal"));
- runDeviceTests(PKG, CLASS, "testDataInternal");
- runDeviceTests(PKG, CLASS, "testDataRead");
- runDeviceTests(PKG, CLASS, "testNative");
-
- // Un-adopt volume and app should still be fine
- getDevice().executeShellCommand("sm partition " + diskId + " public");
- runDeviceTests(PKG, CLASS, "testDataInternal");
- runDeviceTests(PKG, CLASS, "testDataRead");
- runDeviceTests(PKG, CLASS, "testNative");
-
- } finally {
- cleanUp(diskId);
- }
- }
-
- public void testPrimaryStorage() throws Exception {
- if (!hasAdoptable()) return;
- final String diskId = getAdoptionDisk();
- try {
- final String originalVol = getDevice()
- .executeShellCommand("sm get-primary-storage-uuid").trim();
-
- if ("null".equals(originalVol)) {
- verifyPrimaryInternal(diskId);
- } else if ("primary_physical".equals(originalVol)) {
- verifyPrimaryPhysical(diskId);
- }
- } finally {
- cleanUp(diskId);
- }
- }
-
- private void verifyPrimaryInternal(String diskId) throws Exception {
- // Write some data to shared storage
- new InstallMultiple().addApk(APK).run();
- runDeviceTests(PKG, CLASS, "testPrimaryOnSameVolume");
- runDeviceTests(PKG, CLASS, "testPrimaryInternal");
- runDeviceTests(PKG, CLASS, "testPrimaryDataWrite");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
-
- // Adopt that disk!
- assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
- final LocalVolumeInfo vol = getAdoptionVolume();
-
- // Move storage there and verify that data went along for ride
- assertSuccess(getDevice().executeShellCommand("pm move-primary-storage " + vol.uuid));
- runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
-
- // Unmount and verify
- getDevice().executeShellCommand("sm unmount " + vol.volId);
- runDeviceTests(PKG, CLASS, "testPrimaryUnmounted");
- getDevice().executeShellCommand("sm mount " + vol.volId);
- runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
-
- // Move app and verify backing storage volume is same
- assertSuccess(getDevice().executeShellCommand("pm move-package " + PKG + " " + vol.uuid));
- runDeviceTests(PKG, CLASS, "testPrimaryOnSameVolume");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
-
- // And move back to internal
- assertSuccess(getDevice().executeShellCommand("pm move-primary-storage internal"));
- runDeviceTests(PKG, CLASS, "testPrimaryInternal");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
-
- assertSuccess(getDevice().executeShellCommand("pm move-package " + PKG + " internal"));
- runDeviceTests(PKG, CLASS, "testPrimaryOnSameVolume");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
- }
-
- private void verifyPrimaryPhysical(String diskId) throws Exception {
- // Write some data to shared storage
- new InstallMultiple().addApk(APK).run();
- runDeviceTests(PKG, CLASS, "testPrimaryPhysical");
- runDeviceTests(PKG, CLASS, "testPrimaryDataWrite");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
-
- // Adopt that disk!
- assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
- final LocalVolumeInfo vol = getAdoptionVolume();
-
- // Move primary storage there, but since we just nuked primary physical
- // the storage device will be empty
- assertSuccess(getDevice().executeShellCommand("pm move-primary-storage " + vol.uuid));
- runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
- runDeviceTests(PKG, CLASS, "testPrimaryDataWrite");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
-
- // Unmount and verify
- getDevice().executeShellCommand("sm unmount " + vol.volId);
- runDeviceTests(PKG, CLASS, "testPrimaryUnmounted");
- getDevice().executeShellCommand("sm mount " + vol.volId);
- runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
-
- // And move to internal
- assertSuccess(getDevice().executeShellCommand("pm move-primary-storage internal"));
- runDeviceTests(PKG, CLASS, "testPrimaryOnSameVolume");
- runDeviceTests(PKG, CLASS, "testPrimaryInternal");
- runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
- }
-
- /**
- * Verify that we can install both new and inherited packages directly on
- * adopted volumes.
- */
- public void testPackageInstaller() throws Exception {
- if (!hasAdoptable()) return;
- final String diskId = getAdoptionDisk();
- try {
- assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
- final LocalVolumeInfo vol = getAdoptionVolume();
-
- // Install directly onto adopted volume
- new InstallMultiple().locationAuto().forceUuid(vol.uuid)
- .addApk(APK).addApk(APK_mdpi).run();
- runDeviceTests(PKG, CLASS, "testDataNotInternal");
- runDeviceTests(PKG, CLASS, "testDensityBest1");
-
- // Now splice in an additional split which offers better resources
- new InstallMultiple().locationAuto().inheritFrom(PKG)
- .addApk(APK_xxhdpi).run();
- runDeviceTests(PKG, CLASS, "testDataNotInternal");
- runDeviceTests(PKG, CLASS, "testDensityBest2");
-
- } finally {
- cleanUp(diskId);
- }
- }
-
- /**
- * Verify behavior when changes occur while adopted device is ejected and
- * returned at a later time.
- */
- public void testEjected() throws Exception {
- if (!hasAdoptable()) return;
- final String diskId = getAdoptionDisk();
- try {
- assertEmpty(getDevice().executeShellCommand("sm partition " + diskId + " private"));
- final LocalVolumeInfo vol = getAdoptionVolume();
-
- // Install directly onto adopted volume, and write data there
- new InstallMultiple().locationAuto().forceUuid(vol.uuid).addApk(APK).run();
- runDeviceTests(PKG, CLASS, "testDataNotInternal");
- runDeviceTests(PKG, CLASS, "testDataWrite");
- runDeviceTests(PKG, CLASS, "testDataRead");
-
- // Now unmount and uninstall; leaving stale package on adopted volume
- getDevice().executeShellCommand("sm unmount " + vol.volId);
- getDevice().uninstallPackage(PKG);
-
- // Install second copy on internal, but don't write anything
- new InstallMultiple().locationInternalOnly().addApk(APK).run();
- runDeviceTests(PKG, CLASS, "testDataInternal");
-
- // Kick through a remount cycle, which should purge the adopted app
- getDevice().executeShellCommand("sm mount " + vol.volId);
- runDeviceTests(PKG, CLASS, "testDataInternal");
- try {
- runDeviceTests(PKG, CLASS, "testDataRead");
- fail("Unexpected data from adopted volume picked up");
- } catch (AssertionError expected) {
- }
- getDevice().executeShellCommand("sm unmount " + vol.volId);
-
- // Uninstall the internal copy and remount; we should have no record of app
- getDevice().uninstallPackage(PKG);
- getDevice().executeShellCommand("sm mount " + vol.volId);
-
- assertEmpty(getDevice().executeShellCommand("pm list packages " + PKG));
- } finally {
- cleanUp(diskId);
- }
- }
-
- private boolean hasAdoptable() throws Exception {
- return Boolean.parseBoolean(getDevice().executeShellCommand("sm has-adoptable").trim());
- }
-
- private String getAdoptionDisk() throws Exception {
- final String disks = getDevice().executeShellCommand("sm list-disks adoptable");
- if (disks == null || disks.length() == 0) {
- throw new AssertionError("Devices that claim to support adoptable storage must have "
- + "adoptable media inserted during CTS to verify correct behavior");
- }
- return disks.split("\n")[0].trim();
- }
-
- private LocalVolumeInfo getAdoptionVolume() throws Exception {
- String[] lines = null;
- int attempt = 0;
- while (attempt++ < 15) {
- lines = getDevice().executeShellCommand("sm list-volumes private").split("\n");
- for (String line : lines) {
- final LocalVolumeInfo info = new LocalVolumeInfo(line.trim());
- if (!"private".equals(info.volId) && "mounted".equals(info.state)) {
- return info;
- }
- }
- Thread.sleep(1000);
- }
- throw new AssertionError("Expected private volume; found " + Arrays.toString(lines));
- }
-
- private void cleanUp(String diskId) throws Exception {
- getDevice().executeShellCommand("sm partition " + diskId + " public");
- getDevice().executeShellCommand("sm forget all");
- }
-
- private void runDeviceTests(String packageName, String testClassName, String testMethodName)
- throws DeviceNotAvailableException {
- Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
- }
-
- private static void assertSuccess(String str) {
- if (str == null || !str.startsWith("Success")) {
- throw new AssertionError("Expected success string but found " + str);
- }
- }
-
- private static void assertEmpty(String str) {
- if (str != null && str.trim().length() > 0) {
- throw new AssertionError("Expected empty string but found " + str);
- }
- }
-
- private static class LocalVolumeInfo {
- public String volId;
- public String state;
- public String uuid;
-
- public LocalVolumeInfo(String line) {
- final String[] split = line.split(" ");
- volId = split[0];
- state = split[1];
- uuid = split[2];
- }
- }
-
- private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
- public InstallMultiple() {
- super(getDevice(), mCtsBuild, mAbi);
- }
- }
-}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
deleted file mode 100644
index bf9e81c..0000000
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * 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 com.android.cts.appsecurity;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
-import com.android.ddmlib.Log;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-/**
- * Set of tests that verify various security checks involving multiple apps are
- * properly enforced.
- */
-public class AppSecurityTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
-
- // testSharedUidDifferentCerts constants
- private static final String SHARED_UI_APK = "CtsSharedUidInstall.apk";
- private static final String SHARED_UI_PKG = "com.android.cts.shareuidinstall";
- private static final String SHARED_UI_DIFF_CERT_APK = "CtsSharedUidInstallDiffCert.apk";
- private static final String SHARED_UI_DIFF_CERT_PKG =
- "com.android.cts.shareuidinstalldiffcert";
-
- // testAppUpgradeDifferentCerts constants
- private static final String SIMPLE_APP_APK = "CtsSimpleAppInstall.apk";
- private static final String SIMPLE_APP_PKG = "com.android.cts.simpleappinstall";
- private static final String SIMPLE_APP_DIFF_CERT_APK = "CtsSimpleAppInstallDiffCert.apk";
-
- // testAppFailAccessPrivateData constants
- private static final String APP_WITH_DATA_APK = "CtsAppWithData.apk";
- private static final String APP_WITH_DATA_PKG = "com.android.cts.appwithdata";
- private static final String APP_WITH_DATA_CLASS =
- "com.android.cts.appwithdata.CreatePrivateDataTest";
- private static final String APP_WITH_DATA_CREATE_METHOD =
- "testCreatePrivateData";
- private static final String APP_WITH_DATA_CHECK_NOEXIST_METHOD =
- "testEnsurePrivateDataNotExist";
- private static final String APP_ACCESS_DATA_APK = "CtsAppAccessData.apk";
- private static final String APP_ACCESS_DATA_PKG = "com.android.cts.appaccessdata";
-
- // testInstrumentationDiffCert constants
- private static final String TARGET_INSTRUMENT_APK = "CtsTargetInstrumentationApp.apk";
- private static final String TARGET_INSTRUMENT_PKG = "com.android.cts.targetinstrumentationapp";
- private static final String INSTRUMENT_DIFF_CERT_APK = "CtsInstrumentationAppDiffCert.apk";
- private static final String INSTRUMENT_DIFF_CERT_PKG =
- "com.android.cts.instrumentationdiffcertapp";
-
- // testPermissionDiffCert constants
- private static final String DECLARE_PERMISSION_APK = "CtsPermissionDeclareApp.apk";
- private static final String DECLARE_PERMISSION_PKG = "com.android.cts.permissiondeclareapp";
- private static final String DECLARE_PERMISSION_COMPAT_APK = "CtsPermissionDeclareAppCompat.apk";
- private static final String DECLARE_PERMISSION_COMPAT_PKG = "com.android.cts.permissiondeclareappcompat";
-
- private static final String PERMISSION_DIFF_CERT_APK = "CtsUsePermissionDiffCert.apk";
- private static final String PERMISSION_DIFF_CERT_PKG =
- "com.android.cts.usespermissiondiffcertapp";
-
- private static final String LOG_TAG = "AppSecurityTests";
-
- private IAbi mAbi;
- private CtsBuildHelper mCtsBuild;
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- private File getTestAppFile(String fileName) throws FileNotFoundException {
- return mCtsBuild.getTestApp(fileName);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // ensure build has been set before test is run
- assertNotNull(mCtsBuild);
- }
-
- /**
- * Test that an app that declares the same shared uid as an existing app, cannot be installed
- * if it is signed with a different certificate.
- */
- public void testSharedUidDifferentCerts() throws Exception {
- Log.i(LOG_TAG, "installing apks with shared uid, but different certs");
- try {
- // cleanup test apps that might be installed from previous partial test run
- getDevice().uninstallPackage(SHARED_UI_PKG);
- getDevice().uninstallPackage(SHARED_UI_DIFF_CERT_PKG);
-
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- String installResult = getDevice().installPackage(getTestAppFile(SHARED_UI_APK),
- false, options);
- assertNull(String.format("failed to install shared uid app, Reason: %s", installResult),
- installResult);
- installResult = getDevice().installPackage(getTestAppFile(SHARED_UI_DIFF_CERT_APK),
- false, options);
- assertNotNull("shared uid app with different cert than existing app installed " +
- "successfully", installResult);
- assertEquals("INSTALL_FAILED_SHARED_USER_INCOMPATIBLE", installResult);
- } finally {
- getDevice().uninstallPackage(SHARED_UI_PKG);
- getDevice().uninstallPackage(SHARED_UI_DIFF_CERT_PKG);
- }
- }
-
- /**
- * Test that an app update cannot be installed over an existing app if it has a different
- * certificate.
- */
- public void testAppUpgradeDifferentCerts() throws Exception {
- Log.i(LOG_TAG, "installing app upgrade with different certs");
- try {
- // cleanup test app that might be installed from previous partial test run
- getDevice().uninstallPackage(SIMPLE_APP_PKG);
-
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- String installResult = getDevice().installPackage(getTestAppFile(SIMPLE_APP_APK),
- false, options);
- assertNull(String.format("failed to install simple app. Reason: %s", installResult),
- installResult);
- installResult = getDevice().installPackage(getTestAppFile(SIMPLE_APP_DIFF_CERT_APK),
- true /* reinstall */, options);
- assertNotNull("app upgrade with different cert than existing app installed " +
- "successfully", installResult);
- assertEquals("INSTALL_FAILED_UPDATE_INCOMPATIBLE", installResult);
- } finally {
- getDevice().uninstallPackage(SIMPLE_APP_PKG);
- }
- }
-
- /**
- * Test that an app cannot access another app's private data.
- */
- public void testAppFailAccessPrivateData() throws Exception {
- Log.i(LOG_TAG, "installing app that attempts to access another app's private data");
- try {
- // cleanup test app that might be installed from previous partial test run
- getDevice().uninstallPackage(APP_WITH_DATA_PKG);
- getDevice().uninstallPackage(APP_ACCESS_DATA_PKG);
-
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- String installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
- false, options);
- assertNull(String.format("failed to install app with data. Reason: %s", installResult),
- installResult);
- // run appwithdata's tests to create private data
- runDeviceTests(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD);
-
- installResult = getDevice().installPackage(getTestAppFile(APP_ACCESS_DATA_APK),
- false, options);
- assertNull(String.format("failed to install app access data. Reason: %s",
- installResult), installResult);
- // run appaccessdata's tests which attempt to access appwithdata's private data
- runDeviceTests(APP_ACCESS_DATA_PKG);
- } finally {
- getDevice().uninstallPackage(APP_WITH_DATA_PKG);
- getDevice().uninstallPackage(APP_ACCESS_DATA_PKG);
- }
- }
-
- /**
- * Test that uninstall of an app removes its private data.
- */
- public void testUninstallRemovesData() throws Exception {
- Log.i(LOG_TAG, "Uninstalling app, verifying data is removed.");
- try {
- // cleanup test app that might be installed from previous partial test run
- getDevice().uninstallPackage(APP_WITH_DATA_PKG);
-
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- String installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
- false, options);
- assertNull(String.format("failed to install app with data. Reason: %s", installResult),
- installResult);
- // run appwithdata's tests to create private data
- runDeviceTests(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD);
-
- getDevice().uninstallPackage(APP_WITH_DATA_PKG);
-
- installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
- false, options);
- assertNull(String.format("failed to install app with data second time. Reason: %s",
- installResult), installResult);
- // run appwithdata's 'check if file exists' test
- runDeviceTests(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS,
- APP_WITH_DATA_CHECK_NOEXIST_METHOD);
- } finally {
- getDevice().uninstallPackage(APP_WITH_DATA_PKG);
- }
- }
-
- /**
- * Test that an app cannot instrument another app that is signed with different certificate.
- */
- public void testInstrumentationDiffCert() throws Exception {
- Log.i(LOG_TAG, "installing app that attempts to instrument another app");
- try {
- // cleanup test app that might be installed from previous partial test run
- getDevice().uninstallPackage(TARGET_INSTRUMENT_PKG);
- getDevice().uninstallPackage(INSTRUMENT_DIFF_CERT_PKG);
-
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- String installResult = getDevice().installPackage(
- getTestAppFile(TARGET_INSTRUMENT_APK), false, options);
- assertNull(String.format("failed to install target instrumentation app. Reason: %s",
- installResult), installResult);
-
- // the app will install, but will get error at runtime when starting instrumentation
- installResult = getDevice().installPackage(getTestAppFile(INSTRUMENT_DIFF_CERT_APK),
- false, options);
- assertNull(String.format(
- "failed to install instrumentation app with diff cert. Reason: %s",
- installResult), installResult);
- // run INSTRUMENT_DIFF_CERT_PKG tests
- // this test will attempt to call startInstrumentation directly and verify
- // SecurityException is thrown
- runDeviceTests(INSTRUMENT_DIFF_CERT_PKG);
- } finally {
- getDevice().uninstallPackage(TARGET_INSTRUMENT_PKG);
- getDevice().uninstallPackage(INSTRUMENT_DIFF_CERT_PKG);
- }
- }
-
- /**
- * Test that an app cannot use a signature-enforced permission if it is signed with a different
- * certificate than the app that declared the permission.
- */
- public void testPermissionDiffCert() throws Exception {
- Log.i(LOG_TAG, "installing app that attempts to use permission of another app");
- try {
- // cleanup test app that might be installed from previous partial test run
- getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
- getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
- getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);
-
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- String installResult = getDevice().installPackage(
- getTestAppFile(DECLARE_PERMISSION_APK), false, options);
- assertNull(String.format("failed to install declare permission app. Reason: %s",
- installResult), installResult);
-
- installResult = getDevice().installPackage(
- getTestAppFile(DECLARE_PERMISSION_COMPAT_APK), false, options);
- assertNull(String.format("failed to install declare permission compat app. Reason: %s",
- installResult), installResult);
-
- // the app will install, but will get error at runtime
- installResult = getDevice().installPackage(getTestAppFile(PERMISSION_DIFF_CERT_APK),
- false, options);
- assertNull(String.format("failed to install permission app with diff cert. Reason: %s",
- installResult), installResult);
- // run PERMISSION_DIFF_CERT_PKG tests which try to access the permission
- runDeviceTests(PERMISSION_DIFF_CERT_PKG);
- } finally {
- getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
- getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
- getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);
- }
- }
-
- private void runDeviceTests(String packageName) throws DeviceNotAvailableException {
- Utils.runDeviceTests(getDevice(), packageName);
- }
-
- private void runDeviceTests(String packageName, String testClassName, String testMethodName)
- throws DeviceNotAvailableException {
- Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
- }
-}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/DocumentsTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/DocumentsTest.java
deleted file mode 100644
index a4ec65a..0000000
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/DocumentsTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.cts.appsecurity;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-/**
- * Set of tests that verify behavior of
- * {@link android.provider.DocumentsContract} and related intents.
- */
-public class DocumentsTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
- private static final String PROVIDER_PKG = "com.android.cts.documentprovider";
- private static final String PROVIDER_APK = "CtsDocumentProvider.apk";
-
- private static final String CLIENT_PKG = "com.android.cts.documentclient";
- private static final String CLIENT_APK = "CtsDocumentClient.apk";
-
- private IAbi mAbi;
- private CtsBuildHelper mCtsBuild;
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- assertNotNull(mAbi);
- assertNotNull(mCtsBuild);
-
- getDevice().uninstallPackage(PROVIDER_PKG);
- getDevice().uninstallPackage(CLIENT_PKG);
-
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(PROVIDER_APK), false));
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(CLIENT_APK), false));
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- getDevice().uninstallPackage(PROVIDER_PKG);
- getDevice().uninstallPackage(CLIENT_PKG);
- }
-
- public void testOpenSimple() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenSimple");
- }
-
- public void testCreateNew() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateNew");
- }
-
- public void testCreateExisting() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateExisting");
- }
-
- public void testTree() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTree");
- }
-
- public void testGetContent() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testGetContent");
- }
-
- public void runDeviceTests(String packageName, String testClassName, String testMethodName)
- throws DeviceNotAvailableException {
- Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
- }
-}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/ExternalStorageHostTest.java
deleted file mode 100644
index 9c22bdc..0000000
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/ExternalStorageHostTest.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.appsecurity;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
-import com.android.ddmlib.Log;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-/**
- * Set of tests that verify behavior of external storage devices.
- */
-public class ExternalStorageHostTest extends DeviceTestCase
- implements IAbiReceiver, IBuildReceiver {
- private static final String TAG = "ExternalStorageHostTest";
-
- private static final String COMMON_CLASS =
- "com.android.cts.externalstorageapp.CommonExternalStorageTest";
-
- private static final String NONE_APK = "CtsExternalStorageApp.apk";
- private static final String NONE_PKG = "com.android.cts.externalstorageapp";
- private static final String NONE_CLASS = ".ExternalStorageTest";
- private static final String READ_APK = "CtsReadExternalStorageApp.apk";
- private static final String READ_PKG = "com.android.cts.readexternalstorageapp";
- private static final String READ_CLASS = ".ReadExternalStorageTest";
- private static final String WRITE_APK = "CtsWriteExternalStorageApp.apk";
- private static final String WRITE_PKG = "com.android.cts.writeexternalstorageapp";
- private static final String WRITE_CLASS = ".WriteExternalStorageTest";
- private static final String MULTIUSER_APK = "CtsMultiUserStorageApp.apk";
- private static final String MULTIUSER_PKG = "com.android.cts.multiuserstorageapp";
- private static final String MULTIUSER_CLASS = ".MultiUserStorageTest";
-
- private IAbi mAbi;
- private CtsBuildHelper mCtsBuild;
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- private File getTestAppFile(String fileName) throws FileNotFoundException {
- return mCtsBuild.getTestApp(fileName);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- assertNotNull(mAbi);
- assertNotNull(mCtsBuild);
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- /**
- * Verify that app with no external storage permissions works correctly.
- */
- public void testExternalStorageNone() throws Exception {
- final int[] users = createUsersForTest();
- try {
- wipePrimaryExternalStorage();
-
- getDevice().uninstallPackage(NONE_PKG);
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
-
- for (int user : users) {
- runDeviceTests(NONE_PKG, COMMON_CLASS, user);
- runDeviceTests(NONE_PKG, NONE_CLASS, user);
- }
- } finally {
- getDevice().uninstallPackage(NONE_PKG);
- removeUsersForTest(users);
- }
- }
-
- /**
- * Verify that app with
- * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} works
- * correctly.
- */
- public void testExternalStorageRead() throws Exception {
- final int[] users = createUsersForTest();
- try {
- wipePrimaryExternalStorage();
-
- getDevice().uninstallPackage(READ_PKG);
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
-
- for (int user : users) {
- runDeviceTests(READ_PKG, COMMON_CLASS, user);
- runDeviceTests(READ_PKG, READ_CLASS, user);
- }
- } finally {
- getDevice().uninstallPackage(READ_PKG);
- removeUsersForTest(users);
- }
- }
-
- /**
- * Verify that app with
- * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} works
- * correctly.
- */
- public void testExternalStorageWrite() throws Exception {
- final int[] users = createUsersForTest();
- try {
- wipePrimaryExternalStorage();
-
- getDevice().uninstallPackage(WRITE_PKG);
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
-
- for (int user : users) {
- runDeviceTests(WRITE_PKG, COMMON_CLASS, user);
- runDeviceTests(WRITE_PKG, WRITE_CLASS, user);
- }
- } finally {
- getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
- }
- }
-
- /**
- * Verify that app with WRITE_EXTERNAL can leave gifts in external storage
- * directories belonging to other apps, and those apps can read.
- */
- public void testExternalStorageGifts() throws Exception {
- final int[] users = createUsersForTest();
- try {
- wipePrimaryExternalStorage();
-
- getDevice().uninstallPackage(NONE_PKG);
- getDevice().uninstallPackage(READ_PKG);
- getDevice().uninstallPackage(WRITE_PKG);
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
- assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
- assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
-
- for (int user : users) {
- runDeviceTests(WRITE_PKG, "WriteGiftTest", user);
- runDeviceTests(READ_PKG, "ReadGiftTest", user);
- runDeviceTests(NONE_PKG, "GiftTest", user);
- }
- } finally {
- getDevice().uninstallPackage(NONE_PKG);
- getDevice().uninstallPackage(READ_PKG);
- getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
- }
- }
-
- /**
- * Test multi-user emulated storage environment, ensuring that each user has
- * isolated storage.
- */
- public void testMultiUserStorageIsolated() throws Exception {
- final int[] users = createUsersForTest();
- try {
- if (users.length == 1) {
- Log.d(TAG, "Single user device; skipping isolated storage tests");
- return;
- }
-
- final int owner = users[0];
- final int secondary = users[1];
-
- // Install our test app
- getDevice().uninstallPackage(MULTIUSER_PKG);
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- final String installResult = getDevice()
- .installPackage(getTestAppFile(MULTIUSER_APK), false, options);
- assertNull("Failed to install: " + installResult, installResult);
-
- // Clear data from previous tests
- runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testCleanIsolatedStorage", owner);
- runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testCleanIsolatedStorage", secondary);
-
- // Have both users try writing into isolated storage
- runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testWriteIsolatedStorage", owner);
- runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testWriteIsolatedStorage", secondary);
-
- // Verify they both have isolated view of storage
- runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", owner);
- runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", secondary);
-
- // Verify they can't poke at each other
- runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", owner);
- runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", secondary);
- } finally {
- getDevice().uninstallPackage(MULTIUSER_PKG);
- removeUsersForTest(users);
- }
- }
-
- private void wipePrimaryExternalStorage() throws DeviceNotAvailableException {
- getDevice().executeShellCommand("rm -rf /sdcard/Android");
- getDevice().executeShellCommand("rm -rf /sdcard/DCIM");
- getDevice().executeShellCommand("rm -rf /sdcard/MUST_*");
- }
-
- private int[] createUsersForTest() throws DeviceNotAvailableException {
- return Utils.createUsersForTest(getDevice());
- }
-
- private void removeUsersForTest(int[] users) throws DeviceNotAvailableException {
- Utils.removeUsersForTest(getDevice(), users);
- }
-
- private void runDeviceTests(String packageName, String testClassName, int userId)
- throws DeviceNotAvailableException {
- Utils.runDeviceTests(getDevice(), packageName, testClassName, userId);
- }
-
- private void runDeviceTests(String packageName, String testClassName, String testMethodName,
- int userId) throws DeviceNotAvailableException {
- Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName, userId);
- }
-}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java
deleted file mode 100644
index 9637a6c..0000000
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (C) 2014 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.cts.appsecurity;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
-import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.Map;
-
-/**
- * Tests for Keyset based features.
- */
-public class KeySetHostTest extends DeviceTestCase implements IBuildReceiver {
-
- private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
-
- /* package with device-side tests */
- private static final String KEYSET_TEST_PKG = "com.android.cts.keysets.testapp";
- private static final String KEYSET_TEST_APP_APK = "CtsKeySetTestApp.apk";
-
- /* plain test apks with different signing and upgrade keysets */
- private static final String KEYSET_PKG = "com.android.cts.keysets";
- private static final String A_SIGNED_NO_UPGRADE =
- "CtsKeySetSigningAUpgradeNone.apk";
- private static final String A_SIGNED_A_UPGRADE =
- "CtsKeySetSigningAUpgradeA.apk";
- private static final String A_SIGNED_B_UPGRADE =
- "CtsKeySetSigningAUpgradeB.apk";
- private static final String A_SIGNED_A_OR_B_UPGRADE =
- "CtsKeySetSigningAUpgradeAOrB.apk";
- private static final String B_SIGNED_A_UPGRADE =
- "CtsKeySetSigningBUpgradeA.apk";
- private static final String B_SIGNED_B_UPGRADE =
- "CtsKeySetSigningBUpgradeB.apk";
- private static final String A_AND_B_SIGNED_A_UPGRADE =
- "CtsKeySetSigningAAndBUpgradeA.apk";
- private static final String A_AND_B_SIGNED_B_UPGRADE =
- "CtsKeySetSigningAAndBUpgradeB.apk";
- private static final String A_AND_C_SIGNED_B_UPGRADE =
- "CtsKeySetSigningAAndCUpgradeB.apk";
- private static final String SHARED_USR_A_SIGNED_B_UPGRADE =
- "CtsKeySetSharedUserSigningAUpgradeB.apk";
- private static final String SHARED_USR_B_SIGNED_B_UPGRADE =
- "CtsKeySetSharedUserSigningBUpgradeB.apk";
- private static final String A_SIGNED_BAD_B_B_UPGRADE =
- "CtsKeySetSigningABadUpgradeB.apk";
- private static final String C_SIGNED_BAD_A_AB_UPGRADE =
- "CtsKeySetSigningCBadAUpgradeAB.apk";
- private static final String A_SIGNED_NO_B_B_UPGRADE =
- "CtsKeySetSigningANoDefUpgradeB.apk";
- private static final String A_SIGNED_EC_A_UPGRADE =
- "CtsKeySetSigningAUpgradeEcA.apk";
- private static final String EC_A_SIGNED_A_UPGRADE =
- "CtsKeySetSigningEcAUpgradeA.apk";
-
- /* package which defines the KEYSET_PERM_NAME signature permission */
- private static final String KEYSET_PERM_DEF_PKG =
- "com.android.cts.keysets_permdef";
-
- /* The apks defining and using the permission have both A and B as upgrade keys */
- private static final String PERM_DEF_A_SIGNED =
- "CtsKeySetPermDefSigningA.apk";
- private static final String PERM_DEF_B_SIGNED =
- "CtsKeySetPermDefSigningB.apk";
- private static final String PERM_USE_A_SIGNED =
- "CtsKeySetPermUseSigningA.apk";
- private static final String PERM_USE_B_SIGNED =
- "CtsKeySetPermUseSigningB.apk";
-
- private static final String PERM_TEST_CLASS =
- "com.android.cts.keysets.KeySetPermissionsTest";
-
- private static final String LOG_TAG = "AppsecurityHostTests";
-
- private File getTestAppFile(String fileName) throws FileNotFoundException {
- return mCtsBuild.getTestApp(fileName);
- }
-
- /**
- * Helper method that checks that all tests in given result passed, and attempts to generate
- * a meaningful error message if they failed.
- *
- * @param result
- */
- private void assertDeviceTestsPass(TestRunResult result) {
- assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
- result.getName(), result.getRunFailureMessage()), result.isRunFailure());
-
- if (result.hasFailedTests()) {
-
- /* build a meaningful error message */
- StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
- result.getTestResults().entrySet()) {
- if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
- errorBuilder.append(resultEntry.getKey().toString());
- errorBuilder.append(":\n");
- errorBuilder.append(resultEntry.getValue().getStackTrace());
- }
- }
- fail(errorBuilder.toString());
- }
- }
-
- /**
- * Helper method that checks that all tests in given result passed, and attempts to generate
- * a meaningful error message if they failed.
- *
- * @param result
- */
- private void assertDeviceTestsFail(String msg, TestRunResult result) {
- assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
- result.getName(), result.getRunFailureMessage()), result.isRunFailure());
-
- if (!result.hasFailedTests()) {
- fail(msg);
- }
- }
-
- /**
- * Helper method that will run the specified packages tests on device.
- *
- * @param pkgName Android application package for tests
- * @return <code>true</code> if all tests passed.
- * @throws DeviceNotAvailableException if connection to device was lost.
- */
- private boolean runDeviceTests(String pkgName) throws DeviceNotAvailableException {
- return runDeviceTests(pkgName, null, null);
- }
-
- /**
- * Helper method that will run the specified packages tests on device.
- *
- * @param pkgName Android application package for tests
- * @return <code>true</code> if all tests passed.
- * @throws DeviceNotAvailableException if connection to device was lost.
- */
- private boolean runDeviceTests(String pkgName, String testClassName, String testMethodName)
- throws DeviceNotAvailableException {
- TestRunResult runResult = doRunTests(pkgName, testClassName, testMethodName);
- return !runResult.hasFailedTests();
- }
-
- /**
- * Helper method to run tests and return the listener that collected the results.
- *
- * @param pkgName Android application package for tests
- * @return the {@link TestRunResult}
- * @throws DeviceNotAvailableException if connection to device was lost.
- */
- private TestRunResult doRunTests(String pkgName, String testClassName,
- String testMethodName) throws DeviceNotAvailableException {
-
- RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName,
- RUNNER, getDevice().getIDevice());
- if (testClassName != null && testMethodName != null) {
- testRunner.setMethodName(testClassName, testMethodName);
- }
- CollectingTestListener listener = new CollectingTestListener();
- getDevice().runInstrumentationTests(testRunner, listener);
- return listener.getCurrentRunResults();
- }
-
- /**
- * Helper method which installs a package and an upgrade to it.
- *
- * @param pkgName - package name of apk.
- * @param firstApk - first apk to install
- * @param secondApk - apk to which we attempt to upgrade
- * @param expectedResult - null if successful, otherwise expected error.
- */
- private String testPackageUpgrade(String pkgName, String firstApk,
- String secondApk) throws Exception {
- String installResult;
- try {
-
- /* cleanup test apps that might be installed from previous partial test run */
- mDevice.uninstallPackage(pkgName);
-
- installResult = mDevice.installPackage(getTestAppFile(firstApk),
- false);
- /* we should always succeed on first-install */
- assertNull(String.format("failed to install %s, Reason: %s", pkgName,
- installResult), installResult);
-
- /* attempt to install upgrade */
- installResult = mDevice.installPackage(getTestAppFile(secondApk),
- true);
- } finally {
- mDevice.uninstallPackage(pkgName);
- }
- return installResult;
- }
- /**
- * A reference to the device under test.
- */
- private ITestDevice mDevice;
-
- private CtsBuildHelper mCtsBuild;
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mDevice = getDevice();
- assertNotNull(mCtsBuild);
- }
-
- /**
- * Tests for KeySet based key rotation
- */
-
- /*
- * Check if an apk which does not specify an upgrade-key-set may be upgraded
- * to an apk which does.
- */
- public void testNoKSToUpgradeKS() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_NO_UPGRADE, A_SIGNED_A_UPGRADE);
- assertNull(String.format("failed to upgrade keyset app from no specified upgrade-key-set"
- + "to version with specified upgrade-key-set, Reason: %s", installResult),
- installResult);
- }
-
- /*
- * Check if an apk which does specify an upgrade-key-set may be upgraded
- * to an apk which does not.
- */
- public void testUpgradeKSToNoKS() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_NO_UPGRADE);
- assertNull(String.format("failed to upgrade keyset app from specified upgrade-key-set"
- + "to version without specified upgrade-key-set, Reason: %s", installResult),
- installResult);
- }
-
- /*
- * Check if an apk signed by a key other than the upgrade keyset can update
- * an app
- */
- public void testUpgradeKSWithWrongKey() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, B_SIGNED_A_UPGRADE);
- assertNotNull("upgrade to improperly signed app succeeded!", installResult);
- }
-
- /*
- * Check if an apk signed by its signing key, which is not an upgrade key,
- * can upgrade an app.
- */
- public void testUpgradeKSWithWrongSigningKey() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, A_SIGNED_B_UPGRADE);
- assertNotNull("upgrade to improperly signed app succeeded!",
- installResult);
- }
-
- /*
- * Check if an apk signed by its upgrade key, which is not its signing key,
- * can upgrade an app.
- */
- public void testUpgradeKSWithUpgradeKey() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, B_SIGNED_B_UPGRADE);
- assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
- + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
- installResult);
- }
-
- /*
- * Check if an apk signed by its upgrade key, which is its signing key, can
- * upgrade an app.
- */
- public void testUpgradeKSWithSigningUpgradeKey() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_A_UPGRADE);
- assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
- + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
- installResult);
- }
-
- /*
- * Check if an apk signed by multiple keys, one of which is its upgrade key,
- * can upgrade an app.
- */
- public void testMultipleUpgradeKSWithUpgradeKey() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE,
- A_AND_B_SIGNED_A_UPGRADE);
- assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
- + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
- installResult);
- }
-
- /*
- * Check if an apk signed by multiple keys, its signing keys,
- * but none of which is an upgrade key, can upgrade an app.
- */
- public void testMultipleUpgradeKSWithSigningKey() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_AND_C_SIGNED_B_UPGRADE,
- A_AND_C_SIGNED_B_UPGRADE);
- assertNotNull("upgrade to improperly signed app succeeded!", installResult);
- }
-
- /*
- * Check if an apk which defines multiple (two) upgrade keysets is
- * upgrade-able by either.
- */
- public void testUpgradeKSWithMultipleUpgradeKeySetsFirstKey() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
- A_SIGNED_A_UPGRADE);
- assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
- + "to one signed by first upgrade keyset key-a, Reason: %s", installResult),
- installResult);
- installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
- B_SIGNED_B_UPGRADE);
- assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
- + "to one signed by second upgrade keyset key-b, Reason: %s", installResult),
- installResult);
- }
-
- /**
- * Helper method which installs a package defining a permission and a package
- * using the permission, and then rotates the signing keys for one of them.
- * A device-side test is then used to ascertain whether or not the permission
- * was appropriately gained or lost.
- *
- * @param permDefApk - apk to install which defines the sig-permissoin
- * @param permUseApk - apk to install which declares it uses the permission
- * @param upgradeApk - apk to install which upgrades one of the first two
- * @param hasPermBeforeUpgrade - whether we expect the consuming app to have
- * the permission before the upgrade takes place.
- * @param hasPermAfterUpgrade - whether we expect the consuming app to have
- * the permission after the upgrade takes place.
- */
- private void testKeyRotationPerm(String permDefApk, String permUseApk,
- String upgradeApk, boolean hasPermBeforeUpgrade,
- boolean hasPermAfterUpgrade) throws Exception {
- try {
-
- /* cleanup test apps that might be installed from previous partial test run */
- mDevice.uninstallPackage(KEYSET_PKG);
- mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
- mDevice.uninstallPackage(KEYSET_TEST_PKG);
-
- /* install PERM_DEF, KEYSET_APP and KEYSET_TEST_APP */
- String installResult = mDevice.installPackage(
- getTestAppFile(permDefApk), false);
- assertNull(String.format("failed to install keyset perm-def app, Reason: %s",
- installResult), installResult);
- installResult = getDevice().installPackage(
- getTestAppFile(permUseApk), false);
- assertNull(String.format("failed to install keyset test app. Reason: %s",
- installResult), installResult);
- installResult = getDevice().installPackage(
- getTestAppFile(KEYSET_TEST_APP_APK), false);
- assertNull(String.format("failed to install keyset test app. Reason: %s",
- installResult), installResult);
-
- /* verify package does have perm */
- TestRunResult result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
- "testHasPerm");
- if (hasPermBeforeUpgrade) {
- assertDeviceTestsPass(result);
- } else {
- assertDeviceTestsFail(" has permission permission it should not have.", result);
- }
-
- /* rotate keys */
- installResult = mDevice.installPackage(getTestAppFile(upgradeApk),
- true);
- result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
- "testHasPerm");
- if (hasPermAfterUpgrade) {
- assertDeviceTestsPass(result);
- } else {
- assertDeviceTestsFail(KEYSET_PKG + " has permission it should not have.", result);
- }
- } finally {
- mDevice.uninstallPackage(KEYSET_PKG);
- mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
- mDevice.uninstallPackage(KEYSET_TEST_PKG);
- }
- }
-
- /*
- * Check if an apk gains signature-level permission after changing to a new
- * signature, for which a permission should be granted.
- */
- public void testUpgradeSigPermGained() throws Exception {
- testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_USE_A_SIGNED,
- false, true);
- }
-
- /*
- * Check if an apk loses signature-level permission after changing to a new
- * signature, from one for which a permission was previously granted.
- */
- public void testUpgradeSigPermLost() throws Exception {
- testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_USE_B_SIGNED,
- true, false);
- }
-
- /*
- * Check if an apk gains signature-level permission after the app defining
- * it rotates to the same signature.
- */
- public void testUpgradeDefinerSigPermGained() throws Exception {
- testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_DEF_B_SIGNED,
- false, true);
- }
-
- /*
- * Check if an apk loses signature-level permission after the app defining
- * it rotates to a different signature.
- */
- public void testUpgradeDefinerSigPermLost() throws Exception {
- testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_DEF_B_SIGNED,
- true, false);
- }
-
- /*
- * Check if an apk which indicates it uses a sharedUserId and defines an
- * upgrade keyset is allowed to rotate to that keyset.
- */
- public void testUpgradeSharedUser() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, SHARED_USR_A_SIGNED_B_UPGRADE,
- SHARED_USR_B_SIGNED_B_UPGRADE);
- assertNotNull("upgrade allowed for app with shareduserid!", installResult);
- }
-
- /*
- * Check that an apk with an upgrade key represented by a bad public key
- * fails to install.
- */
- public void testBadUpgradeBadPubKey() throws Exception {
- mDevice.uninstallPackage(KEYSET_PKG);
- String installResult = mDevice.installPackage(getTestAppFile(A_SIGNED_BAD_B_B_UPGRADE),
- false);
- assertNotNull("Installation of apk with upgrade key referring to a bad public key succeeded!",
- installResult);
- }
-
- /*
- * Check that an apk with an upgrade keyset that includes a bad public key fails to install.
- */
- public void testBadUpgradeMissingPubKey() throws Exception {
- mDevice.uninstallPackage(KEYSET_PKG);
- String installResult = mDevice.installPackage(getTestAppFile(C_SIGNED_BAD_A_AB_UPGRADE),
- false);
- assertNotNull("Installation of apk with upgrade key referring to a bad public key succeeded!",
- installResult);
- }
-
- /*
- * Check that an apk with an upgrade key that has no corresponding public key fails to install.
- */
- public void testBadUpgradeNoPubKey() throws Exception {
- mDevice.uninstallPackage(KEYSET_PKG);
- String installResult = mDevice.installPackage(getTestAppFile(A_SIGNED_NO_B_B_UPGRADE),
- false);
- assertNotNull("Installation of apk with upgrade key referring to a bad public key succeeded!",
- installResult);
- }
-
- /*
- * Check if an apk signed by RSA pub key can upgrade to apk signed by EC key.
- */
- public void testUpgradeKSRsaToEC() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_EC_A_UPGRADE,
- EC_A_SIGNED_A_UPGRADE);
- assertNull(String.format("failed to upgrade keyset app from one signed by RSA key"
- + "to version signed by EC upgrade-key-set, Reason: %s", installResult),
- installResult);
- }
-
- /*
- * Check if an apk signed by EC pub key can upgrade to apk signed by RSA key.
- */
- public void testUpgradeKSECToRSA() throws Exception {
- String installResult = testPackageUpgrade(KEYSET_PKG, EC_A_SIGNED_A_UPGRADE,
- A_SIGNED_EC_A_UPGRADE);
- assertNull(String.format("failed to upgrade keyset app from one signed by EC key"
- + "to version signed by RSA upgrade-key-set, Reason: %s", installResult),
- installResult);
- }
-}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/PermissionsHostTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/PermissionsHostTest.java
deleted file mode 100644
index 20a92aa..0000000
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/PermissionsHostTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.appsecurity;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-/**
- * Set of tests that verify behavior of runtime permissions, including both
- * dynamic granting and behavior of legacy apps.
- */
-public class PermissionsHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
- private static final String PKG = "com.android.cts.usepermission";
-
- private static final String APK = "CtsUsePermissionApp.apk";
- private static final String APK_COMPAT = "CtsUsePermissionAppCompat.apk";
-
- private IAbi mAbi;
- private CtsBuildHelper mCtsBuild;
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- assertNotNull(mAbi);
- assertNotNull(mCtsBuild);
-
- getDevice().uninstallPackage(PKG);
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- getDevice().uninstallPackage(PKG);
- }
-
- public void testFail() throws Exception {
- // Sanity check that remote failure is host failure
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(APK), false, false));
- try {
- runDeviceTests(PKG, ".UsePermissionTest", "testFail");
- fail("Expected remote failure");
- } catch (AssertionError expected) {
- }
- }
-
- public void testKill() throws Exception {
- // Sanity check that remote kill is host failure
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(APK), false, false));
- try {
- runDeviceTests(PKG, ".UsePermissionTest", "testKill");
- fail("Expected remote failure");
- } catch (AssertionError expected) {
- }
- }
-
- public void testDefault() throws Exception {
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(APK), false, false));
- runDeviceTests(PKG, ".UsePermissionTest", "testDefault");
- }
-
- public void testGranted() throws Exception {
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(APK), false, false));
- grantPermission(PKG, "android.permission.READ_EXTERNAL_STORAGE");
- grantPermission(PKG, "android.permission.WRITE_EXTERNAL_STORAGE");
- runDeviceTests(PKG, ".UsePermissionTest", "testGranted");
- }
-
- public void testInteractiveGrant() throws Exception {
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(APK), false, false));
- runDeviceTests(PKG, ".UsePermissionTest", "testInteractiveGrant");
- }
-
- public void testRuntimeGroupGrantSpecificity() throws Exception {
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(APK), false, false));
- runDeviceTests(PKG, ".UsePermissionTest", "testRuntimeGroupGrantSpecificity");
- }
-
- public void testRuntimeGroupGrantExpansion() throws Exception {
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(APK), false, false));
- runDeviceTests(PKG, ".UsePermissionTest", "testRuntimeGroupGrantExpansion");
- }
-
- public void testCompatDefault() throws Exception {
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(APK_COMPAT), false, false));
- runDeviceTests(PKG, ".UsePermissionCompatTest", "testCompatDefault");
- }
-
- public void testCompatRevoked() throws Exception {
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(APK_COMPAT), false, false));
- setAppOps(PKG, "android:read_external_storage", "deny");
- setAppOps(PKG, "android:write_external_storage", "deny");
- runDeviceTests(PKG, ".UsePermissionCompatTest", "testCompatRevoked");
- }
-
- private void runDeviceTests(String packageName, String testClassName, String testMethodName)
- throws DeviceNotAvailableException {
- Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
- }
-
- private void grantPermission(String pkg, String permission) throws Exception {
- assertEmpty(getDevice().executeShellCommand("pm grant " + pkg + " " + permission));
- }
-
- private void revokePermission(String pkg, String permission) throws Exception {
- assertEmpty(getDevice().executeShellCommand("pm revoke " + pkg + " " + permission));
- }
-
- private void setAppOps(String pkg, String op, String mode) throws Exception {
- assertEmpty(getDevice().executeShellCommand("appops set " + pkg + " " + op + " " + mode));
- }
-
- private static void assertEmpty(String str) {
- if (str == null || str.length() == 0) {
- return;
- } else {
- fail("Expected empty string but found " + str);
- }
- }
-}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
deleted file mode 100644
index ef3af8d..0000000
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.cts.appsecurity;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Tests that verify installing of various split APKs from host side.
- */
-public class SplitTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
- static final String PKG = "com.android.cts.splitapp";
- static final String CLASS = ".SplitAppTest";
-
- static final String APK = "CtsSplitApp.apk";
-
- static final String APK_mdpi = "CtsSplitApp_mdpi-v4.apk";
- static final String APK_hdpi = "CtsSplitApp_hdpi-v4.apk";
- static final String APK_xhdpi = "CtsSplitApp_xhdpi-v4.apk";
- static final String APK_xxhdpi = "CtsSplitApp_xxhdpi-v4.apk";
-
- private static final String APK_v7 = "CtsSplitApp_v7.apk";
- private static final String APK_fr = "CtsSplitApp_fr.apk";
- private static final String APK_de = "CtsSplitApp_de.apk";
-
- private static final String APK_x86 = "CtsSplitApp_x86.apk";
- private static final String APK_x86_64 = "CtsSplitApp_x86_64.apk";
- private static final String APK_armeabi_v7a = "CtsSplitApp_armeabi-v7a.apk";
- private static final String APK_armeabi = "CtsSplitApp_armeabi.apk";
- private static final String APK_arm64_v8a = "CtsSplitApp_arm64-v8a.apk";
- private static final String APK_mips64 = "CtsSplitApp_mips64.apk";
- private static final String APK_mips = "CtsSplitApp_mips.apk";
-
- private static final String APK_DIFF_REVISION = "CtsSplitAppDiffRevision.apk";
- private static final String APK_DIFF_REVISION_v7 = "CtsSplitAppDiffRevision_v7.apk";
-
- private static final String APK_DIFF_VERSION = "CtsSplitAppDiffVersion.apk";
- private static final String APK_DIFF_VERSION_v7 = "CtsSplitAppDiffVersion_v7.apk";
-
- private static final String APK_DIFF_CERT = "CtsSplitAppDiffCert.apk";
- private static final String APK_DIFF_CERT_v7 = "CtsSplitAppDiffCert_v7.apk";
-
- private static final String APK_FEATURE = "CtsSplitAppFeature.apk";
- private static final String APK_FEATURE_v7 = "CtsSplitAppFeature_v7.apk";
-
- static final HashMap<String, String> ABI_TO_APK = new HashMap<>();
-
- static {
- ABI_TO_APK.put("x86", APK_x86);
- ABI_TO_APK.put("x86_64", APK_x86_64);
- ABI_TO_APK.put("armeabi-v7a", APK_armeabi_v7a);
- ABI_TO_APK.put("armeabi", APK_armeabi);
- ABI_TO_APK.put("arm64-v8a", APK_arm64_v8a);
- ABI_TO_APK.put("mips64", APK_mips64);
- ABI_TO_APK.put("mips", APK_mips);
- }
-
- private IAbi mAbi;
- private CtsBuildHelper mCtsBuild;
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- assertNotNull(mAbi);
- assertNotNull(mCtsBuild);
-
- getDevice().uninstallPackage(PKG);
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- getDevice().uninstallPackage(PKG);
- }
-
- public void testSingleBase() throws Exception {
- new InstallMultiple().addApk(APK).run();
- runDeviceTests(PKG, CLASS, "testSingleBase");
- }
-
- public void testDensitySingle() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
- runDeviceTests(PKG, CLASS, "testDensitySingle");
- }
-
- public void testDensityAll() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_mdpi).addApk(APK_hdpi).addApk(APK_xhdpi)
- .addApk(APK_xxhdpi).run();
- runDeviceTests(PKG, CLASS, "testDensityAll");
- }
-
- /**
- * Install first with low-resolution resources, then add a split that offers
- * higher-resolution resources.
- */
- public void testDensityBest() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
- runDeviceTests(PKG, CLASS, "testDensityBest1");
-
- // Now splice in an additional split which offers better resources
- new InstallMultiple().inheritFrom(PKG).addApk(APK_xxhdpi).run();
- runDeviceTests(PKG, CLASS, "testDensityBest2");
- }
-
- /**
- * Verify that an API-based split can change enabled/disabled state of
- * manifest elements.
- */
- public void testApi() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_v7).run();
- runDeviceTests(PKG, CLASS, "testApi");
- }
-
- public void testLocale() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_de).addApk(APK_fr).run();
- runDeviceTests(PKG, CLASS, "testLocale");
- }
-
- /**
- * Install test app with <em>single</em> split that exactly matches the
- * currently active ABI. This also explicitly forces ABI when installing.
- */
- public void testNativeSingle() throws Exception {
- final String abi = mAbi.getName();
- final String apk = ABI_TO_APK.get(abi);
- assertNotNull("Failed to find APK for ABI " + abi, apk);
-
- new InstallMultiple().addApk(APK).addApk(apk).run();
- runDeviceTests(PKG, CLASS, "testNative");
- }
-
- /**
- * Install test app with <em>single</em> split that exactly matches the
- * currently active ABI. This variant <em>does not</em> force the ABI when
- * installing, instead exercising the system's ability to choose the ABI
- * through inspection of the installed app.
- */
- public void testNativeSingleNatural() throws Exception {
- final String abi = mAbi.getName();
- final String apk = ABI_TO_APK.get(abi);
- assertNotNull("Failed to find APK for ABI " + abi, apk);
-
- new InstallMultiple().useNaturalAbi().addApk(APK).addApk(apk).run();
- runDeviceTests(PKG, CLASS, "testNative");
- }
-
- /**
- * Install test app with <em>all</em> possible ABI splits. This also
- * explicitly forces ABI when installing.
- */
- public void testNativeAll() throws Exception {
- final InstallMultiple inst = new InstallMultiple().addApk(APK);
- for (String apk : ABI_TO_APK.values()) {
- inst.addApk(apk);
- }
- inst.run();
- runDeviceTests(PKG, CLASS, "testNative");
- }
-
- /**
- * Install test app with <em>all</em> possible ABI splits. This variant
- * <em>does not</em> force the ABI when installing, instead exercising the
- * system's ability to choose the ABI through inspection of the installed
- * app.
- */
- public void testNativeAllNatural() throws Exception {
- final InstallMultiple inst = new InstallMultiple().useNaturalAbi().addApk(APK);
- for (String apk : ABI_TO_APK.values()) {
- inst.addApk(apk);
- }
- inst.run();
- runDeviceTests(PKG, CLASS, "testNative");
- }
-
- public void testDuplicateBase() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK).runExpectingFailure();
- }
-
- public void testDuplicateSplit() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_v7).addApk(APK_v7).runExpectingFailure();
- }
-
- public void testDiffCert() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
- }
-
- public void testDiffCertInherit() throws Exception {
- new InstallMultiple().addApk(APK).run();
- new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
- }
-
- public void testDiffVersion() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
- }
-
- public void testDiffVersionInherit() throws Exception {
- new InstallMultiple().addApk(APK).run();
- new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
- }
-
- public void testDiffRevision() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_DIFF_REVISION_v7).run();
- runDeviceTests(PKG, CLASS, "testRevision0_12");
- }
-
- public void testDiffRevisionInheritBase() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_v7).run();
- runDeviceTests(PKG, CLASS, "testRevision0_0");
- new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION_v7).run();
- runDeviceTests(PKG, CLASS, "testRevision0_12");
- }
-
- public void testDiffRevisionInheritSplit() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_v7).run();
- runDeviceTests(PKG, CLASS, "testRevision0_0");
- new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION).run();
- runDeviceTests(PKG, CLASS, "testRevision12_0");
- }
-
- public void testDiffRevisionDowngrade() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_DIFF_REVISION_v7).run();
- new InstallMultiple().inheritFrom(PKG).addApk(APK_v7).runExpectingFailure();
- }
-
- public void testFeatureBase() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_FEATURE).run();
- runDeviceTests(PKG, CLASS, "testFeatureBase");
- }
-
- public void testFeatureApi() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_FEATURE).addApk(APK_FEATURE_v7).run();
- runDeviceTests(PKG, CLASS, "testFeatureApi");
- }
-
- public void testInheritUpdatedBase() throws Exception {
- // TODO: flesh out this test
- }
-
- public void testInheritUpdatedSplit() throws Exception {
- // TODO: flesh out this test
- }
-
- /**
- * Verify that installing a new version of app wipes code cache.
- */
- public void testClearCodeCache() throws Exception {
- new InstallMultiple().addApk(APK).run();
- runDeviceTests(PKG, CLASS, "testCodeCacheWrite");
- new InstallMultiple().addArg("-r").addApk(APK_DIFF_VERSION).run();
- runDeviceTests(PKG, CLASS, "testCodeCacheRead");
- }
-
- private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
- public InstallMultiple() {
- super(getDevice(), mCtsBuild, mAbi);
- }
- }
-
- public static class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
- private final ITestDevice mDevice;
- private final CtsBuildHelper mBuild;
- private final IAbi mAbi;
-
- private final List<String> mArgs = new ArrayList<>();
- private final List<File> mApks = new ArrayList<>();
- private boolean mUseNaturalAbi;
-
- public BaseInstallMultiple(ITestDevice device, CtsBuildHelper build, IAbi abi) {
- mDevice = device;
- mBuild = build;
- mAbi = abi;
- addArg("-g");
- }
-
- T addArg(String arg) {
- mArgs.add(arg);
- return (T) this;
- }
-
- T addApk(String apk) throws FileNotFoundException {
- mApks.add(mBuild.getTestApp(apk));
- return (T) this;
- }
-
- T inheritFrom(String packageName) {
- addArg("-r");
- addArg("-p " + packageName);
- return (T) this;
- }
-
- T useNaturalAbi() {
- mUseNaturalAbi = true;
- return (T) this;
- }
-
- T locationAuto() {
- addArg("--install-location 0");
- return (T) this;
- }
-
- T locationInternalOnly() {
- addArg("--install-location 1");
- return (T) this;
- }
-
- T locationPreferExternal() {
- addArg("--install-location 2");
- return (T) this;
- }
-
- T forceUuid(String uuid) {
- addArg("--force-uuid " + uuid);
- return (T) this;
- }
-
- void run() throws DeviceNotAvailableException {
- run(true);
- }
-
- void runExpectingFailure() throws DeviceNotAvailableException {
- run(false);
- }
-
- private void run(boolean expectingSuccess) throws DeviceNotAvailableException {
- final ITestDevice device = mDevice;
-
- // Create an install session
- final StringBuilder cmd = new StringBuilder();
- cmd.append("pm install-create");
- for (String arg : mArgs) {
- cmd.append(' ').append(arg);
- }
- if (!mUseNaturalAbi) {
- cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
- }
-
- String result = device.executeShellCommand(cmd.toString());
- assertTrue(result, result.startsWith("Success"));
-
- final int start = result.lastIndexOf("[");
- final int end = result.lastIndexOf("]");
- int sessionId = -1;
- try {
- if (start != -1 && end != -1 && start < end) {
- sessionId = Integer.parseInt(result.substring(start + 1, end));
- }
- } catch (NumberFormatException e) {
- }
- if (sessionId == -1) {
- throw new IllegalStateException("Failed to create install session: " + result);
- }
-
- // Push our files into session. Ideally we'd use stdin streaming,
- // but ddmlib doesn't support it yet.
- for (int i = 0; i < mApks.size(); i++) {
- final File apk = mApks.get(i);
- final String remotePath = "/data/local/tmp/" + i + "_" + apk.getName();
- if (!device.pushFile(apk, remotePath)) {
- throw new IllegalStateException("Failed to push " + apk);
- }
-
- cmd.setLength(0);
- cmd.append("pm install-write");
- cmd.append(' ').append(sessionId);
- cmd.append(' ').append(i + "_" + apk.getName());
- cmd.append(' ').append(remotePath);
-
- result = device.executeShellCommand(cmd.toString());
- assertTrue(result, result.startsWith("Success"));
- }
-
- // Everything staged; let's pull trigger
- cmd.setLength(0);
- cmd.append("pm install-commit");
- cmd.append(' ').append(sessionId);
-
- result = device.executeShellCommand(cmd.toString());
- if (expectingSuccess) {
- assertTrue(result, result.startsWith("Success"));
- } else {
- assertFalse(result, result.startsWith("Success"));
- }
- }
- }
-
- public void runDeviceTests(String packageName, String testClassName, String testMethodName)
- throws DeviceNotAvailableException {
- Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
- }
-}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/Utils.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/Utils.java
deleted file mode 100644
index fdf84d3..0000000
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/Utils.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.cts.appsecurity;
-
-import com.android.ddmlib.Log;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
-import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.CollectingTestListener;
-
-import java.util.Map;
-
-public class Utils {
- private static final String TAG = "AppSecurity";
-
- public static final int USER_OWNER = 0;
-
- public static void runDeviceTests(ITestDevice device, String packageName)
- throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, null, null, USER_OWNER);
- }
-
- public static void runDeviceTests(ITestDevice device, String packageName, int userId)
- throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, null, null, userId);
- }
-
- public static void runDeviceTests(ITestDevice device, String packageName, String testClassName)
- throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, testClassName, null, USER_OWNER);
- }
-
- public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
- int userId) throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, testClassName, null, userId);
- }
-
- public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
- String testMethodName) throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, testClassName, testMethodName, USER_OWNER);
- }
-
- public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
- String testMethodName, int userId) throws DeviceNotAvailableException {
- if (testClassName != null && testClassName.startsWith(".")) {
- testClassName = packageName + testClassName;
- }
-
- RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName,
- "android.support.test.runner.AndroidJUnitRunner", device.getIDevice());
- if (testClassName != null && testMethodName != null) {
- testRunner.setMethodName(testClassName, testMethodName);
- } else if (testClassName != null) {
- testRunner.setClassName(testClassName);
- }
-
- if (userId != USER_OWNER) {
- // TODO: move this to RemoteAndroidTestRunner once it supports users
- testRunner.addInstrumentationArg("hack_key", "hack_value --user " + userId);
- }
-
- final CollectingTestListener listener = new CollectingTestListener();
- device.runInstrumentationTests(testRunner, listener);
-
- final TestRunResult result = listener.getCurrentRunResults();
- if (result.isRunFailure()) {
- throw new AssertionError("Failed to successfully run device tests for "
- + result.getName() + ": " + result.getRunFailureMessage());
- }
-
- if (result.hasFailedTests()) {
- // build a meaningful error message
- StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
- result.getTestResults().entrySet()) {
- if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
- errorBuilder.append(resultEntry.getKey().toString());
- errorBuilder.append(":\n");
- errorBuilder.append(resultEntry.getValue().getStackTrace());
- }
- }
- throw new AssertionError(errorBuilder.toString());
- }
- }
-
- private static boolean isMultiUserSupportedOnDevice(ITestDevice device)
- throws DeviceNotAvailableException {
- // TODO: move this to ITestDevice once it supports users
- final String output = device.executeShellCommand("pm get-max-users");
- try {
- return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim()) > 1;
- } catch (NumberFormatException e) {
- throw new AssertionError("Failed to parse result: " + output);
- }
- }
-
- /**
- * Return set of users that test should be run for, creating a secondary
- * user if the device supports it. Always call
- * {@link #removeUsersForTest(ITestDevice, int[])} when finished.
- */
- public static int[] createUsersForTest(ITestDevice device) throws DeviceNotAvailableException {
- if (isMultiUserSupportedOnDevice(device)) {
- return new int[] { USER_OWNER, createUserOnDevice(device) };
- } else {
- Log.d(TAG, "Single user device; skipping isolated storage tests");
- return new int[] { USER_OWNER };
- }
- }
-
- public static void removeUsersForTest(ITestDevice device, int[] users)
- throws DeviceNotAvailableException {
- for (int user : users) {
- if (user != USER_OWNER) {
- removeUserOnDevice(device, user);
- }
- }
- }
-
- private static int createUserOnDevice(ITestDevice device) throws DeviceNotAvailableException {
- // TODO: move this to ITestDevice once it supports users
- final String name = "CTS_" + System.currentTimeMillis();
- final String output = device.executeShellCommand("pm create-user " + name);
- if (output.startsWith("Success")) {
- try {
- final int userId = Integer.parseInt(
- output.substring(output.lastIndexOf(" ")).trim());
- device.executeShellCommand("am start-user " + userId);
- return userId;
- } catch (NumberFormatException e) {
- throw new AssertionError("Failed to parse result: " + output);
- }
- } else {
- throw new AssertionError("Failed to create user: " + output);
- }
- }
-
- private static void removeUserOnDevice(ITestDevice device, int userId)
- throws DeviceNotAvailableException {
- // TODO: move this to ITestDevice once it supports users
- final String output = device.executeShellCommand("pm remove-user " + userId);
- if (output.startsWith("Error")) {
- throw new AssertionError("Failed to remove user: " + output);
- }
- }
-
-}
diff --git a/hostsidetests/appsecurity/test-apps/Android.mk b/hostsidetests/appsecurity/test-apps/Android.mk
index f6091e4..ae48006 100644
--- a/hostsidetests/appsecurity/test-apps/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/Android.mk
@@ -16,6 +16,9 @@
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# Build the test APKs using their own makefiles
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk b/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk
index 4459e69..47323a3 100644
--- a/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsAppAccessData
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# although not strictly necessary, sign this app with different cert than CtsAppWithData
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
diff --git a/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java b/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
index 40d3cff..ba27114 100644
--- a/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
+++ b/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
@@ -18,17 +18,20 @@
import java.io.BufferedReader;
import java.io.DataInputStream;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.test.AndroidTestCase;
/**
* Test that another app's private data cannot be accessed, while its public data can.
*
- * Assumes that {@link APP_WITH_DATA_PKG} has already created the private and public data.
+ * Assumes that {@link #APP_WITH_DATA_PKG} has already created the private and public data.
*/
public class AccessPrivateDataTest extends AndroidTestCase {
@@ -39,12 +42,12 @@
/**
* Name of private file to access. This must match the name of the file created by
- * {@link APP_WITH_DATA_PKG}.
+ * {@link #APP_WITH_DATA_PKG}.
*/
private static final String PRIVATE_FILE_NAME = "private_file.txt";
/**
* Name of public file to access. This must match the name of the file created by
- * {@link APP_WITH_DATA_PKG}.
+ * {@link #APP_WITH_DATA_PKG}.
*/
private static final String PUBLIC_FILE_NAME = "public_file.txt";
@@ -56,20 +59,26 @@
public void testAccessPrivateData() throws IOException {
try {
// construct the absolute file path to the app's private file
- String privateFilePath = String.format("/data/data/%s/%s", APP_WITH_DATA_PKG,
- PRIVATE_FILE_NAME);
- FileInputStream inputStream = new FileInputStream(privateFilePath);
+ ApplicationInfo applicationInfo = getApplicationInfo(APP_WITH_DATA_PKG);
+ File privateFile = new File(applicationInfo.dataDir, "files/" + PRIVATE_FILE_NAME);
+ FileInputStream inputStream = new FileInputStream(privateFile);
inputStream.read();
inputStream.close();
fail("Was able to access another app's private data");
- } catch (FileNotFoundException e) {
+ } catch (FileNotFoundException | SecurityException e) {
// expected
- } catch (SecurityException e) {
- // also valid
}
accessPrivateTrafficStats();
}
+ private ApplicationInfo getApplicationInfo(String packageName) {
+ try {
+ return mContext.getPackageManager().getApplicationInfo(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalStateException("Expected package not found: " + e);
+ }
+ }
+
/**
* Tests that another app's public file can be accessed
* @throws IOException
@@ -86,10 +95,10 @@
private int getOtherAppUid() throws IOException, FileNotFoundException, SecurityException {
// construct the absolute file path to the other app's public file
- String publicFilePath = String.format("/data/data/%s/files/%s", APP_WITH_DATA_PKG,
- PUBLIC_FILE_NAME);
- DataInputStream inputStream = new DataInputStream(new FileInputStream(publicFilePath));
- int otherAppUid = (int)inputStream.readInt();
+ ApplicationInfo applicationInfo = getApplicationInfo(APP_WITH_DATA_PKG);
+ File publicFile = new File(applicationInfo.dataDir, "files/" + PUBLIC_FILE_NAME);
+ DataInputStream inputStream = new DataInputStream(new FileInputStream(publicFile));
+ int otherAppUid = inputStream.readInt();
inputStream.close();
return otherAppUid;
}
@@ -98,9 +107,7 @@
int otherAppUid = -1;
try {
otherAppUid = getOtherAppUid();
- } catch (FileNotFoundException e) {
- fail("Was not able to access another app's public file: " + e);
- } catch (SecurityException e) {
+ } catch (FileNotFoundException | SecurityException e) {
fail("Was not able to access another app's public file: " + e);
}
diff --git a/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk b/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk
index 0916254..df52f08 100644
--- a/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsAppWithData
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java b/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java
index e11681a..378ef42 100644
--- a/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java
+++ b/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java
@@ -24,8 +24,8 @@
import android.database.sqlite.SQLiteOpenHelper;
import android.net.TrafficStats;
import android.test.AndroidTestCase;
-import android.util.Log;
+import java.io.File;
import java.net.ServerSocket;
import java.net.Socket;
@@ -97,14 +97,11 @@
try {
// construct the absolute file path to the app's public's file the same
// way as the appaccessdata package will.
- String publicFilePath = String.format("/data/data/%s/files/%s", APP_WITH_DATA_PKG,
- PUBLIC_FILE_NAME);
- DataInputStream inputStream = new DataInputStream(new FileInputStream(publicFilePath));
- int otherAppUid = (int)inputStream.readInt();
+ File publicFile = new File(mContext.getFilesDir(), PUBLIC_FILE_NAME);
+ DataInputStream inputStream = new DataInputStream(new FileInputStream(publicFile));
+ inputStream.readInt();
inputStream.close();
- } catch (FileNotFoundException e) {
- fail("Was not able to access own public file: " + e);
- } catch (SecurityException e) {
+ } catch (FileNotFoundException | SecurityException e) {
fail("Was not able to access own public file: " + e);
}
}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk b/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk
index 272ef28..54c2cc2 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk
@@ -26,6 +26,9 @@
LOCAL_PACKAGE_NAME := CtsDocumentClient
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
index f308211..c2c4345 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
@@ -25,6 +25,7 @@
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsProvider;
+import android.support.test.uiautomator.Configurator;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
@@ -34,6 +35,7 @@
import android.test.MoreAsserts;
import android.text.format.DateUtils;
import android.util.Log;
+import android.view.MotionEvent;
import com.android.cts.documentclient.MyActivity.Result;
@@ -59,6 +61,8 @@
public void setUp() throws Exception {
super.setUp();
+ Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER);
+
mDevice = UiDevice.getInstance(getInstrumentation());
mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
MyActivity.class, null);
@@ -134,15 +138,24 @@
assertTrue("CtsCreate root", findRoot("CtsCreate").exists());
assertFalse("CtsGetContent root", findRoot("CtsGetContent").exists());
- // Pick a specific file from our test provider
+ // Choose the local root.
mDevice.waitForIdle();
findRoot("CtsLocal").click();
+ // Try picking a virtual file. Virtual files must not be returned for CATEGORY_OPENABLE
+ // though, so the click should be ignored.
+ mDevice.waitForIdle();
+ findDocument("VIRTUAL_FILE").click();
+ mDevice.waitForIdle();
+
+ // Pick a regular file.
mDevice.waitForIdle();
findDocument("FILE1").click();
+ // Confirm that the returned file is a regular file caused by the second click.
final Result result = mActivity.getResult();
final Uri uri = result.data.getData();
+ assertEquals("doc:file1", DocumentsContract.getDocumentId(uri));
// We should now have permission to read/write
MoreAsserts.assertEquals("fileone".getBytes(), readFully(uri));
@@ -152,6 +165,26 @@
MoreAsserts.assertEquals("replaced!".getBytes(), readFully(uri));
}
+ public void testOpenVirtual() throws Exception {
+ if (!supportedHardware()) return;
+
+ final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.setType("*/*");
+ mActivity.startActivityForResult(intent, 42);
+
+ // Pick a virtual file from the local root.
+ mDevice.waitForIdle();
+ findRoot("CtsLocal").click();
+
+ mDevice.waitForIdle();
+ findDocument("VIRTUAL_FILE").click();
+
+ // Confirm that the returned file is actually the selected one.
+ final Result result = mActivity.getResult();
+ final Uri uri = result.data.getData();
+ assertEquals("virtual-file", DocumentsContract.getDocumentId(uri));
+ }
+
public void testCreateNew() throws Exception {
if (!supportedHardware()) return;
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk
index bbf7734..84a1665 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk
@@ -26,6 +26,9 @@
LOCAL_PACKAGE_NAME := CtsDocumentProvider
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
index 9d38a94..ab7696f 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
@@ -124,6 +124,13 @@
mCreateRoot.children.add(file2);
}
+ {
+ Doc virtualFile = buildDoc("doc:virtual-file", "VIRTUAL_FILE", "application/icecream");
+ virtualFile.flags = Document.FLAG_VIRTUAL_DOCUMENT;
+ mLocalRoot.children.add(virtualFile);
+ mCreateRoot.children.add(virtualFile);
+ }
+
Doc dir1 = buildDoc("doc:dir1", "DIR1", Document.MIME_TYPE_DIR);
mLocalRoot.children.add(dir1);
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/Android.mk b/hostsidetests/appsecurity/test-apps/EncryptionApp/Android.mk
new file mode 100644
index 0000000..aba23d5
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/Android.mk
@@ -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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsEncryptionApp
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml
new file mode 100644
index 0000000..824e285
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml
@@ -0,0 +1,57 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.encryptionapp">
+
+ <application android:label="EncryptionApp">
+ <activity android:name=".UnawareActivity"
+ android:exported="true"/>
+
+ <receiver android:name=".UnawareReceiver"
+ android:exported="true" />
+
+ <service android:name=".UnawareService"
+ android:exported="true" />
+
+ <provider android:name=".UnawareProvider"
+ android:authorities="com.android.cts.encryptionapp.unaware"
+ android:exported="true" />
+
+ <activity android:name=".AwareActivity"
+ android:encryptionAware="true"
+ android:exported="true" />
+
+ <receiver android:name=".AwareReceiver"
+ android:encryptionAware="true"
+ android:exported="true" />
+
+ <service android:name=".AwareService"
+ android:encryptionAware="true"
+ android:exported="true" />
+
+ <provider android:name=".AwareProvider"
+ android:authorities="com.android.cts.encryptionapp.aware"
+ android:encryptionAware="true"
+ android:exported="true" />
+
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.encryptionapp" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareActivity.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareActivity.java
new file mode 100644
index 0000000..a312a5b
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareActivity.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 com.android.cts.encryptionapp;
+
+import static com.android.cts.encryptionapp.EncryptionApp.AWARE;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+public class AwareActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.v(AWARE, "Activity.onCreate()");
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareProvider.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareProvider.java
new file mode 100644
index 0000000..e8807cd
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareProvider.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 com.android.cts.encryptionapp;
+
+import static com.android.cts.encryptionapp.EncryptionApp.AWARE;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.util.Log;
+
+public class AwareProvider extends ContentProvider {
+ @Override
+ public boolean onCreate() {
+ Log.v(AWARE, "ContentProvider.onCreate()");
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareReceiver.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareReceiver.java
new file mode 100644
index 0000000..1ffefa0
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareReceiver.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 com.android.cts.encryptionapp;
+
+import static com.android.cts.encryptionapp.EncryptionApp.AWARE;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class AwareReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.v(AWARE, "BroadcastReceiver.onReceive()");
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareService.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareService.java
new file mode 100644
index 0000000..60f1189
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/AwareService.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.cts.encryptionapp;
+
+import static com.android.cts.encryptionapp.EncryptionApp.AWARE;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.util.Log;
+
+public class AwareService extends IntentService {
+ public AwareService() {
+ super(AWARE);
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ Log.v(AWARE, "IntentService.onHandleIntent()");
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionApp.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionApp.java
new file mode 100644
index 0000000..238f4e8
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionApp.java
@@ -0,0 +1,30 @@
+/*
+ * 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 com.android.cts.encryptionapp;
+
+import android.app.Application;
+import android.util.Log;
+
+public class EncryptionApp extends Application {
+ static final String AWARE = "Aware";
+ static final String UNAWARE = "Unaware";
+
+ @Override
+ public void onCreate() {
+ Log.v(AWARE, "Application.onCreate()");
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
new file mode 100644
index 0000000..1e161f8
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
@@ -0,0 +1,23 @@
+/*
+ * 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 com.android.cts.encryptionapp;
+
+import android.test.AndroidTestCase;
+
+public class EncryptionAppTest extends AndroidTestCase {
+ private static final String TAG = "EncryptionAppTest";
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareActivity.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareActivity.java
new file mode 100644
index 0000000..e596741
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareActivity.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 com.android.cts.encryptionapp;
+
+import static com.android.cts.encryptionapp.EncryptionApp.UNAWARE;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+public class UnawareActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.v(UNAWARE, "Activity.onCreate()");
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareProvider.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareProvider.java
new file mode 100644
index 0000000..2aae88d
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareProvider.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 com.android.cts.encryptionapp;
+
+import static com.android.cts.encryptionapp.EncryptionApp.UNAWARE;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.util.Log;
+
+public class UnawareProvider extends ContentProvider {
+ @Override
+ public boolean onCreate() {
+ Log.v(UNAWARE, "ContentProvider.onCreate()");
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareReceiver.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareReceiver.java
new file mode 100644
index 0000000..80a8485
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareReceiver.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 com.android.cts.encryptionapp;
+
+import static com.android.cts.encryptionapp.EncryptionApp.UNAWARE;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class UnawareReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.v(UNAWARE, "BroadcastReceiver.onReceive()");
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareService.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareService.java
new file mode 100644
index 0000000..d32654c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/UnawareService.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.cts.encryptionapp;
+
+import static com.android.cts.encryptionapp.EncryptionApp.UNAWARE;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.util.Log;
+
+public class UnawareService extends IntentService {
+ public UnawareService() {
+ super(UNAWARE);
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ Log.v(UNAWARE, "IntentService.onHandleIntent()");
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
index a7de92a..bbe351a 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
@@ -23,6 +23,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CtsExternalStorageApp
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_DEX_PREOPT := false
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
index 7fe0b80..4bd494d 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
@@ -149,6 +149,22 @@
return paths;
}
+ /**
+ * Return a set of several package-specific external storage paths pointing
+ * at "gift" files designed to be exchanged with the target package.
+ */
+ public static List<File> getAllPackageSpecificGiftPaths(Context context,
+ String targetPackageName) {
+ final List<File> files = getAllPackageSpecificPaths(context);
+ final List<File> targetFiles = new ArrayList<>();
+ for (File file : files) {
+ final File targetFile = new File(
+ file.getAbsolutePath().replace(context.getPackageName(), targetPackageName));
+ targetFiles.add(new File(targetFile, targetPackageName + ".gift"));
+ }
+ return targetFiles;
+ }
+
public static List<File> getPrimaryPackageSpecificPaths(Context context) {
final List<File> paths = new ArrayList<File>();
Collections.addAll(paths, context.getExternalCacheDir());
@@ -189,12 +205,6 @@
return after;
}
- public static File buildGiftForPackage(Context context, String packageName) {
- final File myCache = context.getExternalCacheDir();
- return new File(myCache.getAbsolutePath().replace(context.getPackageName(), packageName),
- packageName + ".gift");
- }
-
public static File buildProbeFile(File dir) {
return new File(dir, ".probe_" + System.nanoTime());
}
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/GiftTest.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/GiftTest.java
index e482b2f..14a0180 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/GiftTest.java
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/GiftTest.java
@@ -21,26 +21,33 @@
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.PACKAGE_WRITE;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertFileNoAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertFileReadWriteAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.buildGiftForPackage;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificGiftPaths;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.readInt;
import android.test.AndroidTestCase;
import java.io.File;
+import java.util.List;
public class GiftTest extends AndroidTestCase {
/**
* Verify we can read only our gifts.
*/
public void testGifts() throws Exception {
- final File none = buildGiftForPackage(getContext(), PACKAGE_NONE);
- assertFileReadWriteAccess(none);
- assertEquals(100, readInt(none));
+ final List<File> noneList = getAllPackageSpecificGiftPaths(getContext(), PACKAGE_NONE);
+ for (File none : noneList) {
+ assertFileReadWriteAccess(none);
+ assertEquals(100, readInt(none));
+ }
- final File read = buildGiftForPackage(getContext(), PACKAGE_READ);
- assertFileNoAccess(read);
+ final List<File> readList = getAllPackageSpecificGiftPaths(getContext(), PACKAGE_READ);
+ for (File read : readList) {
+ assertFileNoAccess(read);
+ }
- final File write = buildGiftForPackage(getContext(), PACKAGE_WRITE);
- assertFileNoAccess(write);
+ final List<File> writeList = getAllPackageSpecificGiftPaths(getContext(), PACKAGE_WRITE);
+ for (File write : writeList) {
+ assertFileNoAccess(write);
+ }
}
}
diff --git a/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk
index 4c64204..717d9f9 100644
--- a/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsInstrumentationAppDiffCert
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# sign this app with different cert than CtsTargetInstrumentationApp
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
diff --git a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.mk
index c37d052..270dac8 100644
--- a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsMultiUserStorageApp
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_DEX_PREOPT := false
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
index 43d3547..2c67bdc 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsPermissionDeclareApp
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# sign this app with a different cert than CtsUsePermissionDiffCert
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
index 5109c99..af051a0 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsPermissionDeclareAppCompat
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# sign this app with a different cert than CtsUsePermissionDiffCert
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
diff --git a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.mk
index c662d39..73cb625 100644
--- a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsReadExternalStorageApp
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_DEX_PREOPT := false
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/src/com/android/cts/readexternalstorageapp/ReadGiftTest.java b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/src/com/android/cts/readexternalstorageapp/ReadGiftTest.java
index e72be77..78bb738 100644
--- a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/src/com/android/cts/readexternalstorageapp/ReadGiftTest.java
+++ b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/src/com/android/cts/readexternalstorageapp/ReadGiftTest.java
@@ -21,28 +21,35 @@
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.PACKAGE_WRITE;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertFileReadOnlyAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertFileReadWriteAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.buildGiftForPackage;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificGiftPaths;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.readInt;
import android.test.AndroidTestCase;
import java.io.File;
+import java.util.List;
public class ReadGiftTest extends AndroidTestCase {
/**
* Verify we can read all gifts.
*/
public void testGifts() throws Exception {
- final File none = buildGiftForPackage(getContext(), PACKAGE_NONE);
- assertFileReadOnlyAccess(none);
- assertEquals(100, readInt(none));
+ final List<File> noneList = getAllPackageSpecificGiftPaths(getContext(), PACKAGE_NONE);
+ for (File none : noneList) {
+ assertFileReadOnlyAccess(none);
+ assertEquals(100, readInt(none));
+ }
- final File read = buildGiftForPackage(getContext(), PACKAGE_READ);
- assertFileReadWriteAccess(read);
- assertEquals(101, readInt(read));
+ final List<File> readList = getAllPackageSpecificGiftPaths(getContext(), PACKAGE_READ);
+ for (File read : readList) {
+ assertFileReadWriteAccess(read);
+ assertEquals(101, readInt(read));
+ }
- final File write = buildGiftForPackage(getContext(), PACKAGE_WRITE);
- assertFileReadOnlyAccess(write);
- assertEquals(102, readInt(write));
+ final List<File> writeList = getAllPackageSpecificGiftPaths(getContext(), PACKAGE_WRITE);
+ for (File write : writeList) {
+ assertFileReadOnlyAccess(write);
+ assertEquals(102, readInt(write));
+ }
}
}
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk b/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk
index 05438ef..f1f6efe 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsSharedUidInstall
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# sign this app with a different cert than CtsSharedUidInstallDiffCert
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk
index eaed910..937a8aa 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsSharedUidInstallDiffCert
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# sign this app with a different cert than CtsSharedUidInstall
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk
index 01cffdb..8ba76b6 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsSimpleAppInstall
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# sign this app with a different cert than CtsSimpleAppInstallDiffCert
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk
index 032ef57..17707ee 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsSimpleAppInstallDiffCert
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# sign this app with a different cert than CtsSimpleAppInstall
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
index de46dea..3dd25da 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
@@ -27,6 +27,9 @@
LOCAL_PACKAGE_NAME := CtsSplitApp
LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4 v7 fr de
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
@@ -52,6 +55,9 @@
LOCAL_PACKAGE_NAME := CtsSplitAppDiffRevision
LOCAL_PACKAGE_SPLITS := v7
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MANIFEST_FILE := revision/AndroidManifest.xml
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundredRevisionTwelve --replace-version
@@ -76,6 +82,9 @@
LOCAL_PACKAGE_NAME := CtsSplitAppDiffVersion
LOCAL_PACKAGE_SPLITS := v7
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 101 --version-name OneHundredOne --replace-version
@@ -99,6 +108,9 @@
LOCAL_PACKAGE_NAME := CtsSplitAppDiffCert
LOCAL_PACKAGE_SPLITS := v7
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundred --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
index fbb7764..e6ea9cf 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
@@ -28,6 +28,9 @@
LOCAL_MODULE_TAGS := tests
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
featureOf := CtsSplitApp
featureOfApk := $(call intermediates-dir-for,APPS,$(featureOf))/package.apk
localRStamp := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)/src/R.stamp
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk
index 507b13a..9989ce3 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk
@@ -23,4 +23,7 @@
LOCAL_LDLIBS += -llog
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk
index 5053e7d..ba2da56 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk
@@ -1 +1,15 @@
+# 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.
+
include $(call all-subdir-makefiles)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
index 9faaba1..f322622 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
@@ -22,6 +22,9 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
index 87b32aa..bbdc18b 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
@@ -22,6 +22,9 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
index fe289e0..f10c843 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
@@ -22,6 +22,9 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
index d66d674..fdd2129 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
@@ -22,6 +22,9 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
index 7232324..8c58c0d 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
@@ -22,6 +22,9 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
index f1cd994..fe60583 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
@@ -22,6 +22,9 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
index 521f6f2..32f28db 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
@@ -22,6 +22,9 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk b/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk
index f5ac52f..3300cc3 100644
--- a/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk
@@ -25,6 +25,9 @@
LOCAL_PACKAGE_NAME := CtsTargetInstrumentationApp
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# sign this app with different cert than CtsInstrumentationAppDiffCert
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
index f91d0c4..0842ea3 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
@@ -27,6 +27,9 @@
LOCAL_PACKAGE_NAME := CtsUsePermissionApp
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/Android.mk
index 70b4b0f..45b97c0 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/Android.mk
@@ -27,6 +27,9 @@
LOCAL_PACKAGE_NAME := CtsUsePermissionAppCompat
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
index 6e0d090..966aded 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
@@ -26,6 +26,9 @@
LOCAL_PACKAGE_NAME := CtsUsePermissionDiffCert
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# sign this app with a different cert than CtsPermissionDeclareApp
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
index cdd77e8..53daf9a 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
@@ -23,6 +23,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsWriteExternalStorageApp
LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
index 3861ddf..ea6c0ea 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
@@ -16,6 +16,7 @@
package com.android.cts.writeexternalstorageapp;
+import static android.test.MoreAsserts.assertNotEqual;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.PACKAGE_NONE;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.TAG;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoWriteAccess;
@@ -31,7 +32,10 @@
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.writeInt;
import android.os.Environment;
+import android.os.SystemClock;
+import android.system.Os;
import android.test.AndroidTestCase;
+import android.text.format.DateUtils;
import android.util.Log;
import com.android.cts.externalstorageapp.CommonExternalStorageTest;
@@ -297,4 +301,29 @@
}
}
}
+
+ /**
+ * Verify that moving around package-specific directories causes permissions
+ * to be updated.
+ */
+ public void testMovePackageSpecificPaths() throws Exception {
+ final File before = getContext().getExternalCacheDir();
+ final File beforeFile = new File(before, "test.probe");
+ assertTrue(beforeFile.createNewFile());
+ assertEquals(Os.getuid(), Os.stat(before.getAbsolutePath()).st_uid);
+ assertEquals(Os.getuid(), Os.stat(beforeFile.getAbsolutePath()).st_uid);
+
+ final File after = new File(before.getAbsolutePath()
+ .replace(getContext().getPackageName(), "com.example.does.not.exist"));
+ after.getParentFile().mkdirs();
+
+ Os.rename(before.getAbsolutePath(), after.getAbsolutePath());
+
+ // Sit around long enough for VFS cache to expire
+ SystemClock.sleep(15 * DateUtils.SECOND_IN_MILLIS);
+
+ final File afterFile = new File(after, "test.probe");
+ assertNotEqual(Os.getuid(), Os.stat(after.getAbsolutePath()).st_uid);
+ assertNotEqual(Os.getuid(), Os.stat(afterFile.getAbsolutePath()).st_uid);
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteGiftTest.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteGiftTest.java
index 5da42da..db3813f 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteGiftTest.java
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteGiftTest.java
@@ -20,41 +20,48 @@
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.PACKAGE_READ;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.PACKAGE_WRITE;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertFileReadWriteAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.buildGiftForPackage;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificGiftPaths;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.readInt;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.writeInt;
import android.test.AndroidTestCase;
import java.io.File;
+import java.util.List;
public class WriteGiftTest extends AndroidTestCase {
/**
* Leave gifts for other packages in their primary external cache dirs.
*/
public void testGifts() throws Exception {
- final File none = buildGiftForPackage(getContext(), PACKAGE_NONE);
- none.getParentFile().mkdirs();
- none.createNewFile();
- assertFileReadWriteAccess(none);
+ final List<File> noneList = getAllPackageSpecificGiftPaths(getContext(), PACKAGE_NONE);
+ for (File none : noneList) {
+ none.getParentFile().mkdirs();
+ none.createNewFile();
+ assertFileReadWriteAccess(none);
- writeInt(none, 100);
- assertEquals(100, readInt(none));
+ writeInt(none, 100);
+ assertEquals(100, readInt(none));
+ }
- final File read = buildGiftForPackage(getContext(), PACKAGE_READ);
- read.getParentFile().mkdirs();
- read.createNewFile();
- assertFileReadWriteAccess(read);
+ final List<File> readList = getAllPackageSpecificGiftPaths(getContext(), PACKAGE_READ);
+ for (File read : readList) {
+ read.getParentFile().mkdirs();
+ read.createNewFile();
+ assertFileReadWriteAccess(read);
- writeInt(read, 101);
- assertEquals(101, readInt(read));
+ writeInt(read, 101);
+ assertEquals(101, readInt(read));
+ }
- final File write = buildGiftForPackage(getContext(), PACKAGE_WRITE);
- write.getParentFile().mkdirs();
- write.createNewFile();
- assertFileReadWriteAccess(write);
+ final List<File> writeList = getAllPackageSpecificGiftPaths(getContext(), PACKAGE_WRITE);
+ for (File write : writeList) {
+ write.getParentFile().mkdirs();
+ write.createNewFile();
+ assertFileReadWriteAccess(write);
- writeInt(write, 102);
- assertEquals(102, readInt(write));
+ writeInt(write, 102);
+ assertEquals(102, readInt(write));
+ }
}
}
diff --git a/hostsidetests/appsecurity/test-apps/keysets/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/Android.mk
index 935fa95..7193868 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/Android.mk
@@ -16,6 +16,9 @@
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# Build the test APKs using their own makefiles
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/appsecurity/test-apps/keysets/malBadKey/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/malBadKey/Android.mk
index 207160f..f1cf063 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/malBadKey/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/malBadKey/Android.mk
@@ -17,6 +17,9 @@
#apks signed cts-keyset-test-a
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
diff --git a/hostsidetests/appsecurity/test-apps/keysets/malNoDef/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/malNoDef/Android.mk
index 84f3f75..ed8fdb8 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/malNoDef/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/malNoDef/Android.mk
@@ -17,6 +17,9 @@
#apks signed cts-keyset-test-a
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
diff --git a/hostsidetests/appsecurity/test-apps/keysets/malOneDef/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/malOneDef/Android.mk
index 7290f06..d539925 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/malOneDef/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/malOneDef/Android.mk
@@ -17,6 +17,9 @@
#apks signed cts-keyset-test-a
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk
index f5a7286..6f60a7a 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk
@@ -23,6 +23,8 @@
LOCAL_PACKAGE_NAME := CtsKeySetPermDefSigningA
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_SUPPORT_PACKAGE)
@@ -35,5 +37,7 @@
LOCAL_PACKAGE_NAME := CtsKeySetPermDefSigningB
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk
index 678d89d..e9db2a8 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk
@@ -24,6 +24,9 @@
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
#apks signed cts-keyset-test-b
@@ -36,4 +39,7 @@
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk
index b8acc99..d8f43f7 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk
@@ -16,6 +16,9 @@
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk
index 79d053b..7f00bb3 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk
@@ -16,13 +16,14 @@
#apks signed by cts-keyset-test-a
include $(CLEAR_VARS)
-
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeA
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_SUPPORT_PACKAGE)
@@ -34,24 +35,26 @@
LOCAL_PACKAGE_NAME := CtsKeySetSigningBUpgradeA
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_SUPPORT_PACKAGE)
#apks signed by cts-keyset-test-ec-a
include $(CLEAR_VARS)
-
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
LOCAL_PACKAGE_NAME := CtsKeySetSigningEcAUpgradeA
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-ec-a
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_SUPPORT_PACKAGE)
#apks signed by cts-keyset-test-a and cts-keyset-test-b
include $(CLEAR_VARS)
-
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
@@ -59,4 +62,7 @@
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
LOCAL_ADDITIONAL_CERTIFICATES := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk
index 406529c..6b27445 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk
@@ -17,6 +17,9 @@
#apks signed cts-keyset-test-a
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk
index 23d6b17..b6b230c 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk
@@ -17,6 +17,9 @@
#apks signed cts-keyset-test-a
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk
index f2cedf9..cb1a6a0 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk
@@ -24,6 +24,9 @@
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
#apks signed cts-keyset-test-b
@@ -36,6 +39,9 @@
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
#apks signed by cts-keyset-test-a and cts-keyset-test-c
@@ -49,4 +55,7 @@
LOCAL_ADDITIONAL_CERTIFICATES := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uBsharedUser/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uBsharedUser/Android.mk
index 1d6d5a5..5e56d12 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/uBsharedUser/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/uBsharedUser/Android.mk
@@ -24,6 +24,9 @@
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
#apks signed cts-keyset-test-b
@@ -36,4 +39,7 @@
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uEcA/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uEcA/Android.mk
index 3d0109a..ddc0012 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/uEcA/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/uEcA/Android.mk
@@ -17,6 +17,9 @@
#apks signed by cts-keyset-test-a
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk
index 9b327fe..4e383de 100644
--- a/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk
@@ -17,6 +17,9 @@
#apks signed cts-keyset-test-a
include $(CLEAR_VARS)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
diff --git a/hostsidetests/atrace/Android.mk b/hostsidetests/atrace/Android.mk
index 1fd7102..e2dbaba 100644
--- a/hostsidetests/atrace/Android.mk
+++ b/hostsidetests/atrace/Android.mk
@@ -21,10 +21,15 @@
# Must match the package name in CtsTestCaseList.mk
LOCAL_MODULE := CtsAtraceHostTestCases
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed_v2 compatibility-host-util tradefed-prebuilt
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
LOCAL_CTS_TEST_PACKAGE := android.host.atrace
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/atrace/AndroidTest.xml b/hostsidetests/atrace/AndroidTest.xml
new file mode 100644
index 0000000..b8aeb31
--- /dev/null
+++ b/hostsidetests/atrace/AndroidTest.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<configuration description="Config for CTS atrace host test cases">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsAtraceHostTestCases.jar" />
+ </test>
+</configuration>
diff --git a/hostsidetests/atrace/AtraceTestApp/Android.mk b/hostsidetests/atrace/AtraceTestApp/Android.mk
index 0eb7cfd..bbb79ee 100644
--- a/hostsidetests/atrace/AtraceTestApp/Android.mk
+++ b/hostsidetests/atrace/AtraceTestApp/Android.mk
@@ -30,4 +30,7 @@
#LOCAL_DEX_PREOPT := false
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
index 760723e..5f5ebe1 100644
--- a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
+++ b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
@@ -16,7 +16,7 @@
package android.atrace.cts;
-import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.migration.MigrationHelper;
import com.android.ddmlib.Log;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
@@ -118,14 +118,14 @@
}
}
- private CtsBuildHelper mCtsBuild;
+ private IBuildInfo mCtsBuild;
/**
* {@inheritDoc}
*/
@Override
public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ mCtsBuild = buildInfo;
}
// Collection of all userspace tags, and 'sched'
@@ -201,7 +201,7 @@
getDevice().uninstallPackage(TEST_PKG);
// install the test app
- File testAppFile = mCtsBuild.getTestApp(TEST_APK);
+ File testAppFile = MigrationHelper.getTestFile(mCtsBuild, TEST_APK);
String installResult = getDevice().installPackage(testAppFile, false);
assertNull(
String.format("failed to install atrace test app. Reason: %s", installResult),
diff --git a/hostsidetests/devicepolicy/Android.mk b/hostsidetests/devicepolicy/Android.mk
index dc5e117..ad0d6e1 100644
--- a/hostsidetests/devicepolicy/Android.mk
+++ b/hostsidetests/devicepolicy/Android.mk
@@ -22,11 +22,14 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := tradefed-prebuilt tools-common-prebuilt cts-tradefed
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt tools-common-prebuilt cts-tradefed_v2
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
LOCAL_CTS_TEST_PACKAGE := android.adminhostside
-cts_runtime_hint := 70
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/devicepolicy/AndroidTest.xml b/hostsidetests/devicepolicy/AndroidTest.xml
new file mode 100644
index 0000000..48b3b5b
--- /dev/null
+++ b/hostsidetests/devicepolicy/AndroidTest.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<configuration description="Config for the CTS Device Policy host tests">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsDevicePolicyManagerTestCases.jar" />
+ <option name="runtime-hint" value="31m41s" />
+ </test>
+</configuration>
diff --git a/hostsidetests/devicepolicy/app/AccountManagement/Android.mk b/hostsidetests/devicepolicy/app/AccountManagement/Android.mk
new file mode 100644
index 0000000..eddf8a7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountManagement/Android.mk
@@ -0,0 +1,34 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsAccountManagementDevicePolicyApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctstestrunner ub-uiautomator android-support-test
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/AccountManagement/AndroidManifest.xml b/hostsidetests/devicepolicy/app/AccountManagement/AndroidManifest.xml
new file mode 100644
index 0000000..4ed02a6
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountManagement/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.devicepolicy.accountmanagement">
+
+ <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+ <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+
+ <application>
+ <service android:name=".MockAccountService" android:exported="true">
+ <intent-filter>
+ <action android:name="android.accounts.AccountAuthenticator" />
+ </intent-filter>
+
+ <meta-data android:name="android.accounts.AccountAuthenticator"
+ android:resource="@xml/authenticator" />
+ </service>
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.devicepolicy.accountmanagement"
+ android:label="Account policy CTS Tests" />
+</manifest>
+
diff --git a/hostsidetests/devicepolicy/app/AccountManagement/res/values/strings.xml b/hostsidetests/devicepolicy/app/AccountManagement/res/values/strings.xml
new file mode 100644
index 0000000..dc8bc5d
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountManagement/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Label for this package -->
+ <string name="authenticator_label">DevicePolicy mock account</string>
+</resources>
diff --git a/hostsidetests/devicepolicy/app/AccountManagement/res/xml/authenticator.xml b/hostsidetests/devicepolicy/app/AccountManagement/res/xml/authenticator.xml
new file mode 100644
index 0000000..9c82b80
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountManagement/res/xml/authenticator.xml
@@ -0,0 +1,22 @@
+<!-- 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.
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- for the Account Manager. -->
+
+<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="com.android.cts.devicepolicy.accountmanagement.account.type"
+ android:label="@string/authenticator_label"
+/>
diff --git a/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/AccountManagementTest.java b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/AccountManagementTest.java
new file mode 100644
index 0000000..f91366a
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/AccountManagementTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.devicepolicy.accountmanagement;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.content.Context;
+import android.os.Bundle;
+import android.test.AndroidTestCase;
+
+import java.io.IOException;
+
+/**
+ * Functionality tests for
+ * {@link android.app.admin.DevicePolicyManager#setAccountManagementDisabled}
+ * and (@link android.os.UserManager#DISALLOW_MODIFY_ACCOUNTS}
+ *
+ * This test depend on {@link MockAccountService}, which provides authenticator of type
+ * {@link MockAccountService#ACCOUNT_TYPE}.
+ */
+public class AccountManagementTest extends AndroidTestCase {
+
+ // Account type for MockAccountAuthenticator
+ private final static Account ACCOUNT = new Account("user0",
+ MockAccountAuthenticator.ACCOUNT_TYPE);
+
+ private AccountManager mAccountManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mAccountManager = (AccountManager) mContext.getSystemService(Context.ACCOUNT_SERVICE);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mAccountManager.removeAccountExplicitly(ACCOUNT);
+ assertEquals(0, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ super.tearDown();
+ }
+
+ public void testAddAccount_blocked() throws AuthenticatorException,
+ IOException, OperationCanceledException {
+ assertEquals(0, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ // Management is disabled, adding account should fail.
+ try {
+ mAccountManager.addAccount(MockAccountAuthenticator.ACCOUNT_TYPE,
+ null, null, null, null, null, null).getResult();
+ fail("Expected OperationCanceledException is not thrown.");
+ } catch (OperationCanceledException e) {
+ // Expected
+ }
+ assertEquals(0, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ }
+
+ public void testAddAccount_allowed() throws Exception {
+ Bundle result = mAccountManager.addAccount(MockAccountAuthenticator.ACCOUNT_TYPE,
+ null, null, null, null, null, null).getResult();
+
+ // Normally the expected result of addAccount() is AccountManager returning
+ // an intent to start the authenticator activity for adding new accounts.
+ // But MockAccountAuthenticator returns a new account straightway.
+ assertEquals(MockAccountAuthenticator.ACCOUNT_TYPE,
+ result.getString(AccountManager.KEY_ACCOUNT_TYPE));
+ }
+
+ public void testRemoveAccount_blocked() throws AuthenticatorException,
+ IOException, OperationCanceledException {
+ assertEquals(0, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ // First prepare some accounts by manually adding them,
+ // setAccountManagementDisabled(true) should not stop addAccountExplicitly().
+ assertTrue(mAccountManager.addAccountExplicitly(ACCOUNT, "password", null));
+ assertEquals(1, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+
+ // Removing account should fail, as we just disabled it.
+ try {
+ mAccountManager.removeAccount(ACCOUNT, null, null).getResult();
+ fail("Expected OperationCanceledException is not thrown.");
+ } catch (OperationCanceledException e) {
+ // Expected
+ }
+ // Make sure the removal actually fails.
+ Account[] accounts = mAccountManager.getAccountsByType(
+ MockAccountAuthenticator.ACCOUNT_TYPE);
+ assertEquals(1, accounts.length);
+ assertEquals(ACCOUNT, accounts[0]);
+ }
+
+ public void testRemoveAccount_allowed() throws Exception {
+ assertEquals(0, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ // First prepare some accounts by manually adding them,
+ // setAccountManagementDisabled(true) should not stop addAccountExplicitly().
+ assertTrue(mAccountManager.addAccountExplicitly(ACCOUNT, "password", null));
+ assertEquals(1, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ assertTrue(mAccountManager.removeAccount(ACCOUNT, null, null).getResult());
+
+ // Make sure the removal actually succeeded.
+ assertEquals(0, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/AccountUtilsTest.java b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/AccountUtilsTest.java
new file mode 100644
index 0000000..69945a6
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/AccountUtilsTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.devicepolicy.accountmanagement;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.content.Context;
+import android.os.Bundle;
+import android.test.AndroidTestCase;
+
+import java.io.IOException;
+
+/**
+ * Functionality tests for
+ * {@link android.app.admin.DevicePolicyManager#setAccountManagementDisabled}
+ * and (@link android.os.UserManager#DISALLOW_MODIFY_ACCOUNTS}
+ *
+ * This test depends on {@link MockAccountService}, which provides authenticator of type
+ * {@link MockAccountService#ACCOUNT_TYPE}.
+ */
+public class AccountUtilsTest extends AndroidTestCase {
+
+ // Account type for MockAccountAuthenticator
+ private final static Account ACCOUNT = new Account("user0",
+ MockAccountAuthenticator.ACCOUNT_TYPE);
+
+ private AccountManager mAccountManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mAccountManager = (AccountManager) mContext.getSystemService(Context.ACCOUNT_SERVICE);
+ }
+
+ public void testAddAccountExplicitly() throws Exception {
+ assertEquals(0, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ assertTrue(mAccountManager.addAccountExplicitly(ACCOUNT, "password", null));
+ assertEquals(1, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ }
+
+ public void testRemoveAccountExplicitly() throws Exception {
+ assertEquals(1, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ mAccountManager.removeAccountExplicitly(ACCOUNT);
+ assertEquals(0, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
+ .length);
+ }
+}
+
diff --git a/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountAuthenticator.java b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountAuthenticator.java
new file mode 100644
index 0000000..0ef310b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountAuthenticator.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.devicepolicy.accountmanagement;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.accounts.NetworkErrorException;
+import android.content.Context;
+import android.os.Bundle;
+
+/* package */ class MockAccountAuthenticator extends AbstractAccountAuthenticator {
+ private static MockAccountAuthenticator sMockAuthenticator = null;
+ private static final String ACCOUNT_NAME
+ = "com.android.cts.devicepolicy.accountmanagement.account.name";
+ static final String ACCOUNT_TYPE
+ = "com.android.cts.devicepolicy.accountmanagement.account.type";
+ private static final String AUTH_TOKEN = "mockAuthToken";
+ private static final String AUTH_TOKEN_LABEL = "mockAuthTokenLabel";
+
+ private MockAccountAuthenticator(Context context) {
+ super(context);
+ }
+
+ private Bundle createResultBundle() {
+ Bundle result = new Bundle();
+ result.putString(AccountManager.KEY_ACCOUNT_NAME, ACCOUNT_NAME);
+ result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
+ result.putString(AccountManager.KEY_AUTHTOKEN, AUTH_TOKEN);
+
+ return result;
+ }
+
+ @Override
+ public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
+ String authTokenType, String[] requiredFeatures, Bundle options)
+ throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
+ String authTokenType, Bundle options) throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
+ Bundle options) throws NetworkErrorException {
+
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+ return result;
+ }
+
+ @Override
+ public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
+ String authTokenType, Bundle options) throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public String getAuthTokenLabel(String authTokenType) {
+ return AUTH_TOKEN_LABEL;
+ }
+
+ @Override
+ public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
+ String[] features) throws NetworkErrorException {
+
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+ return result;
+ }
+
+ public static synchronized MockAccountAuthenticator getMockAuthenticator(Context context) {
+ if (null == sMockAuthenticator) {
+ sMockAuthenticator = new MockAccountAuthenticator(context);
+ }
+ return sMockAuthenticator;
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountService.java b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountService.java
new file mode 100644
index 0000000..ace585b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountService.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.devicepolicy.accountmanagement;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * Service for wrapping the {@link MockAccountAuthenticator}
+ */
+public class MockAccountService extends Service {
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return MockAccountAuthenticator.getMockAuthenticator(this).getIBinder();
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/CertInstaller/Android.mk b/hostsidetests/devicepolicy/app/CertInstaller/Android.mk
index 22a78e2..6ef29a5 100644
--- a/hostsidetests/devicepolicy/app/CertInstaller/Android.mk
+++ b/hostsidetests/devicepolicy/app/CertInstaller/Android.mk
@@ -28,4 +28,7 @@
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/ContactDirectoryProvider/Android.mk b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/Android.mk
new file mode 100644
index 0000000..1175765
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/Android.mk
@@ -0,0 +1,37 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsContactDirectoryProvider
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/ContactDirectoryProvider/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/AndroidManifest.xml
new file mode 100644
index 0000000..234cc60
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.contactdirectoryprovider">
+
+ <uses-permission android:name="android.permission.READ_CONTACTS"/>
+ <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+
+ <application>
+ <provider
+ android:name=".DirectoryProvider"
+ android:authorities="com.android.cts.contact.directory.provider"
+ android:readPermission="android.permission.READ_CONTACTS"
+ android:multiprocess="false"
+ android:exported="true"
+ >
+ <meta-data
+ android:name="android.content.ContactDirectory"
+ android:value="true"/>
+ </provider>
+ </application>
+
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/ContactDirectoryProvider/res/values/strings.xml b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/res/values/strings.xml
new file mode 100644
index 0000000..fe0ec10
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/res/values/strings.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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Label for this package -->
+ <string name="directory_resource_id">Android CTS</string>
+</resources>
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ContactDirectoryProvider/src/com/android/cts/contactdirectoryprovider/DirectoryProvider.java b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/src/com/android/cts/contactdirectoryprovider/DirectoryProvider.java
new file mode 100644
index 0000000..8e040b7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/src/com/android/cts/contactdirectoryprovider/DirectoryProvider.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 com.android.cts.contactdirectoryprovider;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
+
+public class DirectoryProvider extends ContentProvider {
+ private final String CONFIG_NAME = "config";
+ private final String SET_CUSTOM_PREFIX = "set_prefix";
+ private final String AUTHORITY = "com.android.cts.contact.directory.provider";
+ private final String TEST_ACCOUNT_NAME = "cts@android.com";
+ private final String TEST_ACCOUNT_TYPE = "com.android.cts";
+ private final String DEFAULT_DISPLAY_NAME = "Directory";
+ private final String DEFAULT_CONTACT_NAME = "DirectoryContact";
+
+ private static final int GAL_BASE = 0;
+ private static final int GAL_DIRECTORIES = GAL_BASE;
+ private static final int GAL_FILTER = GAL_BASE + 1;
+ private static final int GAL_CONTACT = GAL_BASE + 2;
+ private static final int GAL_CONTACT_WITH_ID = GAL_BASE + 3;
+ private static final int GAL_EMAIL_FILTER = GAL_BASE + 4;
+ private static final int GAL_PHONE_FILTER = GAL_BASE + 5;
+ private static final int GAL_PHONE_LOOKUP = GAL_BASE + 6;
+ private static final int GAL_CALLABLES_FILTER = GAL_BASE + 7;
+ private static final int GAL_EMAIL_LOOKUP = GAL_BASE + 8;
+
+ private final UriMatcher mURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+ private SharedPreferences mSharedPrefs;
+
+ @Override
+ public boolean onCreate() {
+ mURIMatcher.addURI(AUTHORITY, "directories", GAL_DIRECTORIES);
+ mURIMatcher.addURI(AUTHORITY, "contacts/filter/*", GAL_FILTER);
+ mURIMatcher.addURI(AUTHORITY, "contacts/lookup/*/entities", GAL_CONTACT);
+ mURIMatcher.addURI(AUTHORITY, "contacts/lookup/*/#/entities", GAL_CONTACT_WITH_ID);
+ mURIMatcher.addURI(AUTHORITY, "data/emails/filter/*", GAL_EMAIL_FILTER);
+ mURIMatcher.addURI(AUTHORITY, "data/phones/filter/*", GAL_PHONE_FILTER);
+ mURIMatcher.addURI(AUTHORITY, "phone_lookup/*", GAL_PHONE_LOOKUP);
+ mURIMatcher.addURI(AUTHORITY, "data/callables/filter/*", GAL_CALLABLES_FILTER);
+ mURIMatcher.addURI(AUTHORITY, "data/emails/lookup/*", GAL_EMAIL_LOOKUP);
+ mSharedPrefs = getContext().getSharedPreferences(CONFIG_NAME, Context.MODE_PRIVATE);
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+
+ final String prefix = mSharedPrefs.getString(SET_CUSTOM_PREFIX, "");
+ final int match = mURIMatcher.match(uri);
+ switch (match) {
+ case GAL_DIRECTORIES: {
+ final MatrixCursor cursor = new MatrixCursor(projection);
+ final Object[] row = new Object[projection.length];
+ for (int i = 0; i < projection.length; i++) {
+ final String column = projection[i];
+ if (column.equals(Directory.ACCOUNT_NAME)) {
+ row[i] = TEST_ACCOUNT_NAME;
+ } else if (column.equals(Directory.ACCOUNT_TYPE)) {
+ row[i] = TEST_ACCOUNT_TYPE;
+ } else if (column.equals(Directory.TYPE_RESOURCE_ID)) {
+ row[i] = R.string.directory_resource_id;
+ } else if (column.equals(Directory.DISPLAY_NAME)) {
+ row[i] = prefix + DEFAULT_DISPLAY_NAME;
+ } else if (column.equals(Directory.EXPORT_SUPPORT)) {
+ row[i] = Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY;
+ } else if (column.equals(Directory.SHORTCUT_SUPPORT)) {
+ row[i] = Directory.SHORTCUT_SUPPORT_NONE;
+ }
+ }
+ cursor.addRow(row);
+ return cursor;
+ }
+ case GAL_FILTER:
+ case GAL_CONTACT:
+ case GAL_CONTACT_WITH_ID:
+ case GAL_EMAIL_FILTER:
+ case GAL_PHONE_FILTER:
+ case GAL_PHONE_LOOKUP:
+ case GAL_CALLABLES_FILTER:
+ case GAL_EMAIL_LOOKUP: {
+ // TODO: Add all CTS tests for these APIs
+ final MatrixCursor cursor = new MatrixCursor(projection);
+ final Object[] row = new Object[projection.length];
+ for (int i = 0; i < projection.length; i++) {
+ String column = projection[i];
+ if (column.equals(Contacts._ID)) {
+ row[i] = -1;
+ } else if (column.equals(Contacts.DISPLAY_NAME)) {
+ row[i] = prefix + DEFAULT_CONTACT_NAME;
+ } else {
+ row[i] = null;
+ }
+ }
+ cursor.addRow(row);
+ return cursor;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle call(String method, String arg, Bundle extras) {
+ // Set custom display name, so primary directory and corp directory will have different
+ // display name
+ if (method.equals(SET_CUSTOM_PREFIX)) {
+ mSharedPrefs.edit().putString(SET_CUSTOM_PREFIX, arg).apply();
+ // Force update the content in CP2
+ final long token = Binder.clearCallingIdentity();
+ getContext().getContentResolver().update(Directory.CONTENT_URI, new ContentValues(),
+ null, null);
+ Binder.restoreCallingIdentity(token);
+ }
+ return new Bundle();
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.mk
index 0548af6..e1f1a89 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/AndroidManifest.xml
index fe07bcb..223b919 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/AndroidManifest.xml
@@ -62,16 +62,7 @@
</intent-filter>
</activity>
- <service android:name=".MockAccountService" android:exported="true">
- <intent-filter>
- <action android:name="android.accounts.AccountAuthenticator" />
- </intent-filter>
-
- <meta-data android:name="android.accounts.AccountAuthenticator"
- android:resource="@xml/authenticator" />
- </service>
-
- <activity android:name=".UserRestrictionActivity" >
+ <activity android:name=".SetPolicyActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT"/>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
deleted file mode 100644
index 4aca824..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?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.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Label for this package -->
- <string name="authenticator_label">Android CTS - Device and Profile Owner</string>
-</resources>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/authenticator.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/authenticator.xml
deleted file mode 100644
index 0d8ecd8..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/authenticator.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!-- 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.
--->
-
-<!-- The attributes in this XML file provide configuration information -->
-<!-- for the Account Manager. -->
-
-<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
- android:accountType="com.android.cts.deviceandprofileowner.account.type"
- android:label="@string/authenticator_label"
-/>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AccountManagementTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AccountManagementTest.java
deleted file mode 100644
index d93c8f2..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AccountManagementTest.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.deviceandprofileowner;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.UserManager;
-
-import java.io.IOException;
-
-/**
- * Functionality tests for {@link DevicePolicyManager#setAccountManagementDisabled}
- *
- * Fire up a remote unprivileged service and attempt to add/remove/list
- * accounts from it to verify the enforcement is in place.
- *
- * This test depend on {@link MockAccountService}, which provides authenticator of type
- * {@link MockAccountService#ACCOUNT_TYPE}.
- */
-public class AccountManagementTest extends BaseDeviceAdminTest {
-
- // Account type for MockAccountAuthenticator
- private final static String ACCOUNT_TYPE_1 = MockAccountAuthenticator.ACCOUNT_TYPE;
- private final static String ACCOUNT_TYPE_2 = "com.dummy.account";
- private final static Account ACCOUNT_0 = new Account("user0", ACCOUNT_TYPE_1);
- private final static Account ACCOUNT_1 = new Account("user1", ACCOUNT_TYPE_1);
-
- private AccountManager mAccountManager;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mAccountManager = (AccountManager) mContext.getSystemService(Context.ACCOUNT_SERVICE);
- clearAllAccountManagementDisabled();
- mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
- UserManager.DISALLOW_MODIFY_ACCOUNTS);
- AccountUtilsTest.removeAllAccountsForType(mAccountManager, ACCOUNT_TYPE_1);
- AccountUtilsTest.removeAllAccountsForType(mAccountManager, ACCOUNT_TYPE_2);
- }
-
- @Override
- protected void tearDown() throws Exception {
- clearAllAccountManagementDisabled();
- mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
- UserManager.DISALLOW_MODIFY_ACCOUNTS);
- AccountUtilsTest.removeAllAccountsForType(mAccountManager, ACCOUNT_TYPE_1);
- AccountUtilsTest.removeAllAccountsForType(mAccountManager, ACCOUNT_TYPE_2);
- super.tearDown();
- }
-
- public void testAccountManagementDisabled_setterAndGetter() {
- // Some local tests: adding and removing disabled accounts and make sure
- // DevicePolicyManager keeps track of the disabled set correctly
- assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
-
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
- true);
- assertEquals(1, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
- assertEquals(ACCOUNT_TYPE_1,
- mDevicePolicyManager.getAccountTypesWithManagementDisabled()[0]);
-
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
- false);
- assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
- }
-
- public void testAccountManagementDisabled_addAccount() throws AuthenticatorException,
- IOException, OperationCanceledException {
- // Test for restriction on addAccount()
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
- true);
- // Test if disabling ACCOUNT_TYPE_2 affects ACCOUNT_TYPE_1
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_2,
- false);
- assertEquals(1, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
-
- assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
- // Management is disabled, adding account should fail.
- try {
- mAccountManager.addAccount(ACCOUNT_TYPE_1, null, null, null, null, null, null)
- .getResult();
- fail("Expected OperationCanceledException is not thrown.");
- } catch (OperationCanceledException e) {
- // Expected
- }
- assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
-
- // Management is re-enabled, adding account should succeed.
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
- false);
- assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
- Bundle result = mAccountManager.addAccount(ACCOUNT_TYPE_1,
- null, null, null, null, null, null).getResult();
-
- // Normally the expected result of addAccount() is AccountManager returning
- // an intent to start the authenticator activity for adding new accounts.
- // But MockAccountAuthenticator returns a new account straightway.
- assertEquals(ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE));
- }
-
- public void testAccountManagementDisabled_removeAccount() throws AuthenticatorException,
- IOException, OperationCanceledException {
- // Test for restriction on removeAccount()
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
- true);
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_2,
- false);
- assertEquals(1, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
-
- assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
- // First prepare some accounts by manually adding them,
- // setAccountManagementDisabled(true) should not stop addAccountExplicitly().
- assertTrue(mAccountManager.addAccountExplicitly(ACCOUNT_0, "password", null));
- assertTrue(mAccountManager.addAccountExplicitly(ACCOUNT_1, "password", null));
- assertEquals(2, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
-
- // Removing account should fail, as we just disabled it.
- try {
- mAccountManager.removeAccount(ACCOUNT_0, null, null).getResult();
- fail("Expected OperationCanceledException is not thrown.");
- } catch (OperationCanceledException e) {
- // Expected
- }
- assertEquals(2, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
-
- // Re-enable management, so we can successfully remove account this time.
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
- false);
- assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
- assertTrue(mAccountManager.removeAccount(ACCOUNT_0, null, null).getResult());
-
- // Make sure the removal actually succeeds.
- Account[] accounts = mAccountManager.getAccountsByType(ACCOUNT_TYPE_1);
- assertEquals(1, accounts.length);
- assertEquals(ACCOUNT_1, accounts[0]);
-
- // Disable account type 2, we should still be able to remove from type 1.
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_2,
- true);
- assertEquals(1, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
- assertTrue(mAccountManager.removeAccount(ACCOUNT_1, null, null).getResult());
-
- // Make sure the removal actually succeeds.
- assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
- }
-
- public void testUserRestriction_addAccount() throws AuthenticatorException, IOException,
- OperationCanceledException {
- // Test for restriction on addAccount()
- mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT,
- UserManager.DISALLOW_MODIFY_ACCOUNTS);
-
- assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
- // Management is disabled, adding account should fail.
- try {
- mAccountManager.addAccount(ACCOUNT_TYPE_1, null, null, null, null, null, null)
- .getResult();
- fail("Expected OperationCanceledException is not thrown.");
- } catch (OperationCanceledException e) {
- // Expected
- }
- assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
-
- // Management is re-enabled, adding account should succeed.
- mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
- UserManager.DISALLOW_MODIFY_ACCOUNTS);
- assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
- Bundle result = mAccountManager.addAccount(ACCOUNT_TYPE_1,
- null, null, null, null, null, null).getResult();
-
- // Normally the expected result of addAccount() is AccountManager returning
- // an intent to start the authenticator activity for adding new accounts.
- // But MockAccountAuthenticator returns a new account straightway.
- assertEquals(ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE));
- }
-
- public void testUserRestriction_removeAccount() throws AuthenticatorException,
- IOException, OperationCanceledException {
- // Test for restriction on removeAccount()
- mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT,
- UserManager.DISALLOW_MODIFY_ACCOUNTS);
-
- assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
- // First prepare some accounts by manually adding them,
- // setAccountManagementDisabled(true) should not stop addAccountExplicitly().
- assertTrue(mAccountManager.addAccountExplicitly(ACCOUNT_0, "password", null));
- assertEquals(1, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
-
- // Removing account should fail, as we just disabled it.
- try {
- mAccountManager.removeAccount(ACCOUNT_0, null, null).getResult();
- fail("Expected OperationCanceledException is not thrown.");
- } catch (OperationCanceledException e) {
- // Expected
- }
- assertEquals(1, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
-
- // Re-enable management, so we can successfully remove account this time.
- mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
- UserManager.DISALLOW_MODIFY_ACCOUNTS);
- assertTrue(mAccountManager.removeAccount(ACCOUNT_0, null, null).getResult());
-
- // Make sure the removal actually succeeds.
- assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
- }
-
- private void clearAllAccountManagementDisabled() {
- for (String accountType : mDevicePolicyManager.getAccountTypesWithManagementDisabled()) {
- mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, accountType,
- false);
- }
- assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
- }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AccountUtilsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AccountUtilsTest.java
deleted file mode 100644
index 7a9e5ad..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AccountUtilsTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.deviceandprofileowner;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerFuture;
-import android.content.Context;
-import android.os.Bundle;
-import android.test.AndroidTestCase;
-
-/**
- * Utility class that allows adding and removing accounts.
- *
- * This test depend on {@link MockAccountService}, which provides authenticator of type
- * {@link MockAccountService#ACCOUNT_TYPE}.
- */
-public class AccountUtilsTest extends AndroidTestCase {
-
- private final static Account ACCOUNT_0 = new Account("user0",
- MockAccountAuthenticator.ACCOUNT_TYPE);
- private AccountManager mAccountManager;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mAccountManager = (AccountManager) getContext().getSystemService(Context.ACCOUNT_SERVICE);
- }
-
- public void testAddAccount() throws Exception {
- assertEquals(0, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
- .length);
- assertTrue(mAccountManager.addAccountExplicitly(ACCOUNT_0, "password", null));
- assertEquals(1, mAccountManager.getAccountsByType(MockAccountAuthenticator.ACCOUNT_TYPE)
- .length);
- }
-
- public void testRemoveAccounts() throws Exception {
- removeAllAccountsForType(mAccountManager, MockAccountAuthenticator.ACCOUNT_TYPE);
- }
-
- static void removeAllAccountsForType(AccountManager am, String accountType)
- throws Exception {
- Account[] accounts = am.getAccountsByType(accountType);
- for (Account account : accounts) {
- AccountManagerFuture<Boolean> result = am.removeAccount(account, null, null);
- assertTrue(result.getResult());
- }
- assertEquals(0, am.getAccountsByType(accountType).length);
- }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DpcAllowedAccountManagementTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DpcAllowedAccountManagementTest.java
new file mode 100644
index 0000000..291159f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DpcAllowedAccountManagementTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.deviceandprofileowner;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.UserManager;
+
+import java.io.IOException;
+
+/**
+ * These tests verify that the device / profile owner can use account management APIs to add
+ * accounts even when policies are set. The policies tested are
+ * {@link DevicePolicyManager#setAccountManagementDisabled} and
+ * {@link UserManager#DISALLOW_MODIFY_ACCOUNTS}.
+ *
+ * This test depends on {@link com.android.cts.devicepolicy.accountmanagement.MockAccountService},
+ * which provides authenticator for a mock account type.
+ *
+ * Note that we cannot test account removal, because only the authenticator can remove an account
+ * and the Dpc is not the authenticator for the mock account type.
+ */
+public class DpcAllowedAccountManagementTest extends BaseDeviceAdminTest {
+
+ // Account type for MockAccountAuthenticator
+ private final static String ACCOUNT_TYPE_1
+ = "com.android.cts.devicepolicy.accountmanagement.account.type";
+ private final static String ACCOUNT_TYPE_2 = "com.dummy.account";
+ private final static Account ACCOUNT_0 = new Account("user0", ACCOUNT_TYPE_1);
+ private final static Account ACCOUNT_1 = new Account("user1", ACCOUNT_TYPE_1);
+
+ private AccountManager mAccountManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mAccountManager = (AccountManager) mContext.getSystemService(Context.ACCOUNT_SERVICE);
+ clearAllAccountManagementDisabled();
+ mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
+ UserManager.DISALLOW_MODIFY_ACCOUNTS);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ clearAllAccountManagementDisabled();
+ mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
+ UserManager.DISALLOW_MODIFY_ACCOUNTS);
+ super.tearDown();
+ }
+
+ public void testAccountManagementDisabled_setterAndGetter() {
+ // Some local tests: adding and removing disabled accounts and make sure
+ // DevicePolicyManager keeps track of the disabled set correctly
+ assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
+ true);
+ // Test if disabling ACCOUNT_TYPE_2 affects ACCOUNT_TYPE_1
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_2,
+ false);
+ assertEquals(1, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+ assertEquals(ACCOUNT_TYPE_1,
+ mDevicePolicyManager.getAccountTypesWithManagementDisabled()[0]);
+
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
+ false);
+ assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+ }
+
+ public void testAccountManagementDisabled_profileAndDeviceOwnerCanAddAccount()
+ throws AuthenticatorException, IOException, OperationCanceledException {
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
+ true);
+
+ assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
+ // Management is disabled, but the device / profile owner is still allowed to use the APIs
+ Bundle result = mAccountManager.addAccount(ACCOUNT_TYPE_1,
+ null, null, null, null, null, null).getResult();
+
+ // Normally the expected result of addAccount() is AccountManager returning
+ // an intent to start the authenticator activity for adding new accounts.
+ // But MockAccountAuthenticator returns a new account straightway.
+ assertEquals(ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE));
+ }
+
+ public void testUserRestriction_profileAndDeviceOwnerCanAddAccount()
+ throws AuthenticatorException, IOException, OperationCanceledException {
+ mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT,
+ UserManager.DISALLOW_MODIFY_ACCOUNTS);
+
+ assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
+ // Management is disabled, but the device / profile owner is still allowed to use the APIs
+ Bundle result = mAccountManager.addAccount(ACCOUNT_TYPE_1,
+ null, null, null, null, null, null).getResult();
+
+ // Normally the expected result of addAccount() is AccountManager returning
+ // an intent to start the authenticator activity for adding new accounts.
+ // But MockAccountAuthenticator returns a new account straightway.
+ assertEquals(ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE));
+ }
+
+ private void clearAllAccountManagementDisabled() {
+ for (String accountType : mDevicePolicyManager.getAccountTypesWithManagementDisabled()) {
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, accountType,
+ false);
+ }
+ assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountAuthenticator.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountAuthenticator.java
deleted file mode 100644
index e8e5b45..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountAuthenticator.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.deviceandprofileowner;
-
-import android.accounts.AbstractAccountAuthenticator;
-import android.accounts.Account;
-import android.accounts.AccountAuthenticatorResponse;
-import android.accounts.AccountManager;
-import android.accounts.NetworkErrorException;
-import android.content.Context;
-import android.os.Bundle;
-
-/* package */ class MockAccountAuthenticator extends AbstractAccountAuthenticator {
- private static MockAccountAuthenticator sMockAuthenticator = null;
- private static final String ACCOUNT_NAME = "com.android.cts.deviceandprofileowner.account.name";
- static final String ACCOUNT_TYPE = "com.android.cts.deviceandprofileowner.account.type";
- private static final String AUTH_TOKEN = "mockAuthToken";
- private static final String AUTH_TOKEN_LABEL = "mockAuthTokenLabel";
-
- private MockAccountAuthenticator(Context context) {
- super(context);
- }
-
- private Bundle createResultBundle() {
- Bundle result = new Bundle();
- result.putString(AccountManager.KEY_ACCOUNT_NAME, ACCOUNT_NAME);
- result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
- result.putString(AccountManager.KEY_AUTHTOKEN, AUTH_TOKEN);
-
- return result;
- }
-
- @Override
- public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
- String authTokenType, String[] requiredFeatures, Bundle options)
- throws NetworkErrorException {
- return createResultBundle();
- }
-
- @Override
- public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
- return createResultBundle();
- }
-
- @Override
- public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
- String authTokenType, Bundle options) throws NetworkErrorException {
- return createResultBundle();
- }
-
- @Override
- public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
- Bundle options) throws NetworkErrorException {
-
- Bundle result = new Bundle();
- result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
- return result;
- }
-
- @Override
- public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
- String authTokenType, Bundle options) throws NetworkErrorException {
- return createResultBundle();
- }
-
- @Override
- public String getAuthTokenLabel(String authTokenType) {
- return AUTH_TOKEN_LABEL;
- }
-
- @Override
- public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
- String[] features) throws NetworkErrorException {
-
- Bundle result = new Bundle();
- result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
- return result;
- }
-
- public static synchronized MockAccountAuthenticator getMockAuthenticator(Context context) {
- if (null == sMockAuthenticator) {
- sMockAuthenticator = new MockAccountAuthenticator(context);
- }
- return sMockAuthenticator;
- }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
deleted file mode 100644
index dfedccb..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.deviceandprofileowner;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-/**
- * a basic Mock Service for wrapping the MockAccountAuthenticator
- */
-public class MockAccountService extends Service {
-
- @Override
- public IBinder onBind(Intent intent) {
- return MockAccountAuthenticator.getMockAuthenticator(this).getIBinder();
- }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java
new file mode 100644
index 0000000..448f730
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+package com.android.cts.deviceandprofileowner;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.Log;
+
+/**
+ * Simple activity that sets or unsets a policy depending on the value of the extras.
+ */
+public class SetPolicyActivity extends Activity {
+
+ private static final String TAG = SetPolicyActivity.class.getName();
+
+ private static final String EXTRA_RESTRICTION_KEY = "extra-restriction-key";
+ private static final String EXTRA_COMMAND = "extra-command";
+ private static final String EXTRA_ACCOUNT_TYPE = "extra-account-type";
+
+ private static final String COMMAND_ADD_USER_RESTRICTION = "add-restriction";
+ private static final String COMMAND_CLEAR_USER_RESTRICTION = "clear-restriction";
+ private static final String COMMAND_BLOCK_ACCOUNT_TYPE = "block-accounttype";
+ private static final String COMMAND_UNBLOCK_ACCOUNT_TYPE = "unblock-accounttype";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ handleIntent(getIntent());
+ }
+
+ // Overriding this method in case another intent is sent to this activity before finish()
+ @Override
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ handleIntent(intent);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // Calling finish() here because doing it in onCreate(), onStart() or onResume() makes
+ // "adb shell am start" timeout if using the -W option.
+ finish();
+ }
+
+ private void handleIntent(Intent intent) {
+ DevicePolicyManager dpm = (DevicePolicyManager)
+ getSystemService(Context.DEVICE_POLICY_SERVICE);
+ String command = intent.getStringExtra(EXTRA_COMMAND);
+ Log.i(TAG, "Command: " + command);
+
+ if (COMMAND_ADD_USER_RESTRICTION.equals(command)) {
+ String restrictionKey = intent.getStringExtra(EXTRA_RESTRICTION_KEY);
+ dpm.addUserRestriction(BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
+ Log.i(TAG, "Added user restriction " + restrictionKey
+ + " for user " + Process.myUserHandle());
+ } else if (COMMAND_CLEAR_USER_RESTRICTION.equals(command)) {
+ String restrictionKey = intent.getStringExtra(EXTRA_RESTRICTION_KEY);
+ dpm.clearUserRestriction(
+ BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
+ Log.i(TAG, "Cleared user restriction " + restrictionKey
+ + " for user " + Process.myUserHandle());
+ } else if (COMMAND_BLOCK_ACCOUNT_TYPE.equals(command)) {
+ String accountType = intent.getStringExtra(EXTRA_ACCOUNT_TYPE);
+ dpm.setAccountManagementDisabled(BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT,
+ accountType, true);
+ Log.i(TAG, "Blocking account management for account type: " + accountType
+ + " for user " + Process.myUserHandle());
+ } else if (COMMAND_UNBLOCK_ACCOUNT_TYPE.equals(command)) {
+ String accountType = intent.getStringExtra(EXTRA_ACCOUNT_TYPE);
+ dpm.setAccountManagementDisabled(BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT,
+ accountType, false);
+ Log.i(TAG, "Unblocking account management for account type: " + accountType
+ + " for user " + Process.myUserHandle());
+ } else {
+ Log.e(TAG, "Invalid command: " + command);
+ }
+ }
+}
+
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionActivity.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionActivity.java
deleted file mode 100644
index fed1a79..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionActivity.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.
- */
-package com.android.cts.deviceandprofileowner;
-
-import android.app.Activity;
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Process;
-import android.util.Log;
-
-/**
- * Simple activity that adds or clears a user restriction depending on the value of the extras.
- */
-public class UserRestrictionActivity extends Activity {
-
- private static final String TAG = UserRestrictionActivity.class.getName();
-
- private static final String EXTRA_RESTRICTION_KEY = "extra-restriction-key";
- private static final String EXTRA_COMMAND = "extra-command";
-
- private static final String ADD_COMMAND = "add-restriction";
- private static final String CLEAR_COMMAND = "clear-restriction";
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- handleIntent(getIntent());
- }
-
- // Overriding this method in case another intent is sent to this activity before finish()
- @Override
- public void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- handleIntent(intent);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- // Calling finish() here because doing it in onCreate(), onStart() or onResume() makes
- // "adb shell am start" timeout if using the -W option.
- finish();
- }
-
- private void handleIntent(Intent intent) {
- DevicePolicyManager dpm = (DevicePolicyManager)
- getSystemService(Context.DEVICE_POLICY_SERVICE);
- String restrictionKey = intent.getStringExtra(EXTRA_RESTRICTION_KEY);
- String command = intent.getStringExtra(EXTRA_COMMAND);
- Log.i(TAG, "Command: \"" + command + "\". Restriction: \"" + restrictionKey + "\"");
-
- if (ADD_COMMAND.equals(command)) {
- dpm.addUserRestriction(BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
- Log.i(TAG, "Added user restriction " + restrictionKey
- + " for user " + Process.myUserHandle());
- } else if (CLEAR_COMMAND.equals(command)) {
- dpm.clearUserRestriction(
- BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
- Log.i(TAG, "Cleared user restriction " + restrictionKey
- + " for user " + Process.myUserHandle());
- } else {
- Log.e(TAG, "Invalid command: " + command);
- }
- }
-
-}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
index 314f996..d75e632 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
@@ -26,8 +26,11 @@
LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner compatibility-device-util_v2
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner compatibility-device-util
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
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 27fd36f..b2848cd 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
@@ -77,17 +77,23 @@
super.tearDown();
}
- public void testCanInstallValidRsaKeypair()
+ public void testCanInstallAndRemoveValidRsaKeypair()
throws CertificateException, NoSuchAlgorithmException, InvalidKeySpecException,
KeyChainException, InterruptedException, UnsupportedEncodingException {
final String alias = "com.android.test.valid-rsa-key-1";
final PrivateKey privKey = getPrivateKey(FAKE_RSA_1.privateKey , "RSA");
final Certificate cert = getCertificate(FAKE_RSA_1.caCertificate);
+
+ // Install key
assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, cert, alias));
+ // Request and retrieve by alias
assertEquals(alias, new KeyChainAliasFuture(alias).get());
- final PrivateKey retrievedKey = KeyChain.getPrivateKey(getActivity(), alias);
- assertEquals(retrievedKey.getAlgorithm(), "RSA");
+ assertEquals(KeyChain.getPrivateKey(getActivity(), alias).getAlgorithm(), "RSA");
+
+ // Delete again
+ assertTrue(mDevicePolicyManager.removeKeyPair(getWho(), alias));
+ assertNull(KeyChain.getPrivateKey(getActivity(), alias));
}
public void testNullKeyParamsFailPredictably()
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk b/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
index 98cdf52..bb9a819 100644
--- a/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/IntentSender/Android.mk b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
index e5246c5..9bb1933 100644
--- a/hostsidetests/devicepolicy/app/IntentSender/Android.mk
+++ b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
index 5f645b6..24b5c39 100644
--- a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
+++ b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/LauncherTestsSupport/Android.mk b/hostsidetests/devicepolicy/app/LauncherTestsSupport/Android.mk
index 2465ef3..2254e39 100644
--- a/hostsidetests/devicepolicy/app/LauncherTestsSupport/Android.mk
+++ b/hostsidetests/devicepolicy/app/LauncherTestsSupport/Android.mk
@@ -28,4 +28,7 @@
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
index b31e74b..229cead 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
@@ -26,9 +26,12 @@
LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner compatibility-device-util_v2 \
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner compatibility-device-util \
ub-uiautomator
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
index 77ecfe1..d116f24 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
@@ -28,16 +28,17 @@
import android.os.Build;
import android.os.RemoteException;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Callable;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.ContactsContract.RawContacts;
import android.test.AndroidTestCase;
import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -66,6 +67,12 @@
private static final String SHARED_CONTACT_EMAIL = "shared@shared.com";
private static final String SHARED_CONTACT_SIP = "baz@sip";
+ // Directory display name
+ private static final String PRIMARY_DIRECTORY_NAME = "PrimaryDirectory";
+ private static final String MANAGED_DIRECTORY_NAME = "ManagedDirectory";
+ private static final String PRIMARY_DIRECTORY_CONTACT_NAME = "PrimaryDirectoryContact";
+ private static final String MANAGED_DIRECTORY_CONTACT_NAME = "ManagedDirectoryContact";
+
private DevicePolicyManager mDevicePolicyManager;
private ContentResolver mResolver;
@@ -97,7 +104,7 @@
}
private boolean hasPhotoId() {
- return photoId != null;
+ return photoId != null && Long.parseLong(photoId) > 0;
}
}
@@ -116,14 +123,16 @@
insertContact(PRIMARY_CONTACT_DISPLAY_NAME, PRIMARY_CONTACT_PHONE,
PRIMARY_CONTACT_EMAIL, PRIMARY_CONTACT_SIP, 0);
- ContactInfo contactInfo = getContactInfo(PRIMARY_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(false /*isEnterprise*/,
+ PRIMARY_CONTACT_PHONE);
assertNotNull(contactInfo);
assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertNoPhotoUri();
assertFalse(contactInfo.hasPhotoId());
assertFalse(isEnterpriseContactId(contactInfo.contactId));
- contactInfo = getContactInfoFromEmail(PRIMARY_CONTACT_EMAIL);
+ contactInfo = getContactInfoFromEmailLookupUri(false /*isEnterprise*/,
+ PRIMARY_CONTACT_EMAIL);
assertNotNull(contactInfo);
assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertNoPhotoUri();
@@ -142,14 +151,16 @@
MANAGED_CONTACT_SIP,
com.android.cts.managedprofile.R.raw.ic_contact_picture);
- ContactInfo contactInfo = getContactInfo(MANAGED_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(false /*isEnterprise*/,
+ MANAGED_CONTACT_PHONE);
assertNotNull(contactInfo);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
assertTrue(contactInfo.hasPhotoId());
assertFalse(isEnterpriseContactId(contactInfo.contactId));
- contactInfo = getContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+ contactInfo = getContactInfoFromEmailLookupUri(false /*isEnterprise*/,
+ MANAGED_CONTACT_EMAIL);
assertNotNull(contactInfo);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
@@ -166,14 +177,15 @@
SHARED_CONTACT_SIP,
com.android.cts.managedprofile.R.raw.ic_contact_picture);
- ContactInfo contactInfo = getContactInfo(SHARED_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(false /*isEnterprise*/,
+ SHARED_CONTACT_PHONE);
assertNotNull(contactInfo);
assertEquals(PRIMARY_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
assertTrue(contactInfo.hasPhotoId());
assertFalse(isEnterpriseContactId(contactInfo.contactId));
- contactInfo = getContactInfoFromEmail(SHARED_CONTACT_EMAIL);
+ contactInfo = getContactInfoFromEmailLookupUri(false /*isEnterprise*/, SHARED_CONTACT_EMAIL);
assertNotNull(contactInfo);
assertEquals(PRIMARY_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
@@ -187,14 +199,15 @@
insertContact(MANAGED_CONTACT_DISPLAY_NAME_2, SHARED_CONTACT_PHONE,
SHARED_CONTACT_EMAIL, SHARED_CONTACT_SIP , 0);
- ContactInfo contactInfo = getContactInfo(SHARED_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(false /*isEnterprise*/,
+ SHARED_CONTACT_PHONE);
assertNotNull(contactInfo);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
contactInfo.assertNoPhotoUri();
assertFalse(contactInfo.hasPhotoId());
assertFalse(isEnterpriseContactId(contactInfo.contactId));
- contactInfo = getContactInfoFromEmail(SHARED_CONTACT_EMAIL);
+ contactInfo = getContactInfoFromEmailLookupUri(false /*isEnterprise*/, SHARED_CONTACT_EMAIL);
assertNotNull(contactInfo);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
contactInfo.assertNoPhotoUri();
@@ -205,7 +218,8 @@
public void testPrimaryProfileEnterprisePhoneLookup_canAccessEnterpriseContact()
throws IOException {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfo(MANAGED_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(true /*isEnterprise*/,
+ MANAGED_CONTACT_PHONE);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
// Cannot get photo id in ENTERPRISE_CONTENT_FILTER_URI
@@ -216,7 +230,8 @@
public void testPrimaryProfileEnterpriseSipLookup_canAccessEnterpriseContact()
throws IOException {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfoFromSipAddress(MANAGED_CONTACT_SIP);
+ ContactInfo contactInfo = getContactInfoFromEnterprisePhoneLookupUriWithSipAddress(
+ true /*isEnterprise*/, MANAGED_CONTACT_SIP);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
assertFalse(contactInfo.hasPhotoId());
@@ -228,7 +243,8 @@
public void testPrimaryProfileEnterpriseEmailLookup_canAccessEnterpriseContact()
throws IOException {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+ ContactInfo contactInfo = getContactInfoFromEmailLookupUri(true /*isEnterprise*/,
+ MANAGED_CONTACT_EMAIL);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
// Cannot get photo id in ENTERPRISE_CONTENT_FILTER_URI
@@ -239,7 +255,8 @@
public void testPrimaryProfileEnterprisePhoneLookupDuplicated_canAccessPrimaryContact()
throws IOException {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfo(SHARED_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(true /*isEnterprise*/,
+ SHARED_CONTACT_PHONE);
assertEquals(PRIMARY_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
assertTrue(contactInfo.hasPhotoId());
@@ -249,7 +266,8 @@
public void testPrimaryProfileEnterpriseEmailLookupDuplicated_canAccessPrimaryContact()
throws IOException {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(SHARED_CONTACT_EMAIL);
+ ContactInfo contactInfo = getContactInfoFromEmailLookupUri(true /*isEnterprise*/,
+ SHARED_CONTACT_EMAIL);
assertEquals(PRIMARY_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
assertTrue(contactInfo.hasPhotoId());
@@ -258,7 +276,8 @@
public void testManagedProfileEnterprisePhoneLookupDuplicated_canAccessEnterpriseContact() {
assertTrue(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfo(SHARED_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(true /*isEnterprise*/,
+ SHARED_CONTACT_PHONE);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
contactInfo.assertNoPhotoUri();
assertFalse(contactInfo.hasPhotoId());
@@ -267,7 +286,8 @@
public void testManagedProfileEnterpriseEmailLookupDuplicated_canAccessEnterpriseContact() {
assertTrue(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(SHARED_CONTACT_EMAIL);
+ ContactInfo contactInfo = getContactInfoFromEmailLookupUri(true /*isEnterprise*/,
+ SHARED_CONTACT_EMAIL);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
contactInfo.assertNoPhotoUri();
assertFalse(contactInfo.hasPhotoId());
@@ -276,19 +296,22 @@
public void testPrimaryProfilePhoneLookup_canNotAccessEnterpriseContact() {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getContactInfo(MANAGED_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(false /*isEnterprise*/,
+ MANAGED_CONTACT_PHONE);
assertNull(contactInfo);
}
public void testPrimaryProfileEmailLookup_canNotAccessEnterpriseContact() {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+ ContactInfo contactInfo = getContactInfoFromEmailLookupUri(false /*isEnterprise*/,
+ MANAGED_CONTACT_EMAIL);
assertNull(contactInfo);
}
public void testPrimaryProfileEnterprisePhoneLookup_canAccessPrimaryContact() {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfo(PRIMARY_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(true /*isEnterprise*/,
+ PRIMARY_CONTACT_PHONE);
assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertNoPhotoUri();
assertFalse(contactInfo.hasPhotoId());
@@ -297,7 +320,8 @@
public void testPrimaryProfileEnterpriseEmailLookup_canAccessPrimaryContact() {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(PRIMARY_CONTACT_EMAIL);
+ ContactInfo contactInfo = getContactInfoFromEmailLookupUri(true /*isEnterprise*/,
+ PRIMARY_CONTACT_EMAIL);
assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertNoPhotoUri();
assertFalse(contactInfo.hasPhotoId());
@@ -307,7 +331,8 @@
public void testManagedProfileEnterprisePhoneLookup_canAccessEnterpriseContact()
throws IOException {
assertTrue(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfo(MANAGED_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(true /*isEnterprise*/,
+ MANAGED_CONTACT_PHONE);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
assertTrue(contactInfo.hasPhotoId());
@@ -317,7 +342,8 @@
public void testManagedProfileEnterpriseEmailLookup_canAccessEnterpriseContact()
throws IOException {
assertTrue(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+ ContactInfo contactInfo = getContactInfoFromEmailLookupUri(true /*isEnterprise*/,
+ MANAGED_CONTACT_EMAIL);
assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
contactInfo.assertPhotoUrisReadable();
assertTrue(contactInfo.hasPhotoId());
@@ -326,37 +352,43 @@
public void testManagedProfileEnterprisePhoneLookup_canNotAccessPrimaryContact() {
assertTrue(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfo(PRIMARY_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(true /*isEnterprise*/,
+ PRIMARY_CONTACT_PHONE);
assertNull(contactInfo);
}
public void testManagedProfileEnterpriseEmailLookup_canNotAccessPrimaryContact() {
assertTrue(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(PRIMARY_CONTACT_EMAIL);
+ ContactInfo contactInfo = getContactInfoFromEmailLookupUri(true /*isEnterprise*/,
+ PRIMARY_CONTACT_EMAIL);
assertNull(contactInfo);
}
public void testManagedProfilePhoneLookup_canNotAccessPrimaryContact() {
assertTrue(isManagedProfile());
- ContactInfo contactInfo = getContactInfo(PRIMARY_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(false /*isEnterprise*/,
+ PRIMARY_CONTACT_PHONE);
assertNull(contactInfo);
}
public void testManagedProfileEmailLookup_canNotAccessPrimaryContact() {
assertTrue(isManagedProfile());
- ContactInfo contactInfo = getContactInfoFromEmail(PRIMARY_CONTACT_EMAIL);
+ ContactInfo contactInfo = getContactInfoFromEmailLookupUri(false /*isEnterprise */,
+ PRIMARY_CONTACT_EMAIL);
assertNull(contactInfo);
}
public void testPrimaryProfileEnterpriseEmailLookup_canNotAccessEnterpriseContact() {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+ ContactInfo contactInfo = getContactInfoFromEmailLookupUri(true /*isEnterprise*/,
+ MANAGED_CONTACT_EMAIL);
assertNull(contactInfo);
}
public void testPrimaryProfileEnterprisePhoneLookup_canNotAccessEnterpriseContact() {
assertFalse(isManagedProfile());
- ContactInfo contactInfo = getEnterpriseContactInfo(MANAGED_CONTACT_PHONE);
+ ContactInfo contactInfo = getContactInfoFromPhoneLookupUri(true /*isEnterprise*/,
+ MANAGED_CONTACT_PHONE);
assertNull(contactInfo);
}
@@ -387,6 +419,329 @@
BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT));
}
+ public void testGetDirectoryListInPrimaryProfile() {
+ assertFalse(isManagedProfile());
+ final Cursor cursor = mResolver.query(Directory.ENTERPRISE_CONTENT_URI,
+ new String[]{
+ Directory._ID,
+ Directory.DISPLAY_NAME
+ }, null, null, null);
+
+ boolean hasPrimaryDefault = false;
+ boolean hasPrimaryInvisible = false;
+ boolean hasManagedDefault = false;
+ boolean hasManagedInvisible = false;
+ boolean hasPrimaryDirectory = false;
+ boolean hasManagedDirectory = false;
+
+ while(cursor.moveToNext()) {
+ final long directoryId = cursor.getLong(0);
+ if (directoryId == Directory.DEFAULT) {
+ hasPrimaryDefault = true;
+ } else if (directoryId == Directory.LOCAL_INVISIBLE) {
+ hasPrimaryInvisible = true;
+ } else if (directoryId == Directory.ENTERPRISE_DEFAULT) {
+ hasManagedDefault = true;
+ } else if (directoryId == Directory.ENTERPRISE_LOCAL_INVISIBLE) {
+ hasManagedInvisible = true;
+ } else {
+ final String displayName = cursor.getString(1);
+ if (Directory.isEnterpriseDirectoryId(directoryId)
+ && displayName.equals(MANAGED_DIRECTORY_NAME)) {
+ hasManagedDirectory = true;
+ }
+ if (!Directory.isEnterpriseDirectoryId(directoryId)
+ && displayName.equals(PRIMARY_DIRECTORY_NAME)) {
+ hasPrimaryDirectory = true;
+ }
+ }
+ }
+ cursor.close();
+ assertTrue(hasPrimaryDefault);
+ assertTrue(hasPrimaryInvisible);
+ assertTrue(hasManagedDefault);
+ assertTrue(hasManagedInvisible);
+ assertTrue(hasPrimaryDirectory);
+ assertTrue(hasManagedDirectory);
+ }
+
+ public void testPrimaryProfileEnterpriseEmailLookup_canAccessPrimaryDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterpriseEmailLookupUriInDirectory(PRIMARY_CONTACT_EMAIL,
+ Directory.DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getPrimaryRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterpriseEmailLookupUriInDirectory(PRIMARY_CONTACT_EMAIL,
+ directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(PRIMARY_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterpriseEmailLookup_canAccessManagedDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterpriseEmailLookupUriInDirectory(MANAGED_CONTACT_EMAIL,
+ Directory.ENTERPRISE_DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(MANAGED_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getEnterpriseRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterpriseEmailLookupUriInDirectory(MANAGED_CONTACT_EMAIL,
+ directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(MANAGED_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterprisePhoneLookup_canAccessPrimaryDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterprisePhoneLookupUriInDirectory(PRIMARY_CONTACT_PHONE,
+ Directory.DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getPrimaryRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterprisePhoneLookupUriInDirectory(PRIMARY_CONTACT_PHONE,
+ directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(PRIMARY_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterprisePhoneLookup_canAccessManagedDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterprisePhoneLookupUriInDirectory(MANAGED_CONTACT_PHONE,
+ Directory.ENTERPRISE_DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(MANAGED_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getEnterpriseRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterprisePhoneLookupUriInDirectory(MANAGED_CONTACT_PHONE,
+ directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(MANAGED_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterpriseCallableFilter_canAccessPrimaryDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterpriseCallableFilterUriInDirectory(
+ PRIMARY_CONTACT_PHONE, Directory.DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getPrimaryRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterpriseCallableFilterUriInDirectory(
+ PRIMARY_CONTACT_PHONE, directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(PRIMARY_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterpriseCallableFilter_canAccessManagedDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterpriseCallableFilterUriInDirectory(
+ MANAGED_CONTACT_PHONE, Directory.ENTERPRISE_DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(MANAGED_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getEnterpriseRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterpriseCallableFilterUriInDirectory(
+ MANAGED_CONTACT_PHONE, directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(MANAGED_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterpriseEmailFilter_canAccessPrimaryDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterpriseEmailFilterUriInDirectory(
+ PRIMARY_CONTACT_EMAIL, Directory.DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getPrimaryRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterpriseEmailFilterUriInDirectory(
+ PRIMARY_CONTACT_EMAIL, directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(PRIMARY_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterpriseEmailFilter_canAccessManagedDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterpriseEmailFilterUriInDirectory(
+ MANAGED_CONTACT_EMAIL, Directory.ENTERPRISE_DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(MANAGED_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getEnterpriseRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterpriseEmailFilterUriInDirectory(
+ MANAGED_CONTACT_EMAIL, directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(MANAGED_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterpriseContactFilter_canAccessPrimaryDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterpriseContactFilterUriInDirectory(
+ PRIMARY_CONTACT_DISPLAY_NAME, Directory.DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getPrimaryRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterpriseEmailFilterUriInDirectory(
+ PRIMARY_CONTACT_DISPLAY_NAME, directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(PRIMARY_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterpriseContactFilter_canAccessManagedDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterpriseContactFilterUriInDirectory(
+ MANAGED_CONTACT_DISPLAY_NAME, Directory.ENTERPRISE_DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(MANAGED_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getEnterpriseRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterpriseEmailFilterUriInDirectory(
+ MANAGED_CONTACT_DISPLAY_NAME, directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(MANAGED_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterprisePhoneFilter_canAccessPrimaryDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterprisePhoneFilterUriInDirectory(
+ PRIMARY_CONTACT_PHONE, Directory.DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getPrimaryRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterprisePhoneFilterUriInDirectory(
+ PRIMARY_CONTACT_PHONE, directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(PRIMARY_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testPrimaryProfileEnterprisePhoneFilter_canAccessManagedDirectories() {
+ assertFalse(isManagedProfile());
+
+ // local directory
+ final ContactInfo defaultContactInfo
+ = getContactInfoFromEnterprisePhoneFilterUriInDirectory(
+ MANAGED_CONTACT_PHONE, Directory.ENTERPRISE_DEFAULT);
+ assertNotNull(defaultContactInfo);
+ assertEquals(MANAGED_CONTACT_DISPLAY_NAME, defaultContactInfo.displayName);
+
+ // remote directory
+ final long directoryId = getEnterpriseRemoteDirectoryId();
+ final ContactInfo directoryContactInfo
+ = getContactInfoFromEnterprisePhoneFilterUriInDirectory(
+ MANAGED_CONTACT_PHONE, directoryId);
+ assertNotNull(directoryContactInfo);
+ assertEquals(MANAGED_DIRECTORY_CONTACT_NAME, directoryContactInfo.displayName);
+ }
+
+ public void testFilterUriWhenDirectoryParamMissing() {
+ assertFailWhenDirectoryParamMissing(Phone.ENTERPRISE_CONTENT_FILTER_URI);
+ assertFailWhenDirectoryParamMissing(Email.ENTERPRISE_CONTENT_FILTER_URI);
+ assertFailWhenDirectoryParamMissing(Contacts.ENTERPRISE_CONTENT_FILTER_URI);
+ assertFailWhenDirectoryParamMissing(Callable.ENTERPRISE_CONTENT_FILTER_URI);
+ }
+
+ private long getPrimaryRemoteDirectoryId() {
+ assertFalse(isManagedProfile());
+ final Cursor cursor = mResolver.query(Directory.ENTERPRISE_CONTENT_URI,
+ new String[]{
+ Directory._ID
+ }, null, null, null);
+ try {
+ while (cursor.moveToNext()) {
+ final long directoryId = cursor.getLong(0);
+ if (!Directory.isEnterpriseDirectoryId(directoryId)
+ && Directory.isRemoteDirectory(directoryId)) {
+ return directoryId;
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+ fail("Cannot find primary directory id");
+ return 0;
+ }
+
+ private long getEnterpriseRemoteDirectoryId() {
+ assertFalse(isManagedProfile());
+ final Cursor cursor = mResolver.query(Directory.ENTERPRISE_CONTENT_URI,
+ new String[] {
+ Directory._ID
+ }, null, null, null);
+ try {
+ while (cursor.moveToNext()) {
+ final long directoryId = cursor.getLong(0);
+ if (Directory.isEnterpriseDirectoryId(directoryId)
+ && Directory.isRemoteDirectory(directoryId)) {
+ return directoryId;
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+ fail("Cannot find enterprise directory id");
+ return 0;
+ }
+
private boolean isManagedProfile() {
String adminPackage = BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT.getPackageName();
return mDevicePolicyManager.isProfileOwnerApp(adminPackage);
@@ -465,92 +820,114 @@
mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
}
- private ContactInfo getContactInfoFromUri(Uri phoneLookupUri, String phoneNumber) {
- return getContactInfoFromPhoneLookup(Uri.withAppendedPath(phoneLookupUri,
- Uri.encode(phoneNumber)), /* forSip =*/ false);
+ private ContactInfo getContactInfoFromPhoneLookupUri(boolean isEnterprise, String phoneNumber) {
+ Uri baseUri = (isEnterprise) ? PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI
+ : PhoneLookup.CONTENT_FILTER_URI;
+ Uri uri = baseUri.buildUpon().appendPath(phoneNumber).build();
+ return getContactInfoFromUri(uri, PhoneLookup._ID, PhoneLookup.DISPLAY_NAME,
+ PhoneLookup.PHOTO_URI, PhoneLookup.PHOTO_THUMBNAIL_URI, PhoneLookup.PHOTO_ID);
}
- private ContactInfo getContactInfoFromSipUri(Uri phoneLookupUri, String sipAddress) {
- return getContactInfoFromPhoneLookup(
- phoneLookupUri.buildUpon().appendEncodedPath(sipAddress).appendQueryParameter(
- PhoneLookup.QUERY_PARAMETER_SIP_ADDRESS, "1").build(), /* forSip =*/ true);
+ private ContactInfo getContactInfoFromEnterprisePhoneLookupUriWithSipAddress(
+ boolean isEnterprise, String sipAddress) {
+ Uri baseUri = (isEnterprise) ? PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI
+ : PhoneLookup.CONTENT_FILTER_URI;
+ Uri uri = baseUri.buildUpon().appendPath(sipAddress)
+ .appendQueryParameter(PhoneLookup.QUERY_PARAMETER_SIP_ADDRESS, "1").build();
+ return getContactInfoFromUri(uri, PhoneLookup._ID, PhoneLookup.DISPLAY_NAME,
+ PhoneLookup.PHOTO_URI, PhoneLookup.PHOTO_THUMBNAIL_URI, PhoneLookup.PHOTO_ID);
}
- private ContactInfo getContactInfoFromPhoneLookup(Uri uri, boolean isForSip) {
+ private ContactInfo getContactInfoFromEnterprisePhoneLookupUriInDirectory(String phoneNumber,
+ long directoryId) {
+ Uri uri = PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.buildUpon().appendPath(phoneNumber)
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId)).build();
+ return getContactInfoFromUri(uri, PhoneLookup._ID, PhoneLookup.DISPLAY_NAME,
+ PhoneLookup.PHOTO_URI, PhoneLookup.PHOTO_THUMBNAIL_URI, PhoneLookup.PHOTO_ID);
+ }
+
+ private ContactInfo getContactInfoFromEmailLookupUri(boolean isEnterprise, String email) {
+ Uri baseUri = (isEnterprise) ? Email.ENTERPRISE_CONTENT_LOOKUP_URI
+ : Email.CONTENT_LOOKUP_URI;
+ Uri uri = Uri.withAppendedPath(baseUri, email);
+ return getContactInfoFromUri(uri, Email.CONTACT_ID, Email.DISPLAY_NAME_PRIMARY,
+ Email.PHOTO_URI, Email.PHOTO_THUMBNAIL_URI, Email.PHOTO_ID);
+ }
+
+ private ContactInfo getContactInfoFromEnterpriseEmailLookupUriInDirectory(String email,
+ long directoryId) {
+ Uri uri = Email.ENTERPRISE_CONTENT_LOOKUP_URI.buildUpon().appendPath(email)
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId)).build();
+ return getContactInfoFromUri(uri, Email.CONTACT_ID, Email.DISPLAY_NAME_PRIMARY,
+ Email.PHOTO_URI, Email.PHOTO_THUMBNAIL_URI, Email.PHOTO_ID);
+ }
+
+ private ContactInfo getContactInfoFromEnterpriseCallableFilterUriInDirectory(String filter,
+ long directoryId) {
+ final Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, filter)
+ .buildUpon().appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId)).build();
+ return getContactInfoFromUri(uri, Callable.CONTACT_ID, Callable.DISPLAY_NAME_PRIMARY,
+ Callable.PHOTO_URI, Callable.PHOTO_THUMBNAIL_URI, Callable.PHOTO_ID);
+ }
+
+ private ContactInfo getContactInfoFromEnterpriseEmailFilterUriInDirectory(String filter,
+ long directoryId) {
+ final Uri uri = Uri.withAppendedPath(Email.ENTERPRISE_CONTENT_FILTER_URI, filter)
+ .buildUpon().appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId)).build();
+ return getContactInfoFromUri(uri, Email.CONTACT_ID, Email.DISPLAY_NAME_PRIMARY,
+ Email.PHOTO_URI, Email.PHOTO_THUMBNAIL_URI, Email.PHOTO_ID);
+ }
+
+ private ContactInfo getContactInfoFromEnterpriseContactFilterUriInDirectory(String filter,
+ long directoryId) {
+ final Uri uri = Uri.withAppendedPath(Contacts.ENTERPRISE_CONTENT_FILTER_URI, filter)
+ .buildUpon().appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId)).build();
+ return getContactInfoFromUri(uri, Contacts._ID, Contacts.DISPLAY_NAME_PRIMARY,
+ Contacts.PHOTO_URI, Contacts.PHOTO_THUMBNAIL_URI, Contacts.PHOTO_ID);
+ }
+
+ private ContactInfo getContactInfoFromEnterprisePhoneFilterUriInDirectory(String filter,
+ long directoryId) {
+ final Uri uri = Uri.withAppendedPath(Phone.ENTERPRISE_CONTENT_FILTER_URI, filter)
+ .buildUpon().appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId)).build();
+ return getContactInfoFromUri(uri, Phone.CONTACT_ID, Phone.DISPLAY_NAME_PRIMARY,
+ Phone.PHOTO_URI, Phone.PHOTO_THUMBNAIL_URI, Phone.PHOTO_ID);
+ }
+
+
+ private ContactInfo getContactInfoFromUri(Uri uri, String idColumn,
+ String displayNameColumn, String photoUriColumn, String photoThumbnailColumn,
+ String photoIdColumn) {
Cursor cursor = mResolver.query(uri,
new String[] {
- PhoneLookup._ID, PhoneLookup.DISPLAY_NAME, PhoneLookup.PHOTO_URI,
- PhoneLookup.PHOTO_THUMBNAIL_URI, PhoneLookup.PHOTO_ID
+ idColumn,
+ displayNameColumn,
+ photoUriColumn,
+ photoIdColumn,
+ photoThumbnailColumn,
}, null, null, null);
if (cursor == null) {
return null;
}
- ContactInfo result = null;
- if (cursor.moveToFirst()) {
- result = new ContactInfo(
- cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup._ID)),
- cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME)),
- cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.PHOTO_URI)),
- cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.PHOTO_THUMBNAIL_URI)),
- cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.PHOTO_ID)));
+ try {
+ if (cursor.moveToFirst()) {
+ return new ContactInfo(
+ cursor.getString(cursor.getColumnIndexOrThrow(idColumn)),
+ cursor.getString(cursor.getColumnIndexOrThrow(displayNameColumn)),
+ cursor.getString(cursor.getColumnIndexOrThrow(photoUriColumn)),
+ cursor.getString(cursor.getColumnIndexOrThrow(photoThumbnailColumn)),
+ cursor.getString(cursor.getColumnIndexOrThrow(photoIdColumn)));
+ }
+ } finally {
+ cursor.close();
}
- cursor.close();
- return result;
- }
-
- private ContactInfo getContactInfoFromEmailUri(Uri emailLookupUri, String email) {
- Uri uri = Uri.withAppendedPath(emailLookupUri, Uri.encode(email));
- Cursor cursor = mResolver.query(uri,
- new String[] {
- Email.CONTACT_ID,
- Email.DISPLAY_NAME_PRIMARY,
- Email.PHOTO_URI,
- Email.PHOTO_ID,
- Email.PHOTO_THUMBNAIL_URI,
- }, null, null, null);
- if (cursor == null) {
- return null;
- }
- ContactInfo result = null;
- if (cursor.moveToFirst()) {
- result = new ContactInfo(
- cursor.getString(cursor.getColumnIndexOrThrow(
- Email.CONTACT_ID)),
- cursor.getString(cursor.getColumnIndexOrThrow(
- Email.DISPLAY_NAME_PRIMARY)),
- cursor.getString(cursor.getColumnIndexOrThrow(
- Email.PHOTO_URI)),
- cursor.getString(cursor.getColumnIndexOrThrow(
- Email.PHOTO_THUMBNAIL_URI)),
- cursor.getString(cursor.getColumnIndexOrThrow(
- Email.PHOTO_ID)));
- }
- cursor.close();
- return result;
- }
-
- private ContactInfo getContactInfo(String phoneNumber) {
- return getContactInfoFromUri(PhoneLookup.CONTENT_FILTER_URI,
- phoneNumber);
- }
-
- private ContactInfo getContactInfoFromEmail(String email) {
- return getContactInfoFromEmailUri(Email.CONTENT_LOOKUP_URI, email);
- }
-
- private ContactInfo getEnterpriseContactInfo(String phoneNumber) {
- return getContactInfoFromUri(
- PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
- phoneNumber);
- }
-
- private ContactInfo getEnterpriseContactInfoFromSipAddress(String phoneNumber) {
- return getContactInfoFromSipUri(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
- phoneNumber);
- }
-
- private ContactInfo getEnterpriseContactInfoFromEmail(String email) {
- return getContactInfoFromEmailUri(Email.ENTERPRISE_CONTENT_LOOKUP_URI, email);
+ return null;
}
private void removeAllTestContactsInProfile() {
@@ -593,4 +970,12 @@
}
}
}
+
+ private void assertFailWhenDirectoryParamMissing(Uri uri) {
+ try {
+ mResolver.query(uri, null, null, null, null);
+ fail("IllegalArgumentException is not thrown");
+ } catch (IllegalArgumentException ex) {
+ }
+ }
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileWidgetTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileWidgetTest.java
index 085d56f..c122b07 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileWidgetTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileWidgetTest.java
@@ -68,9 +68,8 @@
List<String> providers = mDevicePolicyManager.getCrossProfileWidgetProviders(
ADMIN_RECEIVER_COMPONENT);
assertTrue(providers.isEmpty());
- // check that widget can still be found inside the profile
- // This does not currently work correctly: http://b/issues/21180997
- // assertTrue(containsWidgetProviderPkg(mAppWidgetManager.getInstalledProviders()));
+ // Check that widget can still be found inside the profile
+ assertTrue(containsWidgetProviderPkg(mAppWidgetManager.getInstalledProviders()));
}
private boolean containsWidgetProviderPkg(List<AppWidgetProviderInfo> widgets) {
diff --git a/hostsidetests/devicepolicy/app/PackageInstaller/Android.mk b/hostsidetests/devicepolicy/app/PackageInstaller/Android.mk
index e68c884..ecf9837 100644
--- a/hostsidetests/devicepolicy/app/PackageInstaller/Android.mk
+++ b/hostsidetests/devicepolicy/app/PackageInstaller/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/Android.mk b/hostsidetests/devicepolicy/app/SimpleApp/Android.mk
index eae0a4f..744c30d 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/Android.mk
+++ b/hostsidetests/devicepolicy/app/SimpleApp/Android.mk
@@ -24,8 +24,14 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsSimpleApp
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/SimplePreMApp/Android.mk b/hostsidetests/devicepolicy/app/SimplePreMApp/Android.mk
index 7460552..a6dd2c9 100644
--- a/hostsidetests/devicepolicy/app/SimplePreMApp/Android.mk
+++ b/hostsidetests/devicepolicy/app/SimplePreMApp/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := 21
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/WidgetProvider/Android.mk b/hostsidetests/devicepolicy/app/WidgetProvider/Android.mk
index c0e35fa..6890544 100644
--- a/hostsidetests/devicepolicy/app/WidgetProvider/Android.mk
+++ b/hostsidetests/devicepolicy/app/WidgetProvider/Android.mk
@@ -26,4 +26,7 @@
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/WifiConfigCreator/Android.mk b/hostsidetests/devicepolicy/app/WifiConfigCreator/Android.mk
index 47db44e..5aa11b4 100644
--- a/hostsidetests/devicepolicy/app/WifiConfigCreator/Android.mk
+++ b/hostsidetests/devicepolicy/app/WifiConfigCreator/Android.mk
@@ -26,8 +26,11 @@
LOCAL_PACKAGE_NAME := CtsWifiConfigCreator
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util_v2
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
LOCAL_SDK_VERSION := current
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 4fc14e4..6ee1aec 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -16,7 +16,7 @@
package com.android.cts.devicepolicy;
-import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.migration.MigrationHelper;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.testrunner.InstrumentationResultParser;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
@@ -35,8 +35,11 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.annotation.Nullable;
@@ -48,15 +51,20 @@
private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
- protected CtsBuildHelper mCtsBuild;
+ static final int USER_SYSTEM = 0; // From the UserHandle class.
+
+ private static final int FLAG_PRIMARY = 1; // From the UserInfo class
+
+ protected IBuildInfo mCtsBuild;
private String mPackageVerifier;
private HashSet<String> mAvailableFeatures;
protected boolean mHasFeature;
+ private ArrayList<Integer> mOriginalUsers;
@Override
public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ mCtsBuild = buildInfo;
}
@Override
@@ -69,6 +77,7 @@
mPackageVerifier = getDevice().executeShellCommand(
"settings get global package_verifier_enable");
getDevice().executeShellCommand("settings put global package_verifier_enable 0");
+ mOriginalUsers = listUsers();
}
@Override
@@ -82,24 +91,26 @@
protected void installApp(String fileName)
throws FileNotFoundException, DeviceNotAvailableException {
CLog.logAndDisplay(LogLevel.INFO, "Installing app " + fileName);
- String installResult = getDevice().installPackage(mCtsBuild.getTestApp(fileName), true);
+ String installResult = getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, fileName), true);
assertNull(String.format("Failed to install %s, Reason: %s", fileName, installResult),
installResult);
}
protected void installAppAsUser(String appFileName, int userId) throws FileNotFoundException,
DeviceNotAvailableException {
+ CLog.logAndDisplay(LogLevel.INFO, "Installing app " + appFileName + " for user " + userId);
final ITestDevice device = getDevice();
- final File apk = mCtsBuild.getTestApp(appFileName);
+ final File apk = MigrationHelper.getTestFile(mCtsBuild, appFileName);
final String remotePath = "/data/local/tmp/" + apk.getName();
if (!device.pushFile(apk, remotePath)) {
throw new IllegalStateException("Failed to push " + apk);
}
final String result = device.executeShellCommand(
- "pm install -r --user " + userId + " " + remotePath);
- assertTrue(result, result.contains("\nSuccess"));
+ "pm install -r -g --user " + userId + " " + remotePath);
+ assertTrue(result, result.contains("Success"));
}
/** Initializes the user with the given id. This is required so that apps can run on it. */
@@ -112,6 +123,13 @@
commandOutput.startsWith("Success:"));
}
+ protected void switchUser(int userId) throws Exception {
+ String command = "am switch-user " + userId;
+ CLog.logAndDisplay(LogLevel.INFO, "Starting command " + command);
+ String commandOutput = getDevice().executeShellCommand(command);
+ CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
+ }
+
protected int getMaxNumberOfUsersSupported() throws DeviceNotAvailableException {
// TODO: move this to ITestDevice once it supports users
String command = "pm get-max-users";
@@ -126,6 +144,28 @@
return 0;
}
+ protected int getUserFlags(int userId) throws DeviceNotAvailableException {
+ String command = "pm list users";
+ String commandOutput = getDevice().executeShellCommand(command);
+ CLog.i("Output for command " + command + ": " + commandOutput);
+
+ String[] lines = commandOutput.split("\\r?\\n");
+ assertTrue(commandOutput + " should contain at least one line", lines.length >= 1);
+ for (int i = 1; i < lines.length; i++) {
+ // Individual user is printed out like this:
+ // \tUserInfo{$id$:$name$:$Integer.toHexString(flags)$} [running]
+ String[] tokens = lines[i].split("\\{|\\}|:");
+ assertTrue(lines[i] + " doesn't contain 4 or 5 tokens",
+ tokens.length == 4 || tokens.length == 5);
+ // If the user IDs match, return the flags.
+ if (Integer.parseInt(tokens[1]) == userId) {
+ return Integer.parseInt(tokens[3], 16);
+ }
+ }
+ fail("User not found");
+ return 0;
+ }
+
protected ArrayList<Integer> listUsers() throws DeviceNotAvailableException {
String command = "pm list users";
String commandOutput = getDevice().executeShellCommand(command);
@@ -148,11 +188,15 @@
return users;
}
- protected void removeUser(int userId) throws Exception {
- String stopUserCommand = "am stop-user -w " + userId;
+ protected void stopUser(int userId) throws Exception {
+ String stopUserCommand = "am stop-user -w -f " + userId;
CLog.logAndDisplay(LogLevel.INFO, "starting command \"" + stopUserCommand + "\" and waiting.");
CLog.logAndDisplay(LogLevel.INFO, "Output for command " + stopUserCommand + ": "
+ getDevice().executeShellCommand(stopUserCommand));
+ }
+
+ protected void removeUser(int userId) throws Exception {
+ stopUser(userId);
String removeUserCommand = "pm remove-user " + userId;
CLog.logAndDisplay(LogLevel.INFO, "starting command " + removeUserCommand);
CLog.logAndDisplay(LogLevel.INFO, "Output for command " + removeUserCommand + ": "
@@ -161,7 +205,7 @@
protected void removeTestUsers() throws Exception {
for (int userId : listUsers()) {
- if (userId != 0) {
+ if (!mOriginalUsers.contains(userId)) {
removeUser(userId);
}
}
@@ -207,6 +251,30 @@
return !runResult.hasFailedTests() && runResult.getNumTestsInState(TestStatus.PASSED) > 0;
}
+ /** Returns true if the system supports the split between system and primary user. */
+ protected boolean hasUserSplit() throws DeviceNotAvailableException {
+ return getBooleanSystemProperty("ro.fw.system_user_split", false);
+ }
+
+ /** Returns a boolean value of the system property with the specified key. */
+ protected boolean getBooleanSystemProperty(String key, boolean defaultValue)
+ throws DeviceNotAvailableException {
+ final String[] positiveValues = {"1", "y", "yes", "true", "on"};
+ final String[] negativeValues = {"0", "n", "no", "false", "off"};
+ String propertyValue = getDevice().getProperty(key);
+ if (propertyValue == null || propertyValue.isEmpty()) {
+ return defaultValue;
+ }
+ if (Arrays.asList(positiveValues).contains(propertyValue)) {
+ return true;
+ }
+ if (Arrays.asList(negativeValues).contains(propertyValue)) {
+ return false;
+ }
+ fail("Unexpected value of boolean system property '" + key + "': " + propertyValue);
+ return false;
+ }
+
/** Helper method to run tests and return the listener that collected the results. */
private TestRunResult doRunTests(
String pkgName, String testClassName,
@@ -286,7 +354,12 @@
}
protected int createUser() throws Exception {
- String command ="pm create-user TestUser_"+ System.currentTimeMillis();
+ return createUser(false);
+ }
+
+ protected int createUser(boolean ephemeral) throws Exception {
+ String command ="pm create-user " + (ephemeral ? "--ephemeral " : "")
+ + "TestUser_" + System.currentTimeMillis();
CLog.logAndDisplay(LogLevel.INFO, "Starting command " + command);
String commandOutput = getDevice().executeShellCommand(command);
CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
@@ -298,9 +371,9 @@
return Integer.parseInt(tokens[tokens.length-1]);
}
- protected int createManagedProfile() throws DeviceNotAvailableException {
- String command =
- "pm create-user --profileOf 0 --managed TestProfile_" + System.currentTimeMillis();
+ protected int createManagedProfile(int parentUserId) throws DeviceNotAvailableException {
+ String command = "pm create-user --profileOf " + parentUserId + " --managed "
+ + "TestProfile_" + System.currentTimeMillis();
CLog.logAndDisplay(LogLevel.INFO, "Starting command " + command);
String commandOutput = getDevice().executeShellCommand(command);
CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
@@ -313,6 +386,26 @@
return Integer.parseInt(tokens[tokens.length-1]);
}
+ // TODO: use the method from Device.java once it is available.
+ protected int getPrimaryUser() throws DeviceNotAvailableException {
+ final String command = "pm list users";
+ final String commandOutput = getDevice().executeShellCommand(command);
+ CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
+ final String[] lines = commandOutput.split("\\n");
+ final Pattern p = Pattern.compile("\\{(\\d+):.*:(\\d+)");
+ for (String line : lines) {
+ Matcher m = p.matcher(line);
+ if (m.find()) {
+ final int flag = Integer.parseInt(m.group(2));
+ if ((flag & FLAG_PRIMARY) != 0) {
+ return Integer.parseInt(m.group(1));
+ }
+ }
+ }
+ fail("There is no primary user on this device?");
+ return -1;
+ }
+
protected int getUserSerialNumber(int userId) throws DeviceNotAvailableException{
// dumpsys user return lines like "UserInfo{0:Owner:13} serialNo=0"
String commandOutput = getDevice().executeShellCommand("dumpsys user");
@@ -348,8 +441,9 @@
}
}
- protected void setDeviceAdmin(String componentName) throws DeviceNotAvailableException {
- String command = "dpm set-active-admin '" + componentName + "'";
+ protected void setDeviceAdmin(String componentName, int userId)
+ throws DeviceNotAvailableException {
+ String command = "dpm set-active-admin --user " + userId + " '" + componentName + "'";
String commandOutput = getDevice().executeShellCommand(command);
CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
assertTrue(commandOutput + " expected to start with \"Success:\"",
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
index 8d22638..2740c20 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
@@ -16,6 +16,8 @@
package com.android.cts.devicepolicy;
+import com.android.cts.migration.MigrationHelper;
+
import java.io.File;
import java.lang.Exception;
@@ -34,16 +36,6 @@
private static final String DEVICE_OWNER_CLEAR
= DEVICE_OWNER_PKG + ".ClearDeviceOwnerTest";
- private static final String DEVICE_AND_PROFILE_OWNER_PKG
- = "com.android.cts.deviceandprofileowner";
- protected static final String DEVICE_AND_PROFILE_OWNER_APK = "CtsDeviceAndProfileOwnerApp.apk";
- protected static final String DEVICE_AND_PROFILE_OWNER_ADMIN
- = ".BaseDeviceAdminTest$BasicAdminReceiver";
- protected static final String DEVICE_AND_PROFILE_OWNER_ADMIN_COMPONENT
- = DEVICE_AND_PROFILE_OWNER_PKG + "/" + DEVICE_AND_PROFILE_OWNER_ADMIN;
- protected static final String DEVICE_AND_PROFILE_OWNER_CLEAR
- = DEVICE_AND_PROFILE_OWNER_PKG + ".ClearDeviceOwnerTest";
-
private static final String INTENT_RECEIVER_PKG = "com.android.cts.intent.receiver";
private static final String INTENT_RECEIVER_APK = "CtsIntentReceiverApp.apk";
@@ -58,11 +50,16 @@
private static final String PACKAGE_INSTALLER_CLEAR_DEVICE_OWNER_TEST_CLASS =
PACKAGE_INSTALLER_PKG + ".ClearDeviceOwnerTest";
+ private static final String ACCOUNT_MANAGEMENT_PKG
+ = "com.android.cts.devicepolicy.accountmanagement";
+ protected static final String ACCOUNT_MANAGEMENT_APK
+ = "CtsAccountManagementDevicePolicyApp.apk";
+
@Override
public void tearDown() throws Exception {
if (mHasFeature) {
getDevice().uninstallPackage(DEVICE_OWNER_PKG);
- getDevice().uninstallPackage(DEVICE_AND_PROFILE_OWNER_PKG);
+ getDevice().uninstallPackage(ACCOUNT_MANAGEMENT_PKG);
}
super.tearDown();
@@ -115,16 +112,17 @@
if (!mHasFeature) {
return;
}
- installApp(DEVICE_AND_PROFILE_OWNER_APK);
+ installApp(ACCOUNT_MANAGEMENT_APK);
+ installApp(DEVICE_OWNER_APK);
try {
- assertTrue(runDeviceTestsAsUser(DEVICE_AND_PROFILE_OWNER_PKG, ".AccountUtilsTest",
- "testAddAccount", 0));
- assertFalse(setDeviceOwner(DEVICE_AND_PROFILE_OWNER_ADMIN_COMPONENT));
+ assertTrue(runDeviceTestsAsUser(ACCOUNT_MANAGEMENT_PKG, ".AccountUtilsTest",
+ "testAddAccountExplicitly", 0));
+ assertFalse(setDeviceOwner(DEVICE_OWNER_ADMIN_COMPONENT));
} finally {
// make sure we clean up in case we succeeded in setting the device owner
- runDeviceTests(DEVICE_AND_PROFILE_OWNER_PKG, DEVICE_AND_PROFILE_OWNER_CLEAR);
- assertTrue(runDeviceTestsAsUser(DEVICE_AND_PROFILE_OWNER_PKG, ".AccountUtilsTest",
- "testRemoveAccounts", 0));
+ runDeviceTests(DEVICE_OWNER_PKG, DEVICE_OWNER_CLEAR);
+ assertTrue(runDeviceTestsAsUser(ACCOUNT_MANAGEMENT_PKG, ".AccountUtilsTest",
+ "testRemoveAccountExplicitly", 0));
}
}
@@ -132,7 +130,7 @@
if (!mHasFeature) {
return;
}
- final File apk = mCtsBuild.getTestApp(TEST_APP_APK);
+ final File apk = MigrationHelper.getTestFile(mCtsBuild, TEST_APP_APK);
try {
// Install the test and prepare the test apk.
installApp(PACKAGE_INSTALLER_APK);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 43e6730..bc8d9c2 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -16,6 +16,7 @@
package com.android.cts.devicepolicy;
+import com.android.cts.migration.MigrationHelper;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
@@ -50,10 +51,20 @@
private static final String PACKAGE_INSTALLER_PKG = "com.android.cts.packageinstaller";
private static final String PACKAGE_INSTALLER_APK = "CtsPackageInstallerApp.apk";
+ private static final String ACCOUNT_MANAGEMENT_PKG
+ = "com.android.cts.devicepolicy.accountmanagement";
+ private static final String ACCOUNT_MANAGEMENT_APK = "CtsAccountManagementDevicePolicyApp.apk";
+
protected static final int USER_OWNER = 0;
- private static final String ADD_RESTRICTION_COMMAND = "add-restriction";
- private static final String CLEAR_RESTRICTION_COMMAND = "clear-restriction";
+ private static final String COMMAND_ADD_USER_RESTRICTION = "add-restriction";
+ private static final String COMMAND_CLEAR_USER_RESTRICTION = "clear-restriction";
+ private static final String COMMAND_BLOCK_ACCOUNT_TYPE = "block-accounttype";
+ private static final String COMMAND_UNBLOCK_ACCOUNT_TYPE = "unblock-accounttype";
+
+ private static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
+ private static final String ACCOUNT_TYPE
+ = "com.android.cts.devicepolicy.accountmanagement.account.type";
// ID of the user all tests are run as. For device owner this will be 0, for profile owner it
// is the user id of the created profile.
@@ -66,6 +77,7 @@
getDevice().uninstallPackage(PERMISSIONS_APP_PKG);
getDevice().uninstallPackage(SIMPLE_PRE_M_APP_PKG);
getDevice().uninstallPackage(CERT_INSTALLER_PKG);
+ getDevice().uninstallPackage(ACCOUNT_MANAGEMENT_PKG);
}
super.tearDown();
}
@@ -179,41 +191,106 @@
executeDeviceTestClass(".ApplicationHiddenTest");
}
- public void testAccountManagement() throws Exception {
+ public void testAccountManagement_deviceAndProfileOwnerAlwaysAllowed() throws Exception {
if (!mHasFeature) {
return;
}
- executeDeviceTestClass(".AccountManagementTest");
+ installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
+ executeDeviceTestClass(".DpcAllowedAccountManagementTest");
+ }
- // Send a home intent to dismiss an error dialog.
- String command = "am start -a android.intent.action.MAIN -c android.intent.category.HOME";
- CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
- + getDevice().executeShellCommand(command));
+ public void testAccountManagement_userRestrictionAddAccount() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+
+ installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
+ try {
+ changeUserRestrictionForUser(DISALLOW_MODIFY_ACCOUNTS, COMMAND_ADD_USER_RESTRICTION,
+ mUserId);
+ executeAccountTest("testAddAccount_blocked");
+ } finally {
+ // Ensure we clear the user restriction
+ changeUserRestrictionForUser(DISALLOW_MODIFY_ACCOUNTS, COMMAND_CLEAR_USER_RESTRICTION,
+ mUserId);
+ }
+ executeAccountTest("testAddAccount_allowed");
+ }
+
+ public void testAccountManagement_userRestrictionRemoveAccount() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+
+ installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
+ try {
+ changeUserRestrictionForUser(DISALLOW_MODIFY_ACCOUNTS, COMMAND_ADD_USER_RESTRICTION,
+ mUserId);
+ executeAccountTest("testRemoveAccount_blocked");
+ } finally {
+ // Ensure we clear the user restriction
+ changeUserRestrictionForUser(DISALLOW_MODIFY_ACCOUNTS, COMMAND_CLEAR_USER_RESTRICTION,
+ mUserId);
+ }
+ executeAccountTest("testRemoveAccount_allowed");
+ }
+
+ public void testAccountManagement_disabledAddAccount() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+
+ installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
+ try {
+ changeAccountManagement(COMMAND_BLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
+ executeAccountTest("testAddAccount_blocked");
+ } finally {
+ // Ensure we remove account management policies
+ changeAccountManagement(COMMAND_UNBLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
+ }
+ executeAccountTest("testAddAccount_allowed");
+ }
+
+ public void testAccountManagement_disabledRemoveAccount() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+
+ installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
+ try {
+ changeAccountManagement(COMMAND_BLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
+ executeAccountTest("testRemoveAccount_blocked");
+ } finally {
+ // Ensure we remove account management policies
+ changeAccountManagement(COMMAND_UNBLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
+ }
+ executeAccountTest("testRemoveAccount_allowed");
}
public void testDelegatedCertInstaller() throws Exception {
if (!mHasFeature) {
return;
}
+ int parentUserId = getPrimaryUser();
installAppAsUser(CERT_INSTALLER_APK, mUserId);
- installAppAsUser(DEVICE_ADMIN_APK, USER_OWNER);
- setDeviceAdmin(DEVICE_ADMIN_PKG + "/.PrimaryUserDeviceAdmin");
+ installAppAsUser(DEVICE_ADMIN_APK, parentUserId);
+ setDeviceAdmin(DEVICE_ADMIN_PKG + "/.PrimaryUserDeviceAdmin", parentUserId);
final String adminHelperClass = ".PrimaryUserAdminHelper";
try {
// Set a non-empty device lockscreen password, which is a precondition for installing
// private key pairs.
assertTrue("Set lockscreen password failed", runDeviceTestsAsUser(DEVICE_ADMIN_PKG,
- adminHelperClass, "testSetPassword", 0 /* user 0 */));
+ adminHelperClass, "testSetPassword", parentUserId));
assertTrue("DelegatedCertInstaller failed", runDeviceTestsAsUser(DEVICE_ADMIN_PKG,
".DelegatedCertInstallerTest", mUserId));
} finally {
// Reset lockscreen password and remove device admin.
assertTrue("Clear lockscreen password failed", runDeviceTestsAsUser(DEVICE_ADMIN_PKG,
- adminHelperClass, "testClearPassword", 0 /* user 0 */));
+ adminHelperClass, "testClearPassword", parentUserId));
assertTrue("Clear device admin failed", runDeviceTestsAsUser(DEVICE_ADMIN_PKG,
- adminHelperClass, "testClearDeviceAdmin", 0 /* user 0 */));
+ adminHelperClass, "testClearDeviceAdmin", parentUserId));
}
}
@@ -222,7 +299,7 @@
final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
final String UNKNOWN_SOURCES_SETTING = "install_non_market_apps";
final String SECURE_SETTING_CATEGORY = "secure";
- final File apk = mCtsBuild.getTestApp(TEST_APP_APK);
+ final File apk = MigrationHelper.getTestFile(mCtsBuild, TEST_APP_APK);
String unknownSourceSetting = null;
try {
// Install the test and prepare the test apk.
@@ -232,13 +309,13 @@
// Add restrictions and test if we can install the apk.
getDevice().uninstallPackage(TEST_APP_PKG);
changeUserRestrictionForUser(DISALLOW_INSTALL_UNKNOWN_SOURCES,
- ADD_RESTRICTION_COMMAND, mUserId);
+ COMMAND_ADD_USER_RESTRICTION, mUserId);
assertTrue(runDeviceTestsAsUser(PACKAGE_INSTALLER_PKG, ".ManualPackageInstallTest",
"testManualInstallBlocked", mUserId));
// Clear restrictions and test if we can install the apk.
changeUserRestrictionForUser(DISALLOW_INSTALL_UNKNOWN_SOURCES,
- CLEAR_RESTRICTION_COMMAND, mUserId);
+ COMMAND_CLEAR_USER_RESTRICTION, mUserId);
// Enable Unknown sources in Settings.
unknownSourceSetting =
@@ -268,13 +345,32 @@
assertTrue(runDeviceTestsAsUser(DEVICE_ADMIN_PKG, className, testName, mUserId));
}
+ private void executeAccountTest(String testName) throws DeviceNotAvailableException {
+ assertTrue(runDeviceTestsAsUser(ACCOUNT_MANAGEMENT_PKG, ".AccountManagementTest",
+ testName, mUserId));
+ // Send a home intent to dismiss an error dialog.
+ String command = "am start -a android.intent.action.MAIN"
+ + " -c android.intent.category.HOME";
+ CLog.i("Output for command " + command + ": " + getDevice().executeShellCommand(command));
+ }
+
private void changeUserRestrictionForUser(String key, String command, int userId)
throws DeviceNotAvailableException {
+ changePolicy(command, "--es extra-restriction-key " + key, userId);
+ }
+
+ private void changeAccountManagement(String command, String accountType, int userId)
+ throws DeviceNotAvailableException {
+ changePolicy(command, "--es extra-account-type " + accountType, userId);
+ }
+
+ private void changePolicy(String command, String extras, int userId)
+ throws DeviceNotAvailableException {
String adbCommand = "am start -W --user " + userId
+ " -c android.intent.category.DEFAULT "
+ " --es extra-command " + command
- + " --es extra-restriction-key " + key
- + " " + DEVICE_ADMIN_PKG + "/.UserRestrictionActivity";
+ + " " + extras
+ + " " + DEVICE_ADMIN_PKG + "/.SetPolicyActivity";
String commandOutput = getDevice().executeShellCommand(adbCommand);
CLog.logAndDisplay(LogLevel.INFO,
"Output for command " + adbCommand + ": " + commandOutput);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/EphemeralUserTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/EphemeralUserTest.java
new file mode 100644
index 0000000..cb7e67b
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/EphemeralUserTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.devicepolicy;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+
+/**
+ * Tests for emphemeral users and profiles.
+ */
+public class EphemeralUserTest extends BaseDevicePolicyTest {
+
+ private static final int FLAG_EPHEMERAL = 0x00000100;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mHasFeature = getDevice().getApiLevel() >= 24 /* Build.VERSION_CODES.N */
+ && canCreateUsers(1);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ removeTestUsers();
+ super.tearDown();
+ }
+
+ /** The user should have the ephemeral flag set if it was created as ephemeral. */
+ public void testCreateEphemeralUser() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ int userId = createUser(true);
+ int flags = getUserFlags(userId);
+ assertTrue("ephemeral flag must be set", FLAG_EPHEMERAL == (flags & FLAG_EPHEMERAL));
+ }
+
+ /** The user should not have the ephemeral flag set if it was not created as ephemeral. */
+ public void testCreateLongLivedUser() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ int userId = createUser(false);
+ int flags = getUserFlags(userId);
+ assertTrue("ephemeral flag must not be set", 0 == (flags & FLAG_EPHEMERAL));
+ }
+
+ /**
+ * The profile should have the ephemeral flag set automatically if its parent user is
+ * ephemeral.
+ */
+ public void testProfileInheritsEphemeral() throws Exception {
+ if (!mHasFeature || !hasDeviceFeature("android.software.managed_users")
+ || !hasUserSplit() || !canCreateUsers(2)) {
+ return;
+ }
+ int userId = createUser(true);
+ int profileId = createManagedProfile(userId);
+ int flags = getUserFlags(profileId);
+ assertTrue("ephemeral flag must be set", FLAG_EPHEMERAL == (flags & FLAG_EPHEMERAL));
+ }
+
+ /**
+ * Ephemeral user should be automatically removed after it is stopped.
+ */
+ public void testRemoveEphemeralOnStop() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ int userId = createUser(true);
+ startUser(userId);
+ assertTrue("ephemeral user must exists after start", listUsers().contains(userId));
+ stopUser(userId);
+ assertFalse("ephemeral user must be removed after stop", listUsers().contains(userId));
+ }
+
+ /** Checks whether it is possible to create the desired number of users. */
+ private boolean canCreateUsers(int numberOfUsers) throws DeviceNotAvailableException {
+ return listUsers().size() + numberOfUsers <= getMaxNumberOfUsersSupported();
+ }
+
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsMultiUserTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsMultiUserTest.java
index 1d5dd11..8da189f 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsMultiUserTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsMultiUserTest.java
@@ -25,13 +25,11 @@
* apps.
*/
public class LauncherAppsMultiUserTest extends BaseLauncherAppsTest {
- private static final String FEATURE_LIVE_TV = "android.software.live_tv";
private int mSecondaryUserId;
private int mSecondaryUserSerialNumber;
private boolean mMultiUserSupported;
- private boolean mHasLiveTvFeature;
@Override
protected void setUp() throws Exception {
@@ -39,7 +37,6 @@
// We need multi user to be supported in order to create a secondary user
// and api level 21 to support LauncherApps
mMultiUserSupported = getMaxNumberOfUsersSupported() > 1 && getDevice().getApiLevel() >= 21;
- mHasLiveTvFeature = hasDeviceFeature(FEATURE_LIVE_TV);
if (mMultiUserSupported) {
removeTestUsers();
@@ -61,7 +58,7 @@
}
public void testGetActivitiesForNonProfileFails() throws Exception {
- if (!mMultiUserSupported || mHasLiveTvFeature) {
+ if (!mMultiUserSupported) {
return;
}
installApp(SIMPLE_APP_APK);
@@ -76,7 +73,7 @@
}
public void testNoLauncherCallbackPackageAddedSecondaryUser() throws Exception {
- if (!mMultiUserSupported || mHasLiveTvFeature) {
+ if (!mMultiUserSupported) {
return;
}
startCallbackService();
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java
index bb26df1..b7ac088 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java
@@ -31,6 +31,7 @@
MANAGED_PROFILE_PKG + ".BaseManagedProfileTest$BasicAdminReceiver";
private int mProfileUserId;
+ private int mParentUserId;
private int mProfileSerialNumber;
private int mMainUserSerialNumber;
@@ -42,12 +43,13 @@
removeTestUsers();
installTestApps();
// Create a managed profile
- mProfileUserId = createManagedProfile();
+ mParentUserId = getPrimaryUser();
+ mProfileUserId = createManagedProfile(mParentUserId);
installApp(MANAGED_PROFILE_APK);
setProfileOwnerOrFail(MANAGED_PROFILE_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
mProfileUserId);
mProfileSerialNumber = getUserSerialNumber(mProfileUserId);
- mMainUserSerialNumber = getUserSerialNumber(0);
+ mMainUserSerialNumber = getUserSerialNumber(mParentUserId);
startUser(mProfileUserId);
}
}
@@ -73,10 +75,10 @@
assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
LAUNCHER_TESTS_CLASS,
"testSimpleAppInstalledForUser",
- 0, "-e testUser " + mProfileSerialNumber));
+ mParentUserId, "-e testUser " + mProfileSerialNumber));
assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
LAUNCHER_TESTS_PKG + ".LauncherAppsTests", "testSimpleAppInstalledForUser",
- 0, "-e testUser " + mMainUserSerialNumber));
+ mParentUserId, "-e testUser " + mMainUserSerialNumber));
} finally {
getDevice().uninstallPackage(SIMPLE_APP_PKG);
}
@@ -92,7 +94,7 @@
assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
LAUNCHER_TESTS_CLASS,
"testPackageAddedCallbackForUser",
- 0, "-e testUser " + mProfileSerialNumber));
+ mParentUserId, "-e testUser " + mProfileSerialNumber));
} finally {
getDevice().uninstallPackage(SIMPLE_APP_PKG);
}
@@ -109,7 +111,7 @@
assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
LAUNCHER_TESTS_CLASS,
"testPackageRemovedCallbackForUser",
- 0, "-e testUser " + mProfileSerialNumber));
+ mParentUserId, "-e testUser " + mProfileSerialNumber));
} finally {
getDevice().uninstallPackage(SIMPLE_APP_PKG);
}
@@ -126,7 +128,7 @@
assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
LAUNCHER_TESTS_CLASS,
"testPackageChangedCallbackForUser",
- 0, "-e testUser " + mProfileSerialNumber));
+ mParentUserId, "-e testUser " + mProfileSerialNumber));
} finally {
getDevice().uninstallPackage(SIMPLE_APP_PKG);
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 6dc47e6..16ef52b 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -48,6 +48,15 @@
private static final String WIDGET_PROVIDER_APK = "CtsWidgetProviderApp.apk";
private static final String WIDGET_PROVIDER_PKG = "com.android.cts.widgetprovider";
+ private static final String DIRECTORY_PROVIDER_APK = "CtsContactDirectoryProvider.apk";
+ private static final String DIRECTORY_PROVIDER_PKG
+ = "com.android.cts.contactdirectoryprovider";
+ private static final String PRIMARY_DIRECTORY_PREFIX = "Primary";
+ private static final String MANAGED_DIRECTORY_PREFIX = "Managed";
+ private static final String DIRECTORY_PRIVOIDER_URI
+ = "content://com.android.cts.contact.directory.provider/";
+ private static final String SET_CUSTOM_DIRECTORY_PREFIX_METHOD = "set_prefix";
+
private static final String ADMIN_RECEIVER_TEST_CLASS =
MANAGED_PROFILE_PKG + ".BaseManagedProfileTest$BasicAdminReceiver";
@@ -57,10 +66,10 @@
private static final String ADD_RESTRICTION_COMMAND = "add-restriction";
- private static final int USER_OWNER = 0;
+ private int mParentUserId;
- // ID of the profile we'll create. This will always be a profile of USER_OWNER.
- private int mUserId;
+ // ID of the profile we'll create. This will always be a profile of the parent.
+ private int mProfileUserId;
private String mPackageVerifier;
private boolean mHasNfcFeature;
@@ -76,18 +85,21 @@
if (mHasFeature) {
removeTestUsers();
- mUserId = createManagedProfile();
+ mParentUserId = getPrimaryUser();
+ mProfileUserId = createManagedProfile(mParentUserId);
installApp(MANAGED_PROFILE_APK);
- setProfileOwnerOrFail(MANAGED_PROFILE_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS, mUserId);
- startUser(mUserId);
+ setProfileOwnerOrFail(MANAGED_PROFILE_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
+ mProfileUserId);
+ switchUser(mParentUserId);
+ startUser(mProfileUserId);
}
}
@Override
protected void tearDown() throws Exception {
if (mHasFeature) {
- removeUser(mUserId);
+ removeUser(mProfileUserId);
getDevice().uninstallPackage(MANAGED_PROFILE_PKG);
getDevice().uninstallPackage(INTENT_SENDER_PKG);
getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
@@ -100,7 +112,8 @@
return;
}
assertTrue(runDeviceTestsAsUser(
- MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".ManagedProfileSetupTest", mUserId));
+ MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".ManagedProfileSetupTest",
+ mProfileUserId));
}
/**
@@ -110,18 +123,18 @@
if (!mHasFeature) {
return;
}
- assertTrue(listUsers().contains(mUserId));
+ assertTrue(listUsers().contains(mProfileUserId));
assertTrue(runDeviceTestsAsUser(
- MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".WipeDataTest", mUserId));
+ MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".WipeDataTest", mProfileUserId));
// Note: the managed profile is removed by this test, which will make removeUserCommand in
// tearDown() to complain, but that should be OK since its result is not asserted.
- assertFalse(listUsers().contains(mUserId));
+ assertFalse(listUsers().contains(mProfileUserId));
}
public void testMaxOneManagedProfile() throws Exception {
int newUserId = -1;
try {
- newUserId = createManagedProfile();
+ newUserId = createManagedProfile(mParentUserId);
} catch (AssertionFailedError expected) {
}
if (newUserId > 0) {
@@ -139,16 +152,17 @@
return;
}
assertTrue("WiFi config already exists and could not be removed", runDeviceTestsAsUser(
- MANAGED_PROFILE_PKG, ".WifiTest", "testRemoveWifiNetworkIfExists", USER_OWNER));
+ MANAGED_PROFILE_PKG, ".WifiTest", "testRemoveWifiNetworkIfExists", mParentUserId));
try {
installApp(WIFI_CONFIG_CREATOR_APK);
assertTrue("Failed to add WiFi config", runDeviceTestsAsUser(
- MANAGED_PROFILE_PKG, ".WifiTest", "testAddWifiNetwork", mUserId));
+ MANAGED_PROFILE_PKG, ".WifiTest", "testAddWifiNetwork", mProfileUserId));
// Now delete the user - should undo the effect of testAddWifiNetwork.
- removeUser(mUserId);
+ removeUser(mProfileUserId);
assertTrue("WiFi config not removed after deleting profile", runDeviceTestsAsUser(
- MANAGED_PROFILE_PKG, ".WifiTest", "testWifiNetworkDoesNotExist", USER_OWNER));
+ MANAGED_PROFILE_PKG, ".WifiTest", "testWifiNetworkDoesNotExist",
+ mParentUserId));
} finally {
getDevice().uninstallPackage(WIFI_CONFIG_CREATOR_APK);
}
@@ -160,14 +174,14 @@
}
// Set up activities: ManagedProfileActivity will only be enabled in the managed profile and
// PrimaryUserActivity only in the primary one
- disableActivityForUser("ManagedProfileActivity", 0);
- disableActivityForUser("PrimaryUserActivity", mUserId);
+ disableActivityForUser("ManagedProfileActivity", mParentUserId);
+ disableActivityForUser("PrimaryUserActivity", mProfileUserId);
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG,
- MANAGED_PROFILE_PKG + ".ManagedProfileTest", mUserId));
+ MANAGED_PROFILE_PKG + ".ManagedProfileTest", mProfileUserId));
// Set up filters from primary to managed profile
- String command = "am start -W --user " + mUserId + " " + MANAGED_PROFILE_PKG
+ String command = "am start -W --user " + mProfileUserId + " " + MANAGED_PROFILE_PKG
+ "/.PrimaryUserFilterSetterActivity";
CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
+ getDevice().executeShellCommand(command));
@@ -182,32 +196,31 @@
// Disable all pre-existing browsers in the managed profile so they don't interfere with
// intents resolution.
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
- "testDisableAllBrowsers", mUserId));
+ "testDisableAllBrowsers", mProfileUserId));
installApp(INTENT_RECEIVER_APK);
installApp(INTENT_SENDER_APK);
- changeVerificationStatus(USER_OWNER, INTENT_RECEIVER_PKG, "ask");
- changeVerificationStatus(mUserId, INTENT_RECEIVER_PKG, "ask");
+ changeVerificationStatus(mParentUserId, INTENT_RECEIVER_PKG, "ask");
+ changeVerificationStatus(mProfileUserId, INTENT_RECEIVER_PKG, "ask");
// We should have two receivers: IntentReceiverActivity and BrowserActivity in the
// managed profile
assertAppLinkResult("testTwoReceivers");
changeUserRestrictionForUser("allow_parent_profile_app_linking", ADD_RESTRICTION_COMMAND,
- mUserId);
+ mProfileUserId);
// Now we should also have one receiver in the primary user, so three receivers in total.
assertAppLinkResult("testThreeReceivers");
- changeVerificationStatus(USER_OWNER, INTENT_RECEIVER_PKG, "never");
+ changeVerificationStatus(mParentUserId, INTENT_RECEIVER_PKG, "never");
// The primary user one has been set to never: we should only have the managed profile ones.
assertAppLinkResult("testTwoReceivers");
- changeVerificationStatus(mUserId, INTENT_RECEIVER_PKG, "never");
+ changeVerificationStatus(mProfileUserId, INTENT_RECEIVER_PKG, "never");
// Now there's only the browser in the managed profile left
assertAppLinkResult("testReceivedByBrowserActivityInManaged");
-
- changeVerificationStatus(mUserId, INTENT_RECEIVER_PKG, "always");
- changeVerificationStatus(USER_OWNER, INTENT_RECEIVER_PKG, "always");
+ changeVerificationStatus(mProfileUserId, INTENT_RECEIVER_PKG, "always");
+ changeVerificationStatus(mParentUserId, INTENT_RECEIVER_PKG, "always");
// We have one always in the primary user and one always in the managed profile: the managed
// profile one should have precedence.
assertAppLinkResult("testReceivedByAppLinkActivityInManaged");
@@ -219,7 +232,8 @@
return;
}
- assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".SettingsIntentsTest", mUserId));
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".SettingsIntentsTest",
+ mProfileUserId));
}
public void testCrossProfileContent() throws Exception {
@@ -231,17 +245,17 @@
// Test from parent to managed
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
- "testRemoveAllFilters", mUserId));
+ "testRemoveAllFilters", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
- "testAddManagedCanAccessParentFilters", mUserId));
- assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".ContentTest", 0));
+ "testAddManagedCanAccessParentFilters", mProfileUserId));
+ assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".ContentTest", mParentUserId));
// Test from managed to parent
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
- "testRemoveAllFilters", mUserId));
+ "testRemoveAllFilters", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
- "testAddParentCanAccessManagedFilters", mUserId));
- assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".ContentTest", mUserId));
+ "testAddParentCanAccessManagedFilters", mProfileUserId));
+ assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".ContentTest", mProfileUserId));
}
@@ -253,29 +267,29 @@
installApp(INTENT_SENDER_APK);
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
- "testAllowCrossProfileCopyPaste", mUserId));
+ "testAllowCrossProfileCopyPaste", mProfileUserId));
// Test that managed can see what is copied in the parent.
- testCrossProfileCopyPasteInternal(mUserId, true);
+ testCrossProfileCopyPasteInternal(mProfileUserId, true);
// Test that the parent can see what is copied in managed.
- testCrossProfileCopyPasteInternal(0, true);
+ testCrossProfileCopyPasteInternal(mParentUserId, true);
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
- "testDisallowCrossProfileCopyPaste", mUserId));
+ "testDisallowCrossProfileCopyPaste", mProfileUserId));
// Test that managed can still see what is copied in the parent.
- testCrossProfileCopyPasteInternal(mUserId, true);
+ testCrossProfileCopyPasteInternal(mProfileUserId, true);
// Test that the parent cannot see what is copied in managed.
- testCrossProfileCopyPasteInternal(0, false);
+ testCrossProfileCopyPasteInternal(mParentUserId, false);
}
private void testCrossProfileCopyPasteInternal(int userId, boolean shouldSucceed)
throws DeviceNotAvailableException {
- final String direction = (userId == 0)
+ final String direction = (userId == mParentUserId)
? "testAddManagedCanAccessParentFilters"
: "testAddParentCanAccessManagedFilters";
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
- "testRemoveAllFilters", mUserId));
+ "testRemoveAllFilters", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
- direction, mUserId));
+ direction, mProfileUserId));
if (shouldSucceed) {
assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".CopyPasteTest",
"testCanReadAcrossProfiles", userId));
@@ -289,7 +303,7 @@
// TODO: This test is not specific to managed profiles, but applies to multi-user in general.
// Move it to a MultiUserTest class when there is one. Should probably move
- // UserRestrictionActivity to a more generic apk too as it might be useful for different kinds
+ // SetPolicyActivity to a more generic apk too as it might be useful for different kinds
// of tests (same applies to ComponentDisablingActivity).
public void testNoDebuggingFeaturesRestriction() throws Exception {
if (!mHasFeature) {
@@ -306,14 +320,14 @@
String restriction = "no_debugging_features"; // UserManager.DISALLOW_DEBUGGING_FEATURES
String addRestrictionCommandOutput =
- changeUserRestrictionForUser(restriction, ADD_RESTRICTION_COMMAND, mUserId);
+ changeUserRestrictionForUser(restriction, ADD_RESTRICTION_COMMAND, mProfileUserId);
assertTrue("Command was expected to succeed " + addRestrictionCommandOutput,
addRestrictionCommandOutput.contains("Status: ok"));
// This should now fail, as the shell is not available to start activities under a different
// user once the restriction is in place.
addRestrictionCommandOutput =
- changeUserRestrictionForUser(restriction, ADD_RESTRICTION_COMMAND, mUserId);
+ changeUserRestrictionForUser(restriction, ADD_RESTRICTION_COMMAND, mProfileUserId);
assertTrue(
"Expected SecurityException when starting the activity "
+ addRestrictionCommandOutput,
@@ -328,13 +342,13 @@
}
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".BluetoothTest",
- "testEnableDisable", mUserId));
+ "testEnableDisable", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".BluetoothTest",
- "testGetAddress", mUserId));
+ "testGetAddress", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".BluetoothTest",
- "testListenUsingRfcommWithServiceRecord", mUserId));
+ "testListenUsingRfcommWithServiceRecord", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".BluetoothTest",
- "testGetRemoteDevice", mUserId));
+ "testGetRemoteDevice", mProfileUserId));
}
public void testCameraPolicy() throws Exception {
@@ -343,43 +357,43 @@
return;
}
try {
- setDeviceAdmin(MANAGED_PROFILE_PKG + "/.PrimaryUserDeviceAdmin");
+ setDeviceAdmin(MANAGED_PROFILE_PKG + "/.PrimaryUserDeviceAdmin", mParentUserId);
// Disable managed profile camera.
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CameraPolicyTest",
"testDisableCameraInManagedProfile",
- mUserId));
+ mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CameraPolicyTest",
"testIsCameraEnabledInPrimaryProfile",
- 0));
+ mParentUserId));
// Enable managed profile camera.
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CameraPolicyTest",
"testEnableCameraInManagedProfile",
- mUserId));
+ mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CameraPolicyTest",
"testIsCameraEnabledInPrimaryProfile",
- 0));
+ mParentUserId));
// Disable primary profile camera.
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CameraPolicyTest",
"testDisableCameraInPrimaryProfile",
- 0));
+ mParentUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CameraPolicyTest",
"testIsCameraEnabledInManagedProfile",
- mUserId));
+ mProfileUserId));
// Enable primary profile camera.
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CameraPolicyTest",
"testEnableCameraInPrimaryProfile",
- 0));
+ mParentUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CameraPolicyTest",
"testIsCameraEnabledInManagedProfile",
- mUserId));
+ mProfileUserId));
} finally {
final String adminHelperClass = ".PrimaryUserAdminHelper";
assertTrue("Clear device admin failed", runDeviceTestsAsUser(MANAGED_PROFILE_PKG,
- adminHelperClass, "testClearDeviceAdmin", 0 /* user 0 */));
+ adminHelperClass, "testClearDeviceAdmin", mParentUserId));
}
}
@@ -389,123 +403,209 @@
}
try {
+ // Install directory provider to both primary and managed profile
+ installAppAsUser(DIRECTORY_PROVIDER_APK, mProfileUserId);
+ installAppAsUser(DIRECTORY_PROVIDER_APK, mParentUserId);
+ setDirectoryPrefix(PRIMARY_DIRECTORY_PREFIX, mParentUserId);
+ setDirectoryPrefix(MANAGED_DIRECTORY_PREFIX, mProfileUserId);
+
+ // Check enterprise directory API works
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testGetDirectoryListInPrimaryProfile", mParentUserId));
+
// Insert Primary profile Contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfilePhoneAndEmailLookup_insertedAndfound", 0));
+ "testPrimaryProfilePhoneAndEmailLookup_insertedAndfound", mParentUserId));
// Insert Managed profile Contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfilePhoneAndEmailLookup_insertedAndfound", mUserId));
+ "testManagedProfilePhoneAndEmailLookup_insertedAndfound", mProfileUserId));
// Insert a primary contact with same phone & email as other enterprise contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileDuplicatedPhoneEmailContact_insertedAndfound", 0));
+ "testPrimaryProfileDuplicatedPhoneEmailContact_insertedAndfound",
+ mParentUserId));
// Insert a enterprise contact with same phone & email as other primary contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfileDuplicatedPhoneEmailContact_insertedAndfound", mUserId));
-
+ "testManagedProfileDuplicatedPhoneEmailContact_insertedAndfound",
+ mProfileUserId));
// Set cross profile caller id to enabled
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testSetCrossProfileCallerIdDisabled_false", mUserId));
+ "testSetCrossProfileCallerIdDisabled_false", mProfileUserId));
// Primary user cannot use ordinary phone/email lookup api to access managed contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfilePhoneLookup_canNotAccessEnterpriseContact", 0));
+ "testPrimaryProfilePhoneLookup_canNotAccessEnterpriseContact", mParentUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileEmailLookup_canNotAccessEnterpriseContact", 0));
+ "testPrimaryProfileEmailLookup_canNotAccessEnterpriseContact", mParentUserId));
// Primary user can use ENTERPRISE_CONTENT_FILTER_URI to access primary contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileEnterprisePhoneLookup_canAccessPrimaryContact", 0));
+ "testPrimaryProfileEnterprisePhoneLookup_canAccessPrimaryContact",
+ mParentUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileEnterpriseEmailLookup_canAccessPrimaryContact", 0));
+ "testPrimaryProfileEnterpriseEmailLookup_canAccessPrimaryContact",
+ mParentUserId));
// Primary user can use ENTERPRISE_CONTENT_FILTER_URI to access managed profile contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileEnterprisePhoneLookup_canAccessEnterpriseContact", 0));
+ "testPrimaryProfileEnterprisePhoneLookup_canAccessEnterpriseContact",
+ mParentUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileEnterpriseEmailLookup_canAccessEnterpriseContact", 0));
+ "testPrimaryProfileEnterpriseEmailLookup_canAccessEnterpriseContact",
+ mParentUserId));
// When there exist contacts with the same phone/email in primary & enterprise,
// primary user can use ENTERPRISE_CONTENT_FILTER_URI to access the primary contact.
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testPrimaryProfileEnterpriseEmailLookupDuplicated_canAccessPrimaryContact",
- 0));
+ mParentUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testPrimaryProfileEnterprisePhoneLookupDuplicated_canAccessPrimaryContact",
- 0));
+ mParentUserId));
// Make sure SIP enterprise lookup works too.
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileEnterpriseSipLookup_canAccessEnterpriseContact", 0));
+ "testPrimaryProfileEnterpriseSipLookup_canAccessEnterpriseContact",
+ mParentUserId));
// Managed user cannot use ordinary phone/email lookup api to access primary contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfilePhoneLookup_canNotAccessPrimaryContact", mUserId));
+ "testManagedProfilePhoneLookup_canNotAccessPrimaryContact", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfileEmailLookup_canNotAccessPrimaryContact", mUserId));
+ "testManagedProfileEmailLookup_canNotAccessPrimaryContact", mProfileUserId));
// Managed user can use ENTERPRISE_CONTENT_FILTER_URI to access enterprise contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfileEnterprisePhoneLookup_canAccessEnterpriseContact", mUserId));
+ "testManagedProfileEnterprisePhoneLookup_canAccessEnterpriseContact",
+ mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfileEnterpriseEmailLookup_canAccessEnterpriseContact", mUserId));
+ "testManagedProfileEnterpriseEmailLookup_canAccessEnterpriseContact",
+ mProfileUserId));
// Managed user cannot use ENTERPRISE_CONTENT_FILTER_URI to access primary contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfileEnterprisePhoneLookup_canNotAccessPrimaryContact", mUserId));
+ "testManagedProfileEnterprisePhoneLookup_canNotAccessPrimaryContact",
+ mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfileEnterpriseEmailLookup_canNotAccessPrimaryContact", mUserId));
+ "testManagedProfileEnterpriseEmailLookup_canNotAccessPrimaryContact",
+ mProfileUserId));
// When there exist contacts with the same phone/email in primary & enterprise,
// managed user can use ENTERPRISE_CONTENT_FILTER_URI to access the enterprise contact.
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testManagedProfileEnterpriseEmailLookupDuplicated_canAccessEnterpriseContact",
- mUserId));
+ mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testManagedProfileEnterprisePhoneLookupDuplicated_canAccessEnterpriseContact",
- mUserId));
+ mProfileUserId));
// Set cross profile caller id to disabled
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testSetCrossProfileCallerIdDisabled_true", mUserId));
+ "testSetCrossProfileCallerIdDisabled_true", mProfileUserId));
// Primary user cannot use ordinary phone/email lookup api to access managed contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfilePhoneLookup_canNotAccessEnterpriseContact", 0));
+ "testPrimaryProfilePhoneLookup_canNotAccessEnterpriseContact", mParentUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileEmailLookup_canNotAccessEnterpriseContact", 0));
+ "testPrimaryProfileEmailLookup_canNotAccessEnterpriseContact", mParentUserId));
// Primary user cannot use ENTERPRISE_CONTENT_FILTER_URI to access managed contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileEnterprisePhoneLookup_canNotAccessEnterpriseContact", 0));
+ "testPrimaryProfileEnterprisePhoneLookup_canNotAccessEnterpriseContact",
+ mParentUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testPrimaryProfileEnterpriseEmailLookup_canNotAccessEnterpriseContact", 0));
+ "testPrimaryProfileEnterpriseEmailLookup_canNotAccessEnterpriseContact",
+ mParentUserId));
// When there exist contacts with the same phone/email in primary & enterprise,
// primary user can use ENTERPRISE_CONTENT_FILTER_URI to access primary contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testPrimaryProfileEnterpriseEmailLookupDuplicated_canAccessPrimaryContact",
- 0));
+ mParentUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testPrimaryProfileEnterprisePhoneLookupDuplicated_canAccessPrimaryContact",
- 0));
+ mParentUserId));
// Managed user cannot use ordinary phone/email lookup api to access primary contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfilePhoneLookup_canNotAccessPrimaryContact", mUserId));
+ "testManagedProfilePhoneLookup_canNotAccessPrimaryContact", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfileEmailLookup_canNotAccessPrimaryContact", mUserId));
+ "testManagedProfileEmailLookup_canNotAccessPrimaryContact", mProfileUserId));
// Managed user cannot use ENTERPRISE_CONTENT_FILTER_URI to access primary contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfileEnterprisePhoneLookup_canNotAccessPrimaryContact", mUserId));
+ "testManagedProfileEnterprisePhoneLookup_canNotAccessPrimaryContact",
+ mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testManagedProfileEnterpriseEmailLookup_canNotAccessPrimaryContact", mUserId));
+ "testManagedProfileEnterpriseEmailLookup_canNotAccessPrimaryContact",
+ mProfileUserId));
+
+ // Set cross profile caller id to enabled
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testSetCrossProfileCallerIdDisabled_false", mProfileUserId));
+
// When there exist contacts with the same phone/email in primary & enterprise,
// managed user can use ENTERPRISE_CONTENT_FILTER_URI to access enterprise contacts
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testManagedProfileEnterpriseEmailLookupDuplicated_canAccessEnterpriseContact",
- mUserId));
+ mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testManagedProfileEnterprisePhoneLookupDuplicated_canAccessEnterpriseContact",
- mUserId));
+ mProfileUserId));
+
+ // Check if phone lookup can access primary directories
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterprisePhoneLookup_canAccessPrimaryDirectories",
+ mParentUserId));
+
+ // Check if phone lookup can access enterprise directories
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterprisePhoneLookup_canAccessManagedDirectories",
+ mParentUserId));
+
+ // Check if email lookup can access primary directories
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterpriseEmailLookup_canAccessPrimaryDirectories",
+ mParentUserId));
+
+ // Check if email lookup can access enterprise directories
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterpriseEmailLookup_canAccessManagedDirectories",
+ mParentUserId));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterpriseCallableFilter_canAccessPrimaryDirectories",
+ mParentUserId));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterpriseCallableFilter_canAccessManagedDirectories",
+ mParentUserId));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterpriseEmailFilter_canAccessPrimaryDirectories",
+ mParentUserId));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterpriseEmailFilter_canAccessManagedDirectories",
+ mParentUserId));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterpriseContactFilter_canAccessPrimaryDirectories",
+ mParentUserId));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterpriseContactFilter_canAccessManagedDirectories",
+ mParentUserId));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterprisePhoneFilter_canAccessPrimaryDirectories",
+ mParentUserId));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testPrimaryProfileEnterprisePhoneFilter_canAccessManagedDirectories",
+ mParentUserId));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testFilterUriWhenDirectoryParamMissing",
+ mParentUserId));
} finally {
// Clean up in managed profile and primary profile
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testCurrentProfileContacts_removeContacts", mUserId);
+ "testCurrentProfileContacts_removeContacts", mProfileUserId);
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testCurrentProfileContacts_removeContacts", 0);
+ "testCurrentProfileContacts_removeContacts", mParentUserId);
+ getDevice().uninstallPackage(DIRECTORY_PROVIDER_PKG);
}
}
@@ -514,7 +614,7 @@
return;
}
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
- "testSetBluetoothContactSharingDisabled_setterAndGetter", mUserId));
+ "testSetBluetoothContactSharingDisabled_setterAndGetter", mProfileUserId));
}
public void testCannotSetProfileOwnerAgain() throws Exception {
@@ -523,11 +623,11 @@
}
// verify that we can't set the same admin receiver as profile owner again
assertFalse(setProfileOwner(
- MANAGED_PROFILE_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS, mUserId));
+ MANAGED_PROFILE_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS, mProfileUserId));
// verify that we can't set a different admin receiver as profile owner
- installAppAsUser(DEVICE_OWNER_APK, mUserId);
- assertFalse(setProfileOwner(DEVICE_OWNER_PKG + "/" + DEVICE_OWNER_ADMIN, mUserId));
+ installAppAsUser(DEVICE_OWNER_APK, mProfileUserId);
+ assertFalse(setProfileOwner(DEVICE_OWNER_PKG + "/" + DEVICE_OWNER_ADMIN, mProfileUserId));
}
public void testCannotSetDeviceOwnerWhenProfilePresent() throws Exception {
@@ -551,22 +651,22 @@
}
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
- "testNfcShareEnabled", mUserId));
+ "testNfcShareEnabled", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
- "testNfcShareEnabled", 0));
+ "testNfcShareEnabled", mParentUserId));
String restriction = "no_outgoing_beam"; // UserManager.DISALLOW_OUTGOING_BEAM
String command = "add-restriction";
String addRestrictionCommandOutput =
- changeUserRestrictionForUser(restriction, command, mUserId);
+ changeUserRestrictionForUser(restriction, command, mProfileUserId);
assertTrue("Command was expected to succeed " + addRestrictionCommandOutput,
addRestrictionCommandOutput.contains("Status: ok"));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
- "testNfcShareDisabled", mUserId));
+ "testNfcShareDisabled", mProfileUserId));
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
- "testNfcShareEnabled", 0));
+ "testNfcShareEnabled", mParentUserId));
}
public void testCrossProfileWidgets() throws Exception {
@@ -576,40 +676,50 @@
try {
installApp(WIDGET_PROVIDER_APK);
- getDevice().executeShellCommand("appwidget grantbind --user 0 --package "
- + WIDGET_PROVIDER_PKG);
+ getDevice().executeShellCommand("appwidget grantbind --user " + mParentUserId
+ + " --package " + WIDGET_PROVIDER_PKG);
startWidgetHostService();
String commandOutput = changeCrossProfileWidgetForUser(WIDGET_PROVIDER_PKG,
- "add-cross-profile-widget", mUserId);
+ "add-cross-profile-widget", mProfileUserId);
assertTrue("Command was expected to succeed " + commandOutput,
commandOutput.contains("Status: ok"));
assertTrue(runDeviceTests(MANAGED_PROFILE_PKG, ".CrossProfileWidgetTest",
- "testCrossProfileWidgetProviderAdded", mUserId));
+ "testCrossProfileWidgetProviderAdded", mProfileUserId));
assertTrue(runDeviceTests(MANAGED_PROFILE_PKG, ".CrossProfileWidgetPrimaryUserTest",
- "testHasCrossProfileWidgetProvider_true", 0));
+ "testHasCrossProfileWidgetProvider_true", mParentUserId));
assertTrue(runDeviceTests(MANAGED_PROFILE_PKG, ".CrossProfileWidgetPrimaryUserTest",
- "testHostReceivesWidgetUpdates_true", 0));
+ "testHostReceivesWidgetUpdates_true", mParentUserId));
commandOutput = changeCrossProfileWidgetForUser(WIDGET_PROVIDER_PKG,
- "remove-cross-profile-widget", mUserId);
+ "remove-cross-profile-widget", mProfileUserId);
assertTrue("Command was expected to succeed " + commandOutput,
commandOutput.contains("Status: ok"));
assertTrue(runDeviceTests(MANAGED_PROFILE_PKG, ".CrossProfileWidgetTest",
- "testCrossProfileWidgetProviderRemoved", mUserId));
+ "testCrossProfileWidgetProviderRemoved", mProfileUserId));
assertTrue(runDeviceTests(MANAGED_PROFILE_PKG, ".CrossProfileWidgetPrimaryUserTest",
- "testHasCrossProfileWidgetProvider_false", 0));
+ "testHasCrossProfileWidgetProvider_false", mParentUserId));
assertTrue(runDeviceTests(MANAGED_PROFILE_PKG, ".CrossProfileWidgetPrimaryUserTest",
- "testHostReceivesWidgetUpdates_false", 0));
+ "testHostReceivesWidgetUpdates_false", mParentUserId));
} finally {
changeCrossProfileWidgetForUser(WIDGET_PROVIDER_PKG, "remove-cross-profile-widget",
- mUserId);
+ mProfileUserId);
getDevice().uninstallPackage(WIDGET_PROVIDER_PKG);
}
}
+ private void setDirectoryPrefix(String directoryName, int userId)
+ throws DeviceNotAvailableException {
+ String command = "content call --uri " + DIRECTORY_PRIVOIDER_URI
+ + " --user " + userId
+ + " --method " + SET_CUSTOM_DIRECTORY_PREFIX_METHOD
+ + " --arg " + directoryName;
+ CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
+ + getDevice().executeShellCommand(command));
+ }
+
private void disableActivityForUser(String activityName, int userId)
throws DeviceNotAvailableException {
String command = "am start -W --user " + userId
@@ -655,15 +765,16 @@
}
protected void startWidgetHostService() throws Exception {
- String command = "am startservice --user 0 "
- + "-a " + WIDGET_PROVIDER_PKG + ".REGISTER_CALLBACK "
- + "--ei user-extra " + getUserSerialNumber(mUserId)
+ String command = "am startservice --user " + mParentUserId
+ + " -a " + WIDGET_PROVIDER_PKG + ".REGISTER_CALLBACK "
+ + "--ei user-extra " + getUserSerialNumber(mProfileUserId)
+ " " + WIDGET_PROVIDER_PKG + "/.SimpleAppWidgetHostService";
CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
+ getDevice().executeShellCommand(command));
}
private void assertAppLinkResult(String methodName) throws DeviceNotAvailableException {
- assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".AppLinkTest", methodName, mUserId));
+ assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".AppLinkTest", methodName,
+ mProfileUserId));
}
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
index bcc5bf9..0b33e8f 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
@@ -28,6 +28,8 @@
*/
public class MixedProfileOwnerTest extends DeviceAndProfileOwnerTest {
+ private int mParentUserId = -1;
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -37,7 +39,10 @@
if (mHasFeature) {
removeTestUsers();
- mUserId = createManagedProfile();
+ mParentUserId = getPrimaryUser();
+ mUserId = createManagedProfile(mParentUserId);
+ switchUser(mParentUserId);
+ startUser(mUserId);
installAppAsUser(DEVICE_ADMIN_APK, mUserId);
setProfileOwnerOrFail(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS, mUserId);
@@ -64,9 +69,9 @@
return;
}
executeDeviceTestMethod(".ScreenCaptureDisabledTest", "testSetScreenCaptureDisabled_true");
- // start the ScreenCaptureDisabledActivity in the primary user
- installAppAsUser(DEVICE_ADMIN_APK, USER_OWNER);
- String command = "am start -W --user 0 " + DEVICE_ADMIN_PKG + "/"
+ // start the ScreenCaptureDisabledActivity in the parent
+ installAppAsUser(DEVICE_ADMIN_APK, mParentUserId);
+ String command = "am start -W --user " + mParentUserId + " " + DEVICE_ADMIN_PKG + "/"
+ DEVICE_ADMIN_PKG + ".ScreenCaptureDisabledActivity";
getDevice().executeShellCommand(command);
executeDeviceTestMethod(".ScreenCaptureDisabledTest", "testScreenCapturePossible");
diff --git a/hostsidetests/dumpsys/Android.mk b/hostsidetests/dumpsys/Android.mk
index 5b63199..c3432cf 100644
--- a/hostsidetests/dumpsys/Android.mk
+++ b/hostsidetests/dumpsys/Android.mk
@@ -21,9 +21,14 @@
# Must match the package name in CtsTestCaseList.mk
LOCAL_MODULE := CtsDumpsysHostTestCases
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed_v2 tradefed-prebuilt
-LOCAL_CTS_TEST_PACKAGE := android.host.dumpsys
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
+
+LOCAL_CTS_TEST_PACKAGE := android.dumpsys
+
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/dumpsys/AndroidTest.xml b/hostsidetests/dumpsys/AndroidTest.xml
new file mode 100644
index 0000000..f1ebc79
--- /dev/null
+++ b/hostsidetests/dumpsys/AndroidTest.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<configuration description="Config for the CTS dumpsys host tests">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest">
+ <option name="jar" value="CtsDumpsysHostTestCases.jar" />
+ </test>
+</configuration>
diff --git a/hostsidetests/dumpsys/FramestatsTestApp/Android.mk b/hostsidetests/dumpsys/FramestatsTestApp/Android.mk
index 1104523..e13e2b4 100644
--- a/hostsidetests/dumpsys/FramestatsTestApp/Android.mk
+++ b/hostsidetests/dumpsys/FramestatsTestApp/Android.mk
@@ -25,4 +25,7 @@
LOCAL_PACKAGE_NAME := CtsFramestatsTestApp
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/DumpsysHostTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/DumpsysHostTest.java
index 0daae03..e9b08a4 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/DumpsysHostTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/DumpsysHostTest.java
@@ -16,7 +16,7 @@
package android.dumpsys.cts;
-import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.migration.MigrationHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -30,7 +30,8 @@
import java.util.Set;
/**
- * Test to check the format of the dumps of various services (currently only procstats is tested).
+ * Test to check the format of the dumps of various services.
+ * Currently procstats and batterystats are tested.
*/
public class DumpsysHostTest extends DeviceTestCase implements IBuildReceiver {
private static final String TAG = "DumpsysHostTest";
@@ -486,6 +487,8 @@
case "ctr":
checkChargeTimeRemain(parts);
break;
+ case "cpu":
+ checkUidCpuUsage(parts);
default:
break;
}
@@ -515,12 +518,15 @@
private void checkApk(String[] parts) {
assertEquals(10, parts.length);
- assertInteger(parts[4]); // wakeups
+ long wakeup_count = assertInteger(parts[4]); // wakeups
assertNotNull(parts[5]); // apk
assertNotNull(parts[6]); // service
assertInteger(parts[7]); // startTime
assertInteger(parts[8]); // starts
assertInteger(parts[9]); // launches
+
+ // Sanity check.
+ assertTrue("wakeup count must be >= 0", wakeup_count >= 0);
}
private void checkProcess(String[] parts) {
@@ -563,13 +569,18 @@
assertNotNull(parts[4]); // wakelock
assertInteger(parts[5]); // full totalTime
assertEquals("f", parts[6]); // full
- assertInteger(parts[7]); // full count
+ long full_count = assertInteger(parts[7]); // full count
assertInteger(parts[8]); // partial totalTime
assertEquals("p", parts[9]); // partial
- assertInteger(parts[10]); // partial count
+ long partial_count = assertInteger(parts[10]); // partial count
assertInteger(parts[11]); // window totalTime
assertEquals("w", parts[12]); // window
- assertInteger(parts[13]); // window count
+ long window_count = assertInteger(parts[13]); // window count
+
+ // Sanity checks.
+ assertTrue("full wakelock count must be >= 0", full_count >= 0);
+ assertTrue("partial wakelock count must be >= 0", partial_count >= 0);
+ assertTrue("window wakelock count must be >= 0", window_count >= 0);
}
private void checkSync(String[] parts) {
@@ -604,16 +615,26 @@
private void checkNetwork(String[] parts) {
assertEquals(14, parts.length);
- assertInteger(parts[4]); // mobileBytesRx
- assertInteger(parts[5]); // mobileBytesTx
- assertInteger(parts[6]); // wifiBytesRx
- assertInteger(parts[7]); // wifiBytesTx
- assertInteger(parts[8]); // mobilePacketsRx
- assertInteger(parts[9]); // mobilePacketsTx
- assertInteger(parts[10]); // wifiPacketsRx
- assertInteger(parts[11]); // wifiPacketsTx
+ long mbRx = assertInteger(parts[4]); // mobileBytesRx
+ long mbTx = assertInteger(parts[5]); // mobileBytesTx
+ long wbRx = assertInteger(parts[6]); // wifiBytesRx
+ long wbTx = assertInteger(parts[7]); // wifiBytesTx
+ long mpRx = assertInteger(parts[8]); // mobilePacketsRx
+ long mpTx = assertInteger(parts[9]); // mobilePacketsTx
+ long wpRx = assertInteger(parts[10]); // wifiPacketsRx
+ long wpTx = assertInteger(parts[11]); // wifiPacketsTx
assertInteger(parts[12]); // mobileActiveTime (usec)
assertInteger(parts[13]); // mobileActiveCount
+
+ // Assuming each packet contains some bytes, bytes >= packets >= 0.
+ assertTrue("mobileBytesRx must be >= mobilePacketsRx", mbRx >= mpRx);
+ assertTrue("mobilePacketsRx must be >= 0", mpRx >= 0);
+ assertTrue("mobileBytesTx must be >= mobilePacketsTx", mbTx >= mpTx);
+ assertTrue("mobilePacketsTx must be >= 0", mpTx >= 0);
+ assertTrue("wifiBytesRx must be >= wifiPacketsRx", wbRx >= wpRx);
+ assertTrue("wifiPacketsRx must be >= 0", wpRx >= 0);
+ assertTrue("wifiBytesTx must be >= wifiPacketsTx", wbTx >= wpTx);
+ assertTrue("wifiPacketsTx must be >= 0", wpTx >= 0);
}
private void checkUserActivity(String[] parts) {
@@ -628,13 +649,27 @@
if (!parts[4].equals("N/A")) {
assertInteger(parts[4]); // startCount
}
- assertInteger(parts[5]); // batteryRealtime
- assertInteger(parts[6]); // batteryUptime
- assertInteger(parts[7]); // totalRealtime
- assertInteger(parts[8]); // totalUptime
+ long bReal = assertInteger(parts[5]); // batteryRealtime
+ long bUp = assertInteger(parts[6]); // batteryUptime
+ long tReal = assertInteger(parts[7]); // totalRealtime
+ long tUp = assertInteger(parts[8]); // totalUptime
assertInteger(parts[9]); // startClockTime
- assertInteger(parts[10]); // batteryScreenOffRealtime
- assertInteger(parts[11]); // batteryScreenOffUptime
+ long bOffReal = assertInteger(parts[10]); // batteryScreenOffRealtime
+ long bOffUp = assertInteger(parts[11]); // batteryScreenOffUptime
+
+ // The device cannot be up more than there are real-world seconds.
+ assertTrue("batteryRealtime must be >= batteryUptime", bReal >= bUp);
+ assertTrue("totalRealtime must be >= totalUptime", tReal >= tUp);
+ assertTrue("batteryScreenOffRealtime must be >= batteryScreenOffUptime",
+ bOffReal >= bOffUp);
+
+ // total >= battery >= battery screen-off >= 0
+ assertTrue("totalRealtime must be >= batteryRealtime", tReal >= bReal);
+ assertTrue("batteryRealtime must be >= batteryScreenOffRealtime", bReal >= bOffReal);
+ assertTrue("batteryScreenOffRealtime must be >= 0", bOffReal >= 0);
+ assertTrue("totalUptime must be >= batteryUptime", tUp >= bUp);
+ assertTrue("batteryUptime must be >= batteryScreenOffUptime", bUp >= bOffUp);
+ assertTrue("batteryScreenOffUptime must be >= 0", bOffUp >= 0);
}
private void checkBatteryDischarge(String[] parts) {
@@ -790,7 +825,11 @@
private void checkPowerUseItem(String[] parts) {
assertEquals(6, parts.length);
assertNotNull(parts[4]); // label
- assertDouble(parts[5]); // mAh
+ double mAH = assertDouble(parts[5]); // mAh
+
+ assertTrue("powerUseItem mAH must be >= 0", mAH >= 0);
+ // Largest current Android battery is ~5K. 100K shouldn't get made for a while.
+ assertTrue("powerUseItem mAH is expected to be <= 100000", mAH <= 100000);
}
private void checkChargeDischargeStep(String[] parts) {
@@ -814,6 +853,12 @@
assertInteger(parts[4]); // chargeTimeRemaining
}
+ private void checkUidCpuUsage(String[] parts) {
+ assertTrue(parts.length >= 6);
+ assertInteger(parts[4]); // user time
+ assertInteger(parts[5]); // system time
+ }
+
/**
* Tests the output of "dumpsys gfxinfo framestats".
*
@@ -827,7 +872,7 @@
getDevice().uninstallPackage(TEST_PKG);
// install the test app
- File testAppFile = mCtsBuild.getTestApp(TEST_APK);
+ File testAppFile = MigrationHelper.getTestFile(mCtsBuild, TEST_APK);
String installResult = getDevice().installPackage(testAppFile, false);
assertNull(
String.format("failed to install atrace test app. Reason: %s", installResult),
@@ -899,14 +944,14 @@
assertTrue(foundAtLeastOneRow);
}
- private CtsBuildHelper mCtsBuild;
+ private IBuildInfo mCtsBuild;
/**
* {@inheritDoc}
*/
@Override
public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ mCtsBuild = buildInfo;
}
private static long assertInteger(String input) {
@@ -919,11 +964,12 @@
}
}
- private static void assertDouble(String input) {
+ private static double assertDouble(String input) {
try {
- Double.parseDouble(input);
+ return Double.parseDouble(input);
} catch (NumberFormatException e) {
fail("Expected a double but found \"" + input + "\"");
+ return -1;
}
}
diff --git a/hostsidetests/jank/Android.mk b/hostsidetests/jank/Android.mk
new file mode 100644
index 0000000..0698e53
--- /dev/null
+++ b/hostsidetests/jank/Android.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2013 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := CtsJankHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed_v2 compatibility-host-util tradefed-prebuilt
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_CTS_TEST_PACKAGE := android.jank.cts
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_DEVICE_JAR_ := CtsJankTestJar
+cts_library_jar_ := $(CTS_TESTCASES_OUT)/$(LOCAL_DEVICE_JAR_).jar
+
+$(cts_library_jar_): $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_DEVICE_JAR_))/javalib.jar | $(ACP)
+ $(hide) mkdir -p $(CTS_TESTCASES_OUT)
+ $(hide) $(ACP) -fp $< $@
+
+$(CTS_TESTCASES_OUT)/CtsJankHostTestCases.xml: $(cts_library_jar_)
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+$(COMPATIBILITY_TESTCASES_OUT_cts_v2)/CtsJankHostTestCases.jar : $(COMPATIBILITY_TESTCASES_OUT_cts_v2)/CtsOpenGlPerf2TestCases.apk
+
+# Build the library using its own makefile
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/jank/AndroidTest.xml b/hostsidetests/jank/AndroidTest.xml
new file mode 100644
index 0000000..a938678
--- /dev/null
+++ b/hostsidetests/jank/AndroidTest.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<configuration description="Config for CTS Jank host test cases">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsJankHostTestCases.jar" />
+ <option name="runtime-hint" value="4m41s" />
+ </test>
+</configuration>
diff --git a/hostsidetests/jank/app/Android.mk b/hostsidetests/jank/app/Android.mk
new file mode 100644
index 0000000..13f917e
--- /dev/null
+++ b/hostsidetests/jank/app/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2013 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := CtsJankTestJar
+LOCAL_DEX_PREOPT := false
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_JAVA_LIBRARIES := uiautomator.core
+
+LOCAL_STATIC_JAVA_LIBRARIES := com.android.uiautomator.platform.common
+
+include $(BUILD_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/hostsidetests/jank/app/src/android/jank/cts/CtsJankTestBase.java b/hostsidetests/jank/app/src/android/jank/cts/CtsJankTestBase.java
new file mode 100644
index 0000000..1eda12f
--- /dev/null
+++ b/hostsidetests/jank/app/src/android/jank/cts/CtsJankTestBase.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013 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.jank.cts;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.uiautomator.platform.JankTestBase;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Scanner;
+
+public class CtsJankTestBase extends JankTestBase {
+ private final static String TAG = CtsJankTestBase.class.getName();
+ protected final static String START_CMD = "am start -W -a android.intent.action.MAIN -n %s";
+ protected final static String STOP_CMD = "am force-stop %s";
+ protected final static String INTENT_STRING_EXTRA = " --es %s %s";
+ protected final static String INTENT_BOOLEAN_EXTRA = " --ez %s %b";
+ protected final static String INTENT_INTEGER_EXTRA = " --ei %s %d";
+ protected static long SLEEP_TIME = 2000; // 2 seconds
+ protected static int NUM_ITERATIONS = 5;
+ protected static int TRACE_TIME = 5;
+
+ @Override
+ protected String getPropertyString(Bundle params, String key)
+ throws FileNotFoundException, IOException {
+ if (key.equals("iteration")) {
+ return NUM_ITERATIONS + "";
+ }
+ if (key.equals("tracetime")) {
+ return TRACE_TIME + "";
+ }
+ return super.getPropertyString(params, key);
+ }
+
+ protected void runShellCommand(String command) throws Exception {
+ Process p = null;
+ Scanner out = null;
+ Scanner err = null;
+ try {
+ p = Runtime.getRuntime().exec(command);
+
+ StringBuilder outStr = new StringBuilder();
+ StringBuilder errStr = new StringBuilder();
+ out = new Scanner(p.getInputStream());
+ err = new Scanner(p.getErrorStream());
+ boolean read = true;
+ while (read) {
+ if (out.hasNextLine()) {
+ outStr.append(out.nextLine());
+ outStr.append("\n");
+ } else if (err.hasNextLine()) {
+ errStr.append(err.nextLine());
+ errStr.append("\n");
+ } else {
+ read = false;
+ }
+ }
+ Log.i(TAG, command);
+ if (outStr.length() > 0) {
+ Log.i(TAG, outStr.toString());
+ }
+ if (errStr.length() > 0) {
+ Log.e(TAG, errStr.toString());
+ }
+ } finally {
+ if (p != null) {
+ int status = p.waitFor();
+ if (status != 0) {
+ throw new RuntimeException(
+ String.format("Run shell command: %s, status: %s", command, status));
+ }
+ p.destroy();
+ p = null;
+ }
+ if (out != null) {
+ out.close();
+ }
+ if (err != null) {
+ err.close();
+ }
+ }
+ }
+}
diff --git a/hostsidetests/jank/app/src/android/jank/cts/opengl/CtsDeviceJankOpenGl.java b/hostsidetests/jank/app/src/android/jank/cts/opengl/CtsDeviceJankOpenGl.java
new file mode 100755
index 0000000..46dc06c
--- /dev/null
+++ b/hostsidetests/jank/app/src/android/jank/cts/opengl/CtsDeviceJankOpenGl.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 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.jank.cts.opengl;
+
+import android.jank.cts.CtsJankTestBase;
+import android.util.Log;
+
+import com.android.uiautomator.platform.SurfaceFlingerHelper;
+
+public class CtsDeviceJankOpenGl extends CtsJankTestBase {
+ private final static String TAG = CtsDeviceJankOpenGl.class.getName();
+ private final static String PACKAGE = "android.opengl2.cts";
+ private final static String COMPONENT =
+ PACKAGE + "/" + PACKAGE + ".primitive.GLPrimitiveActivity";
+ private static String APP_WINDOW_NAME = "SurfaceView";
+
+ /**
+ * Runs the full OpenGL ES 2.0 pipeline test.
+ */
+ public void testFullPipeline() throws Exception {
+ runBenchmark("FullPipeline");
+ }
+
+ /**
+ * Runs the pixel output test.
+ */
+ public void testPixelOutput() throws Exception {
+ runBenchmark("PixelOutput");
+ }
+
+ /**
+ * Runs the shader performance test.
+ */
+ public void testShaderPerf() throws Exception {
+ runBenchmark("ShaderPerf");
+ }
+
+ /**
+ * Runs the context switch overhead test.
+ */
+ public void testContextSwitch() throws Exception {
+ runBenchmark("ContextSwitch");
+ }
+
+ /**
+ * Runs the benchhmark for jank test.
+ */
+ public void runBenchmark(String benchmark) throws Exception {
+ // Start activity command
+ final StringBuilder sb = new StringBuilder();
+ sb.append(String.format(START_CMD, COMPONENT));
+ sb.append(String.format(INTENT_STRING_EXTRA, "benchmark_name", benchmark));
+ sb.append(String.format(INTENT_BOOLEAN_EXTRA, "offscreen", false));
+ sb.append(String.format(INTENT_INTEGER_EXTRA, "num_frames", 1000));
+ sb.append(String.format(INTENT_INTEGER_EXTRA, "num_iterations", 1));
+ sb.append(String.format(INTENT_INTEGER_EXTRA, "timeout", 10000));
+ final String startCommand = sb.toString();
+ final String stopCommand = String.format(STOP_CMD, PACKAGE);
+
+ Log.i(TAG, "Start command: " + startCommand);
+ Log.i(TAG, "Stop command: " + stopCommand);
+
+ setIteration(NUM_ITERATIONS);
+ for (int i = 0; i < NUM_ITERATIONS; i++) {
+ // Stop any existing instances
+ runShellCommand(stopCommand);
+ // Start activity
+ runShellCommand(startCommand);
+
+ // Wait for the activity to start
+ sleep(SLEEP_TIME / 2);
+
+ // Start systrace
+ startTrace(mTestCaseName, i);
+
+ // Clear SurfaceFlinger buffer
+ Log.i(TAG, "Clearing SurfaceFlinger buffer");
+ SurfaceFlingerHelper.clearBuffer(APP_WINDOW_NAME);
+
+ // This is where user interactions would go, in this case just sleep
+ sleep(SLEEP_TIME);
+
+ // Dump SurfaceFlinger buffer
+ Log.i(TAG, "Dumping SurfaceFlinger buffer");
+ boolean result = SurfaceFlingerHelper.dumpFrameLatency(APP_WINDOW_NAME, true);
+ assertTrue("SurfaceFlingerHelper could not get timestamps", result);
+
+ // Stop systrace
+ endTrace();
+
+ // Record results
+ recordResults(mTestCaseName, i);
+ }
+ // Save aggregated results
+ saveResults(mTestCaseName);
+ // Stop any remaining instances
+ runShellCommand(stopCommand);
+ }
+}
diff --git a/hostsidetests/jank/src/android/jank/cts/CtsHostJankTest.java b/hostsidetests/jank/src/android/jank/cts/CtsHostJankTest.java
new file mode 100644
index 0000000..a33a3e4
--- /dev/null
+++ b/hostsidetests/jank/src/android/jank/cts/CtsHostJankTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 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.jank.cts;
+
+import com.android.compatibility.common.util.MetricsReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.migration.MigrationHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Scanner;
+
+public abstract class CtsHostJankTest extends TestCase
+ implements IAbiReceiver, IDeviceTest, IBuildReceiver {
+
+ private static final String TAG = CtsHostJankTest.class.getSimpleName();
+ private static final String DEVICE_LOCATION = "/data/local/tmp/";
+ // FIXME uiautomator is deprecated and does not support --abi flag
+ private static final String RUN_UI_AUTOMATOR_CMD = "uiautomator runtest %s -c %s";
+ private final String mHostTestClass;
+ private final String mDeviceTestClass;
+ private final String mJarName;
+ private final String mJarPath;
+ protected ITestDevice mDevice;
+ protected IBuildInfo mBuild;
+ protected IAbi mAbi;
+
+ public CtsHostJankTest(String jarName, String deviceTestClass, String hostTestClass) {
+ this.mHostTestClass = hostTestClass;
+ this.mDeviceTestClass = deviceTestClass;
+ this.mJarName = jarName;
+ this.mJarPath = DEVICE_LOCATION + jarName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mBuild = buildInfo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setDevice(ITestDevice device) {
+ mDevice = device;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ITestDevice getDevice() {
+ return mDevice;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+ // Push jar to device.
+ File jarFile = MigrationHelper.getTestFile(mBuild, mJarName);
+ boolean result = mDevice.pushFile(jarFile, mJarPath);
+ assertTrue("Failed to push file to " + mJarPath, result);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ // Delete jar from device.
+ mDevice.executeShellCommand("rm " + mJarPath);
+ super.tearDown();
+ }
+
+ public void runUiAutomatorTest(String testName) throws Exception {
+ // Delete any existing result files
+ mDevice.executeShellCommand("rm -r " + DEVICE_LOCATION + "*.txt");
+
+ // Run ui automator test.
+ mDevice.executeShellCommand(
+ String.format(RUN_UI_AUTOMATOR_CMD, mJarName, mDeviceTestClass + "#" + testName));
+
+ // Pull result file across
+ File result = mDevice.pullFile(DEVICE_LOCATION + "UiJankinessTestsOutput.txt");
+ assertNotNull("Couldn't get result file", result);
+ // Parse result file
+ Scanner in = new Scanner(result);
+ HashMap<String, Double> results = new HashMap<String, Double>(4);
+ while (in.hasNextLine()) {
+ String[] parts = in.nextLine().split(":");
+ if (parts.length == 2) {
+ results.put(parts[0], Double.parseDouble(parts[1]));
+ }
+ }
+ in.close();
+ assertEquals("Could not parse the results file: ", 4, results.size());
+
+ double avgNumJanks = results.get("average number of jankiness");
+ double maxNumJanks = results.get("max number of jankiness");
+ double avgFrameRate = results.get("average frame rate");
+ double avgMaxAccFrames = results.get("average of max accumulated frames");
+
+ // Create and deliver the report.
+ MetricsReportLog report = new MetricsReportLog(mDevice.getSerialNumber(), mAbi.getName(),
+ mHostTestClass + "#" + testName);
+ report.addValue(
+ "Average Frame Rate", avgFrameRate, ResultType.HIGHER_BETTER, ResultUnit.COUNT);
+ report.addValue("Average of Maximum Accumulated Frames", avgMaxAccFrames,
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ report.addValue(
+ "Maximum Number of Janks", maxNumJanks, ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ report.setSummary(
+ "Average Number of Janks", avgNumJanks, ResultType.LOWER_BETTER, ResultUnit.SCORE);
+ report.submit();
+ }
+
+}
diff --git a/hostsidetests/jank/src/android/jank/cts/opengl/CtsHostJankOpenGl.java b/hostsidetests/jank/src/android/jank/cts/opengl/CtsHostJankOpenGl.java
new file mode 100644
index 0000000..193d543
--- /dev/null
+++ b/hostsidetests/jank/src/android/jank/cts/opengl/CtsHostJankOpenGl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 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.jank.cts.opengl;
+
+import android.jank.cts.CtsHostJankTest;
+
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.cts.migration.MigrationHelper;
+
+import java.io.File;
+
+public class CtsHostJankOpenGl extends CtsHostJankTest {
+
+ private static final String APK_PACKAGE = "android.opengl2.cts";
+ private static final String APK = "CtsOpenGlPerf2TestCases.apk";
+ private static final String PACKAGE = "android.jank.cts";
+ private static final String HOST_CLASS = CtsHostJankOpenGl.class.getName();
+ private static final String DEVICE_CLASS = PACKAGE + ".opengl.CtsDeviceJankOpenGl";
+ private static final String JAR_NAME = "CtsJankTestJar.jar";
+
+ public CtsHostJankOpenGl() {
+ super(JAR_NAME, DEVICE_CLASS, HOST_CLASS);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Install the app.
+ mDevice.uninstallPackage(APK_PACKAGE);
+ File app = MigrationHelper.getTestFile(mBuild, APK);
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ mDevice.installPackage(app, false, options);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Uninstall the app.
+ mDevice.uninstallPackage(APK_PACKAGE);
+ super.tearDown();
+ }
+
+ public void testFullPipeline() throws Exception {
+ runUiAutomatorTest("testFullPipeline");
+ }
+
+ public void testPixelOutput() throws Exception {
+ runUiAutomatorTest("testPixelOutput");
+ }
+
+ public void testShaderPerf() throws Exception {
+ runUiAutomatorTest("testShaderPerf");
+ }
+
+ public void testContextSwitch() throws Exception {
+ runUiAutomatorTest("testContextSwitch");
+ }
+}
diff --git a/hostsidetests/jdwpsecurity/Android.mk b/hostsidetests/jdwpsecurity/Android.mk
index 561d346..82d6987 100644
--- a/hostsidetests/jdwpsecurity/Android.mk
+++ b/hostsidetests/jdwpsecurity/Android.mk
@@ -23,7 +23,10 @@
# Must match the package name in CtsTestCaseList.mk
LOCAL_MODULE := CtsJdwpSecurityHostTestCases
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt cts-migration-lib
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
LOCAL_CTS_TEST_PACKAGE := android.host.jdwpsecurity
diff --git a/hostsidetests/jdwpsecurity/AndroidTest.xml b/hostsidetests/jdwpsecurity/AndroidTest.xml
new file mode 100644
index 0000000..bbb99e9
--- /dev/null
+++ b/hostsidetests/jdwpsecurity/AndroidTest.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<configuration description="Config for the CTS JDWP host test cases">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsJdwpSecurityHostTestCases.jar" />
+ </test>
+</configuration>
diff --git a/hostsidetests/jdwpsecurity/app/Android.mk b/hostsidetests/jdwpsecurity/app/Android.mk
index 13b5be4..efa7b5c 100644
--- a/hostsidetests/jdwpsecurity/app/Android.mk
+++ b/hostsidetests/jdwpsecurity/app/Android.mk
@@ -18,6 +18,8 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := CtsJdwpApp
LOCAL_SRC_FILES := $(call all-subdir-java-files)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_JAVA_LIBRARY)
# Copy the built module to the cts dir
diff --git a/hostsidetests/jdwpsecurity/src/android/jdwpsecurity/cts/JdwpSecurityHostTest.java b/hostsidetests/jdwpsecurity/src/android/jdwpsecurity/cts/JdwpSecurityHostTest.java
index 8e276ed..186728c 100644
--- a/hostsidetests/jdwpsecurity/src/android/jdwpsecurity/cts/JdwpSecurityHostTest.java
+++ b/hostsidetests/jdwpsecurity/src/android/jdwpsecurity/cts/JdwpSecurityHostTest.java
@@ -16,7 +16,7 @@
package android.jdwpsecurity.cts;
-import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.migration.MigrationHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
@@ -45,7 +45,7 @@
private static final String DEVICE_JAR_FILENAME = "CtsJdwpApp.jar";
private static final String JAR_MAIN_CLASS_NAME = "com.android.cts.jdwpsecurity.JdwpTest";
- private CtsBuildHelper mCtsBuild;
+ private IBuildInfo mBuildInfo;
private static String getDeviceScriptFilepath() {
return DEVICE_LOCATION + File.separator + DEVICE_SCRIPT_FILENAME;
@@ -57,7 +57,7 @@
@Override
public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ mBuildInfo = buildInfo;
}
@Override
@@ -85,7 +85,7 @@
getDevice().executeShellCommand("chmod 755 " + getDeviceScriptFilepath());
// Push jar file.
- File jarFile = mCtsBuild.getTestApp(DEVICE_JAR_FILENAME);
+ File jarFile = MigrationHelper.getTestFile(mBuildInfo, DEVICE_JAR_FILENAME);
boolean success = getDevice().pushFile(jarFile, getDeviceJarFilepath());
assertTrue("Failed to push jar file to " + getDeviceScriptFilepath(), success);
}
diff --git a/hostsidetests/monkey/Android.mk b/hostsidetests/monkey/Android.mk
index c9f3bb3..b377996 100644
--- a/hostsidetests/monkey/Android.mk
+++ b/hostsidetests/monkey/Android.mk
@@ -22,11 +22,16 @@
LOCAL_MODULE := CtsMonkeyTestCases
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed_v2 compatibility-host-util tradefed-prebuilt
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
# prefix zzz intentional to run this last
LOCAL_CTS_TEST_PACKAGE := zzz.android.monkey
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/monkey/AndroidTest.xml b/hostsidetests/monkey/AndroidTest.xml
new file mode 100644
index 0000000..799ee6a
--- /dev/null
+++ b/hostsidetests/monkey/AndroidTest.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<configuration description="Config for the CTS monkey host tests">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsMonkeyTestCases.jar" />
+ <option name="runtime-hint" value="5m7s" />
+ </test>
+</configuration>
diff --git a/hostsidetests/monkey/src/com/android/cts/monkey/AbstractMonkeyTest.java b/hostsidetests/monkey/src/com/android/cts/monkey/AbstractMonkeyTest.java
index b31a32d..26023be 100755
--- a/hostsidetests/monkey/src/com/android/cts/monkey/AbstractMonkeyTest.java
+++ b/hostsidetests/monkey/src/com/android/cts/monkey/AbstractMonkeyTest.java
@@ -1,7 +1,7 @@
package com.android.cts.monkey;
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.cts.migration.MigrationHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
@@ -23,7 +23,7 @@
static final String MONKEY_CMD = "monkey --pct-motion 0 --pct-majornav 0 --pct-syskeys 0 --pct-anyevent 0 --pct-rotation 0";
IAbi mAbi;
- CtsBuildHelper mBuild;
+ IBuildInfo mBuild;
ITestDevice mDevice;
@Override
@@ -33,7 +33,7 @@
@Override
public void setBuild(IBuildInfo buildInfo) {
- mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ mBuild = buildInfo;
}
@Override
@@ -43,7 +43,7 @@
String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
for (int i = 0; i < PKGS.length; i++) {
mDevice.uninstallPackage(PKGS[i]);
- File app = mBuild.getTestApp(APKS[i]);
+ File app = MigrationHelper.getTestFile(mBuild, APKS[i]);
mDevice.installPackage(app, false, options);
}
clearLogCat();
diff --git a/hostsidetests/monkey/test-apps/CtsMonkeyApp/Android.mk b/hostsidetests/monkey/test-apps/CtsMonkeyApp/Android.mk
index c04d4b2..49288ad 100644
--- a/hostsidetests/monkey/test-apps/CtsMonkeyApp/Android.mk
+++ b/hostsidetests/monkey/test-apps/CtsMonkeyApp/Android.mk
@@ -30,4 +30,7 @@
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/monkey/test-apps/CtsMonkeyApp2/Android.mk b/hostsidetests/monkey/test-apps/CtsMonkeyApp2/Android.mk
index b3cb181..8d58435 100644
--- a/hostsidetests/monkey/test-apps/CtsMonkeyApp2/Android.mk
+++ b/hostsidetests/monkey/test-apps/CtsMonkeyApp2/Android.mk
@@ -30,4 +30,7 @@
LOCAL_DEX_PREOPT := false
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/net/Android.mk b/hostsidetests/net/Android.mk
index 6637d61..b4e1e3d 100644
--- a/hostsidetests/net/Android.mk
+++ b/hostsidetests/net/Android.mk
@@ -21,10 +21,15 @@
LOCAL_MODULE := CtsHostsideNetworkTests
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed_v2 compatibility-host-util tradefed-prebuilt
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
LOCAL_CTS_TEST_PACKAGE := android.net.hostsidenetwork
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
# Build the test APKs using their own makefiles
diff --git a/hostsidetests/net/AndroidTest.xml b/hostsidetests/net/AndroidTest.xml
new file mode 100644
index 0000000..4b6994a
--- /dev/null
+++ b/hostsidetests/net/AndroidTest.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<configuration description="Config for CTS net host test cases">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsHostsideNetworkTests.jar" />
+ </test>
+</configuration>
diff --git a/hostsidetests/net/app/Android.mk b/hostsidetests/net/app/Android.mk
index 055287a..b64c4c9 100644
--- a/hostsidetests/net/app/Android.mk
+++ b/hostsidetests/net/app/Android.mk
@@ -29,4 +29,7 @@
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTests.java b/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTests.java
index a7698f3..f42de0e 100644
--- a/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTests.java
+++ b/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTests.java
@@ -16,7 +16,7 @@
package com.android.cts.net;
-import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.migration.MigrationHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult;
@@ -39,7 +39,7 @@
private static final String TEST_APK = "CtsHostsideNetworkTestsApp.apk";
private IAbi mAbi;
- private CtsBuildHelper mCtsBuild;
+ private IBuildInfo mCtsBuild;
@Override
public void setAbi(IAbi abi) {
@@ -48,7 +48,7 @@
@Override
public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ mCtsBuild = buildInfo;
}
@Override
@@ -60,7 +60,8 @@
getDevice().uninstallPackage(TEST_PKG);
- assertNull(getDevice().installPackage(mCtsBuild.getTestApp(TEST_APK), false));
+ assertNull(getDevice().installPackage(
+ MigrationHelper.getTestFile(mCtsBuild, TEST_APK), false));
}
@Override
diff --git a/hostsidetests/os/Android.mk b/hostsidetests/os/Android.mk
index 6962e0c..a318622 100644
--- a/hostsidetests/os/Android.mk
+++ b/hostsidetests/os/Android.mk
@@ -27,7 +27,10 @@
LOCAL_CTS_TEST_PACKAGE := android.host.os
-LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/$(CTS_MODULE_TEST_CONFIG)
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/os/AndroidTest.xml b/hostsidetests/os/AndroidTest.xml
index 6694c30..ff6e6b0 100644
--- a/hostsidetests/os/AndroidTest.xml
+++ b/hostsidetests/os/AndroidTest.xml
@@ -13,7 +13,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="CTS package preparer for install/uninstall of the apk used as a test operation target">
- <include name="common-config" />
- <option name="cts-apk-installer:test-file-name" value="CtsDeviceOsTestApp.apk" />
+<configuration description="Config for the CTS OS host test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsDeviceOsTestApp.apk" />
+ </target_preparer>
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsOsHostTestCases.jar" />
+ </test>
</configuration>
diff --git a/hostsidetests/os/OldAndroidTest.xml b/hostsidetests/os/OldAndroidTest.xml
new file mode 100644
index 0000000..6694c30
--- /dev/null
+++ b/hostsidetests/os/OldAndroidTest.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+<configuration description="CTS package preparer for install/uninstall of the apk used as a test operation target">
+ <include name="common-config" />
+ <option name="cts-apk-installer:test-file-name" value="CtsDeviceOsTestApp.apk" />
+</configuration>
diff --git a/hostsidetests/os/app/Android.mk b/hostsidetests/os/app/Android.mk
index 46861d69..ed0c4e8 100644
--- a/hostsidetests/os/app/Android.mk
+++ b/hostsidetests/os/app/Android.mk
@@ -23,6 +23,9 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsDeviceOsTestApp
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/os/app/AndroidManifest.xml b/hostsidetests/os/app/AndroidManifest.xml
index 103cf63..4c4338b 100755
--- a/hostsidetests/os/app/AndroidManifest.xml
+++ b/hostsidetests/os/app/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.app.os.test">
+ package="android.os.app">
<application>
<activity android:name=".TestNonExported"
diff --git a/hostsidetests/os/app/src/android/os/app/TestNonExported.java b/hostsidetests/os/app/src/android/os/app/TestNonExported.java
new file mode 100644
index 0000000..11c41c9
--- /dev/null
+++ b/hostsidetests/os/app/src/android/os/app/TestNonExported.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package android.os.app;
+
+import android.app.Activity;
+
+/**
+ * Should never be launched: intentionally not exported
+ */
+public class TestNonExported extends Activity {
+}
diff --git a/hostsidetests/os/app/src/com/android/cts/app/os/test/TestNonExported.java b/hostsidetests/os/app/src/com/android/cts/app/os/test/TestNonExported.java
deleted file mode 100644
index c865c89..0000000
--- a/hostsidetests/os/app/src/com/android/cts/app/os/test/TestNonExported.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.app.os.test;
-
-import android.app.Activity;
-
-/**
- * Should never be launched: intentionally not exported
- */
-public class TestNonExported extends Activity {
-}
diff --git a/hostsidetests/os/src/android/os/cts/OsHostTests.java b/hostsidetests/os/src/android/os/cts/OsHostTests.java
new file mode 100644
index 0000000..73e36c5
--- /dev/null
+++ b/hostsidetests/os/src/android/os/cts/OsHostTests.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+package android.os.cts;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+public class OsHostTests extends DeviceTestCase implements IBuildReceiver {
+ private static final String TEST_APP_PACKAGE = "android.os.app";
+ private static final String TEST_NON_EXPORTED_ACTIVITY_CLASS = "TestNonExported";
+
+ private static final String START_NON_EXPORTED_ACTIVITY_COMMAND = String.format(
+ "am start -n %s/%s.%s",
+ TEST_APP_PACKAGE, TEST_APP_PACKAGE, TEST_NON_EXPORTED_ACTIVITY_CLASS);
+
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Get the device, this gives a handle to run commands and install APKs.
+ mDevice = getDevice();
+ }
+
+ /**
+ * Test whether non-exported activities are properly not launchable.
+ *
+ * @throws Exception
+ */
+ public void testNonExportedActivities() throws Exception {
+ // Attempt to launch the non-exported activity in the test app
+ CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ mDevice.executeShellCommand(START_NON_EXPORTED_ACTIVITY_COMMAND, outputReceiver);
+ final String output = outputReceiver.getOutput();
+
+ assertTrue(output.contains("Permission Denial") && output.contains(" not exported"));
+ }
+}
diff --git a/hostsidetests/os/src/com/android/cts/app/os/OsHostTests.java b/hostsidetests/os/src/com/android/cts/app/os/OsHostTests.java
deleted file mode 100644
index d01a521..0000000
--- a/hostsidetests/os/src/com/android/cts/app/os/OsHostTests.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.app.os;
-
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.CollectingOutputReceiver;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-public class OsHostTests extends DeviceTestCase implements IBuildReceiver {
- private static final String TEST_APP_PACKAGE = "com.android.cts.app.os.test";
- private static final String TEST_NON_EXPORTED_ACTIVITY_CLASS = "TestNonExported";
-
- private static final String START_NON_EXPORTED_ACTIVITY_COMMAND = String.format(
- "am start -n %s/%s.%s",
- TEST_APP_PACKAGE, TEST_APP_PACKAGE, TEST_NON_EXPORTED_ACTIVITY_CLASS);
-
- /**
- * A reference to the device under test.
- */
- private ITestDevice mDevice;
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- // Get the device, this gives a handle to run commands and install APKs.
- mDevice = getDevice();
- }
-
- /**
- * Test whether non-exported activities are properly not launchable.
- *
- * @throws Exception
- */
- public void testNonExportedActivities() throws Exception {
- // Attempt to launch the non-exported activity in the test app
- CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
- mDevice.executeShellCommand(START_NON_EXPORTED_ACTIVITY_COMMAND, outputReceiver);
- final String output = outputReceiver.getOutput();
-
- assertTrue(output.contains("Permission Denial") && output.contains(" not exported"));
- }
-}
diff --git a/hostsidetests/sample/Android.mk b/hostsidetests/sample/Android.mk
index e8cbdda..8a76a8b 100644
--- a/hostsidetests/sample/Android.mk
+++ b/hostsidetests/sample/Android.mk
@@ -18,15 +18,15 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
-# Must match the package name in CtsTestCaseList.mk
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_MODULE := CtsSampleHostTestCases
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := compatibility-host-util cts-tradefed_v2 tradefed-prebuilt
-LOCAL_CTS_TEST_PACKAGE := android.host.sample
-
-include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+include $(BUILD_HOST_JAVA_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/sample/AndroidTest.xml b/hostsidetests/sample/AndroidTest.xml
new file mode 100644
index 0000000..5f5d23d
--- /dev/null
+++ b/hostsidetests/sample/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Sample host test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSampleDeviceApp.apk" />
+ </target_preparer>
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsSampleHostTestCases.jar" />
+ </test>
+</configuration>
diff --git a/hostsidetests/sample/app/Android.mk b/hostsidetests/sample/app/Android.mk
index 4af45b9..773f24f 100644
--- a/hostsidetests/sample/app/Android.mk
+++ b/hostsidetests/sample/app/Android.mk
@@ -16,16 +16,22 @@
include $(CLEAR_VARS)
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
-
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsSampleDeviceApp
LOCAL_SDK_VERSION := current
-include $(BUILD_CTS_PACKAGE)
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/sample/app/AndroidManifest.xml b/hostsidetests/sample/app/AndroidManifest.xml
index c087435..dfacf25 100755
--- a/hostsidetests/sample/app/AndroidManifest.xml
+++ b/hostsidetests/sample/app/AndroidManifest.xml
@@ -18,7 +18,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.sample.app">
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
<activity android:name=".SampleDeviceActivity" >
<intent-filter>
diff --git a/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java b/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java
index bed4c05..b75ea94 100644
--- a/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java
+++ b/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java
@@ -16,15 +16,13 @@
package android.sample.cts;
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.tradefed.util.HostReportLog;
-import com.android.cts.util.MeasureRun;
-import com.android.cts.util.MeasureTime;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.Stat;
-import com.android.ddmlib.IDevice;
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.util.MeasureRun;
+import com.android.compatibility.common.util.MeasureTime;
+import com.android.compatibility.common.util.MetricsReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -37,7 +35,6 @@
import com.android.tradefed.util.RunUtil;
import java.io.File;
-import java.lang.Exception;
/**
* Test to measure the transfer time of a file from the host to the device.
@@ -52,16 +49,21 @@
private static final int REPEAT = 5;
/**
- * The name of the plan to transfer.
- *
- * In this case we will transfer the CTS.xml file.
+ * The device-side location to write the file to.
*/
- private static final String PLAN_NAME = "CTS";
+ private static final String FILE_PATH = "/data/local/tmp/%s";
/**
- * A reference to the build.
+ * The name of the file to transfer.
+ *
+ * In this case we will transfer this test's module config.
*/
- private CtsBuildHelper mBuild;
+ private static final String FILE_NAME = "CtsSampleHostTestCases.config";
+
+ /**
+ * A helper to access resources in the build.
+ */
+ private CompatibilityBuildHelper mBuildHelper;
/**
* A reference to the device under test.
@@ -81,7 +83,7 @@
@Override
public void setBuild(IBuildInfo buildInfo) {
// Get the build, this is used to access the APK.
- mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ mBuildHelper = new CompatibilityBuildHelper(buildInfo);
}
@Override
@@ -100,13 +102,10 @@
*/
public void testTransferTime() throws Exception {
final ITestDevice device = mDevice;
- // Get the external storage location and ensure its not null.
- final String externalStorePath = mDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- assertNotNull("External storage location no found", externalStorePath);
// Create the device side path where the file will be transfered.
- final String devicePath = String.format("%s/%s", externalStorePath, "tmp_testPushPull.txt");
- // Get the file from the build.
- final File testFile = mBuild.getTestPlanFile(PLAN_NAME);
+ final String devicePath = String.format(FILE_PATH, "tmp_testPushPull.txt");
+ // Get this test's module config file from the build.
+ final File testFile = new File(mBuildHelper.getTestsDir(), FILE_NAME);
double[] result = MeasureTime.measure(REPEAT, new MeasureRun() {
@Override
public void prepare(int i) throws Exception {
@@ -133,15 +132,15 @@
// Compute the stats.
Stat.StatResult stat = Stat.getStat(result);
// Get the report for this test and add the results to record.
- HostReportLog report = new HostReportLog(mDevice.getSerialNumber(), mAbi.getName(),
- ReportLog.getClassMethodNames());
- report.printArray("Times", result, ResultType.LOWER_BETTER, ResultUnit.MS);
- report.printValue("Min", stat.mMin, ResultType.LOWER_BETTER, ResultUnit.MS);
- report.printValue("Max", stat.mMax, ResultType.LOWER_BETTER, ResultUnit.MS);
+ MetricsReportLog report = new MetricsReportLog(mDevice.getSerialNumber(), mAbi.getName(),
+ String.format("%s#testTransferTime", getClass().getCanonicalName()));
+ report.addValues("Times", result, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValue("Min", stat.mMin, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValue("Max", stat.mMax, ResultType.LOWER_BETTER, ResultUnit.MS);
// Every report must have a summary,
- report.printSummary("Average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.setSummary("Average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
// Send the report to Tradefed.
- report.deliverReportToHost();
+ report.submit();
}
/**
diff --git a/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java b/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java
index ab7e0b0..f276712 100644
--- a/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java
+++ b/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java
@@ -16,27 +16,19 @@
package android.sample.cts;
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
-import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-import java.io.File;
-import java.lang.String;
import java.util.Scanner;
/**
* Test to check the APK logs to Logcat.
*
* When this test builds, it also builds {@link android.sample.app.SampleDeviceActivity} into an APK
- * which it then installs at runtime and starts. The activity simply prints a message to Logcat and
- * then gets uninstalled.
+ * which it then installed at runtime and started. The activity simply prints a message to Logcat
+ * and then gets uninstalled.
*/
-public class SampleHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+public class SampleHostTest extends DeviceTestCase {
/**
* The package name of the APK.
@@ -44,11 +36,6 @@
private static final String PACKAGE = "android.sample.app";
/**
- * The file name of the APK.
- */
- private static final String APK = "CtsSampleDeviceApp.apk";
-
- /**
* The class name of the main activity in the APK.
*/
private static final String CLASS = "SampleDeviceActivity";
@@ -65,65 +52,18 @@
private static final String TEST_STRING = "SampleTestString";
/**
- * The ABI to use.
- */
- private IAbi mAbi;
-
- /**
- * A reference to the build.
- */
- private CtsBuildHelper mBuild;
-
- /**
- * A reference to the device under test.
- */
- private ITestDevice mDevice;
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- // Get the build, this is used to access the APK.
- mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // Get the device, this gives a handle to run commands and install APKs.
- mDevice = getDevice();
- // Remove any previously installed versions of this APK.
- mDevice.uninstallPackage(PACKAGE);
- // Get the APK from the build.
- File app = mBuild.getTestApp(APK);
- // Get the ABI flag.
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- // Install the APK on the device.
- mDevice.installPackage(app, false, options);
- }
-
- @Override
- protected void tearDown() throws Exception {
- // Remove the package once complete.
- mDevice.uninstallPackage(PACKAGE);
- super.tearDown();
- }
-
- /**
* Tests the string was successfully logged to Logcat from the activity.
*
* @throws Exception
*/
public void testLogcat() throws Exception {
+ ITestDevice device = getDevice();
// Clear logcat.
- mDevice.executeAdbCommand("logcat", "-c");
+ device.executeAdbCommand("logcat", "-c");
// Start the APK and wait for it to complete.
- mDevice.executeShellCommand(START_COMMAND);
+ device.executeShellCommand(START_COMMAND);
// Dump logcat.
- String logs = mDevice.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
+ String logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
// Search for string.
String testString = "";
Scanner in = new Scanner(logs);
diff --git a/hostsidetests/security/Android.mk b/hostsidetests/security/Android.mk
index ad708ca..5bac9a7 100644
--- a/hostsidetests/security/Android.mk
+++ b/hostsidetests/security/Android.mk
@@ -20,6 +20,9 @@
LOCAL_MODULE_TAGS := optional
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# Must match the package name in CtsTestCaseList.mk
LOCAL_MODULE := CtsSecurityHostTestCases
diff --git a/hostsidetests/security/AndroidTest.xml b/hostsidetests/security/AndroidTest.xml
new file mode 100644
index 0000000..e521761
--- /dev/null
+++ b/hostsidetests/security/AndroidTest.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<configuration description="Config for the CTS Security host tests">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsSecurityHostTestCases.jar" />
+ <option name="runtime-hint" value="12m13s" />
+ </test>
+</configuration>
diff --git a/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
deleted file mode 100644
index c80d676..0000000
--- a/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * Copyright (C) 2014 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.cts.security;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.CollectingOutputReceiver;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.String;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.Scanner;
-import java.util.Set;
-
-/**
- * Host-side SELinux tests.
- *
- * These tests analyze the policy file in use on the subject device directly or
- * run as the shell user to evaluate aspects of the state of SELinux on the test
- * device which otherwise would not be available to a normal apk.
- */
-public class SELinuxHostTest extends DeviceTestCase {
-
- private File sepolicyAnalyze;
- private File checkSeapp;
- private File checkFc;
- private File aospSeappFile;
- private File aospFcFile;
- private File aospPcFile;
- private File aospSvcFile;
- private File devicePolicyFile;
- private File deviceSeappFile;
- private File deviceFcFile;
- private File devicePcFile;
- private File deviceSvcFile;
- private File seappNeverAllowFile;
-
- /**
- * A reference to the device under test.
- */
- private ITestDevice mDevice;
-
- private File copyResourceToTempFile(String resName) throws IOException {
- InputStream is = this.getClass().getResourceAsStream(resName);
- File tempFile = File.createTempFile("SELinuxHostTest", ".tmp");
- FileOutputStream os = new FileOutputStream(tempFile);
- int rByte = 0;
- while ((rByte = is.read()) != -1) {
- os.write(rByte);
- }
- os.flush();
- os.close();
- tempFile.deleteOnExit();
- return tempFile;
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mDevice = getDevice();
-
- /* retrieve the sepolicy-analyze executable from jar */
- sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
- sepolicyAnalyze.setExecutable(true);
-
- /* retrieve the checkseapp executable from jar */
- checkSeapp = copyResourceToTempFile("/checkseapp");
- checkSeapp.setExecutable(true);
-
- /* retrieve the checkfc executable from jar */
- checkFc = copyResourceToTempFile("/checkfc");
- checkFc.setExecutable(true);
-
- /* obtain sepolicy file from running device */
- devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
- devicePolicyFile.deleteOnExit();
- mDevice.pullFile("/sys/fs/selinux/policy", devicePolicyFile);
-
- /* obtain seapp_contexts file from running device */
- deviceSeappFile = File.createTempFile("seapp_contexts", ".tmp");
- deviceSeappFile.deleteOnExit();
- mDevice.pullFile("/seapp_contexts", deviceSeappFile);
-
- /* obtain file_contexts.bin file from running device */
- deviceFcFile = File.createTempFile("file_contexts", ".bin");
- deviceFcFile.deleteOnExit();
- mDevice.pullFile("/file_contexts.bin", deviceFcFile);
-
- /* obtain property_contexts file from running device */
- devicePcFile = File.createTempFile("property_contexts", ".tmp");
- devicePcFile.deleteOnExit();
- mDevice.pullFile("/property_contexts", devicePcFile);
-
- /* obtain service_contexts file from running device */
- deviceSvcFile = File.createTempFile("service_contexts", ".tmp");
- deviceSvcFile.deleteOnExit();
- mDevice.pullFile("/service_contexts", deviceSvcFile);
-
- /* retrieve the AOSP *_contexts files from jar */
- aospSeappFile = copyResourceToTempFile("/general_seapp_contexts");
- aospFcFile = copyResourceToTempFile("/general_file_contexts.bin");
- aospPcFile = copyResourceToTempFile("/general_property_contexts");
- aospSvcFile = copyResourceToTempFile("/general_service_contexts");
- seappNeverAllowFile = copyResourceToTempFile("/general_seapp_neverallows");
- }
-
- /**
- * Tests that all domains in the running policy file are in enforcing mode
- *
- * @throws Exception
- */
- public void testAllEnforcing() throws Exception {
-
- /* run sepolicy-analyze permissive check on policy file */
- ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
- devicePolicyFile.getAbsolutePath(), "permissive");
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.waitFor();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
- StringBuilder errorString = new StringBuilder();
- while ((line = result.readLine()) != null) {
- errorString.append(line);
- errorString.append("\n");
- }
- assertTrue("The following SELinux domains were found to be in permissive mode:\n"
- + errorString, errorString.length() == 0);
- }
-
- /**
- * Asserts that specified type is not associated with the specified
- * attribute.
- *
- * @param attribute
- * The attribute name.
- * @param type
- * The type name.
- */
- private void assertNotInAttribute(String attribute, String badtype) throws Exception {
- /* run sepolicy-analyze attribute check on policy file */
- ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
- devicePolicyFile.getAbsolutePath(), "attribute", attribute);
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.waitFor();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String type;
- while ((type = result.readLine()) != null) {
- assertFalse("Attribute " + attribute + " includes " + type + "\n",
- type.equals(badtype));
- }
- }
-
- /**
- * Tests that mlstrustedsubject does not include untrusted_app
- * and that mlstrustedobject does not include app_data_file.
- * This helps prevent circumventing the per-user isolation of
- * normal apps via levelFrom=user.
- *
- * @throws Exception
- */
- public void testMLSAttributes() throws Exception {
- assertNotInAttribute("mlstrustedsubject", "untrusted_app");
- assertNotInAttribute("mlstrustedobject", "app_data_file");
- }
-
- /**
- * Tests that the seapp_contexts file on the device is valid.
- *
- * @throws Exception
- */
- public void testValidSeappContexts() throws Exception {
-
- /* run checkseapp on seapp_contexts */
- ProcessBuilder pb = new ProcessBuilder(checkSeapp.getAbsolutePath(),
- "-p", devicePolicyFile.getAbsolutePath(),
- seappNeverAllowFile.getAbsolutePath(),
- deviceSeappFile.getAbsolutePath());
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.waitFor();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
- StringBuilder errorString = new StringBuilder();
- while ((line = result.readLine()) != null) {
- errorString.append(line);
- errorString.append("\n");
- }
- assertTrue("The seapp_contexts file was invalid:\n"
- + errorString, errorString.length() == 0);
- }
-
- /**
- * Asserts that the actual file contents starts with the expected file
- * contents.
- *
- * @param expectedFile
- * The file with the expected contents.
- * @param actualFile
- * The actual file being checked.
- */
- private void assertFileStartsWith(File expectedFile, File actualFile) throws Exception {
- BufferedReader expectedReader = new BufferedReader(new FileReader(expectedFile.getAbsolutePath()));
- BufferedReader actualReader = new BufferedReader(new FileReader(actualFile.getAbsolutePath()));
- String expectedLine, actualLine;
- while ((expectedLine = expectedReader.readLine()) != null) {
- actualLine = actualReader.readLine();
- assertEquals("Lines do not match:", expectedLine, actualLine);
- }
- }
-
- /**
- * Tests that the seapp_contexts file on the device contains
- * the standard AOSP entries.
- *
- * @throws Exception
- */
- public void testAospSeappContexts() throws Exception {
- assertFileStartsWith(aospSeappFile, deviceSeappFile);
- }
-
- /**
- * Tests that the file_contexts.bin file on the device contains
- * the standard AOSP entries.
- *
- * @throws Exception
- */
- public void testAospFileContexts() throws Exception {
- /* run checkfc -c general_file_contexts.bin file_contexts.bin */
- ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
- "-c", aospFcFile.getAbsolutePath(),
- deviceFcFile.getAbsolutePath());
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.waitFor();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line = result.readLine();
- assertTrue("The file_contexts.bin file did not include the AOSP entries:\n"
- + line + "\n",
- line.equals("equal") || line.equals("subset"));
- }
-
- /**
- * Tests that the property_contexts file on the device contains
- * the standard AOSP entries.
- *
- * @throws Exception
- */
- public void testAospPropertyContexts() throws Exception {
- assertFileStartsWith(aospPcFile, devicePcFile);
- }
-
- /**
- * Tests that the service_contexts file on the device contains
- * the standard AOSP entries.
- *
- * @throws Exception
- */
- public void testAospServiceContexts() throws Exception {
- assertFileStartsWith(aospSvcFile, deviceSvcFile);
- }
-
- /**
- * Tests that the file_contexts.bin file on the device is valid.
- *
- * @throws Exception
- */
- public void testValidFileContexts() throws Exception {
-
- /* run checkfc sepolicy file_contexts.bin */
- ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
- devicePolicyFile.getAbsolutePath(),
- deviceFcFile.getAbsolutePath());
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.waitFor();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
- StringBuilder errorString = new StringBuilder();
- while ((line = result.readLine()) != null) {
- errorString.append(line);
- errorString.append("\n");
- }
- assertTrue("The file_contexts.bin file was invalid:\n"
- + errorString, errorString.length() == 0);
- }
-
- /**
- * Tests that the property_contexts file on the device is valid.
- *
- * @throws Exception
- */
- public void testValidPropertyContexts() throws Exception {
-
- /* run checkfc -p on property_contexts */
- ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
- "-p", devicePolicyFile.getAbsolutePath(),
- devicePcFile.getAbsolutePath());
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.waitFor();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
- StringBuilder errorString = new StringBuilder();
- while ((line = result.readLine()) != null) {
- errorString.append(line);
- errorString.append("\n");
- }
- assertTrue("The property_contexts file was invalid:\n"
- + errorString, errorString.length() == 0);
- }
-
- /**
- * Tests that the service_contexts file on the device is valid.
- *
- * @throws Exception
- */
- public void testValidServiceContexts() throws Exception {
-
- /* run checkfc -s on service_contexts */
- ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
- "-s", devicePolicyFile.getAbsolutePath(),
- deviceSvcFile.getAbsolutePath());
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.waitFor();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
- StringBuilder errorString = new StringBuilder();
- while ((line = result.readLine()) != null) {
- errorString.append(line);
- errorString.append("\n");
- }
- assertTrue("The service_contexts file was invalid:\n"
- + errorString, errorString.length() == 0);
- }
-
- /**
- * Tests that the policy defines no booleans (runtime conditional policy).
- *
- * @throws Exception
- */
- public void testNoBooleans() throws Exception {
-
- /* run sepolicy-analyze booleans check on policy file */
- ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
- devicePolicyFile.getAbsolutePath(), "booleans");
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.waitFor();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
- StringBuilder errorString = new StringBuilder();
- while ((line = result.readLine()) != null) {
- errorString.append(line);
- errorString.append("\n");
- }
- assertTrue("The policy contained booleans:\n"
- + errorString, errorString.length() == 0);
- }
-
- /**
- * Tests that important domain labels are being appropriately applied.
- */
-
- /**
- * Asserts that no processes are running in a domain.
- *
- * @param domain
- * The domain or SELinux context to check.
- */
- private void assertDomainEmpty(String domain) throws DeviceNotAvailableException {
- List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
- String msg = "Expected no processes in SELinux domain \"" + domain + "\""
- + " Found: \"" + procs + "\"";
- assertNull(msg, procs);
- }
-
- /**
- * Asserts that a domain exists and that only one, well defined, process is
- * running in that domain.
- *
- * @param domain
- * The domain or SELinux context to check.
- * @param executable
- * The path of the executable or application package name.
- */
- private void assertDomainOne(String domain, String executable) throws DeviceNotAvailableException {
- List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
- List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(executable);
- String msg = "Expected 1 process in SELinux domain \"" + domain + "\""
- + " Found \"" + procs + "\"";
- assertNotNull(msg, procs);
- assertEquals(msg, 1, procs.size());
-
- msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
- + "Found: \"" + procs + "\"";
- assertEquals(msg, executable, procs.get(0).procTitle);
-
- msg = "Expected 1 process with executable \"" + executable + "\""
- + " Found \"" + procs + "\"";
- assertNotNull(msg, exeProcs);
- assertEquals(msg, 1, exeProcs.size());
-
- msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
- + "Found: \"" + procs + "\"";
- assertEquals(msg, domain, exeProcs.get(0).label);
- }
-
- /**
- * Asserts that a domain may exist. If a domain exists, the cardinality of
- * the domain is verified to be 1 and that the correct process is running in
- * that domain.
- *
- * @param domain
- * The domain or SELinux context to check.
- * @param executable
- * The path of the executable or application package name.
- */
- private void assertDomainZeroOrOne(String domain, String executable)
- throws DeviceNotAvailableException {
- List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
- List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(executable);
-
- if (procs != null) {
- String msg = "Expected 1 process in SELinux domain \"" + domain + "\""
- + " Found: \"" + procs + "\"";
- assertEquals(msg, 1, procs.size());
-
- msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
- + "Found: \"" + procs.get(0) + "\"";
- assertEquals(msg, executable, procs.get(0).procTitle);
- }
-
- if (exeProcs != null) {
- String msg = "Expected 1 process with executable \"" + executable + "\""
- + " Found: \"" + procs + "\"";
- assertEquals(msg, 1, exeProcs.size());
-
- msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
- + "Found: \"" + procs.get(0) + "\"";
- assertEquals(msg, domain, exeProcs.get(0).label);
- }
- }
-
- /**
- * Asserts that a domain must exist, and that the cardinality is greater
- * than or equal to 1.
- *
- * @param domain
- * The domain or SELinux context to check.
- * @param executables
- * The path of the allowed executables or application package names.
- */
- private void assertDomainN(String domain, String... executables)
- throws DeviceNotAvailableException {
- List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
- String msg = "Expected 1 or more processes in SELinux domain but found none.";
- assertNotNull(msg, procs);
-
- Set<String> execList = new HashSet<String>(Arrays.asList(executables));
-
- for (ProcessDetails p : procs) {
- msg = "Expected one of \"" + execList + "\" in SELinux domain \"" + domain + "\""
- + " Found: \"" + p + "\"";
- assertTrue(msg, execList.contains(p.procTitle));
- }
-
- for (String exe : executables) {
- List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(exe);
-
- if (exeProcs != null) {
- for (ProcessDetails p : exeProcs) {
- msg = "Expected executable \"" + exe + "\" in SELinux domain \""
- + domain + "\"" + " Found: \"" + p + "\"";
- assertEquals(msg, domain, p.label);
- }
- }
- }
- }
-
- /**
- * Asserts that a domain, if it exists, is only running the listed executables.
- *
- * @param domain
- * The domain or SELinux context to check.
- * @param executables
- * The path of the allowed executables or application package names.
- */
- private void assertDomainHasExecutable(String domain, String... executables)
- throws DeviceNotAvailableException {
- List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
-
- if (procs != null) {
- Set<String> execList = new HashSet<String>(Arrays.asList(executables));
-
- for (ProcessDetails p : procs) {
- String msg = "Expected one of \"" + execList + "\" in SELinux domain \""
- + domain + "\"" + " Found: \"" + p + "\"";
- assertTrue(msg, execList.contains(p.procTitle));
- }
- }
-
- for (String exe : executables) {
- List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(exe);
-
- if (exeProcs != null) {
- for (ProcessDetails p : exeProcs) {
- String msg = "Expected executable \"" + exe + "\" in SELinux domain \""
- + domain + "\"" + " Found: \"" + p + "\"";
- assertEquals(msg, domain, p.label);
- }
- }
- }
- }
-
- /* Init is always there */
- public void testInitDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:init:s0", "/init");
- }
-
- /* Ueventd is always there */
- public void testUeventdDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:ueventd:s0", "/sbin/ueventd");
- }
-
- /* Devices always have healthd */
- public void testHealthdDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:healthd:s0", "/sbin/healthd");
- }
-
- /* Servicemanager is always there */
- public void testServicemanagerDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:servicemanager:s0", "/system/bin/servicemanager");
- }
-
- /* Vold is always there */
- public void testVoldDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:vold:s0", "/system/bin/vold");
- }
-
- /* netd is always there */
- public void testNetdDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:netd:s0", "/system/bin/netd");
- }
-
- /* Debuggerd is always there */
- public void testDebuggerdDomain() throws DeviceNotAvailableException {
- assertDomainN("u:r:debuggerd:s0", "/system/bin/debuggerd", "/system/bin/debuggerd64");
- }
-
- /* Surface flinger is always there */
- public void testSurfaceflingerDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:surfaceflinger:s0", "/system/bin/surfaceflinger");
- }
-
- /* Zygote is always running */
- public void testZygoteDomain() throws DeviceNotAvailableException {
- assertDomainN("u:r:zygote:s0", "zygote", "zygote64");
- }
-
- /* Checks drmserver for devices that require it */
- public void testDrmServerDomain() throws DeviceNotAvailableException {
- assertDomainZeroOrOne("u:r:drmserver:s0", "/system/bin/drmserver");
- }
-
- /* Media server is always running */
- public void testMediaserverDomain() throws DeviceNotAvailableException {
- assertDomainN("u:r:mediaserver:s0", "media.log", "/system/bin/mediaserver");
- }
-
- /* Installd is always running */
- public void testInstalldDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:installd:s0", "/system/bin/installd");
- }
-
- /* keystore is always running */
- public void testKeystoreDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:keystore:s0", "/system/bin/keystore");
- }
-
- /* System server better be running :-P */
- public void testSystemServerDomain() throws DeviceNotAvailableException {
- assertDomainOne("u:r:system_server:s0", "system_server");
- }
-
- /*
- * Some OEMs do not use sdcardd so transient. Other OEMs have multiple sdcards
- * so they run the daemon multiple times.
- */
- public void testSdcarddDomain() throws DeviceNotAvailableException {
- assertDomainHasExecutable("u:r:sdcardd:s0", "/system/bin/sdcard");
- }
-
- /* Watchdogd may or may not be there */
- public void testWatchdogdDomain() throws DeviceNotAvailableException {
- assertDomainZeroOrOne("u:r:watchdogd:s0", "/sbin/watchdogd");
- }
-
- /* logd may or may not be there */
- public void testLogdDomain() throws DeviceNotAvailableException {
- assertDomainZeroOrOne("u:r:logd:s0", "/system/bin/logd");
- }
-
- /* lmkd may or may not be there */
- public void testLmkdDomain() throws DeviceNotAvailableException {
- assertDomainZeroOrOne("u:r:lmkd:s0", "/system/bin/lmkd");
- }
-
- /* Wifi may be off so cardinality of 0 or 1 is ok */
- public void testWpaDomain() throws DeviceNotAvailableException {
- assertDomainZeroOrOne("u:r:wpa:s0", "/system/bin/wpa_supplicant");
- }
-
- /*
- * Nothing should be running in this domain, cardinality test is all thats
- * needed
- */
- public void testInitShellDomain() throws DeviceNotAvailableException {
- assertDomainEmpty("u:r:init_shell:s0");
- }
-
- /*
- * Nothing should be running in this domain, cardinality test is all thats
- * needed
- */
- public void testRecoveryDomain() throws DeviceNotAvailableException {
- assertDomainEmpty("u:r:recovery:s0");
- }
-
- /*
- * Nothing should be running in this domain, cardinality test is all thats
- * needed
- */
- public void testSuDomain() throws DeviceNotAvailableException {
- assertDomainEmpty("u:r:su:s0");
- }
-
- /*
- * All kthreads should be in kernel context.
- */
- public void testKernelDomain() throws DeviceNotAvailableException {
- String domain = "u:r:kernel:s0";
- List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
- if (procs != null) {
- for (ProcessDetails p : procs) {
- assertTrue("Non Kernel thread \"" + p + "\" found!", p.isKernel());
- }
- }
- }
-
- private static class ProcessDetails {
- public String label;
- public String user;
- public int pid;
- public int ppid;
- public String procTitle;
-
- private static HashMap<String, ArrayList<ProcessDetails>> procMap;
- private static HashMap<String, ArrayList<ProcessDetails>> exeMap;
- private static int kernelParentThreadpid = -1;
-
- ProcessDetails(String label, String user, int pid, int ppid, String procTitle) {
- this.label = label;
- this.user = user;
- this.pid = pid;
- this.ppid = ppid;
- this.procTitle = procTitle;
- }
-
- @Override
- public String toString() {
- return "label: " + label
- + " user: " + user
- + " pid: " + pid
- + " ppid: " + ppid
- + " cmd: " + procTitle;
- }
-
-
- private static void createProcMap(ITestDevice tDevice) throws DeviceNotAvailableException {
-
- /* take the output of a ps -Z to do our analysis */
- CollectingOutputReceiver psOut = new CollectingOutputReceiver();
- tDevice.executeShellCommand("ps -Z", psOut);
- String psOutString = psOut.getOutput();
- Pattern p = Pattern.compile(
- "^([\\w_:]+)\\s+([\\w_]+)\\s+(\\d+)\\s+(\\d+)\\s+(\\p{Graph}+)\\s*$",
- Pattern.MULTILINE);
- Matcher m = p.matcher(psOutString);
- procMap = new HashMap<String, ArrayList<ProcessDetails>>();
- exeMap = new HashMap<String, ArrayList<ProcessDetails>>();
- while(m.find()) {
- String domainLabel = m.group(1);
- String user = m.group(2);
- int pid = Integer.parseInt(m.group(3));
- int ppid = Integer.parseInt(m.group(4));
- String procTitle = m.group(5);
- ProcessDetails proc = new ProcessDetails(domainLabel, user, pid, ppid, procTitle);
- if (procMap.get(domainLabel) == null) {
- procMap.put(domainLabel, new ArrayList<ProcessDetails>());
- }
- procMap.get(domainLabel).add(proc);
- if (procTitle.equals("kthreadd") && ppid == 0) {
- kernelParentThreadpid = pid;
- }
- if (exeMap.get(procTitle) == null) {
- exeMap.put(procTitle, new ArrayList<ProcessDetails>());
- }
- exeMap.get(procTitle).add(proc);
- }
- }
-
- public static HashMap<String, ArrayList<ProcessDetails>> getProcMap(ITestDevice tDevice)
- throws DeviceNotAvailableException{
- if (procMap == null) {
- createProcMap(tDevice);
- }
- return procMap;
- }
-
- public static HashMap<String, ArrayList<ProcessDetails>> getExeMap(ITestDevice tDevice)
- throws DeviceNotAvailableException{
- if (exeMap == null) {
- createProcMap(tDevice);
- }
- return exeMap;
- }
-
- public boolean isKernel() {
- return (pid == kernelParentThreadpid || ppid == kernelParentThreadpid);
- }
- }
-}
diff --git a/hostsidetests/security/src/android/security/cts/EncryptionHostTest.java b/hostsidetests/security/src/android/security/cts/EncryptionHostTest.java
new file mode 100644
index 0000000..5e12143
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/EncryptionHostTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package android.security.cts;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.DeviceTestCase;
+
+import java.util.UUID;
+
+/**
+ * Host side encryption tests
+ *
+ * These tests analyze a userdebug device for correct encryption properties
+ */
+public class EncryptionHostTest extends DeviceTestCase {
+ ITestDevice mDevice;
+ boolean mUserDebug;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+ mUserDebug = "userdebug".equals(mDevice.executeShellCommand("getprop ro.build.type").trim());
+ if (!mUserDebug) {
+ return;
+ }
+
+ mDevice.executeAdbCommand("root");
+ assertTrue(mDevice.isAdbRoot());
+ }
+
+ public void testEncrypted() throws DeviceNotAvailableException {
+ if (!mUserDebug || !mDevice.isDeviceEncrypted()) {
+ return;
+ }
+ /*
+ // Create file with name and contents a random UUID so we can search for it
+ String uuid = UUID.randomUUID().toString();
+ mDevice.executeShellCommand("echo " + uuid + " > /data/local/tmp/" + uuid);
+ String uuidReturned = mDevice.executeShellCommand("cat /data/local/tmp/" + uuid).trim();
+ assertTrue(uuid.equals(uuidReturned));
+
+ // Get name of /data device
+ String fstabName = mDevice.executeShellCommand("ls /fstab.*");
+ String[] fstab = mDevice.executeShellCommand("cat " + fstabName).split("\n");
+ String path = null;
+ for (String line : fstab) {
+ String[] entries = line.split("[ \t]+");
+ if (entries.length < 2) continue;
+ if ("/data".equals(entries[1])) {
+ path = entries[0];
+ break;
+ }
+ }
+ assertFalse(path == null);
+
+ // grep it for the data
+ String result = mDevice.executeShellCommand("grep " + uuid + " " + path + " ").trim();
+ assertTrue("".equals(result));
+
+ // Clean up
+ mDevice.executeShellCommand("rm /data/local/tmp/" + uuid);
+ */
+ }
+}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
new file mode 100644
index 0000000..3163100
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -0,0 +1,773 @@
+/*
+ * Copyright (C) 2014 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 com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.String;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.Scanner;
+import java.util.Set;
+
+/**
+ * Host-side SELinux tests.
+ *
+ * These tests analyze the policy file in use on the subject device directly or
+ * run as the shell user to evaluate aspects of the state of SELinux on the test
+ * device which otherwise would not be available to a normal apk.
+ */
+public class SELinuxHostTest extends DeviceTestCase {
+
+ private File sepolicyAnalyze;
+ private File checkSeapp;
+ private File checkFc;
+ private File aospSeappFile;
+ private File aospFcFile;
+ private File aospPcFile;
+ private File aospSvcFile;
+ private File devicePolicyFile;
+ private File deviceSeappFile;
+ private File deviceFcFile;
+ private File devicePcFile;
+ private File deviceSvcFile;
+ private File seappNeverAllowFile;
+
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ private File copyResourceToTempFile(String resName) throws IOException {
+ InputStream is = this.getClass().getResourceAsStream(resName);
+ File tempFile = File.createTempFile("SELinuxHostTest", ".tmp");
+ FileOutputStream os = new FileOutputStream(tempFile);
+ int rByte = 0;
+ while ((rByte = is.read()) != -1) {
+ os.write(rByte);
+ }
+ os.flush();
+ os.close();
+ tempFile.deleteOnExit();
+ return tempFile;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+
+ /* retrieve the sepolicy-analyze executable from jar */
+ sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
+ sepolicyAnalyze.setExecutable(true);
+
+ /* retrieve the checkseapp executable from jar */
+ checkSeapp = copyResourceToTempFile("/checkseapp");
+ checkSeapp.setExecutable(true);
+
+ /* retrieve the checkfc executable from jar */
+ checkFc = copyResourceToTempFile("/checkfc");
+ checkFc.setExecutable(true);
+
+ /* obtain sepolicy file from running device */
+ devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
+ devicePolicyFile.deleteOnExit();
+ mDevice.pullFile("/sys/fs/selinux/policy", devicePolicyFile);
+
+ /* obtain seapp_contexts file from running device */
+ deviceSeappFile = File.createTempFile("seapp_contexts", ".tmp");
+ deviceSeappFile.deleteOnExit();
+ mDevice.pullFile("/seapp_contexts", deviceSeappFile);
+
+ /* obtain file_contexts.bin file from running device */
+ deviceFcFile = File.createTempFile("file_contexts", ".bin");
+ deviceFcFile.deleteOnExit();
+ mDevice.pullFile("/file_contexts.bin", deviceFcFile);
+
+ /* obtain property_contexts file from running device */
+ devicePcFile = File.createTempFile("property_contexts", ".tmp");
+ devicePcFile.deleteOnExit();
+ mDevice.pullFile("/property_contexts", devicePcFile);
+
+ /* obtain service_contexts file from running device */
+ deviceSvcFile = File.createTempFile("service_contexts", ".tmp");
+ deviceSvcFile.deleteOnExit();
+ mDevice.pullFile("/service_contexts", deviceSvcFile);
+
+ /* retrieve the AOSP *_contexts files from jar */
+ aospSeappFile = copyResourceToTempFile("/general_seapp_contexts");
+ aospFcFile = copyResourceToTempFile("/general_file_contexts.bin");
+ aospPcFile = copyResourceToTempFile("/general_property_contexts");
+ aospSvcFile = copyResourceToTempFile("/general_service_contexts");
+ seappNeverAllowFile = copyResourceToTempFile("/general_seapp_neverallows");
+ }
+
+ /**
+ * Tests that all domains in the running policy file are in enforcing mode
+ *
+ * @throws Exception
+ */
+ public void testAllEnforcing() throws Exception {
+
+ /* run sepolicy-analyze permissive check on policy file */
+ ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
+ devicePolicyFile.getAbsolutePath(), "permissive");
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ StringBuilder errorString = new StringBuilder();
+ while ((line = result.readLine()) != null) {
+ errorString.append(line);
+ errorString.append("\n");
+ }
+ assertTrue("The following SELinux domains were found to be in permissive mode:\n"
+ + errorString, errorString.length() == 0);
+ }
+
+ /**
+ * Asserts that specified type is not associated with the specified
+ * attribute.
+ *
+ * @param attribute
+ * The attribute name.
+ * @param type
+ * The type name.
+ */
+ private void assertNotInAttribute(String attribute, String badtype) throws Exception {
+ /* run sepolicy-analyze attribute check on policy file */
+ ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
+ devicePolicyFile.getAbsolutePath(), "attribute", attribute);
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String type;
+ while ((type = result.readLine()) != null) {
+ assertFalse("Attribute " + attribute + " includes " + type + "\n",
+ type.equals(badtype));
+ }
+ }
+
+ /**
+ * Tests that mlstrustedsubject does not include untrusted_app
+ * and that mlstrustedobject does not include app_data_file.
+ * This helps prevent circumventing the per-user isolation of
+ * normal apps via levelFrom=user.
+ *
+ * @throws Exception
+ */
+ public void testMLSAttributes() throws Exception {
+ assertNotInAttribute("mlstrustedsubject", "untrusted_app");
+ assertNotInAttribute("mlstrustedobject", "app_data_file");
+ }
+
+ /**
+ * Tests that the seapp_contexts file on the device is valid.
+ *
+ * @throws Exception
+ */
+ public void testValidSeappContexts() throws Exception {
+
+ /* run checkseapp on seapp_contexts */
+ ProcessBuilder pb = new ProcessBuilder(checkSeapp.getAbsolutePath(),
+ "-p", devicePolicyFile.getAbsolutePath(),
+ seappNeverAllowFile.getAbsolutePath(),
+ deviceSeappFile.getAbsolutePath());
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ StringBuilder errorString = new StringBuilder();
+ while ((line = result.readLine()) != null) {
+ errorString.append(line);
+ errorString.append("\n");
+ }
+ assertTrue("The seapp_contexts file was invalid:\n"
+ + errorString, errorString.length() == 0);
+ }
+
+ /**
+ * Asserts that the actual file contents starts with the expected file
+ * contents.
+ *
+ * @param expectedFile
+ * The file with the expected contents.
+ * @param actualFile
+ * The actual file being checked.
+ */
+ private void assertFileStartsWith(File expectedFile, File actualFile) throws Exception {
+ BufferedReader expectedReader = new BufferedReader(new FileReader(expectedFile.getAbsolutePath()));
+ BufferedReader actualReader = new BufferedReader(new FileReader(actualFile.getAbsolutePath()));
+ String expectedLine, actualLine;
+ while ((expectedLine = expectedReader.readLine()) != null) {
+ actualLine = actualReader.readLine();
+ assertEquals("Lines do not match:", expectedLine, actualLine);
+ }
+ }
+
+ /**
+ * Tests that the seapp_contexts file on the device contains
+ * the standard AOSP entries.
+ *
+ * @throws Exception
+ */
+ public void testAospSeappContexts() throws Exception {
+ assertFileStartsWith(aospSeappFile, deviceSeappFile);
+ }
+
+ /**
+ * Tests that the file_contexts.bin file on the device contains
+ * the standard AOSP entries.
+ *
+ * @throws Exception
+ */
+ public void testAospFileContexts() throws Exception {
+ /* run checkfc -c general_file_contexts.bin file_contexts.bin */
+ ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
+ "-c", aospFcFile.getAbsolutePath(),
+ deviceFcFile.getAbsolutePath());
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line = result.readLine();
+ assertTrue("The file_contexts.bin file did not include the AOSP entries:\n"
+ + line + "\n",
+ line.equals("equal") || line.equals("subset"));
+ }
+
+ /**
+ * Tests that the property_contexts file on the device contains
+ * the standard AOSP entries.
+ *
+ * @throws Exception
+ */
+ public void testAospPropertyContexts() throws Exception {
+ assertFileStartsWith(aospPcFile, devicePcFile);
+ }
+
+ /**
+ * Tests that the service_contexts file on the device contains
+ * the standard AOSP entries.
+ *
+ * @throws Exception
+ */
+ public void testAospServiceContexts() throws Exception {
+ assertFileStartsWith(aospSvcFile, deviceSvcFile);
+ }
+
+ /**
+ * Tests that the file_contexts.bin file on the device is valid.
+ *
+ * @throws Exception
+ */
+ public void testValidFileContexts() throws Exception {
+
+ /* run checkfc sepolicy file_contexts.bin */
+ ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
+ devicePolicyFile.getAbsolutePath(),
+ deviceFcFile.getAbsolutePath());
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ StringBuilder errorString = new StringBuilder();
+ while ((line = result.readLine()) != null) {
+ errorString.append(line);
+ errorString.append("\n");
+ }
+ assertTrue("The file_contexts.bin file was invalid:\n"
+ + errorString, errorString.length() == 0);
+ }
+
+ /**
+ * Tests that the property_contexts file on the device is valid.
+ *
+ * @throws Exception
+ */
+ public void testValidPropertyContexts() throws Exception {
+
+ /* run checkfc -p on property_contexts */
+ ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
+ "-p", devicePolicyFile.getAbsolutePath(),
+ devicePcFile.getAbsolutePath());
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ StringBuilder errorString = new StringBuilder();
+ while ((line = result.readLine()) != null) {
+ errorString.append(line);
+ errorString.append("\n");
+ }
+ assertTrue("The property_contexts file was invalid:\n"
+ + errorString, errorString.length() == 0);
+ }
+
+ /**
+ * Tests that the service_contexts file on the device is valid.
+ *
+ * @throws Exception
+ */
+ public void testValidServiceContexts() throws Exception {
+
+ /* run checkfc -s on service_contexts */
+ ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
+ "-s", devicePolicyFile.getAbsolutePath(),
+ deviceSvcFile.getAbsolutePath());
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ StringBuilder errorString = new StringBuilder();
+ while ((line = result.readLine()) != null) {
+ errorString.append(line);
+ errorString.append("\n");
+ }
+ assertTrue("The service_contexts file was invalid:\n"
+ + errorString, errorString.length() == 0);
+ }
+
+ /**
+ * Tests that the policy defines no booleans (runtime conditional policy).
+ *
+ * @throws Exception
+ */
+ public void testNoBooleans() throws Exception {
+
+ /* run sepolicy-analyze booleans check on policy file */
+ ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
+ devicePolicyFile.getAbsolutePath(), "booleans");
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ StringBuilder errorString = new StringBuilder();
+ while ((line = result.readLine()) != null) {
+ errorString.append(line);
+ errorString.append("\n");
+ }
+ assertTrue("The policy contained booleans:\n"
+ + errorString, errorString.length() == 0);
+ }
+
+ /**
+ * Tests that important domain labels are being appropriately applied.
+ */
+
+ /**
+ * Asserts that no processes are running in a domain.
+ *
+ * @param domain
+ * The domain or SELinux context to check.
+ */
+ private void assertDomainEmpty(String domain) throws DeviceNotAvailableException {
+ List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
+ String msg = "Expected no processes in SELinux domain \"" + domain + "\""
+ + " Found: \"" + procs + "\"";
+ assertNull(msg, procs);
+ }
+
+ /**
+ * Asserts that a domain exists and that only one, well defined, process is
+ * running in that domain.
+ *
+ * @param domain
+ * The domain or SELinux context to check.
+ * @param executable
+ * The path of the executable or application package name.
+ */
+ private void assertDomainOne(String domain, String executable) throws DeviceNotAvailableException {
+ List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
+ List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(executable);
+ String msg = "Expected 1 process in SELinux domain \"" + domain + "\""
+ + " Found \"" + procs + "\"";
+ assertNotNull(msg, procs);
+ assertEquals(msg, 1, procs.size());
+
+ msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
+ + "Found: \"" + procs + "\"";
+ assertEquals(msg, executable, procs.get(0).procTitle);
+
+ msg = "Expected 1 process with executable \"" + executable + "\""
+ + " Found \"" + procs + "\"";
+ assertNotNull(msg, exeProcs);
+ assertEquals(msg, 1, exeProcs.size());
+
+ msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
+ + "Found: \"" + procs + "\"";
+ assertEquals(msg, domain, exeProcs.get(0).label);
+ }
+
+ /**
+ * Asserts that a domain may exist. If a domain exists, the cardinality of
+ * the domain is verified to be 1 and that the correct process is running in
+ * that domain.
+ *
+ * @param domain
+ * The domain or SELinux context to check.
+ * @param executable
+ * The path of the executable or application package name.
+ */
+ private void assertDomainZeroOrOne(String domain, String executable)
+ throws DeviceNotAvailableException {
+ List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
+ List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(executable);
+
+ if (procs != null) {
+ String msg = "Expected 1 process in SELinux domain \"" + domain + "\""
+ + " Found: \"" + procs + "\"";
+ assertEquals(msg, 1, procs.size());
+
+ msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
+ + "Found: \"" + procs.get(0) + "\"";
+ assertEquals(msg, executable, procs.get(0).procTitle);
+ }
+
+ if (exeProcs != null) {
+ String msg = "Expected 1 process with executable \"" + executable + "\""
+ + " Found: \"" + procs + "\"";
+ assertEquals(msg, 1, exeProcs.size());
+
+ msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
+ + "Found: \"" + procs.get(0) + "\"";
+ assertEquals(msg, domain, exeProcs.get(0).label);
+ }
+ }
+
+ /**
+ * Asserts that a domain must exist, and that the cardinality is greater
+ * than or equal to 1.
+ *
+ * @param domain
+ * The domain or SELinux context to check.
+ * @param executables
+ * The path of the allowed executables or application package names.
+ */
+ private void assertDomainN(String domain, String... executables)
+ throws DeviceNotAvailableException {
+ List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
+ String msg = "Expected 1 or more processes in SELinux domain but found none.";
+ assertNotNull(msg, procs);
+
+ Set<String> execList = new HashSet<String>(Arrays.asList(executables));
+
+ for (ProcessDetails p : procs) {
+ msg = "Expected one of \"" + execList + "\" in SELinux domain \"" + domain + "\""
+ + " Found: \"" + p + "\"";
+ assertTrue(msg, execList.contains(p.procTitle));
+ }
+
+ for (String exe : executables) {
+ List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(exe);
+
+ if (exeProcs != null) {
+ for (ProcessDetails p : exeProcs) {
+ msg = "Expected executable \"" + exe + "\" in SELinux domain \""
+ + domain + "\"" + " Found: \"" + p + "\"";
+ assertEquals(msg, domain, p.label);
+ }
+ }
+ }
+ }
+
+ /**
+ * Asserts that a domain, if it exists, is only running the listed executables.
+ *
+ * @param domain
+ * The domain or SELinux context to check.
+ * @param executables
+ * The path of the allowed executables or application package names.
+ */
+ private void assertDomainHasExecutable(String domain, String... executables)
+ throws DeviceNotAvailableException {
+ List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
+
+ if (procs != null) {
+ Set<String> execList = new HashSet<String>(Arrays.asList(executables));
+
+ for (ProcessDetails p : procs) {
+ String msg = "Expected one of \"" + execList + "\" in SELinux domain \""
+ + domain + "\"" + " Found: \"" + p + "\"";
+ assertTrue(msg, execList.contains(p.procTitle));
+ }
+ }
+
+ for (String exe : executables) {
+ List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(exe);
+
+ if (exeProcs != null) {
+ for (ProcessDetails p : exeProcs) {
+ String msg = "Expected executable \"" + exe + "\" in SELinux domain \""
+ + domain + "\"" + " Found: \"" + p + "\"";
+ assertEquals(msg, domain, p.label);
+ }
+ }
+ }
+ }
+
+ /* Init is always there */
+ public void testInitDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:init:s0", "/init");
+ }
+
+ /* Ueventd is always there */
+ public void testUeventdDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:ueventd:s0", "/sbin/ueventd");
+ }
+
+ /* Devices always have healthd */
+ public void testHealthdDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:healthd:s0", "/sbin/healthd");
+ }
+
+ /* Servicemanager is always there */
+ public void testServicemanagerDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:servicemanager:s0", "/system/bin/servicemanager");
+ }
+
+ /* Vold is always there */
+ public void testVoldDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:vold:s0", "/system/bin/vold");
+ }
+
+ /* netd is always there */
+ public void testNetdDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:netd:s0", "/system/bin/netd");
+ }
+
+ /* Debuggerd is always there */
+ public void testDebuggerdDomain() throws DeviceNotAvailableException {
+ assertDomainN("u:r:debuggerd:s0", "/system/bin/debuggerd", "/system/bin/debuggerd64");
+ }
+
+ /* Surface flinger is always there */
+ public void testSurfaceflingerDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:surfaceflinger:s0", "/system/bin/surfaceflinger");
+ }
+
+ /* Zygote is always running */
+ public void testZygoteDomain() throws DeviceNotAvailableException {
+ assertDomainN("u:r:zygote:s0", "zygote", "zygote64");
+ }
+
+ /* Checks drmserver for devices that require it */
+ public void testDrmServerDomain() throws DeviceNotAvailableException {
+ assertDomainZeroOrOne("u:r:drmserver:s0", "/system/bin/drmserver");
+ }
+
+ /* Media server is always running */
+ public void testMediaserverDomain() throws DeviceNotAvailableException {
+ assertDomainN("u:r:mediaserver:s0", "media.log", "/system/bin/mediaserver");
+ }
+
+ /* Installd is always running */
+ public void testInstalldDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:installd:s0", "/system/bin/installd");
+ }
+
+ /* keystore is always running */
+ public void testKeystoreDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:keystore:s0", "/system/bin/keystore");
+ }
+
+ /* System server better be running :-P */
+ public void testSystemServerDomain() throws DeviceNotAvailableException {
+ assertDomainOne("u:r:system_server:s0", "system_server");
+ }
+
+ /*
+ * Some OEMs do not use sdcardd so transient. Other OEMs have multiple sdcards
+ * so they run the daemon multiple times.
+ */
+ public void testSdcarddDomain() throws DeviceNotAvailableException {
+ assertDomainHasExecutable("u:r:sdcardd:s0", "/system/bin/sdcard");
+ }
+
+ /* Watchdogd may or may not be there */
+ public void testWatchdogdDomain() throws DeviceNotAvailableException {
+ assertDomainZeroOrOne("u:r:watchdogd:s0", "/sbin/watchdogd");
+ }
+
+ /* logd may or may not be there */
+ public void testLogdDomain() throws DeviceNotAvailableException {
+ assertDomainZeroOrOne("u:r:logd:s0", "/system/bin/logd");
+ }
+
+ /* lmkd may or may not be there */
+ public void testLmkdDomain() throws DeviceNotAvailableException {
+ assertDomainZeroOrOne("u:r:lmkd:s0", "/system/bin/lmkd");
+ }
+
+ /* Wifi may be off so cardinality of 0 or 1 is ok */
+ public void testWpaDomain() throws DeviceNotAvailableException {
+ assertDomainZeroOrOne("u:r:wpa:s0", "/system/bin/wpa_supplicant");
+ }
+
+ /*
+ * Nothing should be running in this domain, cardinality test is all thats
+ * needed
+ */
+ public void testInitShellDomain() throws DeviceNotAvailableException {
+ assertDomainEmpty("u:r:init_shell:s0");
+ }
+
+ /*
+ * Nothing should be running in this domain, cardinality test is all thats
+ * needed
+ */
+ public void testRecoveryDomain() throws DeviceNotAvailableException {
+ assertDomainEmpty("u:r:recovery:s0");
+ }
+
+ /*
+ * Nothing should be running in this domain, cardinality test is all thats
+ * needed
+ */
+ public void testSuDomain() throws DeviceNotAvailableException {
+ assertDomainEmpty("u:r:su:s0");
+ }
+
+ /*
+ * All kthreads should be in kernel context.
+ */
+ public void testKernelDomain() throws DeviceNotAvailableException {
+ String domain = "u:r:kernel:s0";
+ List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
+ if (procs != null) {
+ for (ProcessDetails p : procs) {
+ assertTrue("Non Kernel thread \"" + p + "\" found!", p.isKernel());
+ }
+ }
+ }
+
+ private static class ProcessDetails {
+ public String label;
+ public String user;
+ public int pid;
+ public int ppid;
+ public String procTitle;
+
+ private static HashMap<String, ArrayList<ProcessDetails>> procMap;
+ private static HashMap<String, ArrayList<ProcessDetails>> exeMap;
+ private static int kernelParentThreadpid = -1;
+
+ ProcessDetails(String label, String user, int pid, int ppid, String procTitle) {
+ this.label = label;
+ this.user = user;
+ this.pid = pid;
+ this.ppid = ppid;
+ this.procTitle = procTitle;
+ }
+
+ @Override
+ public String toString() {
+ return "label: " + label
+ + " user: " + user
+ + " pid: " + pid
+ + " ppid: " + ppid
+ + " cmd: " + procTitle;
+ }
+
+
+ private static void createProcMap(ITestDevice tDevice) throws DeviceNotAvailableException {
+
+ /* take the output of a ps -Z to do our analysis */
+ CollectingOutputReceiver psOut = new CollectingOutputReceiver();
+ // TODO: remove "toybox" below and just run "ps"
+ tDevice.executeShellCommand("toybox ps -A -o label,user,pid,ppid,cmdline", psOut);
+ String psOutString = psOut.getOutput();
+ Pattern p = Pattern.compile(
+ "^([\\w_:]+)\\s+([\\w_]+)\\s+(\\d+)\\s+(\\d+)\\s+(\\p{Graph}+)\\s*$",
+ Pattern.MULTILINE);
+ Matcher m = p.matcher(psOutString);
+ procMap = new HashMap<String, ArrayList<ProcessDetails>>();
+ exeMap = new HashMap<String, ArrayList<ProcessDetails>>();
+ while(m.find()) {
+ String domainLabel = m.group(1);
+ String user = m.group(2);
+ int pid = Integer.parseInt(m.group(3));
+ int ppid = Integer.parseInt(m.group(4));
+ String procTitle = m.group(5);
+ ProcessDetails proc = new ProcessDetails(domainLabel, user, pid, ppid, procTitle);
+ if (procMap.get(domainLabel) == null) {
+ procMap.put(domainLabel, new ArrayList<ProcessDetails>());
+ }
+ procMap.get(domainLabel).add(proc);
+ if (procTitle.equals("[kthreadd]") && ppid == 0) {
+ kernelParentThreadpid = pid;
+ }
+ if (exeMap.get(procTitle) == null) {
+ exeMap.put(procTitle, new ArrayList<ProcessDetails>());
+ }
+ exeMap.get(procTitle).add(proc);
+ }
+ }
+
+ public static HashMap<String, ArrayList<ProcessDetails>> getProcMap(ITestDevice tDevice)
+ throws DeviceNotAvailableException{
+ if (procMap == null) {
+ createProcMap(tDevice);
+ }
+ return procMap;
+ }
+
+ public static HashMap<String, ArrayList<ProcessDetails>> getExeMap(ITestDevice tDevice)
+ throws DeviceNotAvailableException{
+ if (exeMap == null) {
+ createProcMap(tDevice);
+ }
+ return exeMap;
+ }
+
+ public boolean isKernel() {
+ return (pid == kernelParentThreadpid || ppid == kernelParentThreadpid);
+ }
+ }
+}
diff --git a/hostsidetests/services/Android.mk b/hostsidetests/services/Android.mk
new file mode 100644
index 0000000..178cb8a
--- /dev/null
+++ b/hostsidetests/services/Android.mk
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+
+include $(call all-subdir-makefiles)
diff --git a/hostsidetests/services/activitymanager/Android.mk b/hostsidetests/services/activitymanager/Android.mk
new file mode 100644
index 0000000..35d34da
--- /dev/null
+++ b/hostsidetests/services/activitymanager/Android.mk
@@ -0,0 +1,38 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+# Must match the package name in CtsTestCaseList.mk
+LOCAL_MODULE := CtsServicesHostTestCases
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+
+LOCAL_CTS_TEST_PACKAGE := android.server
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/services/activitymanager/AndroidTest.xml b/hostsidetests/services/activitymanager/AndroidTest.xml
new file mode 100644
index 0000000..ce407a3
--- /dev/null
+++ b/hostsidetests/services/activitymanager/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Sample host test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsDeviceServicesTestApp.apk" />
+ </target_preparer>
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsServicesHostTestCases.jar" />
+ </test>
+</configuration>
diff --git a/hostsidetests/services/activitymanager/OldAndroidTest.xml b/hostsidetests/services/activitymanager/OldAndroidTest.xml
new file mode 100644
index 0000000..37393763
--- /dev/null
+++ b/hostsidetests/services/activitymanager/OldAndroidTest.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<configuration description="CTS package preparer for install/uninstall of the apk used as a test operation target">
+ <include name="common-config" />
+ <!-- This will tell tradefed to install the test apk. -->
+ <option name="cts-apk-installer:test-file-name" value="CtsDeviceServicesTestApp.apk" />
+</configuration>
diff --git a/hostsidetests/services/activitymanager/app/Android.mk b/hostsidetests/services/activitymanager/app/Android.mk
new file mode 100644
index 0000000..4633ce2
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/Android.mk
@@ -0,0 +1,31 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsDeviceServicesTestApp
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/services/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
new file mode 100755
index 0000000..09dc4d8
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
@@ -0,0 +1,80 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ package="android.server.app">
+
+ <application>
+ <activity android:name=".TestActivity"
+ android:resizeable="true"
+ android:exported="true"
+ />
+ <activity android:name=".NoRelaunchActivity"
+ android:resizeable="true"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|layoutDirection"
+ android:exported="true"
+ />
+ <activity android:name=".SlowCreateActivity"
+ android:resizeable="true"
+ android:exported="true"
+ />
+ <activity android:name=".LaunchToSideActivity"
+ android:resizeable="true"
+ android:exported="true"
+ android:taskAffinity="nobody.but.LaunchToSideActivity"
+ />
+ <activity android:name=".PipActivity"
+ android:resizeable="true"
+ android:supportsPictureInPicture="true"
+ android:exported="true"
+ />
+ <activity android:name=".AutoEnterPipActivity"
+ android:resizeable="true"
+ android:supportsPictureInPicture="true"
+ android:exported="true"
+ />
+ <activity android:name=".AlwaysFocusablePipActivity"
+ android:theme="@style/Theme.Transparent"
+ android:resizeable="true"
+ android:supportsPictureInPicture="true"
+ androidprv:alwaysFocusable="true"
+ android:exported="true"
+ android:taskAffinity="nobody.but.AlwaysFocusablePipActivity"
+ />
+ <activity android:name=".LaunchIntoPinnedStackPipActivity"
+ android:resizeable="true"
+ android:supportsPictureInPicture="true"
+ androidprv:alwaysFocusable="true"
+ android:exported="true"
+ />
+ <activity android:name=".VisibleBehindActivity"
+ android:resizeable="true"
+ android:supportsPictureInPicture="true"
+ android:exported="true"
+ android:taskAffinity="nobody.but.VisibleBehindActivity"
+ />
+ <activity android:name=".LaunchPipOnPipActivity"
+ android:resizeable="true"
+ android:supportsPictureInPicture="true"
+ android:taskAffinity="nobody.but.LaunchPipOnPipActivity"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|layoutDirection"
+ android:exported="true"
+ />
+ </application>
+</manifest>
+
diff --git a/hostsidetests/services/activitymanager/app/res/values/styles.xml b/hostsidetests/services/activitymanager/app/res/values/styles.xml
new file mode 100644
index 0000000..59ebad2
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/res/values/styles.xml
@@ -0,0 +1,24 @@
+<?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
+ -->
+
+<resources>
+ <style name="Theme.Transparent" parent="android:Theme">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowNoTitle">true</item>
+ </style>
+</resources>
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/AlwaysFocusablePipActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/AlwaysFocusablePipActivity.java
new file mode 100644
index 0000000..3c6f6a1
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/AlwaysFocusablePipActivity.java
@@ -0,0 +1,54 @@
+/*
+ * 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.server.app;
+
+import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.content.Intent;
+import android.graphics.Rect;
+
+import java.lang.reflect.Method;
+
+public class AlwaysFocusablePipActivity extends Activity {
+
+ static void launchAlwaysFocusablePipActivity(Activity caller) {
+ final Intent intent = new Intent(caller, AlwaysFocusablePipActivity.class);
+ intent.setFlags(FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchBounds(new Rect(0, 0, 500, 500));
+ try {
+ setLaunchStackId(options);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+
+ caller.startActivity(intent, options.toBundle());
+ }
+
+ /** ActivityOptions#setLaunchStackId is a @hidden API so we access it through reflection...*/
+ static void setLaunchStackId(ActivityOptions options) throws Exception {
+ final Method method = options.getClass().getDeclaredMethod(
+ "setLaunchStackId", new Class[] { int.class });
+
+ method.setAccessible(true);
+ method.invoke(options, 4 /* ActivityManager.StackId.PINNED_STACK_ID */);
+ }
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java
new file mode 100644
index 0000000..97bc041
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java
@@ -0,0 +1,27 @@
+/*
+ * 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
+ */
+
+package android.server.app;
+
+import android.app.Activity;
+
+public class AutoEnterPipActivity extends Activity {
+ @Override
+ protected void onResume() {
+ super.onResume();
+ enterPictureInPictureMode();
+ }
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchIntoPinnedStackPipActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchIntoPinnedStackPipActivity.java
new file mode 100644
index 0000000..45386bf
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchIntoPinnedStackPipActivity.java
@@ -0,0 +1,27 @@
+/*
+ * 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.server.app;
+
+import android.app.Activity;
+
+public class LaunchIntoPinnedStackPipActivity extends Activity {
+ @Override
+ protected void onResume() {
+ super.onResume();
+ AlwaysFocusablePipActivity.launchAlwaysFocusablePipActivity(this);
+ }
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java
new file mode 100644
index 0000000..b328a09
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java
@@ -0,0 +1,27 @@
+/*
+ * 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.server.app;
+
+import android.app.Activity;
+
+public class LaunchPipOnPipActivity extends Activity {
+ @Override
+ public void onPictureInPictureModeChanged(boolean pictureInPictureMode) {
+ super.onPictureInPictureModeChanged(pictureInPictureMode);
+ AlwaysFocusablePipActivity.launchAlwaysFocusablePipActivity(this);
+ }
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchToSideActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchToSideActivity.java
new file mode 100644
index 0000000..388c9a6
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchToSideActivity.java
@@ -0,0 +1,22 @@
+package android.server.app;
+
+import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_TO_SIDE;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class LaunchToSideActivity extends Activity {
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ final Bundle extras = intent.getExtras();
+ if (extras != null && extras.getBoolean("launch_to_the_side")) {
+ Intent newIntent = new Intent(this, TestActivity.class);
+ newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_LAUNCH_TO_SIDE);
+ startActivity(newIntent);
+ }
+ }
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/NoRelaunchActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/NoRelaunchActivity.java
new file mode 100644
index 0000000..37963de
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/NoRelaunchActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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.server.app;
+
+import android.app.Activity;
+
+public class NoRelaunchActivity extends Activity {
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/PipActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/PipActivity.java
new file mode 100644
index 0000000..b750389
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/PipActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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
+ */
+
+package android.server.app;
+
+import android.app.Activity;
+
+public class PipActivity extends Activity {
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/SlowCreateActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/SlowCreateActivity.java
new file mode 100644
index 0000000..481f5be
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/SlowCreateActivity.java
@@ -0,0 +1,30 @@
+/*
+ * 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.server.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SlowCreateActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ try {
+ Thread.sleep(2000);
+ } catch(InterruptedException e) {}
+ super.onCreate(savedInstanceState);
+ }
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/TestActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/TestActivity.java
new file mode 100644
index 0000000..222cdde
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/TestActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.server.app;
+
+import android.app.Activity;
+
+public class TestActivity extends Activity {
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/VisibleBehindActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/VisibleBehindActivity.java
new file mode 100644
index 0000000..cc8f273
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/VisibleBehindActivity.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.server.app;
+
+import android.app.Activity;
+import android.util.Log;
+
+public class VisibleBehindActivity extends Activity {
+ private static final String TAG = "VisibleBehindActivity";
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (requestVisibleBehind(true)) {
+ Log.e(TAG, "Failed to request visibility behind...");
+ }
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
new file mode 100644
index 0000000..27b5c7a
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
@@ -0,0 +1,198 @@
+/*
+ * 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.server.cts;
+
+import com.android.tradefed.device.ITestDevice;
+
+import junit.framework.Assert;
+
+import android.server.cts.ActivityManagerState.ActivityStack;
+import android.server.cts.ActivityManagerState.ActivityTask;
+import android.server.cts.WindowManagerState.WindowStack;
+import android.server.cts.WindowManagerState.WindowTask;
+
+import java.awt.Rectangle;
+
+import static android.server.cts.ActivityManagerTestBase.FREEFORM_WORKSPACE_STACK_ID;
+
+/** Combined state of the activity manager and window manager. */
+class ActivityAndWindowManagersState extends Assert {
+
+ private ActivityManagerState mAmState = new ActivityManagerState();
+ private WindowManagerState mWmState = new WindowManagerState();
+
+ void computeState(ITestDevice device) throws Exception {
+ computeState(device, true);
+ }
+
+ void computeState(ITestDevice device, boolean visibleOnly) throws Exception {
+ mAmState.computeState(device);
+ mWmState.computeState(device, visibleOnly);
+ }
+
+ ActivityManagerState getAmState() {
+ return mAmState;
+ }
+
+ WindowManagerState getWmState() {
+ return mWmState;
+ }
+
+ void assertSanity() throws Exception {
+ assertTrue("Must have stacks", mAmState.getStackCount() > 0);
+ assertEquals("There should be one and only one resumed activity in the system.",
+ 1, mAmState.getResumedActivitiesCount());
+ assertNotNull("Must have focus activity.", mAmState.getFocusedActivity());
+
+ for (ActivityStack aStack : mAmState.getStacks()) {
+ final int stackId = aStack.mStackId;
+ for (ActivityTask aTask : aStack.getTasks()) {
+ assertEquals("Stack can only contain its own tasks", stackId, aTask.mStackId);
+ }
+ }
+
+ assertNotNull("Must have front window.", mWmState.getFrontWindow());
+ assertNotNull("Must have focused window.", mWmState.getFocusedWindow());
+ assertNotNull("Must have app.", mWmState.getFocusedApp());
+ }
+
+ void assertContainsStack(String msg, int stackId) throws Exception {
+ assertTrue(msg, mAmState.containsStack(stackId));
+ assertTrue(msg, mWmState.containsStack(stackId));
+ }
+
+ void assertDoesNotContainsStack(String msg, int stackId) throws Exception {
+ assertFalse(msg, mAmState.containsStack(stackId));
+ assertFalse(msg, mWmState.containsStack(stackId));
+ }
+
+ void assertFrontStack(String msg, int stackId) throws Exception {
+ assertEquals(msg, stackId, mAmState.getFrontStackId());
+ assertEquals(msg, stackId, mWmState.getFrontStackId());
+ }
+
+ void assertFocusedStack(String msg, int stackId) throws Exception {
+ assertEquals(msg, stackId, mAmState.getFocusedStackId());
+ }
+
+ void assertNotFocusedStack(String msg, int stackId) throws Exception {
+ if (stackId == mAmState.getFocusedStackId()) {
+ failNotEquals(msg, stackId, mAmState.getFocusedStackId());
+ }
+ }
+
+ void assertFocusedActivity(String msg, String activityName) throws Exception {
+ assertEquals(msg, activityName, mAmState.getFocusedActivity());
+ assertEquals(msg, activityName, mWmState.getFocusedApp());
+ }
+
+ void assertNotFocusedActivity(String msg, String activityName) throws Exception {
+ if (mAmState.getFocusedActivity().equals(activityName)) {
+ failNotEquals(msg, mAmState.getFocusedActivity(), activityName);
+ }
+ if (mWmState.getFocusedApp().equals(activityName)) {
+ failNotEquals(msg, mWmState.getFocusedApp(), activityName);
+ }
+ }
+
+ void assertResumedActivity(String msg, String activityName) throws Exception {
+ assertEquals(msg, activityName, mAmState.getResumedActivity());
+ }
+
+ void assertNotResumedActivity(String msg, String activityName) throws Exception {
+ if (mAmState.getResumedActivity().equals(activityName)) {
+ failNotEquals(msg, mAmState.getResumedActivity(), activityName);
+ }
+ }
+
+ void assertFocusedWindow(String msg, String windowName) {
+ assertEquals(msg, windowName, mWmState.getFocusedWindow());
+ }
+
+ void assertNotFocusedWindow(String msg, String windowName) {
+ if (mWmState.getFocusedWindow().equals(windowName)) {
+ failNotEquals(msg, mWmState.getFocusedWindow(), windowName);
+ }
+ }
+
+ void assertFrontWindow(String msg, String windowName) {
+ assertEquals(msg, windowName, mWmState.getFrontWindow());
+ }
+
+ void assertVisibility(String activityName, boolean visible) {
+ final String activityComponentName =
+ ActivityManagerTestBase.getActivityComponentName(activityName);
+ final String windowName =
+ ActivityManagerTestBase.getWindowName(activityName);
+
+ final boolean activityVisible = mAmState.isActivityVisible(activityComponentName);
+ final boolean windowVisible = mWmState.isWindowVisible(windowName);
+
+ if (visible) {
+ assertTrue("Activity=" + activityComponentName + " must be visible.", activityVisible);
+ assertTrue("Window=" + windowName + " must be visible.", windowVisible);
+ } else {
+ assertFalse("Activity=" + activityComponentName + " must NOT be visible.",
+ activityVisible);
+ assertFalse("Window=" + windowName + " must NOT be visible.", windowVisible);
+ }
+ }
+
+ void assertValidBounds() {
+ for (ActivityStack aStack : mAmState.getStacks()) {
+ final int stackId = aStack.mStackId;
+ final WindowStack wStack = mWmState.getStack(stackId);
+ assertNotNull("stackId=" + stackId + " in AM but not in WM?", wStack);
+
+ assertEquals("Stack fullscreen state in AM and WM must be equal stackId=" + stackId,
+ aStack.isFullscreen(), wStack.isFullscreen());
+
+ final Rectangle aStackBounds = aStack.getBounds();
+ final Rectangle wStackBounds = wStack.getBounds();
+ assertEquals("Stack bounds in AM and WM must be equal stackId=" + stackId,
+ aStackBounds, wStackBounds);
+
+ for (ActivityTask aTask : aStack.getTasks()) {
+ final int taskId = aTask.mTaskId;
+ final WindowTask wTask = wStack.getTask(taskId);
+ assertNotNull(
+ "taskId=" + taskId + " in AM but not in WM? stackId=" + stackId, wTask);
+
+ final boolean aTaskIsFullscreen = aTask.isFullscreen();
+ final boolean wTaskIsFullscreen = wTask.isFullscreen();
+ assertEquals("Task fullscreen state in AM and WM must be equal taskId=" + taskId
+ + ", stackId=" + stackId, aTaskIsFullscreen, wTaskIsFullscreen);
+
+ final Rectangle aTaskBounds = aTask.getBounds();
+ final Rectangle wTaskBounds = wTask.getBounds();
+
+ if (aTaskIsFullscreen) {
+ assertNull("Task bounds in AM must be null for fullscreen taskId=" + taskId,
+ aTaskBounds);
+ } else {
+ assertEquals("Task bounds in AM and WM must be equal taskId=" + taskId
+ + ", stackId=" + stackId, aTaskBounds, wTaskBounds);
+
+ if (stackId != FREEFORM_WORKSPACE_STACK_ID) {
+ assertEquals("Task bounds must be equal to stack bounds taskId=" + taskId
+ + ", stackId=" + stackId, aStackBounds, wTaskBounds);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
new file mode 100644
index 0000000..9f00215
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+package android.server.cts;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.lang.Exception;
+import java.lang.String;
+
+public class ActivityManagerDockedStackTests extends ActivityManagerTestBase {
+
+ private static final String TEST_ACTIVITY_NAME = "TestActivity";
+ private static final String LAUNCH_TO_SIDE_ACTIVITY_NAME = "LaunchToSideActivity";
+
+ private static final String AM_MOVE_TASK = "am stack movetask ";
+
+ // TODO: Add test for non-resizeable activity.
+
+ public void testStackList() throws Exception {
+ mDevice.executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertSanity();
+ mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
+ mAmWmState.assertContainsStack(
+ "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
+ }
+
+ public void testDockActivity() throws Exception {
+ launchActivityInDockStack(TEST_ACTIVITY_NAME);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertSanity();
+ mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
+ mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
+ }
+
+ public void testLaunchToSide() throws Exception {
+ launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+ printStacksAndTasks();
+ launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertSanity();
+ mAmWmState.assertContainsStack(
+ "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
+ mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
+ }
+
+ public void testRotationWhenDocked() throws Exception {
+ launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+ launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertSanity();
+ mAmWmState.assertContainsStack(
+ "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
+ mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
+
+ // Rotate device single steps (90°) 0-1-2-3
+ setDeviceRotation(0);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertValidBounds();
+ setDeviceRotation(1);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertValidBounds();
+ setDeviceRotation(2);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertValidBounds();
+ setDeviceRotation(3);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertValidBounds();
+ // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for double
+ // step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side.
+ setDeviceRotation(1);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertValidBounds();
+ setDeviceRotation(3);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertValidBounds();
+ setDeviceRotation(0);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertValidBounds();
+ setDeviceRotation(2);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertValidBounds();
+ setDeviceRotation(0);
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertValidBounds();
+ }
+
+ private void launchActivityInDockStack(String activityName) throws Exception {
+ mDevice.executeShellCommand(getAmStartCmd(activityName));
+ final int taskId = getActivityTaskId(activityName);
+ final String cmd = AM_MOVE_TASK + taskId + " " + DOCKED_STACK_ID + " true";
+ mDevice.executeShellCommand(cmd);
+ }
+
+ private void launchActivityToSide(String activityName) throws Exception {
+ mDevice.executeShellCommand(
+ getAmStartCmd(activityName) + " -f 0x20000000 --ez launch_to_the_side true");
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
new file mode 100644
index 0000000..0542ba4
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -0,0 +1,124 @@
+/*
+ * 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.server.cts;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.lang.Exception;
+import java.lang.String;
+
+public class ActivityManagerPinnedStackTests extends ActivityManagerTestBase {
+ private static final String PIP_ACTIVITY_COMPONENT_NAME = "android.server.app/.PipActivity";
+ private static final String PIP_WINDOW_NAME =
+ "android.server.app/android.server.app.PipActivity";
+
+ private static final String AUTO_ENTER_PIP_ACTIVITY_COMPONENT_NAME =
+ "android.server.app/.AutoEnterPipActivity";
+ private static final String AUTO_ENTER_PIP_WINDOW_NAME =
+ "android.server.app/android.server.app.AutoEnterPipActivity";
+
+ private static final String ALWAYS_FOCUSABLE_PIP_ACTIVITY_COMPONENT_NAME =
+ "android.server.app/.AlwaysFocusablePipActivity";
+ private static final String ALWAYS_FOCUSABLE_PIP_WINDOW_NAME =
+ "android.server.app/android.server.app.AlwaysFocusablePipActivity";
+
+ private static final String LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY_COMPONENT_NAME =
+ "android.server.app/.LaunchIntoPinnedStackPipActivity";
+ private static final String LAUNCH_INTO_PINNED_STACK_PIP_WINDOW_NAME =
+ "android.server.app/android.server.app.LaunchIntoPinnedStackPipActivity";
+
+ private static final String AM_START_PIP_ACTIVITY =
+ "am start -n " + PIP_ACTIVITY_COMPONENT_NAME;
+ private static final String AM_START_AUTO_ENTER_PIP_ACTIVITY =
+ "am start -n " + AUTO_ENTER_PIP_ACTIVITY_COMPONENT_NAME;
+ private static final String AM_START_ALWAYS_FOCUSABLE_PIP_ACTIVITY =
+ "am start -n " + ALWAYS_FOCUSABLE_PIP_ACTIVITY_COMPONENT_NAME;
+ private static final String AM_START_LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY =
+ "am start -n " + LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY_COMPONENT_NAME;
+
+ public void testEnterPictureInPictureMode() throws Exception {
+ final String[] commands = { AM_START_AUTO_ENTER_PIP_ACTIVITY };
+ pinnedStackTester(AUTO_ENTER_PIP_ACTIVITY_COMPONENT_NAME,
+ AUTO_ENTER_PIP_WINDOW_NAME, commands, false);
+ }
+
+ public void testMoveTopActivityToPinnedStack() throws Exception {
+ final String[] commands = { AM_START_PIP_ACTIVITY,
+ AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND };
+ pinnedStackTester(PIP_ACTIVITY_COMPONENT_NAME, PIP_WINDOW_NAME, commands, false);
+ }
+
+ public void testAlwaysFocusablePipActivity() throws Exception {
+ final String[] commands = { AM_START_ALWAYS_FOCUSABLE_PIP_ACTIVITY,
+ AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND };
+ pinnedStackTester(ALWAYS_FOCUSABLE_PIP_ACTIVITY_COMPONENT_NAME,
+ ALWAYS_FOCUSABLE_PIP_WINDOW_NAME, commands, true);
+ }
+
+ public void testLaunchIntoPinnedStack() throws Exception {
+ final String[] commands = { AM_START_LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY };
+ pinnedStackTester(
+ ALWAYS_FOCUSABLE_PIP_ACTIVITY_COMPONENT_NAME,
+ ALWAYS_FOCUSABLE_PIP_WINDOW_NAME, commands, true);
+ // TODO:
+ // - Verify size of pinned stack
+ // - Verify that LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY_COMPONENT_NAME is on fullscreen
+ // stack as we don't want the fact that it launched
+ // ALWAYS_FOCUSABLE_PIP_ACTIVITY_COMPONENT_NAME to move it to the pinned stack just
+ // bacause they have the same task affinity due to package.
+ }
+
+ private void pinnedStackTester(String activiyName, String windowName, String[] commands,
+ boolean isFocusable) throws Exception {
+
+ for (String command : commands) {
+ mDevice.executeShellCommand(command);
+ }
+
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertSanity();
+
+ if (supportsPip()) {
+ mAmWmState.assertContainsStack("Must contain pinned stack.", PINNED_STACK_ID);
+ mAmWmState.assertFrontStack("Pinned stack must be the front stack.", PINNED_STACK_ID);
+ mAmWmState.assertFrontWindow("Pinned window must be the front window.", windowName);
+
+ if (isFocusable) {
+ mAmWmState.assertFocusedStack(
+ "Pinned stack must be the focused stack.", PINNED_STACK_ID);
+ mAmWmState.assertFocusedActivity(
+ "Pinned activity must be focused activity.", activiyName);
+ mAmWmState.assertResumedActivity(
+ "Pinned activity must be the resumed activity.", activiyName);
+ mAmWmState.assertFocusedWindow(
+ "Pinned window must be focused window.", windowName);
+ } else {
+ mAmWmState.assertNotFocusedStack(
+ "Pinned stack can't be the focused stack.", PINNED_STACK_ID);
+ mAmWmState.assertNotFocusedActivity(
+ "Pinned stack can't be the focused activity.", activiyName);
+ mAmWmState.assertNotResumedActivity(
+ "Pinned stack can't be the resumed activity.", activiyName);
+ mAmWmState.assertNotFocusedWindow(
+ "Pinned window can't be focused window.", windowName);
+ }
+ } else {
+ mAmWmState.assertDoesNotContainsStack(
+ "Must not contain pinned stack.", PINNED_STACK_ID);
+ }
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
new file mode 100644
index 0000000..785e487
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
@@ -0,0 +1,103 @@
+/*
+ * 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.server.cts;
+
+import java.lang.Exception;
+import java.lang.String;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import junit.framework.Assert;
+
+import static com.android.ddmlib.Log.LogLevel.INFO;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+
+public class ActivityManagerReplaceWindowTests extends ActivityManagerTestBase {
+
+ private static final String SLOW_CREATE_ACTIVITY_NAME = "SlowCreateActivity";
+ private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
+
+ private static final String AM_MOVE_TASK = "am stack movetask ";
+
+ private List<String> mTempWindowTokens = new ArrayList();
+
+ public void testReplaceWindow_Dock_Relaunch() throws Exception {
+ testReplaceWindow_Dock(true);
+ }
+
+ public void testReplaceWindow_Dock_NoRelaunch() throws Exception {
+ testReplaceWindow_Dock(false);
+ }
+
+ private void testReplaceWindow_Dock(boolean relaunch) throws Exception {
+ final String activityName =
+ relaunch ? SLOW_CREATE_ACTIVITY_NAME : NO_RELAUNCH_ACTIVITY_NAME;
+ final String windowName = getWindowName(activityName);
+ final String amStartCmd = getAmStartCmd(activityName);
+
+ mDevice.executeShellCommand(amStartCmd);
+
+ // Sleep 2 seconds, then check if the window is started properly.
+ // SlowCreateActivity will do a sleep inside its onCreate() to simulate a
+ // slow-starting app. So instead of relying on WindowManagerState's
+ // retrying mechanism, we do an explicit sleep to avoid excess spews
+ // from WindowManagerState.
+ if (SLOW_CREATE_ACTIVITY_NAME.equals(activityName)) {
+ Thread.sleep(2000);
+ }
+
+ CLog.logAndDisplay(INFO, "==========Before Docking========");
+ final String oldToken = getFocusedWindowToken(windowName, true);
+
+ // Move to docked stack
+ final int taskId = getActivityTaskId(activityName);
+ final String cmd = AM_MOVE_TASK + taskId + " " + DOCKED_STACK_ID + " true";
+ mDevice.executeShellCommand(cmd);
+
+ // Sleep 5 seconds, then check if the window is replaced properly.
+ Thread.sleep(5000);
+
+ CLog.logAndDisplay(INFO, "==========After Docking========");
+ final String newToken = getFocusedWindowToken(windowName, false);
+
+ if (relaunch) {
+ Assert.assertFalse("Window not replaced after relaunch.", oldToken.equals(newToken));
+ } else {
+ Assert.assertEquals("Window replaced without relaunch.", oldToken, newToken);
+ }
+ }
+
+ private String getFocusedWindowToken(String windowName, boolean visibleOnly)
+ throws Exception {
+ mAmWmState.computeState(mDevice, visibleOnly);
+
+ mAmWmState.assertSanity();
+
+ mAmWmState.assertFocusedWindow("Test window must be the front window.",
+ windowName);
+
+ mAmWmState.getWmState().getMatchingWindowTokens(windowName, mTempWindowTokens);
+
+ Assert.assertEquals("Should have exactly one window for the activity.",
+ 1, mTempWindowTokens.size());
+
+ return mTempWindowTokens.get(0);
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
new file mode 100644
index 0000000..003d8e6
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
@@ -0,0 +1,519 @@
+/*
+ * 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.server.cts;
+
+import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import java.awt.Rectangle;
+import java.lang.Integer;
+import java.lang.String;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+import static com.android.ddmlib.Log.LogLevel.INFO;
+
+class ActivityManagerState {
+ private static final String DUMPSYS_ACTIVITY_ACTIVITIES = "dumpsys activity activities";
+
+ private final Pattern mStackIdPattern = Pattern.compile("Stack #(\\d+)\\:");
+ private final Pattern mFocusedActivityPattern =
+ Pattern.compile("mFocusedActivity\\: ActivityRecord\\{(.+) u(\\d+) (\\S+) (\\S+)\\}");
+ private final Pattern mFocusedStackPattern =
+ Pattern.compile("mFocusedStack=ActivityStack\\{(.+) stackId=(\\d+), (.+)");
+
+ private final Pattern[] mExtractStackExitPatterns =
+ { mStackIdPattern, mFocusedActivityPattern, mFocusedStackPattern};
+
+ // Stacks in z-order with the top most at the front of the list.
+ private final List<ActivityStack> mStacks = new ArrayList();
+ private int mFocusedStackId = -1;
+ private String mFocusedActivityRecord = null;
+ private final List<String> mResumedActivities = new ArrayList();
+ private final LinkedList<String> mSysDump = new LinkedList();
+
+ void computeState(ITestDevice device) throws DeviceNotAvailableException {
+ // It is possible the system is in the middle of transition to the right state when we get
+ // the dump. We try a few times to get the information we need before giving up.
+ int retriesLeft = 3;
+ boolean retry = false;
+ String dump = null;
+
+ do {
+ if (retry) {
+ CLog.logAndDisplay(INFO, "***Incomplete AM state. Retrying...");
+ // Wait half a second between retries for activity manager to finish transitioning.
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ CLog.logAndDisplay(INFO, e.toString());
+ // Well I guess we are not waiting...
+ }
+ }
+
+ final CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ device.executeShellCommand(DUMPSYS_ACTIVITY_ACTIVITIES, outputReceiver);
+ dump = outputReceiver.getOutput();
+ parseSysDump(dump);
+
+ retry = mStacks.isEmpty() || mFocusedStackId == -1 || mFocusedActivityRecord == null
+ || mResumedActivities.isEmpty();
+ } while (retry && retriesLeft-- > 0);
+
+ if (retry) {
+ CLog.logAndDisplay(INFO, dump);
+ }
+
+ if (mStacks.isEmpty()) {
+ CLog.logAndDisplay(INFO, "No stacks found...");
+ }
+ if (mFocusedStackId == -1) {
+ CLog.logAndDisplay(INFO, "No focused stack found...");
+ }
+ if (mFocusedActivityRecord == null) {
+ CLog.logAndDisplay(INFO, "No focused activity found...");
+ }
+ if (mResumedActivities.isEmpty()) {
+ CLog.logAndDisplay(INFO, "No resumed activities found...");
+ }
+ }
+
+ private void parseSysDump(String sysDump) {
+ reset();
+
+ Collections.addAll(mSysDump, sysDump.split("\\n"));
+
+ while (!mSysDump.isEmpty()) {
+ final ActivityStack stack =
+ ActivityStack.create(mSysDump, mStackIdPattern, mExtractStackExitPatterns);
+
+ if (stack != null) {
+ mStacks.add(stack);
+ if (stack.mResumedActivity != null) {
+ mResumedActivities.add(stack.mResumedActivity);
+ }
+ continue;
+ }
+
+ final String line = mSysDump.pop().trim();
+
+ Matcher matcher = mFocusedStackPattern.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ final String stackId = matcher.group(2);
+ CLog.logAndDisplay(INFO, stackId);
+ mFocusedStackId = Integer.parseInt(stackId);
+ continue;
+ }
+
+ matcher = mFocusedActivityPattern.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ mFocusedActivityRecord = matcher.group(3);
+ CLog.logAndDisplay(INFO, mFocusedActivityRecord);
+ continue;
+ }
+ }
+ }
+
+ private void reset() {
+ mStacks.clear();
+ mFocusedStackId = -1;
+ mFocusedActivityRecord = null;
+ mResumedActivities.clear();
+ mSysDump.clear();
+ }
+
+ int getFrontStackId() {
+ return mStacks.get(0).mStackId;
+ }
+
+ int getFocusedStackId() {
+ return mFocusedStackId;
+ }
+
+ String getFocusedActivity() {
+ return mFocusedActivityRecord;
+ }
+
+ String getResumedActivity() {
+ return mResumedActivities.get(0);
+ }
+
+ int getResumedActivitiesCount() {
+ return mResumedActivities.size();
+ }
+
+ boolean containsStack(int stackId) {
+ for (ActivityStack stack : mStacks) {
+ if (stackId == stack.mStackId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ List<ActivityStack> getStacks() {
+ return new ArrayList(mStacks);
+ }
+
+ int getStackCount() {
+ return mStacks.size();
+ }
+
+ boolean isActivityVisible(String activityName) {
+ for (ActivityStack stack : mStacks) {
+ for (ActivityTask task : stack.mTasks) {
+ for (Activity activity : task.mActivities) {
+ if (activity.name.equals(activityName)) {
+ return activity.visible;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ static class ActivityStack extends ActivityContainer {
+
+ private static final Pattern TASK_ID_PATTERN = Pattern.compile("Task id #(\\d+)");
+ private static final Pattern RESUMED_ACTIVITY_PATTERN = Pattern.compile(
+ "mResumedActivity\\: ActivityRecord\\{(.+) u(\\d+) (\\S+) (\\S+)\\}");
+
+ int mStackId;
+ String mResumedActivity;
+ ArrayList<ActivityTask> mTasks = new ArrayList();
+
+ private ActivityStack() {
+ }
+
+ static ActivityStack create(
+ LinkedList<String> dump, Pattern stackIdPattern, Pattern[] exitPatterns) {
+ final String line = dump.peek().trim();
+
+ final Matcher matcher = stackIdPattern.matcher(line);
+ if (!matcher.matches()) {
+ // Not a stack.
+ return null;
+ }
+ // For the stack Id line we just read.
+ dump.pop();
+
+ final ActivityStack stack = new ActivityStack();
+ CLog.logAndDisplay(INFO, line);
+ final String stackId = matcher.group(1);
+ CLog.logAndDisplay(INFO, stackId);
+ stack.mStackId = Integer.parseInt(stackId);
+ stack.extract(dump, exitPatterns);
+ return stack;
+ }
+
+ private void extract(LinkedList<String> dump, Pattern[] exitPatterns) {
+
+ final List<Pattern> taskExitPatterns = new ArrayList();
+ Collections.addAll(taskExitPatterns, exitPatterns);
+ taskExitPatterns.add(TASK_ID_PATTERN);
+ taskExitPatterns.add(RESUMED_ACTIVITY_PATTERN);
+ final Pattern[] taskExitPatternsArray =
+ taskExitPatterns.toArray(new Pattern[taskExitPatterns.size()]);
+
+ while (!doneExtracting(dump, exitPatterns)) {
+ final ActivityTask task =
+ ActivityTask.create(dump, TASK_ID_PATTERN, taskExitPatternsArray);
+
+ if (task != null) {
+ mTasks.add(task);
+ continue;
+ }
+
+ final String line = dump.pop().trim();
+
+ if (extractFullscreen(line)) {
+ continue;
+ }
+
+ if (extractBounds(line)) {
+ continue;
+ }
+
+ Matcher matcher = RESUMED_ACTIVITY_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ mResumedActivity = matcher.group(3);
+ CLog.logAndDisplay(INFO, mResumedActivity);
+ continue;
+ }
+ }
+ }
+
+ List<ActivityTask> getTasks() {
+ return new ArrayList(mTasks);
+ }
+ }
+
+ static class ActivityTask extends ActivityContainer {
+ private static final Pattern TASK_RECORD_PATTERN = Pattern.compile(
+ "\\* TaskRecord\\{(\\S+) #(\\d+) A=(\\S+) U=(\\d+) StackId=(\\d+) sz=(\\d+)\\}");
+
+ private static final Pattern LAST_NON_FULLSCREEN_BOUNDS_PATTERN = Pattern.compile(
+ "mLastNonFullscreenBounds=Rect\\((\\d+), (\\d+) - (\\d+), (\\d+)\\)");
+
+ private static final Pattern ORIG_ACTIVITY_PATTERN = Pattern.compile("origActivity=(\\S+)");
+ private static final Pattern REAL_ACTIVITY_PATTERN = Pattern.compile("realActivity=(\\S+)");
+
+ private static final Pattern ACTIVITY_NAME_PATTERN = Pattern.compile(
+ "\\* Hist #(\\d+)\\: ActivityRecord\\{(\\S+) u(\\d+) (\\S+) t(\\d+)\\}");
+
+ private static final Pattern TASK_TYPE_PATTERN = Pattern.compile("autoRemoveRecents=(\\S+) "
+ + "isPersistable=(\\S+) numFullscreen=(\\d+) taskType=(\\d+) "
+ + "mTaskToReturnTo=(\\d+)");
+
+ int mTaskId;
+ int mStackId;
+ Rectangle mLastNonFullscreenBounds;
+ String mRealActivity;
+ String mOrigActivity;
+ ArrayList<Activity> mActivities = new ArrayList();
+ int mTaskType = -1;
+ int mReturnToType = -1;
+
+ private ActivityTask() {
+ }
+
+ static ActivityTask create(
+ LinkedList<String> dump, Pattern taskIdPattern, Pattern[] exitPatterns) {
+ final String line = dump.peek().trim();
+
+ final Matcher matcher = taskIdPattern.matcher(line);
+ if (!matcher.matches()) {
+ // Not a task.
+ return null;
+ }
+ // For the task Id line we just read.
+ dump.pop();
+
+ final ActivityTask task = new ActivityTask();
+ CLog.logAndDisplay(INFO, line);
+ final String taskId = matcher.group(1);
+ CLog.logAndDisplay(INFO, taskId);
+ task.mTaskId = Integer.parseInt(taskId);
+ task.extract(dump, exitPatterns);
+ return task;
+ }
+
+ private void extract(LinkedList<String> dump, Pattern[] exitPatterns) {
+ final List<Pattern> activityExitPatterns = new ArrayList();
+ Collections.addAll(activityExitPatterns, exitPatterns);
+ activityExitPatterns.add(ACTIVITY_NAME_PATTERN);
+ final Pattern[] activityExitPatternsArray =
+ activityExitPatterns.toArray(new Pattern[activityExitPatterns.size()]);
+
+ while (!doneExtracting(dump, exitPatterns)) {
+ final Activity activity =
+ Activity.create(dump, ACTIVITY_NAME_PATTERN, activityExitPatternsArray);
+
+ if (activity != null) {
+ mActivities.add(activity);
+ continue;
+ }
+
+ final String line = dump.pop().trim();
+
+ if (extractFullscreen(line)) {
+ continue;
+ }
+
+ if (extractBounds(line)) {
+ continue;
+ }
+
+ Matcher matcher = TASK_RECORD_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ final String stackId = matcher.group(5);
+ mStackId = Integer.valueOf(stackId);
+ CLog.logAndDisplay(INFO, stackId);
+ continue;
+ }
+
+ matcher = LAST_NON_FULLSCREEN_BOUNDS_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ mLastNonFullscreenBounds = extractBounds(matcher);
+ }
+
+ matcher = REAL_ACTIVITY_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ if (mRealActivity == null) {
+ CLog.logAndDisplay(INFO, line);
+ mRealActivity = matcher.group(1);
+ CLog.logAndDisplay(INFO, mRealActivity);
+ }
+ continue;
+ }
+
+ matcher = ORIG_ACTIVITY_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ if (mOrigActivity == null) {
+ CLog.logAndDisplay(INFO, line);
+ mOrigActivity = matcher.group(1);
+ CLog.logAndDisplay(INFO, mOrigActivity);
+ }
+ continue;
+ }
+
+ matcher = TASK_TYPE_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ mTaskType = Integer.valueOf(matcher.group(4));
+ mReturnToType = Integer.valueOf(matcher.group(5));
+ continue;
+ }
+ }
+ }
+ }
+
+ static class Activity {
+ private static final Pattern VISIBILITY_PATTERN = Pattern.compile(
+ "keysPaused=(\\S+) inHistory=(\\S+) visible=(\\S+) sleeping=(\\S+) idle=(\\S+)");
+ private static final Pattern FRONT_OF_TASK_PATTERN = Pattern.compile("frontOfTask=(\\S+) "
+ + "task=TaskRecord\\{(\\S+) #(\\d+) A=(\\S+) U=(\\d+) StackId=(\\d+) sz=(\\d+)\\}");
+
+ String name;
+ boolean visible;
+ boolean frontOfTask;
+
+ private Activity() {
+ }
+
+ static Activity create(
+ LinkedList<String> dump, Pattern activityNamePattern, Pattern[] exitPatterns) {
+ final String line = dump.peek().trim();
+
+ final Matcher matcher = activityNamePattern.matcher(line);
+ if (!matcher.matches()) {
+ // Not an activity.
+ return null;
+ }
+ // For the activity name line we just read.
+ dump.pop();
+
+ final Activity activity = new Activity();
+ CLog.logAndDisplay(INFO, line);
+ activity.name = matcher.group(4);
+ CLog.logAndDisplay(INFO, activity.name);
+ activity.extract(dump, exitPatterns);
+ return activity;
+ }
+
+ private void extract(LinkedList<String> dump, Pattern[] exitPatterns) {
+
+ while (!doneExtracting(dump, exitPatterns)) {
+ final String line = dump.pop().trim();
+
+ Matcher matcher = VISIBILITY_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ final String visibleString = matcher.group(3);
+ visible = Boolean.valueOf(visibleString);
+ CLog.logAndDisplay(INFO, visibleString);
+ continue;
+ }
+
+ matcher = FRONT_OF_TASK_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ final String frontOfTaskString = matcher.group(1);
+ frontOfTask = Boolean.valueOf(frontOfTaskString);
+ CLog.logAndDisplay(INFO, frontOfTaskString);
+ continue;
+ }
+ }
+ }
+ }
+
+ static abstract class ActivityContainer {
+ protected static final Pattern FULLSCREEN_PATTERN = Pattern.compile("mFullscreen=(\\S+)");
+ protected static final Pattern BOUNDS_PATTERN =
+ Pattern.compile("mBounds=Rect\\((\\d+), (\\d+) - (\\d+), (\\d+)\\)");
+
+ protected boolean mFullscreen;
+ protected Rectangle mBounds;
+
+ boolean extractFullscreen(String line) {
+ final Matcher matcher = FULLSCREEN_PATTERN.matcher(line);
+ if (!matcher.matches()) {
+ return false;
+ }
+ CLog.logAndDisplay(INFO, line);
+ final String fullscreen = matcher.group(1);
+ CLog.logAndDisplay(INFO, fullscreen);
+ mFullscreen = Boolean.valueOf(fullscreen);
+ return true;
+ }
+
+ boolean extractBounds(String line) {
+ final Matcher matcher = BOUNDS_PATTERN.matcher(line);
+ if (!matcher.matches()) {
+ return false;
+ }
+ CLog.logAndDisplay(INFO, line);
+ mBounds = extractBounds(matcher);
+ return true;
+ }
+
+ static Rectangle extractBounds(Matcher matcher) {
+ final int left = Integer.valueOf(matcher.group(1));
+ final int top = Integer.valueOf(matcher.group(2));
+ final int right = Integer.valueOf(matcher.group(3));
+ final int bottom = Integer.valueOf(matcher.group(4));
+ final Rectangle rect = new Rectangle(left, top, right - left, bottom - top);
+
+ CLog.logAndDisplay(INFO, rect.toString());
+ return rect;
+ }
+
+ Rectangle getBounds() {
+ return mBounds;
+ }
+
+ boolean isFullscreen() {
+ return mFullscreen;
+ }
+ }
+
+ static boolean doneExtracting(LinkedList<String> dump, Pattern[] exitPatterns) {
+ if (dump.isEmpty()) {
+ return true;
+ }
+ final String line = dump.peek().trim();
+
+ for (Pattern pattern : exitPatterns) {
+ if (pattern.matcher(line).matches()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
new file mode 100644
index 0000000..0203294
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
@@ -0,0 +1,187 @@
+/*
+ * 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.server.cts;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.DeviceTestCase;
+
+import java.lang.Exception;
+import java.lang.Integer;
+import java.lang.String;
+import java.util.HashSet;
+
+public abstract class ActivityManagerTestBase extends DeviceTestCase {
+ private static final boolean PRETEND_DEVICE_SUPPORTS_PIP = false;
+
+ // Constants copied from ActivityManager.StackId. If they are changed there, these must be
+ // updated.
+ /** First static stack ID. */
+ public static final int FIRST_STATIC_STACK_ID = 0;
+
+ /** Home activity stack ID. */
+ public static final int HOME_STACK_ID = FIRST_STATIC_STACK_ID;
+
+ /** ID of stack where fullscreen activities are normally launched into. */
+ public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;
+
+ /** ID of stack where freeform/resized activities are normally launched into. */
+ public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;
+
+ /** ID of stack that occupies a dedicated region of the screen. */
+ public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;
+
+ /** ID of stack that always on top (always visible) when it exist. */
+ public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
+
+ private static final String TASK_ID_PREFIX = "taskId";
+
+ private static final String AM_STACK_LIST = "am stack list";
+
+ private static final String AM_FORCE_STOP_TEST_PACKAGE = "am force-stop android.server.app";
+
+ protected static final String AM_START_HOME_ACTIVITY_COMMAND =
+ "am start -a android.intent.action.MAIN -c android.intent.category.HOME";
+
+ protected static final String AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND =
+ "am stack move-top-activity-to-pinned-stack 1 0 0 500 500";
+
+ /** A reference to the device under test. */
+ protected ITestDevice mDevice;
+
+ private HashSet<String> mAvailableFeatures;
+
+ protected static String getAmStartCmd(final String activityName) {
+ return "am start -n " + getActivityComponentName(activityName);
+ }
+
+ protected static String getAmStartCmdOverHome(final String activityName) {
+ return "am start --activity-task-on-home -n " + getActivityComponentName(activityName);
+ }
+
+ static String getActivityComponentName(final String activityName) {
+ return "android.server.app/." + activityName;
+ }
+
+ static String getWindowName(final String activityName) {
+ return "android.server.app/android.server.app." + activityName;
+ }
+
+ protected ActivityAndWindowManagersState mAmWmState = new ActivityAndWindowManagersState();
+
+ private int mInitialAccelerometerRotation;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Get the device, this gives a handle to run commands and install APKs.
+ mDevice = getDevice();
+ mInitialAccelerometerRotation = getAccelerometerRotation();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ try {
+ mDevice.executeShellCommand(AM_FORCE_STOP_TEST_PACKAGE);
+ setAccelerometerRotation(mInitialAccelerometerRotation);
+ } catch (DeviceNotAvailableException e) {
+ }
+ }
+
+ // Utility method for debugging, not used directly here, but useful, so kept around.
+ protected void printStacksAndTasks() throws DeviceNotAvailableException {
+ CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ mDevice.executeShellCommand(AM_STACK_LIST, outputReceiver);
+ String output = outputReceiver.getOutput();
+ for (String line : output.split("\\n")) {
+ CLog.logAndDisplay(LogLevel.INFO, line);
+ }
+ }
+
+ protected int getActivityTaskId(String name) throws DeviceNotAvailableException {
+ CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ mDevice.executeShellCommand(AM_STACK_LIST, outputReceiver);
+ final String output = outputReceiver.getOutput();
+ for (String line : output.split("\\n")) {
+ if (line.contains(name)) {
+ for (String word : line.split("\\s+")) {
+ if (word.startsWith(TASK_ID_PREFIX)) {
+ final String withColon = word.split("=")[1];
+ return Integer.parseInt(withColon.substring(0, withColon.length() - 1));
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ protected boolean supportsPip() throws DeviceNotAvailableException {
+ return hasDeviceFeature("android.software.picture_in_picture")
+ || PRETEND_DEVICE_SUPPORTS_PIP;
+ }
+
+ protected boolean hasDeviceFeature(String requiredFeature) throws DeviceNotAvailableException {
+ if (mAvailableFeatures == null) {
+ // TODO: Move this logic to ITestDevice.
+ final String output = runCommandAndPrintOutput("pm list features");
+
+ // Extract the id of the new user.
+ mAvailableFeatures = new HashSet<>();
+ for (String feature: output.split("\\s+")) {
+ // Each line in the output of the command has the format "feature:{FEATURE_VALUE}".
+ String[] tokens = feature.split(":");
+ assertTrue("\"" + feature + "\" expected to have format feature:{FEATURE_VALUE}",
+ tokens.length > 1);
+ assertEquals(feature, "feature", tokens[0]);
+ mAvailableFeatures.add(tokens[1]);
+ }
+ }
+ boolean result = mAvailableFeatures.contains(requiredFeature);
+ if (!result) {
+ CLog.logAndDisplay(LogLevel.INFO, "Device doesn't support " + requiredFeature);
+ }
+ return result;
+ }
+
+ protected void setDeviceRotation(int rotation) throws DeviceNotAvailableException {
+ setAccelerometerRotation(0);
+ runCommandAndPrintOutput("settings put system user_rotation " + rotation);
+ }
+
+ private int getAccelerometerRotation() throws DeviceNotAvailableException {
+ final String rotation =
+ runCommandAndPrintOutput("settings get system accelerometer_rotation");
+ return Integer.valueOf(rotation.trim());
+ }
+
+ private void setAccelerometerRotation(int rotation) throws DeviceNotAvailableException {
+ runCommandAndPrintOutput(
+ "settings put system accelerometer_rotation " + rotation);
+ }
+
+ private String runCommandAndPrintOutput(String command) throws DeviceNotAvailableException {
+ final String output = mDevice.executeShellCommand(command);
+ CLog.logAndDisplay(LogLevel.INFO, command);
+ CLog.logAndDisplay(LogLevel.INFO, output);
+ return output;
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerVisibleBehindActivityTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerVisibleBehindActivityTests.java
new file mode 100644
index 0000000..d45b32d
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerVisibleBehindActivityTests.java
@@ -0,0 +1,78 @@
+/*
+ * 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.server.cts;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.lang.Exception;
+import java.lang.String;
+
+public class ActivityManagerVisibleBehindActivityTests extends ActivityManagerTestBase {
+ private static final String TRANSLUCENT_ACTIVITY = "AlwaysFocusablePipActivity";
+ private static final String VISIBLE_BEHIND_ACTIVITY = "VisibleBehindActivity";
+ private static final String PIP_ON_PIP_ACTIVITY = "LaunchPipOnPipActivity";
+
+ public void testVisibleBehindHomeActivity() throws Exception {
+ mDevice.executeShellCommand(getAmStartCmd(VISIBLE_BEHIND_ACTIVITY));
+ mDevice.executeShellCommand(AM_START_HOME_ACTIVITY_COMMAND);
+
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertSanity();
+ mAmWmState.assertContainsStack(
+ "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
+ mAmWmState.assertFrontStack("Home stack must be the front stack.", HOME_STACK_ID);
+ mAmWmState.assertVisibility(
+ VISIBLE_BEHIND_ACTIVITY, hasDeviceFeature("android.software.leanback"));
+ }
+
+ public void testVisibleBehindOtherActivity_NotOverHome() throws Exception {
+ mDevice.executeShellCommand(getAmStartCmd(VISIBLE_BEHIND_ACTIVITY));
+ mDevice.executeShellCommand(getAmStartCmd(TRANSLUCENT_ACTIVITY));
+
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertSanity();
+ mAmWmState.assertVisibility(VISIBLE_BEHIND_ACTIVITY, true);
+ mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
+ }
+
+ public void testVisibleBehindOtherActivity_OverHome() throws Exception {
+ mDevice.executeShellCommand(getAmStartCmdOverHome(VISIBLE_BEHIND_ACTIVITY));
+ mDevice.executeShellCommand(getAmStartCmdOverHome(TRANSLUCENT_ACTIVITY));
+
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertSanity();
+ mAmWmState.assertVisibility(VISIBLE_BEHIND_ACTIVITY, true);
+ mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
+ }
+
+ public void testTranslucentActivityOnTopOfPinnedStack() throws Exception {
+ if (!supportsPip()) {
+ return;
+ }
+
+ mDevice.executeShellCommand(getAmStartCmdOverHome(PIP_ON_PIP_ACTIVITY));
+ // NOTE: moving to pinned stack will trigger the pip-on-pip activity to launch the
+ // translucent activity.
+ mDevice.executeShellCommand(AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND);
+
+ mAmWmState.computeState(mDevice);
+ mAmWmState.assertSanity();
+ mAmWmState.assertFrontStack("Pinned stack must be the front stack.", PINNED_STACK_ID);
+ mAmWmState.assertVisibility(PIP_ON_PIP_ACTIVITY, true);
+ mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java b/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
new file mode 100644
index 0000000..a30a2a7
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
@@ -0,0 +1,457 @@
+/*
+ * 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.server.cts;
+
+import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import java.awt.Rectangle;
+import java.lang.String;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+import static com.android.ddmlib.Log.LogLevel.INFO;
+
+class WindowManagerState {
+ private static final String DUMPSYS_WINDOWS_APPS = "dumpsys window apps";
+ private static final String DUMPSYS_WINDOWS_VISIBLE_APPS = "dumpsys window visible-apps";
+
+ private final Pattern mWindowPattern =
+ Pattern.compile("Window #(\\d+) Window\\{([0-9a-fA-F]+) u(\\d+) (.+)\\}\\:");
+ private final Pattern mStartingWindowPattern =
+ Pattern.compile("Window #(\\d+) Window\\{([0-9a-fA-F]+) u(\\d+) Starting (.+)\\}\\:");
+ private final Pattern mExitingWindowPattern =
+ Pattern.compile("Window #(\\d+) Window\\{([0-9a-fA-F]+) u(\\d+) (.+) EXITING\\}\\:");
+
+ private final Pattern mFocusedWindowPattern = Pattern.compile(
+ "mCurrentFocus=Window\\{([0-9a-fA-F]+) u(\\d+) (\\S+)\\}");
+ private final Pattern mAppErrorFocusedWindowPattern = Pattern.compile(
+ "mCurrentFocus=Window\\{([0-9a-fA-F]+) u(\\d+) Application Error\\: (\\S+)\\}");
+
+ private final Pattern mFocusedAppPattern =
+ Pattern.compile("mFocusedApp=AppWindowToken\\{(.+) token=Token\\{(.+) "
+ + "ActivityRecord\\{(.+) u(\\d+) (\\S+) (\\S+)");
+
+ private final Pattern mStackIdPattern = Pattern.compile("mStackId=(\\d+)");
+
+ private final Pattern[] mExtractStackExitPatterns = { mStackIdPattern, mWindowPattern,
+ mStartingWindowPattern, mExitingWindowPattern, mFocusedWindowPattern,
+ mAppErrorFocusedWindowPattern, mFocusedAppPattern };
+
+ // Windows in z-order with the top most at the front of the list.
+ private List<String> mWindows = new ArrayList();
+ private List<String> mRawWindows = new ArrayList();
+ private List<WindowStack> mStacks = new ArrayList();
+ private String mFocusedWindow = null;
+ private String mFocusedApp = null;
+ private final LinkedList<String> mSysDump = new LinkedList();
+
+ void computeState(ITestDevice device, boolean visibleOnly) throws DeviceNotAvailableException {
+ // It is possible the system is in the middle of transition to the right state when we get
+ // the dump. We try a few times to get the information we need before giving up.
+ int retriesLeft = 3;
+ boolean retry = false;
+ String dump = null;
+
+ do {
+ if (retry) {
+ CLog.logAndDisplay(INFO, "***Incomplete WM state. Retrying...");
+ // Wait half a second between retries for window manager to finish transitioning...
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ CLog.logAndDisplay(INFO, e.toString());
+ // Well I guess we are not waiting...
+ }
+ }
+
+ final CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ final String dumpsysCmd = visibleOnly ?
+ DUMPSYS_WINDOWS_VISIBLE_APPS : DUMPSYS_WINDOWS_APPS;
+ device.executeShellCommand(dumpsysCmd, outputReceiver);
+ dump = outputReceiver.getOutput();
+ parseSysDump(dump, visibleOnly);
+
+ retry = mWindows.isEmpty() || mFocusedWindow == null || mFocusedApp == null;
+ } while (retry && retriesLeft-- > 0);
+
+ if (retry) {
+ CLog.logAndDisplay(INFO, dump);
+ }
+
+ if (mWindows.isEmpty()) {
+ CLog.logAndDisplay(INFO, "No Windows found...");
+ }
+ if (mFocusedWindow == null) {
+ CLog.logAndDisplay(INFO, "No Focused Window...");
+ }
+ if (mFocusedApp == null) {
+ CLog.logAndDisplay(INFO, "No Focused App...");
+ }
+ }
+
+ private void parseSysDump(String sysDump,boolean visibleOnly) {
+ reset();
+
+ Collections.addAll(mSysDump, sysDump.split("\\n"));
+
+ while (!mSysDump.isEmpty()) {
+ final WindowStack stack =
+ WindowStack.create(mSysDump, mStackIdPattern, mExtractStackExitPatterns);
+
+ if (stack != null) {
+ mStacks.add(stack);
+ continue;
+ }
+
+ final String line = mSysDump.pop().trim();
+
+ Matcher matcher = mWindowPattern.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ final String window = matcher.group(4);
+
+ if (visibleOnly && mWindows.isEmpty()) {
+ // This is the front window. Check to see if we are in the middle of
+ // transitioning. If we are, we want to skip dumping until window manager is
+ // done transitioning the top window.
+ matcher = mStartingWindowPattern.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO,
+ "Skipping dump due to starting window transition...");
+ return;
+ }
+
+ matcher = mExitingWindowPattern.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO,
+ "Skipping dump due to exiting window transition...");
+ return;
+ }
+ }
+
+ CLog.logAndDisplay(INFO, window);
+ mWindows.add(window);
+ mRawWindows.add(line);
+ continue;
+ }
+
+ matcher = mFocusedWindowPattern.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ final String focusedWindow = matcher.group(3);
+ CLog.logAndDisplay(INFO, focusedWindow);
+ mFocusedWindow = focusedWindow;
+ continue;
+ }
+
+ matcher = mAppErrorFocusedWindowPattern.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ final String focusedWindow = matcher.group(3);
+ CLog.logAndDisplay(INFO, focusedWindow);
+ mFocusedWindow = focusedWindow;
+ continue;
+ }
+
+ matcher = mFocusedAppPattern.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ final String focusedApp = matcher.group(5);
+ CLog.logAndDisplay(INFO, focusedApp);
+ mFocusedApp = focusedApp;
+ continue;
+ }
+ }
+ }
+
+ void getMatchingWindowTokens(final String windowName, List<String> tokenList) {
+ tokenList.clear();
+
+ for (String line : mRawWindows) {
+ if (line.contains(windowName)) {
+ Matcher matcher = mWindowPattern.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, "Found activity window: " + line);
+ tokenList.add(matcher.group(2));
+ }
+ }
+ }
+ }
+
+ String getFrontWindow() {
+ return mWindows.get(0);
+ }
+
+ String getFocusedWindow() {
+ return mFocusedWindow;
+ }
+
+ String getFocusedApp() {
+ return mFocusedApp;
+ }
+
+ int getFrontStackId() {
+ return mStacks.get(0).mStackId;
+ }
+
+ boolean containsStack(int stackId) {
+ for (WindowStack stack : mStacks) {
+ if (stackId == stack.mStackId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean isWindowVisible(String windowName) {
+ for (String window : mWindows) {
+ if (window.equals(windowName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ WindowStack getStack(int stackId) {
+ for (WindowStack stack : mStacks) {
+ if (stackId == stack.mStackId) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ private void reset() {
+ mSysDump.clear();
+ mStacks.clear();
+ mWindows.clear();
+ mRawWindows.clear();
+ mFocusedWindow = null;
+ mFocusedApp = null;
+ }
+
+ static class WindowStack extends WindowContainer {
+
+ private static final Pattern TASK_ID_PATTERN = Pattern.compile("taskId=(\\d+)");
+
+ int mStackId;
+ ArrayList<WindowTask> mTasks = new ArrayList();
+
+ private WindowStack() {
+
+ }
+
+ static WindowStack create(
+ LinkedList<String> dump, Pattern stackIdPattern, Pattern[] exitPatterns) {
+ final String line = dump.peek().trim();
+
+ final Matcher matcher = stackIdPattern.matcher(line);
+ if (!matcher.matches()) {
+ // Not a stack.
+ return null;
+ }
+ // For the stack Id line we just read.
+ dump.pop();
+
+ final WindowStack stack = new WindowStack();
+ CLog.logAndDisplay(INFO, line);
+ final String stackId = matcher.group(1);
+ CLog.logAndDisplay(INFO, stackId);
+ stack.mStackId = Integer.parseInt(stackId);
+ stack.extract(dump, exitPatterns);
+ return stack;
+ }
+
+ void extract(LinkedList<String> dump, Pattern[] exitPatterns) {
+
+ final List<Pattern> taskExitPatterns = new ArrayList();
+ Collections.addAll(taskExitPatterns, exitPatterns);
+ taskExitPatterns.add(TASK_ID_PATTERN);
+ final Pattern[] taskExitPatternsArray =
+ taskExitPatterns.toArray(new Pattern[taskExitPatterns.size()]);
+
+ while (!doneExtracting(dump, exitPatterns)) {
+ final WindowTask task =
+ WindowTask.create(dump, TASK_ID_PATTERN, taskExitPatternsArray);
+
+ if (task != null) {
+ mTasks.add(task);
+ continue;
+ }
+
+ final String line = dump.pop().trim();
+
+ if (extractFullscreen(line)) {
+ continue;
+ }
+
+ if (extractBounds(line)) {
+ continue;
+ }
+ }
+ }
+
+ WindowTask getTask(int taskId) {
+ for (WindowTask task : mTasks) {
+ if (taskId == task.mTaskId) {
+ return task;
+ }
+ }
+ return null;
+ }
+ }
+
+ static class WindowTask extends WindowContainer {
+ private static final Pattern TEMP_INSET_BOUNDS_PATTERN =
+ Pattern.compile("mTempInsetBounds=\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]");
+
+ private static final Pattern APP_TOKEN_PATTERN = Pattern.compile(
+ "Activity #(\\d+) AppWindowToken\\{(\\S+) token=Token\\{(\\S+) "
+ + "ActivityRecord\\{(\\S+) u(\\d+) (\\S+) t(\\d+)\\}\\}\\}");
+
+
+ int mTaskId;
+ Rectangle mTempInsetBounds;
+ List<String> mAppTokens = new ArrayList();
+
+ private WindowTask() {
+ }
+
+ static WindowTask create(
+ LinkedList<String> dump, Pattern taskIdPattern, Pattern[] exitPatterns) {
+ final String line = dump.peek().trim();
+
+ final Matcher matcher = taskIdPattern.matcher(line);
+ if (!matcher.matches()) {
+ // Not a task.
+ return null;
+ }
+ // For the task Id line we just read.
+ dump.pop();
+
+ final WindowTask task = new WindowTask();
+ CLog.logAndDisplay(INFO, line);
+ final String taskId = matcher.group(1);
+ CLog.logAndDisplay(INFO, taskId);
+ task.mTaskId = Integer.parseInt(taskId);
+ task.extract(dump, exitPatterns);
+ return task;
+ }
+
+ private void extract(LinkedList<String> dump, Pattern[] exitPatterns) {
+
+ while (!doneExtracting(dump, exitPatterns)) {
+ final String line = dump.pop().trim();
+
+ if (extractFullscreen(line)) {
+ continue;
+ }
+
+ if (extractBounds(line)) {
+ continue;
+ }
+
+ Matcher matcher = TEMP_INSET_BOUNDS_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ mTempInsetBounds = extractBounds(matcher);
+ }
+
+ matcher = APP_TOKEN_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ CLog.logAndDisplay(INFO, line);
+ final String appToken = matcher.group(6);
+ CLog.logAndDisplay(INFO, appToken);
+ mAppTokens.add(appToken);
+ continue;
+ }
+ }
+ }
+ }
+
+ static abstract class WindowContainer {
+ protected static final Pattern FULLSCREEN_PATTERN = Pattern.compile("mFullscreen=(\\S+)");
+ protected static final Pattern BOUNDS_PATTERN =
+ Pattern.compile("mBounds=\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]");
+
+ protected boolean mFullscreen;
+ protected Rectangle mBounds;
+
+ static boolean doneExtracting(LinkedList<String> dump, Pattern[] exitPatterns) {
+ if (dump.isEmpty()) {
+ return true;
+ }
+ final String line = dump.peek().trim();
+
+ for (Pattern pattern : exitPatterns) {
+ if (pattern.matcher(line).matches()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean extractFullscreen(String line) {
+ final Matcher matcher = FULLSCREEN_PATTERN.matcher(line);
+ if (!matcher.matches()) {
+ return false;
+ }
+ CLog.logAndDisplay(INFO, line);
+ final String fullscreen = matcher.group(1);
+ CLog.logAndDisplay(INFO, fullscreen);
+ mFullscreen = Boolean.valueOf(fullscreen);
+ return true;
+ }
+
+ boolean extractBounds(String line) {
+ final Matcher matcher = BOUNDS_PATTERN.matcher(line);
+ if (!matcher.matches()) {
+ return false;
+ }
+ CLog.logAndDisplay(INFO, line);
+ mBounds = extractBounds(matcher);
+ return true;
+ }
+
+ static Rectangle extractBounds(Matcher matcher) {
+ final int left = Integer.valueOf(matcher.group(1));
+ final int top = Integer.valueOf(matcher.group(2));
+ final int right = Integer.valueOf(matcher.group(3));
+ final int bottom = Integer.valueOf(matcher.group(4));
+ final Rectangle rect = new Rectangle(left, top, right - left, bottom - top);
+
+ CLog.logAndDisplay(INFO, rect.toString());
+ return rect;
+ }
+
+ Rectangle getBounds() {
+ return mBounds;
+ }
+
+ boolean isFullscreen() {
+ return mFullscreen;
+ }
+ }
+}
diff --git a/hostsidetests/theme/Android.mk b/hostsidetests/theme/Android.mk
index 188bf7a..3d27270 100644
--- a/hostsidetests/theme/Android.mk
+++ b/hostsidetests/theme/Android.mk
@@ -27,10 +27,15 @@
LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
+
LOCAL_CTS_TEST_PACKAGE := android.host.theme
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/theme/AndroidTest.xml b/hostsidetests/theme/AndroidTest.xml
new file mode 100644
index 0000000..516df3d
--- /dev/null
+++ b/hostsidetests/theme/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Theme host test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsThemeDeviceApp.apk" />
+ </target_preparer>
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsThemeHostTestCases.jar" />
+ </test>
+</configuration>
diff --git a/hostsidetests/theme/app/Android.mk b/hostsidetests/theme/app/Android.mk
index 1be2983..7278a5b 100644
--- a/hostsidetests/theme/app/Android.mk
+++ b/hostsidetests/theme/app/Android.mk
@@ -36,6 +36,9 @@
LOCAL_PACKAGE_NAME := CtsThemeDeviceApp
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
-include $(BUILD_CTS_PACKAGE)
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
index b4bb748..30b0337 100644
--- a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
+++ b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
@@ -16,9 +16,8 @@
package android.theme.cts;
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
-import com.android.cts.util.TimeoutReq;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.cts.migration.MigrationHelper;
import com.android.ddmlib.Log;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.build.IBuildInfo;
@@ -73,7 +72,7 @@
private IAbi mAbi;
/** A reference to the build. */
- private CtsBuildHelper mBuild;
+ private IBuildInfo mBuildInfo;
/** A reference to the device under test. */
private ITestDevice mDevice;
@@ -89,8 +88,7 @@
@Override
public void setBuild(IBuildInfo buildInfo) {
- // Get the build, this is used to access the APK.
- mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ mBuildInfo = buildInfo;
}
@Override
@@ -101,14 +99,13 @@
mDevice.uninstallPackage(APP_PACKAGE_NAME);
// Get the APK from the build.
- final File app = mBuild.getTestApp(String.format("%s.apk", APK_NAME));
+ final File app = MigrationHelper.getTestFile(mBuildInfo, String.format("%s.apk", APK_NAME));
final String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
mDevice.installPackage(app, false, options);
final String density = getDensityBucketForDevice(mDevice);
final String zipFile = String.format("/%s.zip", density);
- Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Loading resources from " + zipFile);
final InputStream zipStream = ThemeHostTest.class.getResourceAsStream(zipFile);
if (zipStream != null) {
@@ -162,7 +159,6 @@
super.tearDown();
}
- @TimeoutReq(minutes = 60)
public void testThemes() throws Exception {
if (checkHardwareTypeSkipTest(mDevice.executeShellCommand(HARDWARE_TYPE_CMD).trim())) {
Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Skipped themes test for watch");
@@ -174,8 +170,6 @@
return;
}
- Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Generating device images...");
-
assertTrue("Aborted image generation", generateDeviceImages());
// Pull ZIP file from remote device.
@@ -184,8 +178,6 @@
int numTasks = 0;
- Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Extracting generated images...");
-
// Extract generated images to temporary files.
final byte[] data = new byte[4096];
final ZipInputStream zipInput = new ZipInputStream(new FileInputStream(localZip));
@@ -216,16 +208,12 @@
zipInput.close();
- Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Waiting for comparison tasks...");
-
int failures = 0;
for (int i = numTasks; i > 0; i--) {
failures += mCompletionService.take().get() ? 0 : 1;
}
assertTrue(failures + " failures in theme test", failures == 0);
-
- Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Finished!");
}
private boolean generateDeviceImages() throws Exception {
@@ -238,8 +226,6 @@
// Start activity
mDevice.executeShellCommand(START_CMD);
- Log.logAndDisplay(LogLevel.VERBOSE, LOG_TAG, "Starting image generation...");
-
boolean aborted = false;
boolean waiting = true;
do {
@@ -272,8 +258,6 @@
in.close();
} while (waiting && !aborted);
- Log.logAndDisplay(LogLevel.VERBOSE, LOG_TAG, "Image generation completed!");
-
return !aborted;
}
diff --git a/hostsidetests/ui/Android.mk b/hostsidetests/ui/Android.mk
new file mode 100644
index 0000000..b0de7fc
--- /dev/null
+++ b/hostsidetests/ui/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := CtsUiHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed_v2 compatibility-host-util tradefed-prebuilt
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+$(COMPATIBILITY_TESTCASES_OUT_cts_v2)/CtsUiHostTestCases.jar : $(COMPATIBILITY_TESTCASES_OUT_cts_v2)/com.replica.replicaisland.apk
+
+LOCAL_CTS_TEST_PACKAGE := android.ui.cts
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/ui/AndroidTest.xml b/hostsidetests/ui/AndroidTest.xml
new file mode 100644
index 0000000..7d17e2b
--- /dev/null
+++ b/hostsidetests/ui/AndroidTest.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<configuration description="Config for CTS UI host test cases">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsUiHostTestCases.jar" />
+ <option name="runtime-hint" value="2m" />
+ </test>
+</configuration>
diff --git a/hostsidetests/ui/appA/Android.mk b/hostsidetests/ui/appA/Android.mk
new file mode 100644
index 0000000..41bffeb
--- /dev/null
+++ b/hostsidetests/ui/appA/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsDeviceTaskSwitchingAppA
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/ui/appA/AndroidManifest.xml b/hostsidetests/ui/appA/AndroidManifest.xml
new file mode 100644
index 0000000..f336abd
--- /dev/null
+++ b/hostsidetests/ui/appA/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.taskswitching.appa">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+ <application>
+ <activity
+ android:name=".AppAActivity"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
+ android:screenOrientation="portrait" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/hostsidetests/ui/appA/src/android/taskswitching/appa/AppAActivity.java b/hostsidetests/ui/appA/src/android/taskswitching/appa/AppAActivity.java
new file mode 100644
index 0000000..32ccfc1
--- /dev/null
+++ b/hostsidetests/ui/appA/src/android/taskswitching/appa/AppAActivity.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 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.taskswitching.appa;
+
+import android.app.ListActivity;
+import android.content.Intent;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.WindowManager;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * Simple activity to notify completion via broadcast after onResume.
+ * This is for measuring taskswitching time between two apps.
+ */
+public class AppAActivity extends ListActivity {
+ static final String TAG = "AppAActivity";
+ private static final int NUMBER_ELEMENTS = 1000;
+ private static final String TASKSWITCHING_INTENT = "android.taskswitching.appa";
+ private Handler mHandler;
+
+ private String[] mItems = new String[NUMBER_ELEMENTS];
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ for (int i = 0; i < NUMBER_ELEMENTS; i++) {
+ mItems[i] = "A" + Integer.toString(i);
+ }
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, mItems));
+ ListView view = getListView();
+ mHandler = new Handler();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ Intent intent = new Intent(TASKSWITCHING_INTENT);
+ sendBroadcast(intent);
+ }
+ });
+ }
+}
diff --git a/hostsidetests/ui/appB/Android.mk b/hostsidetests/ui/appB/Android.mk
new file mode 100644
index 0000000..3b9cdae
--- /dev/null
+++ b/hostsidetests/ui/appB/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsDeviceTaskSwitchingAppB
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/ui/appB/AndroidManifest.xml b/hostsidetests/ui/appB/AndroidManifest.xml
new file mode 100644
index 0000000..aaf7a2c
--- /dev/null
+++ b/hostsidetests/ui/appB/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.taskswitching.appb">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+ <application>
+ <activity
+ android:name=".AppBActivity"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
+ android:screenOrientation="portrait" >
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/hostsidetests/ui/appB/src/android/taskswitching/appb/AppBActivity.java b/hostsidetests/ui/appB/src/android/taskswitching/appb/AppBActivity.java
new file mode 100644
index 0000000..ea7f52a
--- /dev/null
+++ b/hostsidetests/ui/appB/src/android/taskswitching/appb/AppBActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 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.taskswitching.appb;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.WindowManager;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * Simple activity to notify completion via broadcast after onResume.
+ * This is for measuring taskswitching time between two apps.
+ */
+public class AppBActivity extends ListActivity {
+ static final String TAG = "AppBActivity";
+ private static final int NUMBER_ELEMENTS = 1000;
+ private static final String TASKSWITCHING_INTENT = "android.taskswitching.appb";
+ private Handler mHandler;
+
+ private String[] mItems = new String[NUMBER_ELEMENTS];
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ for (int i = 0; i < NUMBER_ELEMENTS; i++) {
+ mItems[i] = "B" + Integer.toString(i);
+ }
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, mItems));
+ ListView view = getListView();
+ mHandler = new Handler();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ Intent intent = new Intent(TASKSWITCHING_INTENT);
+ sendBroadcast(intent);
+ }
+ });
+ }
+}
diff --git a/hostsidetests/ui/control/Android.mk b/hostsidetests/ui/control/Android.mk
new file mode 100644
index 0000000..e1ff237
--- /dev/null
+++ b/hostsidetests/ui/control/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsDeviceTaskSwitchingControl
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/ui/control/AndroidManifest.xml b/hostsidetests/ui/control/AndroidManifest.xml
new file mode 100644
index 0000000..fd48287
--- /dev/null
+++ b/hostsidetests/ui/control/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.taskswitching.control.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation
+ android:targetPackage="android.taskswitching.control.cts"
+ android:name="android.support.test.runner.AndroidJUnitRunner" >
+ <meta-data
+ android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+</manifest>
diff --git a/hostsidetests/ui/control/src/android/taskswitching/control/cts/TaskSwitchingDeviceTest.java b/hostsidetests/ui/control/src/android/taskswitching/control/cts/TaskSwitchingDeviceTest.java
new file mode 100644
index 0000000..13b60be
--- /dev/null
+++ b/hostsidetests/ui/control/src/android/taskswitching/control/cts/TaskSwitchingDeviceTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 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.taskswitching.control.cts;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import android.cts.util.CtsAndroidTestCase;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.MeasureRun;
+import com.android.compatibility.common.util.MeasureTime;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+
+/**
+ * Device test which actually launches two apps sequentially and
+ * measure time for switching.
+ * Completion of launch is notified via broadcast.
+ */
+public class TaskSwitchingDeviceTest extends CtsAndroidTestCase {
+ private static final String PKG_A = "android.taskswitching.appa";
+ private static final String PKG_B = "android.taskswitching.appb";
+ private static final String ACTIVITY_A = "AppAActivity";
+ private static final String ACTIVITY_B = "AppBActivity";
+ private static final long TASK_SWITCHING_WAIT_TIME = 5;
+ private final AppBroadcastReceiver mReceiverA = new AppBroadcastReceiver();
+ private final AppBroadcastReceiver mReceiverB = new AppBroadcastReceiver();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ startActivity(PKG_A, ACTIVITY_A);
+ startActivity(PKG_B, ACTIVITY_B);
+ IntentFilter filterA = new IntentFilter();
+ filterA.addAction(PKG_A);
+ IntentFilter filterB = new IntentFilter();
+ filterB.addAction(PKG_B);
+ getContext().registerReceiver(mReceiverA, filterA);
+ getContext().registerReceiver(mReceiverB, filterB);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ getContext().unregisterReceiver(mReceiverA);
+ getContext().unregisterReceiver(mReceiverB);
+ super.tearDown();
+ }
+
+ public void testMeasureTaskSwitching() throws Exception {
+ final int NUMBER_REPEAT = 10;
+ final int SWITCHING_PER_ONE_TRY = 10;
+
+ double[] results = MeasureTime.measure(NUMBER_REPEAT, new MeasureRun() {
+
+ @Override
+ public void run(int i) throws Exception {
+ for (int j = 0; j < SWITCHING_PER_ONE_TRY; j++) {
+ startActivity(PKG_A, ACTIVITY_A);
+ assertTrue(mReceiverA.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
+ startActivity(PKG_B, ACTIVITY_B);
+ assertTrue(mReceiverB.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
+ }
+ }
+ });
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValues("task switching time", results, ResultType.LOWER_BETTER, ResultUnit.MS);
+ Stat.StatResult stat = Stat.getStat(results);
+ report.setSummary("task switching time", stat.mAverage,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.submit(getInstrumentation());
+ }
+
+ private void startActivity(String packageName, String activityName) {
+ Context context = getContext();
+ Intent intent = new Intent();
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setComponent(new ComponentName(packageName, packageName + "." + activityName));
+ context.startActivity(intent);
+ }
+
+ class AppBroadcastReceiver extends BroadcastReceiver {
+ private final Semaphore mSemaphore = new Semaphore(0);
+
+ public boolean waitForBroadcast(long timeoutInSec) throws InterruptedException {
+ return mSemaphore.tryAcquire(timeoutInSec, TimeUnit.SECONDS);
+ }
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mSemaphore.release();
+ }
+ }
+}
diff --git a/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java b/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
new file mode 100644
index 0000000..d91944a
--- /dev/null
+++ b/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 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.ui.cts;
+
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.compatibility.common.util.MeasureRun;
+import com.android.compatibility.common.util.MeasureTime;
+import com.android.compatibility.common.util.MetricsReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+import com.android.cts.migration.MigrationHelper;
+import com.android.ddmlib.Log;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+
+/**
+ * Test to measure installation time of a APK.
+ */
+public class InstallTimeTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+ private IBuildInfo mBuild;
+ private ITestDevice mDevice;
+ private IAbi mAbi;
+
+ private static final String TAG = "InstallTimeTest";
+ static final String PACKAGE = "com.replica.replicaisland";
+ static final String APK = "com.replica.replicaisland.apk";
+ private static final double OUTLIER_THRESHOLD = 0.1;
+
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mBuild = buildInfo;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+ }
+
+
+ @Override
+ protected void tearDown() throws Exception {
+ mDevice.uninstallPackage(PACKAGE);
+ super.tearDown();
+ }
+
+ public void testInstallTime() throws Exception {
+ MetricsReportLog report = new MetricsReportLog(mDevice.getSerialNumber(), mAbi.getName(),
+ String.format("%s#%s", getClass().getName(), "testInstallTime"));
+ final int NUMBER_REPEAT = 10;
+ final IBuildInfo build = mBuild;
+ final ITestDevice device = mDevice;
+ double[] result = MeasureTime.measure(NUMBER_REPEAT, new MeasureRun() {
+ @Override
+ public void prepare(int i) throws Exception {
+ device.uninstallPackage(PACKAGE);
+ }
+ @Override
+ public void run(int i) throws Exception {
+ File app = MigrationHelper.getTestFile(build, APK);
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ device.installPackage(app, false, options);
+ }
+ });
+ report.addValues("install time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
+ Stat.StatResult stat = Stat.getStatWithOutlierRejection(result, OUTLIER_THRESHOLD);
+ if (stat.mDataCount != result.length) {
+ Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
+ }
+ report.setSummary("install time", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.submit();
+ }
+
+}
diff --git a/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java b/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
new file mode 100644
index 0000000..4af40a2
--- /dev/null
+++ b/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 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.ui.cts;
+
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.compatibility.common.util.MetricsStore;
+import com.android.compatibility.common.util.ReportLog;
+import com.android.cts.migration.MigrationHelper;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Measure time to taskswitching between two Apps: A & B
+ * Actual test is done in device, but this host side code installs all necessary APKs
+ * and starts device test which is in CtsDeviceTaskswitchingControl.
+ */
+public class TaskSwitchingTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+ private static final String TAG = "TaskSwitchingTest";
+ private final static String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+ private static final String RESULT_KEY = "COMPATIBILITY_TEST_RESULT";
+ private IBuildInfo mBuild;
+ private ITestDevice mDevice;
+ private ReportLog mReport = null;
+ private IAbi mAbi;
+
+ static final String[] PACKAGES = {
+ "android.taskswitching.control.cts",
+ "android.taskswitching.appa",
+ "android.taskswitching.appb"
+ };
+ static final String[] APKS = {
+ "CtsDeviceTaskSwitchingControl.apk",
+ "CtsDeviceTaskSwitchingAppA.apk",
+ "CtsDeviceTaskSwitchingAppB.apk"
+ };
+
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mBuild = buildInfo;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ for (int i = 0; i < PACKAGES.length; i++) {
+ mDevice.uninstallPackage(PACKAGES[i]);
+ File app = MigrationHelper.getTestFile(mBuild, APKS[i]);
+ mDevice.installPackage(app, false, options);
+ }
+ }
+
+
+ @Override
+ protected void tearDown() throws Exception {
+ for (int i = 0; i < PACKAGES.length; i++) {
+ mDevice.uninstallPackage(PACKAGES[i]);
+ }
+ super.tearDown();
+ }
+
+ public void testTaskSwitching() throws Exception {
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(PACKAGES[0], RUNNER,
+ mDevice.getIDevice());
+ LocalListener listener = new LocalListener();
+ mDevice.runInstrumentationTests(testRunner, listener);
+ TestRunResult result = listener.getCurrentRunResults();
+ if (result.isRunFailure()) {
+ fail(result.getRunFailureMessage());
+ }
+ assertNotNull("no performance data", mReport);
+ MetricsStore.storeResult(mDevice.getSerialNumber(), mAbi.getName(),
+ String.format("%s#%s", getClass().getName(), "testTaskSwitching"), mReport);
+
+ }
+
+ public class LocalListener extends CollectingTestListener {
+ @Override
+ public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
+ // necessary as testMetrics passed from CollectingTestListerner is empty
+ if (testMetrics.containsKey(RESULT_KEY)) {
+ try {
+ mReport = ReportLog.parse(testMetrics.get(RESULT_KEY));
+ } catch (XmlPullParserException | IOException e) {
+ e.printStackTrace();
+ }
+ }
+ super.testEnded(test, testMetrics);
+ }
+ }
+}
diff --git a/hostsidetests/usage/Android.mk b/hostsidetests/usage/Android.mk
index 1d4e36d..203b684 100644
--- a/hostsidetests/usage/Android.mk
+++ b/hostsidetests/usage/Android.mk
@@ -19,12 +19,15 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
# Must match the package name in CtsTestCaseList.mk
-LOCAL_MODULE := CtsUsageHostTestCases
+LOCAL_MODULE := CtsAppUsageHostTestCases
LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
LOCAL_CTS_TEST_PACKAGE := android.host.app.usage
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/usage/AndroidTest.xml b/hostsidetests/usage/AndroidTest.xml
new file mode 100644
index 0000000..bba2748
--- /dev/null
+++ b/hostsidetests/usage/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS App Usage host test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAppUsageTestApp.apk" />
+ </target_preparer>
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsAppUsageHostTestCases.jar" />
+ </test>
+</configuration>
diff --git a/hostsidetests/usage/app/Android.mk b/hostsidetests/usage/app/Android.mk
index b23efbc..31b6d8f 100644
--- a/hostsidetests/usage/app/Android.mk
+++ b/hostsidetests/usage/app/Android.mk
@@ -23,6 +23,9 @@
LOCAL_SDK_VERSION := current
-LOCAL_PACKAGE_NAME := CtsDeviceAppUsageTestApp
+LOCAL_PACKAGE_NAME := CtsAppUsageTestApp
+
+# tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/usage/app/AndroidManifest.xml b/hostsidetests/usage/app/AndroidManifest.xml
index bad453f..7d5ce48 100755
--- a/hostsidetests/usage/app/AndroidManifest.xml
+++ b/hostsidetests/usage/app/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.app.usage.test">
+ package="android.app.usage.app">
<application>
<activity android:name=".TestActivity">
diff --git a/hostsidetests/usage/app/src/android/app/usage/app/TestActivity.java b/hostsidetests/usage/app/src/android/app/usage/app/TestActivity.java
new file mode 100644
index 0000000..8cb5842
--- /dev/null
+++ b/hostsidetests/usage/app/src/android/app/usage/app/TestActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.app.usage.app;
+
+import android.app.Activity;
+
+public class TestActivity extends Activity {
+}
\ No newline at end of file
diff --git a/hostsidetests/usage/app/src/com/android/cts/app/usage/test/TestActivity.java b/hostsidetests/usage/app/src/com/android/cts/app/usage/test/TestActivity.java
deleted file mode 100644
index 9432477..0000000
--- a/hostsidetests/usage/app/src/com/android/cts/app/usage/test/TestActivity.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.app.usage.test;
-
-import android.app.Activity;
-
-public class TestActivity extends Activity {
-}
\ No newline at end of file
diff --git a/hostsidetests/usage/src/android/app/usage/cts/AppIdleHostTest.java b/hostsidetests/usage/src/android/app/usage/cts/AppIdleHostTest.java
new file mode 100644
index 0000000..3cd7bda
--- /dev/null
+++ b/hostsidetests/usage/src/android/app/usage/cts/AppIdleHostTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+package android.app.usage.cts;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+
+public class AppIdleHostTest extends DeviceTestCase {
+ private static final String SETTINGS_APP_IDLE_CONSTANTS = "app_idle_constants";
+
+ private static final String TEST_APP_PACKAGE = "android.app.usage.app";
+ private static final String TEST_APP_CLASS = "TestActivity";
+
+ private static final long ACTIVITY_LAUNCH_WAIT_MILLIS = 500;
+
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Get the device, this gives a handle to run commands and install APKs.
+ mDevice = getDevice();
+ }
+
+ /**
+ * Checks whether an package is idle.
+ * @param appPackage The package to check for idleness.
+ * @return true if the package is idle
+ * @throws DeviceNotAvailableException
+ */
+ private boolean isAppIdle(String appPackage) throws DeviceNotAvailableException {
+ String result = mDevice.executeShellCommand(String.format("am get-inactive %s", appPackage));
+ return result.contains("Idle=true");
+ }
+
+ /**
+ * Set the app idle settings.
+ * @param settingsStr The settings string, a comma separated key=value list.
+ * @throws DeviceNotAvailableException
+ */
+ private void setAppIdleSettings(String settingsStr) throws DeviceNotAvailableException {
+ mDevice.executeShellCommand(String.format("settings put global %s \"%s\"",
+ SETTINGS_APP_IDLE_CONSTANTS, settingsStr));
+ }
+
+ /**
+ * Get the current app idle settings.
+ * @throws DeviceNotAvailableException
+ */
+ private String getAppIdleSettings() throws DeviceNotAvailableException {
+ String result = mDevice.executeShellCommand(String.format("settings get global %s",
+ SETTINGS_APP_IDLE_CONSTANTS));
+ return result.trim();
+ }
+
+ /**
+ * Launch the test app for a few hundred milliseconds then launch home.
+ * @throws DeviceNotAvailableException
+ */
+ private void startAndStopTestApp() throws DeviceNotAvailableException {
+ // Launch the app.
+ mDevice.executeShellCommand(
+ String.format("am start -W -a android.intent.action.MAIN -n %s/%s.%s",
+ TEST_APP_PACKAGE, TEST_APP_PACKAGE, TEST_APP_CLASS));
+
+ // Wait for some time.
+ sleepUninterrupted(ACTIVITY_LAUNCH_WAIT_MILLIS);
+
+ // Launch home.
+ mDevice.executeShellCommand(
+ "am start -W -a android.intent.action.MAIN -c android.intent.category.HOME");
+ }
+
+ /**
+ * Tests that the app is not idle right after it is launched.
+ */
+ public void testAppIsNotIdleAfterBeingLaunched() throws Exception {
+ final String previousState = getAppIdleSettings();
+ try {
+ // Set the app idle time to something large.
+ setAppIdleSettings("idle_duration=10000,wallclock_threshold=10000");
+ startAndStopTestApp();
+ assertFalse(isAppIdle(TEST_APP_PACKAGE));
+ } finally {
+ setAppIdleSettings(previousState);
+ }
+ }
+
+ private static void sleepUninterrupted(long timeMillis) {
+ boolean interrupted;
+ do {
+ try {
+ Thread.sleep(timeMillis);
+ interrupted = false;
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ } while (interrupted);
+ }
+}
diff --git a/hostsidetests/usage/src/com/android/cts/app/usage/AppIdleHostTest.java b/hostsidetests/usage/src/com/android/cts/app/usage/AppIdleHostTest.java
deleted file mode 100644
index b94d086..0000000
--- a/hostsidetests/usage/src/com/android/cts/app/usage/AppIdleHostTest.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.app.usage;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-public class AppIdleHostTest extends DeviceTestCase implements IBuildReceiver {
- private static final String SETTINGS_APP_IDLE_CONSTANTS = "app_idle_constants";
-
- private static final String TEST_APP_PACKAGE = "com.android.cts.app.usage.test";
- private static final String TEST_APP_APK = "CtsDeviceAppUsageTestApp.apk";
- private static final String TEST_APP_CLASS = "TestActivity";
-
- private static final long ACTIVITY_LAUNCH_WAIT_MILLIS = 500;
-
- /**
- * A reference to the build.
- */
- private CtsBuildHelper mBuild;
-
- /**
- * A reference to the device under test.
- */
- private ITestDevice mDevice;
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- // Get the build, this is used to access the APK.
- mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // Get the device, this gives a handle to run commands and install APKs.
- mDevice = getDevice();
-
- // Remove any previously installed versions of this APK.
- mDevice.uninstallPackage(TEST_APP_PACKAGE);
-
- // Install the APK on the device.
- mDevice.installPackage(mBuild.getTestApp(TEST_APP_APK), false);
- }
-
- @Override
- protected void tearDown() throws Exception {
- // Remove the package once complete.
- mDevice.uninstallPackage(TEST_APP_PACKAGE);
- super.tearDown();
- }
-
- /**
- * Checks whether an package is idle.
- * @param appPackage The package to check for idleness.
- * @return true if the package is idle
- * @throws DeviceNotAvailableException
- */
- private boolean isAppIdle(String appPackage) throws DeviceNotAvailableException {
- String result = mDevice.executeShellCommand(String.format("am get-inactive %s", appPackage));
- return result.contains("Idle=true");
- }
-
- /**
- * Set the app idle settings.
- * @param settingsStr The settings string, a comma separated key=value list.
- * @throws DeviceNotAvailableException
- */
- private void setAppIdleSettings(String settingsStr) throws DeviceNotAvailableException {
- mDevice.executeShellCommand(String.format("settings put global %s \"%s\"",
- SETTINGS_APP_IDLE_CONSTANTS, settingsStr));
- }
-
- /**
- * Get the current app idle settings.
- * @throws DeviceNotAvailableException
- */
- private String getAppIdleSettings() throws DeviceNotAvailableException {
- String result = mDevice.executeShellCommand(String.format("settings get global %s",
- SETTINGS_APP_IDLE_CONSTANTS));
- return result.trim();
- }
-
- /**
- * Launch the test app for a few hundred milliseconds then launch home.
- * @throws DeviceNotAvailableException
- */
- private void startAndStopTestApp() throws DeviceNotAvailableException {
- // Launch the app.
- mDevice.executeShellCommand(
- String.format("am start -W -a android.intent.action.MAIN -n %s/%s.%s",
- TEST_APP_PACKAGE, TEST_APP_PACKAGE, TEST_APP_CLASS));
-
- // Wait for some time.
- sleepUninterrupted(ACTIVITY_LAUNCH_WAIT_MILLIS);
-
- // Launch home.
- mDevice.executeShellCommand(
- "am start -W -a android.intent.action.MAIN -c android.intent.category.HOME");
- }
-
- /**
- * Tests that the app is not idle right after it is launched.
- */
- public void testAppIsNotIdleAfterBeingLaunched() throws Exception {
- final String previousState = getAppIdleSettings();
- try {
- // Set the app idle time to something large.
- setAppIdleSettings("idle_duration=10000,wallclock_threshold=10000");
- startAndStopTestApp();
- assertFalse(isAppIdle(TEST_APP_PACKAGE));
- } finally {
- setAppIdleSettings(previousState);
- }
- }
-
- private static void sleepUninterrupted(long timeMillis) {
- boolean interrupted;
- do {
- try {
- Thread.sleep(timeMillis);
- interrupted = false;
- } catch (InterruptedException e) {
- interrupted = true;
- }
- } while (interrupted);
- }
-}
diff --git a/hostsidetests/usb/Android.mk b/hostsidetests/usb/Android.mk
index f93dfa4..facc4d8 100644
--- a/hostsidetests/usb/Android.mk
+++ b/hostsidetests/usb/Android.mk
@@ -21,10 +21,15 @@
LOCAL_MODULE := CtsUsbTests
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed_v2 compatibility-host-util tradefed-prebuilt
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
LOCAL_CTS_TEST_PACKAGE := android.usb
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
# Build the test APKs using their own makefiles
diff --git a/hostsidetests/usb/AndroidTest.xml b/hostsidetests/usb/AndroidTest.xml
new file mode 100644
index 0000000..013e97f
--- /dev/null
+++ b/hostsidetests/usb/AndroidTest.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<configuration description="Config for CTS USB host test cases">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsUsbTests.jar" />
+ </test>
+</configuration>
diff --git a/hostsidetests/usb/SerialTestApp/Android.mk b/hostsidetests/usb/SerialTestApp/Android.mk
index a8f51ad..80316b2 100644
--- a/hostsidetests/usb/SerialTestApp/Android.mk
+++ b/hostsidetests/usb/SerialTestApp/Android.mk
@@ -28,4 +28,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
index 3af52c0..5377711 100644
--- a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
+++ b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
@@ -15,8 +15,8 @@
*/
package com.android.cts.usb;
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.cts.migration.MigrationHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
@@ -45,7 +45,7 @@
private static final String APK_NAME="CtsUsbSerialTestApp.apk";
private ITestDevice mDevice;
private IAbi mAbi;
- private CtsBuildHelper mBuild;
+ private IBuildInfo mBuild;
@Override
public void setAbi(IAbi abi) {
@@ -54,7 +54,7 @@
@Override
public void setBuild(IBuildInfo buildInfo) {
- mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ mBuild = buildInfo;
}
@Override
@@ -62,7 +62,7 @@
super.setUp();
mDevice = getDevice();
mDevice.uninstallPackage(PACKAGE_NAME);
- File app = mBuild.getTestApp(APK_NAME);
+ File app = MigrationHelper.getTestFile(mBuild, APK_NAME);
String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
mDevice.installPackage(app, false, options);
}
diff --git a/libs/commonutil/Android.mk b/libs/commonutil/Android.mk
deleted file mode 100644
index 9c131b0..0000000
--- a/libs/commonutil/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-include $(call all-subdir-makefiles)
-
-# ======================================================
-# Build a static host library for the AbiUtils
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := src/com/android/cts/util/AbiUtils.java
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE := ctsabiutilslib
-include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/libs/commonutil/src/com/android/cts/util/AbiUtils.java b/libs/commonutil/src/com/android/cts/util/AbiUtils.java
deleted file mode 100644
index 42336f3..0000000
--- a/libs/commonutil/src/com/android/cts/util/AbiUtils.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.cts.util;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Utility class for handling device ABIs
- */
-public class AbiUtils {
-
- /**
- * The set of 32Bit ABIs.
- */
- private static final Set<String> ABIS_32BIT = new HashSet<String>();
-
- /**
- * The set of 64Bit ABIs.
- */
- private static final Set<String> ABIS_64BIT = new HashSet<String>();
-
- /**
- * The set of ARM ABIs.
- */
- private static final Set<String> ARM_ABIS = new HashSet<String>();
-
- /**
- * The set of Intel ABIs.
- */
- private static final Set<String> INTEL_ABIS = new HashSet<String>();
-
- /**
- * The set of Mips ABIs.
- */
- private static final Set<String> MIPS_ABIS = new HashSet<String>();
-
- /**
- * The set of ABI names which CTS supports.
- */
- private static final Set<String> ABIS_SUPPORTED_BY_CTS = new HashSet<String>();
-
- /**
- * The map of architecture to ABI.
- */
- private static final Map<String, Set<String>> ARCH_TO_ABIS = new HashMap<String, Set<String>>();
- static {
- ABIS_32BIT.add("armeabi-v7a");
- ABIS_32BIT.add("x86");
- ABIS_32BIT.add("mips");
-
- ABIS_64BIT.add("arm64-v8a");
- ABIS_64BIT.add("x86_64");
- ABIS_64BIT.add("mips64");
-
- ARM_ABIS.add("armeabi-v7a");
- ARM_ABIS.add("arm64-v8a");
-
- INTEL_ABIS.add("x86");
- INTEL_ABIS.add("x86_64");
-
- MIPS_ABIS.add("mips");
- MIPS_ABIS.add("mips64");
-
- ARCH_TO_ABIS.put("arm", ARM_ABIS);
- ARCH_TO_ABIS.put("arm64", ARM_ABIS);
- ARCH_TO_ABIS.put("x86", INTEL_ABIS);
- ARCH_TO_ABIS.put("x86_64", INTEL_ABIS);
- ARCH_TO_ABIS.put("mips", MIPS_ABIS);
- ARCH_TO_ABIS.put("mips64", MIPS_ABIS);
-
- ABIS_SUPPORTED_BY_CTS.addAll(ARM_ABIS);
- ABIS_SUPPORTED_BY_CTS.addAll(INTEL_ABIS);
- ABIS_SUPPORTED_BY_CTS.addAll(MIPS_ABIS);
- }
-
- /**
- * Private constructor to avoid instantiation.
- */
- private AbiUtils() {}
-
- /**
- * Returns the set of ABIs associated with the given architecture.
- * @param arch The architecture to look up.
- * @return a new Set containing the ABIs.
- */
- public static Set<String> getAbisForArch(String arch) {
- if (arch == null || arch.isEmpty() || !ARCH_TO_ABIS.containsKey(arch)) {
- return getAbisSupportedByCts();
- }
- return new HashSet<String>(ARCH_TO_ABIS.get(arch));
- }
-
- /**
- * Returns the set of ABIs supported by CTS.
- * @return a new Set containing the supported ABIs.
- */
- public static Set<String> getAbisSupportedByCts() {
- return new HashSet<String>(ABIS_SUPPORTED_BY_CTS);
- }
-
- /**
- * @param abi The ABI name to test.
- * @return true if the given ABI is supported by CTS.
- */
- public static boolean isAbiSupportedByCts(String abi) {
- return ABIS_SUPPORTED_BY_CTS.contains(abi);
- }
-
- /**
- * Creates a flag for the given ABI.
- * @param abi the ABI to create the flag for.
- * @return a string which can be add to a command sent to ADB.
- */
- public static String createAbiFlag(String abi) {
- if (abi == null || abi.isEmpty() || !isAbiSupportedByCts(abi)) {
- return "";
- }
- return String.format("--abi %s ", abi);
- }
-
- /**
- * Creates a unique id from the given ABI and name.
- * @param abi The ABI to use.
- * @param name The name to use.
- * @return a string which uniquely identifies a run.
- */
- public static String createId(String abi, String name) {
- return String.format("%s %s", abi, name);
- }
-
- /**
- * Parses a unique id into the ABI and name.
- * @param id The id to parse.
- * @return a string array containing the ABI and name.
- */
- public static String[] parseId(String id) {
- if (id == null || !id.contains(" ")) {
- return new String[] {"", ""};
- }
- return id.split(" ");
- }
-
- /**
- * @return the test name portion of the test id.
- * e.g. armeabi-v7a android.mytest = android.mytest
- */
- public static String parseTestName(String id) {
- return parseId(id)[1];
- }
-
- /**
- * @return the abi portion of the test id.
- * e.g. armeabi-v7a android.mytest = armeabi-v7a
- */
- public static String parseAbi(String id) {
- return parseId(id)[0];
- }
-
- /**
- * @param name The name of the ABI.
- * @return The bitness of the ABI with the given name
- */
- public static String getBitness(String name) {
- return ABIS_32BIT.contains(name) ? "32" : "64";
- }
-
- /**
- * @param abilistString A comma separated string containing abis.
- * @return A List of Strings containing valid ABIs.
- */
- public static Set<String> parseAbiList(String unsupportedAbiDescription) {
- Set<String> abiSet = new HashSet<>();
- String[] descSegments = unsupportedAbiDescription.split(":");
- if (descSegments.length == 2) {
- for (String abi : descSegments[1].split(",")) {
- String trimmedAbi = abi.trim();
- if (isAbiSupportedByCts(trimmedAbi)) {
- abiSet.add(trimmedAbi);
- }
- }
- }
- return abiSet;
- }
-}
diff --git a/libs/commonutil/src/com/android/cts/util/MeasureRun.java b/libs/commonutil/src/com/android/cts/util/MeasureRun.java
deleted file mode 100644
index 43b5acf..0000000
--- a/libs/commonutil/src/com/android/cts/util/MeasureRun.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.util;
-
-/**
- * interface for measuring time for each run.
- */
-public abstract class MeasureRun {
- /**
- * called before each run. not included to time measurement.
- */
- public void prepare(int i) throws Exception {
- // default empty implementation
- };
-
- abstract public void run(int i) throws Exception;
-}
diff --git a/libs/commonutil/src/com/android/cts/util/MeasureTime.java b/libs/commonutil/src/com/android/cts/util/MeasureTime.java
deleted file mode 100644
index fd22ef2..0000000
--- a/libs/commonutil/src/com/android/cts/util/MeasureTime.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.util;
-
-
-public class MeasureTime {
- /**
- * measure time taken for each run for given count
- * @param count
- * @param run
- * @return array of time taken in each run in msec.
- * @throws Exception
- */
- public static double[] measure(int count, MeasureRun run) throws Exception {
- double[] result = new double[count];
-
- for (int i = 0; i < count; i++) {
- run.prepare(i);
- long start = System.currentTimeMillis();
- run.run(i);
- long end = System.currentTimeMillis();
- result[i] = end - start;
- }
- return result;
- }
-}
diff --git a/libs/commonutil/src/com/android/cts/util/ReportLog.java b/libs/commonutil/src/com/android/cts/util/ReportLog.java
index dd4b414..05dec0f 100644
--- a/libs/commonutil/src/com/android/cts/util/ReportLog.java
+++ b/libs/commonutil/src/com/android/cts/util/ReportLog.java
@@ -16,29 +16,28 @@
package com.android.cts.util;
-import java.util.LinkedList;
-import java.util.List;
+import com.android.compatibility.common.util.Stat;
-import junit.framework.Assert;
+import org.xmlpull.v1.XmlPullParserException;
+import java.io.IOException;
/**
* Utility class to print performance measurement result back to host.
* For now, throws know exception with message.
*
- * Format:
- * Message = summary log SUMMARY_SEPARATOR [LOG_SEPARATOR log]*
- * summary = message|target|unit|type|value, target can be " " if there is no target set.
- * log for array = classMethodName:line_number|message|unit|type|space seSummaryparated values
+ * This class is deprecated, use {@link com.android.compatibility.common.util.ReportLog}
+ * instead.
*/
+@Deprecated
public class ReportLog {
- private static final String LOG_SEPARATOR = "+++";
- private static final String SUMMARY_SEPARATOR = "++++";
- private static final String LOG_ELEM_SEPARATOR = "|";
- private List<String> mMessages = new LinkedList<String> ();
- private String mSummary = null;
protected static int mDepth = 3;
+ protected com.android.compatibility.common.util.ReportLog mReportLog;
+
+ public ReportLog(com.android.compatibility.common.util.ReportLog reportLog) {
+ mReportLog = reportLog;
+ }
/**
* print array of values to output log
@@ -80,23 +79,11 @@
private void doPrintArray(String testId, String message,
double[] values, ResultType type, ResultUnit unit) {
- StringBuilder builder = new StringBuilder();
- // note mDepth + 1 as this function will be called by printVaue or printArray
- // and we need caller of printValue / printArray
- builder.append(testId);
- builder.append(LOG_ELEM_SEPARATOR);
- builder.append(message);
- builder.append(LOG_ELEM_SEPARATOR);
- builder.append(type.getXmlString());
- builder.append(LOG_ELEM_SEPARATOR);
- builder.append(unit.getXmlString());
- builder.append(LOG_ELEM_SEPARATOR);
- for (double v : values) {
- builder.append(v);
- builder.append(" ");
- }
- mMessages.add(builder.toString());
- printLog(builder.toString());
+ mReportLog.addValues(testId, message, values,
+ com.android.compatibility.common.util.ResultType.parseReportString(
+ type.getXmlString()),
+ com.android.compatibility.common.util.ResultUnit.parseReportString(
+ unit.getXmlString()));
}
/**
@@ -113,18 +100,12 @@
*/
public void printSummaryWithTarget(String message, double target, double value,
ResultType type, ResultUnit unit) {
- mSummary = message + LOG_ELEM_SEPARATOR + target + LOG_ELEM_SEPARATOR + type.getXmlString()
- + LOG_ELEM_SEPARATOR + unit.getXmlString() + LOG_ELEM_SEPARATOR + value;
- boolean resultOk = true;
- if (type == ResultType.HIGHER_BETTER) {
- resultOk = value >= target;
- } else if (type == ResultType.LOWER_BETTER) {
- resultOk = value <= target;
- }
- if (!resultOk) {
- Assert.fail("Measured result " + value + " does not meet perf target " + target +
- " with type " + type.getXmlString());
- }
+ // Ignore target
+ mReportLog.setSummary(message, value,
+ com.android.compatibility.common.util.ResultType.parseReportString(
+ type.getXmlString()),
+ com.android.compatibility.common.util.ResultUnit.parseReportString(
+ unit.getXmlString()));
}
/**
@@ -136,32 +117,24 @@
* @param unit unit of the data
*/
public void printSummary(String message, double value, ResultType type, ResultUnit unit) {
- mSummary = message + LOG_ELEM_SEPARATOR + " " + LOG_ELEM_SEPARATOR + type.getXmlString() +
- LOG_ELEM_SEPARATOR + unit.getXmlString() + LOG_ELEM_SEPARATOR + value;
+ mReportLog.setSummary(message, value,
+ com.android.compatibility.common.util.ResultType.parseReportString(
+ type.getXmlString()),
+ com.android.compatibility.common.util.ResultUnit.parseReportString(
+ unit.getXmlString()));
}
/**
* @return a string representation of this report.
*/
protected String generateReport() {
- if ((mSummary == null) && mMessages.isEmpty()) {
- // just return empty string
- return "";
+ try {
+ return com.android.compatibility.common.util.ReportLog.serialize(mReportLog);
+ } catch (IllegalArgumentException | IllegalStateException | XmlPullParserException
+ | IOException e) {
+ e.printStackTrace();
}
- StringBuilder builder = new StringBuilder();
- builder.append(mSummary);
- builder.append(SUMMARY_SEPARATOR);
- for (String entry : mMessages) {
- builder.append(entry);
- builder.append(LOG_SEPARATOR);
- }
- // delete the last separator
- if (builder.length() >= LOG_SEPARATOR.length()) {
- builder.delete(builder.length() - LOG_SEPARATOR.length(), builder.length());
- }
- mSummary = null;
- mMessages.clear();
- return builder.toString();
+ return null;
}
/**
@@ -172,27 +145,14 @@
* @return
*/
public static double calcRatePerSec(double change, double timeInMSec) {
- if (timeInMSec == 0) {
- return change * 1000.0 / 0.001; // do not allow zero
- } else {
- return change * 1000.0 / timeInMSec;
- }
+ return Stat.calcRatePerSec(change, timeInMSec);
}
/**
* array version of calcRatePerSecArray
*/
public static double[] calcRatePerSecArray(double change, double[] timeInMSec) {
- double[] result = new double[timeInMSec.length];
- change *= 1000.0;
- for (int i = 0; i < timeInMSec.length; i++) {
- if (timeInMSec[i] == 0) {
- result[i] = change / 0.001;
- } else {
- result[i] = change / timeInMSec[i];
- }
- }
- return result;
+ return Stat.calcRatePerSecArray(change, timeInMSec);
}
/**
@@ -219,10 +179,4 @@
return names;
}
- /**
- * to be overridden by child to print message to be passed
- */
- protected void printLog(String msg) {
-
- }
}
diff --git a/libs/commonutil/src/com/android/cts/util/ResultType.java b/libs/commonutil/src/com/android/cts/util/ResultType.java
index a5a388c..dbe8602 100644
--- a/libs/commonutil/src/com/android/cts/util/ResultType.java
+++ b/libs/commonutil/src/com/android/cts/util/ResultType.java
@@ -18,7 +18,11 @@
/**
* Enum for distinguishing performance results.
+ *
+ * This class is deprecated, use {@link com.android.compatibility.common.util.ResultType}
+ * instead.
*/
+@Deprecated
public enum ResultType {
/** lower score shows better performance */
LOWER_BETTER,
diff --git a/libs/commonutil/src/com/android/cts/util/ResultUnit.java b/libs/commonutil/src/com/android/cts/util/ResultUnit.java
index a216a7e..2148821 100644
--- a/libs/commonutil/src/com/android/cts/util/ResultUnit.java
+++ b/libs/commonutil/src/com/android/cts/util/ResultUnit.java
@@ -19,7 +19,10 @@
/**
* Enum for representing the unit of performance results.
*
+ * This class is deprecated, use {@link com.android.compatibility.common.util.ResultUnit}
+ * instead.
*/
+@Deprecated
public enum ResultUnit {
/** for value with no unit */
NONE,
diff --git a/libs/commonutil/src/com/android/cts/util/Stat.java b/libs/commonutil/src/com/android/cts/util/Stat.java
deleted file mode 100644
index ceafa4e..0000000
--- a/libs/commonutil/src/com/android/cts/util/Stat.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.util;
-
-import java.util.Arrays;
-
-/**
- * Utilities for doing statistics
- *
- */
-public class Stat {
-
- /**
- * Collection of statistical propertirs like average, max, min, and stddev
- */
- public static class StatResult {
- public double mAverage;
- public double mMin;
- public double mMax;
- public double mStddev;
- public int mDataCount;
- public StatResult(double average, double min, double max, double stddev, int dataCount) {
- mAverage = average;
- mMin = min;
- mMax = max;
- mStddev = stddev;
- mDataCount = dataCount;
- }
- }
-
- /**
- * Calculate statistics properties likes average, min, max, and stddev for the given array
- */
- public static StatResult getStat(double[] data) {
- double average = data[0];
- double min = data[0];
- double max = data[0];
- double eX2 = data[0] * data[0]; // will become E[X^2]
- for (int i = 1; i < data.length; i++) {
- average += data[i];
- eX2 += data[i] * data[i];
- if (data[i] > max) {
- max = data[i];
- }
- if (data[i] < min) {
- min = data[i];
- }
- }
- average /= data.length;
- eX2 /= data.length;
- // stddev = sqrt(E[X^2] - (E[X])^2)
- double stddev = Math.sqrt(eX2 - average * average);
- return new StatResult(average, min, max, stddev, data.length);
- }
-
- /**
- * Calculate statistics properties likes average, min, max, and stddev for the given array
- * while rejecting outlier +/- median * rejectionThreshold.
- * rejectionThreshold should be bigger than 0.0 and be lowerthan 1.0
- */
- public static StatResult getStatWithOutlierRejection(double[] data, double rejectionThreshold) {
- double[] dataCopied = Arrays.copyOf(data, data.length);
- Arrays.sort(dataCopied);
- int medianIndex = dataCopied.length / 2;
- double median;
- if (dataCopied.length % 2 == 1) {
- median = dataCopied[medianIndex];
- } else {
- median = (dataCopied[medianIndex - 1] + dataCopied[medianIndex]) / 2.0;
- }
- double thresholdMin = median * (1.0 - rejectionThreshold);
- double thresholdMax = median * (1.0 + rejectionThreshold);
-
- double average = 0.0;
- double min = median;
- double max = median;
- double eX2 = 0.0; // will become E[X^2]
- int validDataCounter = 0;
- for (int i = 0; i < data.length; i++) {
- if ((data[i] > thresholdMin) && (data[i] < thresholdMax)) {
- validDataCounter++;
- average += data[i];
- eX2 += data[i] * data[i];
- if (data[i] > max) {
- max = data[i];
- }
- if (data[i] < min) {
- min = data[i];
- }
- }
- //TODO report rejected data
- }
- double stddev;
- if (validDataCounter > 0) {
- average /= validDataCounter;
- eX2 /= validDataCounter;
- // stddev = sqrt(E[X^2] - (E[X])^2)
- stddev = Math.sqrt(eX2 - average * average);
- } else { // both median is showing too much diff
- average = median;
- stddev = 0; // don't care
- }
-
- return new StatResult(average, min, max, stddev, validDataCounter);
- }
-
- /**
- * return the average value of the passed array
- */
- public static double getAverage(double[] data) {
- double sum = data[0];
- for (int i = 1; i < data.length; i++) {
- sum += data[i];
- }
- return sum / data.length;
- }
-
- /**
- * return the minimum value of the passed array
- */
- public static double getMin(double[] data) {
- double min = data[0];
- for (int i = 1; i < data.length; i++) {
- if (data[i] < min) {
- min = data[i];
- }
- }
- return min;
- }
-
- /**
- * return the maximum value of the passed array
- */
- public static double getMax(double[] data) {
- double max = data[0];
- for (int i = 1; i < data.length; i++) {
- if (data[i] > max) {
- max = data[i];
- }
- }
- return max;
- }
-}
diff --git a/libs/commonutil/src/com/android/cts/util/StatisticsUtils.java b/libs/commonutil/src/com/android/cts/util/StatisticsUtils.java
deleted file mode 100644
index d6589af..0000000
--- a/libs/commonutil/src/com/android/cts/util/StatisticsUtils.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.cts.util;
-
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Set of static helper methods for CTS tests.
- */
-public class StatisticsUtils {
-
-
- /**
- * Private constructor for static class.
- */
- private StatisticsUtils() {}
-
- /**
- * Get the value of the 95th percentile using nearest rank algorithm.
- *
- * @throws IllegalArgumentException if the collection is null or empty
- */
- public static <TValue extends Comparable<? super TValue>> TValue get95PercentileValue(
- Collection<TValue> collection) {
- validateCollection(collection);
-
- List<TValue> arrayCopy = new ArrayList<TValue>(collection);
- Collections.sort(arrayCopy);
-
- // zero-based array index
- int arrayIndex = (int) Math.round(arrayCopy.size() * 0.95 + .5) - 1;
-
- return arrayCopy.get(arrayIndex);
- }
-
- /**
- * Calculate the mean of a collection.
- *
- * @throws IllegalArgumentException if the collection is null or empty
- */
- public static <TValue extends Number> double getMean(Collection<TValue> collection) {
- validateCollection(collection);
-
- double sum = 0.0;
- for(TValue value : collection) {
- sum += value.doubleValue();
- }
- return sum / collection.size();
- }
-
- /**
- * Calculate the bias-corrected sample variance of a collection.
- *
- * @throws IllegalArgumentException if the collection is null or empty
- */
- public static <TValue extends Number> double getVariance(Collection<TValue> collection) {
- validateCollection(collection);
-
- double mean = getMean(collection);
- ArrayList<Double> squaredDiffs = new ArrayList<Double>();
- for(TValue value : collection) {
- double difference = mean - value.doubleValue();
- squaredDiffs.add(Math.pow(difference, 2));
- }
-
- double sum = 0.0;
- for (Double value : squaredDiffs) {
- sum += value;
- }
- return sum / (squaredDiffs.size() - 1);
- }
-
- /**
- * Calculate the bias-corrected standard deviation of a collection.
- *
- * @throws IllegalArgumentException if the collection is null or empty
- */
- public static <TValue extends Number> double getStandardDeviation(
- Collection<TValue> collection) {
- return Math.sqrt(getVariance(collection));
- }
-
- /**
- * Validate that a collection is not null or empty.
- *
- * @throws IllegalStateException if collection is null or empty.
- */
- private static <T> void validateCollection(Collection<T> collection) {
- if(collection == null || collection.size() == 0) {
- throw new IllegalStateException("Collection cannot be null or empty");
- }
- }
-
-}
diff --git a/libs/commonutil/src/com/android/cts/util/StatisticsUtilsTest.java b/libs/commonutil/src/com/android/cts/util/StatisticsUtilsTest.java
deleted file mode 100644
index d78ba99..0000000
--- a/libs/commonutil/src/com/android/cts/util/StatisticsUtilsTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.cts.util;
-
-import junit.framework.TestCase;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Unit tests for the {@link StatisticsUtils} class.
- */
-public class StatisticsUtilsTest extends TestCase {
-
- /**
- * Test {@link StatisticsUtils#get95PercentileValue(Collection)}.
- */
- public void testGet95PercentileValue() {
- Collection<Integer> values = new HashSet<Integer>();
- for (int i = 0; i < 100; i++) {
- values.add(i);
- }
- assertEquals(95, (int) StatisticsUtils.get95PercentileValue(values));
-
- values = new HashSet<Integer>();
- for (int i = 0; i < 1000; i++) {
- values.add(i);
- }
- assertEquals(950, (int) StatisticsUtils.get95PercentileValue(values));
-
- values = new HashSet<Integer>();
- for (int i = 0; i < 100; i++) {
- values.add(i * i);
- }
- assertEquals(95 * 95, (int) StatisticsUtils.get95PercentileValue(values));
- }
-
- /**
- * Test {@link StatisticsUtils#getMean(Collection)}.
- */
- public void testGetMean() {
- List<Integer> values = Arrays.asList(0, 1, 2, 3, 4);
- double mean = StatisticsUtils.getMean(values);
- assertEquals(2.0, mean, 0.00001);
-
- values = Arrays.asList(1, 2, 3, 4, 5);
- mean = StatisticsUtils.getMean(values);
- assertEquals(3.0, mean, 0.00001);
-
- values = Arrays.asList(0, 1, 4, 9, 16);
- mean = StatisticsUtils.getMean(values);
- assertEquals(6.0, mean, 0.00001);
- }
-
- /**
- * Test {@link StatisticsUtils#getVariance(Collection)}.
- */
- public void testGetVariance() {
- List<Integer> values = Arrays.asList(0, 1, 2, 3, 4);
- double variance = StatisticsUtils.getVariance(values);
- assertEquals(2.5, variance, 0.00001);
-
- values = Arrays.asList(1, 2, 3, 4, 5);
- variance = StatisticsUtils.getVariance(values);
- assertEquals(2.5, variance, 0.00001);
-
- values = Arrays.asList(0, 2, 4, 6, 8);
- variance = StatisticsUtils.getVariance(values);
- assertEquals(10.0, variance, 0.00001);
- }
-
- /**
- * Test {@link StatisticsUtils#getStandardDeviation(Collection)}.
- */
- public void testGetStandardDeviation() {
- List<Integer> values = Arrays.asList(0, 1, 2, 3, 4);
- double stddev = StatisticsUtils.getStandardDeviation(values);
- assertEquals(Math.sqrt(2.5), stddev, 0.00001);
-
- values = Arrays.asList(1, 2, 3, 4, 5);
- stddev = StatisticsUtils.getStandardDeviation(values);
- assertEquals(Math.sqrt(2.5), stddev, 0.00001);
-
- values = Arrays.asList(0, 2, 4, 6, 8);
- stddev = StatisticsUtils.getStandardDeviation(values);
- assertEquals(Math.sqrt(10.0), stddev, 0.00001);
- }
-
-
-}
diff --git a/libs/deviceutil/Android.mk b/libs/deviceutil/Android.mk
index 8c81ee4..bb039ca 100644
--- a/libs/deviceutil/Android.mk
+++ b/libs/deviceutil/Android.mk
@@ -22,6 +22,8 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
+
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := ctsdeviceutil
diff --git a/libs/deviceutil/src/android/cts/util/CtsActivityInstrumentationTestCase2.java b/libs/deviceutil/src/android/cts/util/CtsActivityInstrumentationTestCase2.java
deleted file mode 100644
index e039407..0000000
--- a/libs/deviceutil/src/android/cts/util/CtsActivityInstrumentationTestCase2.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2012 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.cts.util;
-
-import com.android.cts.util.ReportLog;
-
-import android.app.Activity;
-import android.test.ActivityInstrumentationTestCase2;
-
-
-public class CtsActivityInstrumentationTestCase2<T extends Activity> extends
- ActivityInstrumentationTestCase2<T> {
-
- private DeviceReportLog mReportLog = new DeviceReportLog();
-
- public CtsActivityInstrumentationTestCase2(Class<T> activityClass) {
- super(activityClass);
- }
-
- public ReportLog getReportLog() {
- return mReportLog;
- }
-
- @Override
- protected void tearDown() throws Exception {
- mReportLog.deliverReportToHost(getInstrumentation());
- super.tearDown();
- }
-
-}
diff --git a/libs/deviceutil/src/android/cts/util/CtsAndroidTestCase.java b/libs/deviceutil/src/android/cts/util/CtsAndroidTestCase.java
index b1164bc..7cf0f7e 100644
--- a/libs/deviceutil/src/android/cts/util/CtsAndroidTestCase.java
+++ b/libs/deviceutil/src/android/cts/util/CtsAndroidTestCase.java
@@ -18,13 +18,14 @@
package android.cts.util;
import android.content.Context;
+import android.test.ActivityInstrumentationTestCase2;
/**
* This class emulates AndroidTestCase, but internally it is ActivityInstrumentationTestCase2
* to access Instrumentation.
* DummyActivity is not supposed to be accessed.
*/
-public class CtsAndroidTestCase extends CtsActivityInstrumentationTestCase2<DummyActivity> {
+public class CtsAndroidTestCase extends ActivityInstrumentationTestCase2<DummyActivity> {
public CtsAndroidTestCase() {
super(DummyActivity.class);
}
diff --git a/libs/deviceutil/src/android/cts/util/DeviceReportLog.java b/libs/deviceutil/src/android/cts/util/DeviceReportLog.java
index 63b07b7..4dd185e 100644
--- a/libs/deviceutil/src/android/cts/util/DeviceReportLog.java
+++ b/libs/deviceutil/src/android/cts/util/DeviceReportLog.java
@@ -22,6 +22,11 @@
import com.android.cts.util.ReportLog;
+/**
+ * This class is deprecated, use {@link com.android.compatibility.common.util.DeviceReportLog}
+ * instead.
+ */
+@Deprecated
public class DeviceReportLog extends ReportLog {
private static final String TAG = "DeviceCtsReport";
private static final String CTS_RESULT_KEY = "CTS_TEST_RESULT";
@@ -33,21 +38,17 @@
}
public DeviceReportLog(int depth) {
+ super(new com.android.compatibility.common.util.DeviceReportLog());
mDepth = BASE_DEPTH + depth;
}
- @Override
- protected void printLog(String msg) {
- Log.i(TAG, msg);
- }
-
public void deliverReportToHost(Instrumentation instrumentation) {
Log.i(TAG, "deliverReportToHost");
String report = generateReport();
- if (!report.equals("")) {
+ if (report != null && !report.isEmpty()) {
Bundle output = new Bundle();
output.putString(CTS_RESULT_KEY, report);
instrumentation.sendStatus(INST_STATUS_IN_PROGRESS, output);
}
}
-}
+}
\ No newline at end of file
diff --git a/libs/migration/Android.mk b/libs/migration/Android.mk
new file mode 100644
index 0000000..18dc837
--- /dev/null
+++ b/libs/migration/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := cts-migration-lib
+
+LOCAL_SDK_VERSION := current
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+include $(BUILD_HOST_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/libs/migration/src/com/android/cts/migration/MigrationHelper.java b/libs/migration/src/com/android/cts/migration/MigrationHelper.java
new file mode 100644
index 0000000..5fa0ff8
--- /dev/null
+++ b/libs/migration/src/com/android/cts/migration/MigrationHelper.java
@@ -0,0 +1,53 @@
+package com.android.cts.migration;
+
+import com.android.tradefed.build.IBuildInfo;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * A temporary helper to enable tests to work with both cts v1 and v2.
+ */
+public class MigrationHelper {
+
+ private static final String COMPATIBILITY_BUILD_HELPER =
+ "com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper";
+ private static final String CTS_BUILD_HELPER =
+ "com.android.cts.tradefed.build.CtsBuildHelper";
+
+ public static File getTestFile(IBuildInfo mBuild, String filename)
+ throws FileNotFoundException {
+ try {
+ Class<?> cls = Class.forName(COMPATIBILITY_BUILD_HELPER);
+ Constructor<?> cons = cls.getConstructor(IBuildInfo.class);
+ Object instance = cons.newInstance(mBuild);
+ Method method = cls.getMethod("getTestsDir");
+ File dir = (File) method.invoke(instance);
+ File file = new File(dir, filename);
+ if (file.exists()) {
+ return file;
+ }
+ } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException |
+ IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ // Ignore and fall back to CtsBuildHelper
+ }
+ try {
+ Class<?> cls = Class.forName(CTS_BUILD_HELPER);
+ Method builder = cls.getMethod("createBuildHelper", IBuildInfo.class);
+ Object helper = builder.invoke(null, mBuild);
+ Method method = cls.getMethod("getTestApp", String.class);
+ File file = (File) method.invoke(helper, filename);
+ if (file.exists()) {
+ return file;
+ }
+ } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException |
+ IllegalArgumentException | InvocationTargetException e) {
+ // Ignore
+ }
+ throw new FileNotFoundException("Couldn't load file " + filename);
+ }
+
+}
diff --git a/libs/vogar-expect/src/vogar/ExpectationStore.java b/libs/vogar-expect/src/vogar/ExpectationStore.java
index 090322d..b7b8d5a 100644
--- a/libs/vogar-expect/src/vogar/ExpectationStore.java
+++ b/libs/vogar-expect/src/vogar/ExpectationStore.java
@@ -27,12 +27,14 @@
import java.io.FileReader;
import java.io.IOException;
import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
+
import vogar.commands.Command;
import vogar.util.Log;
@@ -269,4 +271,12 @@
}
}
}
+
+ public Map<String, Expectation> getAllOutComes() {
+ return outcomes;
+ }
+
+ public Map<String, Expectation> getAllFailures() {
+ return failures;
+ }
}
diff --git a/run_unit_tests.sh b/run_unit_tests.sh
new file mode 100755
index 0000000..d83da77
--- /dev/null
+++ b/run_unit_tests.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+# 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.
+
+# Helper script for running unit tests for compatibility libraries
+
+CTS_DIR=$(dirname ${0})
+source ${CTS_DIR}/test_defs.sh
+
+echo
+echo "---- BUILD ---- "
+echo
+
+# check if in Android build env
+if [ ! -z ${ANDROID_BUILD_TOP} ]; then
+ HOST=`uname`
+ if [ "$HOST" == "Linux" ]; then
+ OS="linux-x86"
+ elif [ "$HOST" == "Darwin" ]; then
+ OS="darwin-x86"
+ else
+ echo "Unrecognized OS"
+ exit
+ fi;
+fi;
+
+BUILD_TARGETS="
+ compatibility-common-util-tests\
+ compatibility-host-util-tests\
+ compatibility-device-util-tests\
+ compatibility-tradefed-tests\
+ cts-tradefed-tests_v2\
+ compatibility-device-info-tests\
+ compatibility-manifest-generator-tests
+ compatibility-host-media-preconditions-tests\
+ CompatibilityTestApp"
+
+pushd ${CTS_DIR}/..
+make ${BUILD_TARGETS} -j32
+BUILD_STATUS=$?
+popd
+if [ "${BUILD_STATUS}" != "0" ]; then
+ echo "BUILD FAILED - EXIT"
+ exit 1;
+fi;
+
+
+echo
+echo "---- DEVICE-SIDE TESTS ---- "
+echo
+
+${CTS_DIR}/common/device-side/test-app/run_tests.sh
+
+echo
+echo "---- HOST TESTS ---- "
+echo
+
+############### Run the host side tests ###############
+${CTS_DIR}/common/host-side/tradefed/tests/run_tests.sh
+${CTS_DIR}/common/host-side/manifest-generator/tests/run_tests.sh
+${CTS_DIR}/common/host-side/util/tests/run_tests.sh
+${CTS_DIR}/common/util/tests/run_tests.sh
+
+${CTS_DIR}/tools/cts-tradefed/tests/run_tests.sh
+
+${CTS_DIR}/tests/tests/mediastress/preconditions/tests/run_tests.sh
diff --git a/suite/cts/deviceTests/browserbench/Android.mk b/suite/cts/deviceTests/browserbench/Android.mk
deleted file mode 100644
index 3696bcd..0000000
--- a/suite/cts/deviceTests/browserbench/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceBrowserBench
-
-LOCAL_SDK_VERSION := 16
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/cts/deviceTests/browserbench/AndroidManifest.xml b/suite/cts/deviceTests/browserbench/AndroidManifest.xml
deleted file mode 100644
index 4bf5b5e..0000000
--- a/suite/cts/deviceTests/browserbench/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.browser">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.browser" />
-</manifest>
diff --git a/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java b/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
deleted file mode 100644
index d74ddb2..0000000
--- a/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.browser;
-
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.cts.util.WatchDog;
-import android.net.Uri;
-import android.provider.Browser;
-import android.util.Log;
-import android.webkit.cts.CtsTestServer;
-
-import android.cts.util.CtsAndroidTestCase;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.Stat;
-import com.android.cts.util.TimeoutReq;
-
-import java.net.URLDecoder;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.RequestLine;
-/**
- * Browser benchmarking.
- * It launches an activity with URL and wait for POST from the client.
- */
-public class BrowserBenchTest extends CtsAndroidTestCase {
- private static final String TAG = BrowserBenchTest.class.getSimpleName();
- private static final boolean DEBUG = false;
- private static final String OCTANE_START_FILE = "octane/index.html";
- private static final String ROBOHORNET_START_FILE = "robohornet/robohornet.html";
- private static final String HOST_COMPLETION_BROADCAST = "com.android.cts.browser.completion";
- // time-out for watch-dog. POST should happen within this time.
- private static long BROWSER_POST_TIMEOUT_IN_MS = 10 * 60 * 1000L;
- // watch-dog will time-out first. So make it long enough.
- private static long BROWSER_COMPLETION_TIMEOUT_IN_MS = 60 * 60 * 1000L;
- private static final String HTTP_USER_AGENT = "User-Agent";
- private CtsTestServer mWebServer;
- // used for final score
- private ResultType mTypeNonFinal = ResultType.NEUTRAL;
- private ResultUnit mUnitNonFinal = ResultUnit.NONE;
- // used for all other scores
- private ResultType mTypeFinal = ResultType.NEUTRAL;
- private ResultUnit mUnitFinal = ResultUnit.SCORE;
- private WatchDog mWatchDog;
- private CountDownLatch mLatch;
- // can be changed by each test before starting
- private volatile int mNumberRepeat;
- /** tells how many tests have run up to now */
- private volatile int mRunIndex;
- /** stores results for each runs. last entry will be the final score. */
- private LinkedHashMap<String, double[]> mResultsMap;
- private PackageManager mPackageManager;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mPackageManager = getInstrumentation().getContext().getPackageManager();
- mWebServer = new CtsTestServer(getContext()) {
- @Override
- protected HttpResponse onPost(HttpRequest request) throws Exception {
- // post uri will look like "cts_report.html?final=1&score=10.1&message=hello"
- RequestLine requestLine = request.getRequestLine();
- String uriString = URLDecoder.decode(requestLine.getUri(), "UTF-8");
- if (DEBUG) {
- Log.i(TAG, "uri:" + uriString);
- }
- String resultRe =
- ".*cts_report.html\\?final=([\\d])&score=([\\d]+\\.?[\\d]*)&message=([\\w][\\w ]*)";
- Pattern resultPattern = Pattern.compile(resultRe);
- Matcher matchResult = resultPattern.matcher(uriString);
- if (matchResult.find()) {
- int isFinal = Integer.parseInt(matchResult.group(1));
- double score = Double.parseDouble(matchResult.group(2));
- String message = matchResult.group(3);
- Log.i(TAG, message + ":" + score);
- if (!mResultsMap.containsKey(message)) {
- mResultsMap.put(message, new double[mNumberRepeat]);
- }
- double[] scores = mResultsMap.get(message);
- scores[mRunIndex] = score;
- if (isFinal == 1) {
- String userAgent = request.getFirstHeader(HTTP_USER_AGENT).getValue();
- getReportLog().printValue(HTTP_USER_AGENT + "=" + userAgent, 0,
- ResultType.NEUTRAL, ResultUnit.NONE);
- mLatch.countDown();
- }
- mWatchDog.reset();
- }
- return null; // default response is OK as it will be ignored by client anyway.
- }
- };
- mResultsMap = new LinkedHashMap<String, double[]>();
- mWatchDog = new WatchDog(BROWSER_POST_TIMEOUT_IN_MS);
- mWatchDog.start();
- }
-
- @Override
- protected void tearDown() throws Exception {
- mWatchDog.stop();
- mWebServer.shutdown();
- mWebServer = null;
- mResultsMap = null;
- super.tearDown();
- }
-
- @TimeoutReq(minutes = 60)
- public void testOctane() throws InterruptedException {
- if (!isBrowserSupported()) {
- Log.i(TAG, "Skipping test for device with no supported browser");
- return;
- }
- String url = mWebServer.getAssetUrl(OCTANE_START_FILE) + "?auto=1";
- final int kRepeat = 5;
- doTest(url, ResultType.LOWER_BETTER, ResultUnit.MS,
- ResultType.HIGHER_BETTER, ResultUnit.SCORE, kRepeat);
- }
-
- private void doTest(String url, ResultType typeNonFinal, ResultUnit unitNonFinal,
- ResultType typeFinal, ResultUnit unitFinal, int numberRepeat)
- throws InterruptedException {
- mTypeNonFinal = typeNonFinal;
- mUnitNonFinal = unitNonFinal;
- mTypeFinal = typeFinal;
- mUnitFinal = unitFinal;
- mNumberRepeat = numberRepeat;
- Uri uri = Uri.parse(url);
- for (mRunIndex = 0; mRunIndex < numberRepeat; mRunIndex++) {
- Log.i(TAG, mRunIndex + "-th round");
- mLatch = new CountDownLatch(1);
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- // force using only one window or tab
- intent.putExtra(Browser.EXTRA_APPLICATION_ID, getContext().getPackageName());
- getContext().startActivity(intent);
- boolean ok = mLatch.await(BROWSER_COMPLETION_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS);
- assertTrue("timed-out", ok);
- }
- // it is somewhat awkward to handle the last one specially with Map
- int numberEntries = mResultsMap.size();
- int numberToProcess = 1;
- for (Map.Entry<String, double[]> entry : mResultsMap.entrySet()) {
- String message = entry.getKey();
- double[] scores = entry.getValue();
- if (numberToProcess == numberEntries) { // final score
- // store the whole results first
- getReportLog().printArray(message, scores, mTypeFinal, mUnitFinal);
- getReportLog().printSummary(message, Stat.getAverage(scores), mTypeFinal,
- mUnitFinal);
- } else { // interim results
- getReportLog().printArray(message, scores, mTypeNonFinal, mUnitNonFinal);
- }
- numberToProcess++;
- }
- }
-
- /**
- * @return true iff this device is has a working browser.
- */
- private boolean isBrowserSupported() {
- return !(mPackageManager.hasSystemFeature("android.hardware.type.television")
- || mPackageManager.hasSystemFeature("android.software.leanback")
- || mPackageManager.hasSystemFeature("android.hardware.type.watch"));
- }
-}
diff --git a/suite/cts/deviceTests/dram/Android.mk b/suite/cts/deviceTests/dram/Android.mk
deleted file mode 100644
index 879d151..0000000
--- a/suite/cts/deviceTests/dram/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# Include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_JNI_SHARED_LIBRARIES := libctsdram_jni
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceDram
-
-LOCAL_SDK_VERSION := 16
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/cts/deviceTests/dram/AndroidManifest.xml b/suite/cts/deviceTests/dram/AndroidManifest.xml
deleted file mode 100644
index c9aaf3d..0000000
--- a/suite/cts/deviceTests/dram/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.dram">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.dram"
- android:label="DRAM bandwidth measurement" />
-</manifest>
diff --git a/suite/cts/deviceTests/dram/jni/MemoryNativeJni.cpp b/suite/cts/deviceTests/dram/jni/MemoryNativeJni.cpp
deleted file mode 100644
index 7d9a5fc..0000000
--- a/suite/cts/deviceTests/dram/jni/MemoryNativeJni.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#include <jni.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-
-double currentTimeMillis()
-{
- struct timeval tv;
- gettimeofday(&tv, (struct timezone *) NULL);
- return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
-}
-
-extern "C" JNIEXPORT jdouble JNICALL Java_com_android_cts_dram_MemoryNative_runMemcpy(JNIEnv* env,
- jclass clazz, jint bufferSize, jint repetition)
-{
- char* src = new char[bufferSize];
- char* dst = new char[bufferSize];
- if ((src == NULL) || (dst == NULL)) {
- delete[] src;
- delete[] dst;
- env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "No memory");
- return -1;
- }
- memset(src, 0, bufferSize);
- memset(dst, 0, bufferSize);
- double start = currentTimeMillis();
- for (int i = 0; i < repetition; i++) {
- memcpy(dst, src, bufferSize);
- src[bufferSize - 1] = i & 0xff;
- }
- double end = currentTimeMillis();
- delete[] src;
- delete[] dst;
- return end - start;
-}
-
-extern "C" JNIEXPORT jdouble JNICALL Java_com_android_cts_dram_MemoryNative_runMemset(JNIEnv* env,
- jclass clazz, jint bufferSize, jint repetition, jint c)
-{
- char* dst = new char[bufferSize];
- if (dst == NULL) {
- delete[] dst;
- env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "No memory");
- return -1;
- }
- memset(dst, 0, bufferSize);
- double start = currentTimeMillis();
- for (int i = 0; i < repetition; i++) {
- memset(dst, (c + i) & 0xff, bufferSize);
- }
- double end = currentTimeMillis();
- delete[] dst;
- return end - start;
-}
-
diff --git a/suite/cts/deviceTests/dram/src/com/android/cts/dram/BandwidthTest.java b/suite/cts/deviceTests/dram/src/com/android/cts/dram/BandwidthTest.java
deleted file mode 100644
index eeb7f9b..0000000
--- a/suite/cts/deviceTests/dram/src/com/android/cts/dram/BandwidthTest.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.dram;
-
-import android.content.Context;
-import android.graphics.Point;
-import android.util.Log;
-import android.view.WindowManager;
-
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import android.cts.util.CtsAndroidTestCase;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.Stat;
-
-/**
- * check how many screens the memcpy function can copy in a sec.
- * Note that this does not represent the total memory bandwidth available in the system
- * as typically CPU cannot use the whole bandwidth.
- * Smaller buffers can fit into L1 or L2 cache, which can show big boost.
- */
-public class BandwidthTest extends CtsAndroidTestCase {
- private static final String TAG = BandwidthTest.class.getSimpleName();
- private static final int MEMCPY_REPETITION = 10;
- private static final int MEMSET_REPETITION = 30;
- private static final int REPEAT_IN_EACH_CALL = 100;
- private static final int KB = 1024;
- private static final int MB = 1024 * 1024;
- private static final int MEMSET_CHAR = 0xa5;
- // reject data outside +/- this value * median
- private static final double OUTLIER_THRESHOLD = 0.1;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // warm-up
- MemoryNative.runMemcpy(2 * MB, 100);
- }
-
- public void testMemcpyK004() {
- doRunMemcpy(4 * KB);
- }
-
- public void testMemcpyK008() {
- doRunMemcpy(8 * KB);
- }
-
- public void testMemcpyK016() {
- doRunMemcpy(16 * KB);
- }
-
- public void testMemcpyK032() {
- doRunMemcpy(32 * KB);
- }
-
- public void testMemcpyK064() {
- doRunMemcpy(64 * KB);
- }
-
- public void testMemcpyK128() {
- doRunMemcpy(128 * KB);
- }
-
- public void testMemcpyK256() {
- doRunMemcpy(256 * KB);
- }
-
- public void testMemcpyK512() {
- doRunMemcpy(512 * KB);
- }
-
- public void testMemcpyM001() {
- doRunMemcpy(1 * MB);
- }
-
- public void testMemcpyM002() {
- doRunMemcpy(2 * MB);
- }
-
- public void testMemcpyM004() {
- doRunMemcpy(4 * MB);
- }
-
- public void testMemcpyM008() {
- doRunMemcpy(8 * MB);
- }
-
- public void testMemcpyM016() {
- doRunMemcpy(16 * MB);
- }
-
- public void testMemsetK004() {
- doRunMemset(4 * KB);
- }
-
- public void testMemsetK008() {
- doRunMemset(8 * KB);
- }
-
- public void testMemsetK016() {
- doRunMemset(16 * KB);
- }
-
- public void testMemsetK032() {
- doRunMemset(32 * KB);
- }
-
- public void testMemsetK064() {
- doRunMemset(64 * KB);
- }
-
- public void testMemsetK128() {
- doRunMemset(128 * KB);
- }
-
- public void testMemsetK256() {
- doRunMemset(256 * KB);
- }
-
- public void testMemsetK512() {
- doRunMemset(512 * KB);
- }
-
- public void testMemsetM001() {
- doRunMemset(1 * MB);
- }
-
- public void testMemsetM002() {
- doRunMemset(2 * MB);
- }
-
- public void testMemsetM004() {
- doRunMemset(4 * MB);
- }
-
- public void testMemsetM008() {
- doRunMemset(8 * MB);
- }
-
- public void testMemsetM016() {
- doRunMemset(16 * MB);
- }
-
- private void doRunMemcpy(int bufferSize) {
- double[] result = new double[MEMCPY_REPETITION];
- int repeatInEachCall = REPEAT_IN_EACH_CALL;
- if (bufferSize < (1 * MB)) {
- // too small buffer size finishes too early to give accurate result.
- repeatInEachCall *= (1 * MB / bufferSize);
- }
- for (int i = 0; i < MEMCPY_REPETITION; i++) {
- result[i] = MemoryNative.runMemcpy(bufferSize, repeatInEachCall);
- }
- getReportLog().printArray("memcpy time", result, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- double[] mbps = ReportLog.calcRatePerSecArray(
- (double)bufferSize * repeatInEachCall / 1024.0 / 1024.0, result);
- getReportLog().printArray("memcpy throughput", mbps, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
- Stat.StatResult stat = Stat.getStatWithOutlierRejection(mbps, OUTLIER_THRESHOLD);
- if (stat.mDataCount != result.length) {
- Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
- }
- WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
- Point size = new Point();
- wm.getDefaultDisplay().getSize(size);
- Log.i(TAG, " x " + size.x + " y " + size.y);
- double pixels = size.x * size.y;
- // now this represents how many times the whole screen can be copied in a sec.
- double screensPerSecAverage = stat.mAverage / pixels * 1024.0 * 1024.0 / 4.0;
- getReportLog().printValue("memcpy in fps", screensPerSecAverage,
- ResultType.HIGHER_BETTER, ResultUnit.FPS);
- getReportLog().printSummary("memcpy throughput", stat.mAverage, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
- }
-
- private void doRunMemset(int bufferSize) {
- double[] result = new double[MEMSET_REPETITION];
- int repeatInEachCall = REPEAT_IN_EACH_CALL;
- if (bufferSize < (1 * MB)) {
- // too small buffer size finishes too early to give accurate result.
- repeatInEachCall *= (1 * MB / bufferSize);
- }
- for (int i = 0; i < MEMSET_REPETITION; i++) {
- result[i] = MemoryNative.runMemset(bufferSize, repeatInEachCall, MEMSET_CHAR);
- }
- getReportLog().printArray("memset time", result, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- double[] mbps = ReportLog.calcRatePerSecArray(
- (double)bufferSize * repeatInEachCall / 1024.0 / 1024.0, result);
- getReportLog().printArray("memset throughput", mbps, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
- Stat.StatResult stat = Stat.getStatWithOutlierRejection(mbps, OUTLIER_THRESHOLD);
- if (stat.mDataCount != result.length) {
- Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
- }
- WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
- Point size = new Point();
- wm.getDefaultDisplay().getSize(size);
- Log.i(TAG, " x " + size.x + " y " + size.y);
- double pixels = size.x * size.y;
- // now this represents how many times the whole screen can be copied in a sec.
- double screensPerSecAverage = stat.mAverage / pixels * 1024.0 * 1024.0 / 4.0;
- getReportLog().printValue("memset in fps", screensPerSecAverage,
- ResultType.HIGHER_BETTER, ResultUnit.FPS);
- getReportLog().printSummary("memset throughput", stat.mAverage, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
- }
-}
diff --git a/suite/cts/deviceTests/dram/src/com/android/cts/dram/MemoryNative.java b/suite/cts/deviceTests/dram/src/com/android/cts/dram/MemoryNative.java
deleted file mode 100644
index e55127d..0000000
--- a/suite/cts/deviceTests/dram/src/com/android/cts/dram/MemoryNative.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.dram;
-
-public class MemoryNative {
- static {
- System.loadLibrary("ctsdram_jni");
- }
- /**
- * run memcpy for given number of repetition from a source to a destination buffers
- * with each having the size of bufferSize.
- * @param bufferSize
- * @param repeatition
- * @return time spent in copying in ms.
- */
- public static native double runMemcpy(int bufferSize, int repetition);
-
- /**
- * run memset for given number of repetition from a source to a destination buffers
- * with each having the size of bufferSize.
- * @param bufferSize
- * @param repetition
- * @param c char to set. Only LSBs will be used to get char value.
- * @return time spent in memset in ms.
- */
- public static native double runMemset(int bufferSize, int repetition, int c);
-}
diff --git a/suite/cts/deviceTests/filesystemperf/Android.mk b/suite/cts/deviceTests/filesystemperf/Android.mk
deleted file mode 100644
index 7ee93de..0000000
--- a/suite/cts/deviceTests/filesystemperf/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceFilePerf
-
-LOCAL_SDK_VERSION := 16
-
-cts_runtime_hint := 28
-
-include $(BUILD_CTS_PACKAGE)
-
diff --git a/suite/cts/deviceTests/filesystemperf/AndroidManifest.xml b/suite/cts/deviceTests/filesystemperf/AndroidManifest.xml
deleted file mode 100644
index 329bf19..0000000
--- a/suite/cts/deviceTests/filesystemperf/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.filesystemperf">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.filesystemperf"
- android:label="UI Latency measurement" />
-</manifest>
diff --git a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/AlmostFullTest.java b/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/AlmostFullTest.java
deleted file mode 100644
index ab81f16..0000000
--- a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/AlmostFullTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.filesystemperf;
-
-import android.util.Log;
-
-import android.cts.util.CtsAndroidTestCase;
-import android.cts.util.SystemUtil;
-
-import com.android.cts.util.TimeoutReq;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class AlmostFullTest extends CtsAndroidTestCase {
-
- private static final String DIR_INITIAL_FILL = "INITIAL_FILL";
- private static final String DIR_SEQ_UPDATE = "SEQ_UPDATE";
- private static final String DIR_RANDOM_WR = "RANDOM_WR";
- private static final String DIR_RANDOM_RD = "RANDOM_RD";
- private static final String TAG = "AlmostFullTest";
-
- private static final long FREE_SPACE_FINAL = 1000L * 1024 * 1024L;
-
- // test runner creates multiple instances at the begging.
- // use that to fill disk only once.
- // set as final to initialize it only once
- private static final AtomicInteger mRefCounter = new AtomicInteger(0);
- private static final AtomicBoolean mDiskFilled = new AtomicBoolean(false);
-
- public AlmostFullTest() {
- int currentCounter = mRefCounter.incrementAndGet();
- Log.i(TAG, "++currentCounter: " + currentCounter);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- if (mDiskFilled.compareAndSet(false, true)) {
- Log.i(TAG, "Filling disk");
- // initial fill done in two stage as disk can be filled by other
- // components
- long freeDisk = SystemUtil.getFreeDiskSize(getContext());
- long diskToFill = freeDisk - FREE_SPACE_FINAL;
- if (diskToFill >= 0) {
- Log.i(TAG, "free disk " + freeDisk + ", to fill " + diskToFill);
- } else {
- Log.i(TAG, "free disk " + freeDisk + " too small, needs " + FREE_SPACE_FINAL);
- return;
- }
- final long MAX_FILE_SIZE_TO_FILL = 1024L * 1024L * 1024L;
- long filled = 0;
- while (filled < diskToFill) {
- long toFill = diskToFill - filled;
- if (toFill > MAX_FILE_SIZE_TO_FILL) {
- toFill = MAX_FILE_SIZE_TO_FILL;
- }
- Log.i(TAG, "Generating file " + toFill);
- FileUtil.createNewFilledFile(getContext(),
- DIR_INITIAL_FILL, toFill);
- filled += toFill;
- }
- }
- Log.i(TAG, "free disk " + SystemUtil.getFreeDiskSize(getContext()));
- }
-
- @Override
- protected void tearDown() throws Exception {
- Log.i(TAG, "tearDown free disk " + SystemUtil.getFreeDiskSize(getContext()));
- int currentCounter = mRefCounter.decrementAndGet();
- Log.i(TAG, "--currentCounter: " + currentCounter);
- if (currentCounter == 0) {
- FileUtil.removeFileOrDir(getContext(), DIR_INITIAL_FILL);
- }
- FileUtil.removeFileOrDir(getContext(), DIR_SEQ_UPDATE);
- FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_WR);
- FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_RD);
- Log.i(TAG, "tearDown free disk " + SystemUtil.getFreeDiskSize(getContext()));
- super.tearDown();
- }
-
- @TimeoutReq(minutes = 30)
- public void testSequentialUpdate() throws Exception {
- // now about freeSpaceToLeave should be left
- // and try updating exceeding the free space size
- final long FILE_SIZE = 400L * 1024L * 1024L;
- long freeDisk = SystemUtil.getFreeDiskSize(getContext());
- Log.i(TAG, "Now free space is " + freeDisk);
- if (freeDisk < FILE_SIZE) {
- Log.w(TAG, "too little space: " + freeDisk);
- return;
- }
- final int BUFFER_SIZE = 10 * 1024 * 1024;
- final int NUMBER_REPETITION = 10;
- FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, getReportLog(), FILE_SIZE,
- BUFFER_SIZE, NUMBER_REPETITION);
- }
-
- // TODO: file size too small and caching will give wrong better result.
- // needs to flush cache by reading big files per each read.
- @TimeoutReq(minutes = 60)
- public void testRandomRead() throws Exception {
- final int BUFFER_SIZE = 4 * 1024;
- final long fileSize = 400L * 1024L * 1024L;
- long freeDisk = SystemUtil.getFreeDiskSize(getContext());
- if (freeDisk < fileSize) {
- Log.w(TAG, "too little space: " + freeDisk);
- return;
- }
- FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, getReportLog(), fileSize,
- BUFFER_SIZE);
- }
-
- @TimeoutReq(minutes = 60)
- public void testRandomUpdate() throws Exception {
- final int BUFFER_SIZE = 4 * 1024;
- final long fileSize = 256L * 1024L * 1024L;
- long freeDisk = SystemUtil.getFreeDiskSize(getContext());
- if (freeDisk < fileSize) {
- Log.w(TAG, "too little space: " + freeDisk);
- return;
- }
- FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, getReportLog(), fileSize,
- BUFFER_SIZE);
- }
-}
diff --git a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/FileUtil.java b/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/FileUtil.java
deleted file mode 100755
index 6231774..0000000
--- a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/FileUtil.java
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.filesystemperf;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.RandomAccessFile;
-import java.util.Random;
-
-import com.android.cts.util.MeasureRun;
-import com.android.cts.util.MeasureTime;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.Stat;
-import android.cts.util.SystemUtil;
-
-import android.content.Context;
-import android.util.Log;
-
-public class FileUtil {
- private static final String TAG = "FileUtil";
- private static final Random mRandom = new Random(0);
- private static long mFileId = 0;
- /**
- * create array with different data per each call
- *
- * @param length
- * @param randomSeed
- * @return
- */
- public static byte[] generateRandomData(int length) {
- byte[] buffer = new byte[length];
- int val = mRandom.nextInt();
- for (int i = 0; i < length / 4; i++) {
- // in little-endian
- buffer[i * 4] = (byte)(val & 0x000000ff);
- buffer[i * 4 + 1] = (byte)((val & 0x0000ff00) >> 8);
- buffer[i * 4 + 2] = (byte)((val & 0x00ff0000) >> 16);
- buffer[i * 4 + 3] = (byte)((val & 0xff000000) >> 24);
- val++;
- }
- for (int i = (length / 4) * 4; i < length; i++) {
- buffer[i] = 0;
- }
- return buffer;
- }
-
- /**
- * create a new file under the given dirName.
- * Existing files will not be affected.
- * @param context
- * @param dirName
- * @return
- */
- public static File createNewFile(Context context, String dirName) {
- File topDir = new File(context.getFilesDir(), dirName);
- topDir.mkdir();
- String[] list = topDir.list();
-
- String newFileName;
- while (true) {
- newFileName = Long.toString(mFileId);
- boolean fileExist = false;
- for (String child : list) {
- if (child.equals(newFileName)) {
- fileExist = true;
- break;
- }
- }
- if (!fileExist) {
- break;
- }
- mFileId++;
- }
- mFileId++;
- //Log.i(TAG, "filename" + Long.toString(mFileId));
- return new File(topDir, newFileName);
- }
-
- /**
- * create multiple new files
- * @param context
- * @param dirName
- * @param count number of files to create
- * @return
- */
- public static File[] createNewFiles(Context context, String dirName, int count) {
- File[] files = new File[count];
- for (int i = 0; i < count; i++) {
- files[i] = createNewFile(context, dirName);
- }
- return files;
- }
-
- /**
- * write file with given byte array
- * @param file
- * @param data
- * @param append will append if set true. Otherwise, write from beginning
- * @throws IOException
- */
- public static void writeFile(File file, byte[] data, boolean append) throws IOException {
- final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
- if (append) {
- randomFile.seek(randomFile.length());
- } else {
- randomFile.seek(0L);
- }
- randomFile.write(data);
- randomFile.close();
- }
-
- /**
- * create a new file with given length.
- * @param context
- * @param dirName
- * @param length
- * @return
- * @throws IOException
- */
- public static File createNewFilledFile(Context context, String dirName, long length)
- throws IOException {
- final int BUFFER_SIZE = 10 * 1024 * 1024;
- File file = createNewFile(context, dirName);
- FileOutputStream out = new FileOutputStream(file);
- byte[] data = generateRandomData(BUFFER_SIZE);
- long written = 0;
- while (written < length) {
- out.write(data);
- written += BUFFER_SIZE;
- }
- out.flush();
- out.close();
- return file;
- }
-
- /**
- * remove given file or directory under the current app's files dir.
- * @param context
- * @param name
- */
- public static void removeFileOrDir(Context context, String name) {
- File entry = new File(context.getFilesDir(), name);
- if (entry.exists()) {
- removeEntry(entry);
- }
- }
-
- private static void removeEntry(File entry) {
- if (entry.isDirectory()) {
- String[] children = entry.list();
- for (String child : children) {
- removeEntry(new File(entry, child));
- }
- }
- Log.i(TAG, "delete file " + entry.getAbsolutePath());
- entry.delete();
- }
-
- /**
- * measure time taken for each IO run with amount R/W
- * @param count
- * @param run
- * @param readAmount returns amount of read in bytes for each interval.
- * Value will not be written if /proc/self/io does not exist.
- * @param writeAmount returns amount of write in bytes for each interval.
- * @return time per each interval
- * @throws IOException
- */
- public static double[] measureIO(int count, double[] readAmount, double[] writeAmount,
- MeasureRun run) throws Exception {
- double[] result = new double[count];
- File procIo = new File("/proc/self/io");
- boolean measureIo = procIo.exists() && procIo.canRead();
- long prev = System.currentTimeMillis();
- RWAmount prevAmount = new RWAmount();
- if (measureIo) {
- prevAmount = getRWAmount(procIo);
- }
- for (int i = 0; i < count; i++) {
- run.run(i);
- long current = System.currentTimeMillis();
- result[i] = current - prev;
- prev = current;
- if (measureIo) {
- RWAmount currentAmount = getRWAmount(procIo);
- readAmount[i] = currentAmount.mRd - prevAmount.mRd;
- writeAmount[i] = currentAmount.mWr - prevAmount.mWr;
- prevAmount = currentAmount;
- }
- }
- return result;
- }
-
- private static class RWAmount {
- public double mRd = 0.0;
- public double mWr = 0.0;
- };
-
- private static RWAmount getRWAmount(File file) throws IOException {
- RWAmount amount = new RWAmount();
-
- BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
- String line;
- while((line = br.readLine())!= null) {
- if (line.startsWith("read_bytes")) {
- amount.mRd = Double.parseDouble(line.split(" ")[1]);
- } else if (line.startsWith("write_bytes")) {
- amount.mWr = Double.parseDouble(line.split(" ")[1]);
- }
- }
- br.close();
- return amount;
- }
-
- /**
- * get file size exceeding total memory size ( 2x total memory).
- * The size is rounded in bufferSize. And the size will be bigger than 400MB.
- * @param context
- * @param bufferSize
- * @return file size or 0 if there is not enough space.
- */
- public static long getFileSizeExceedingMemory(Context context, int bufferSize) {
- long freeDisk = SystemUtil.getFreeDiskSize(context);
- long memSize = SystemUtil.getTotalMemory(context);
- long diskSizeTarget = (2 * memSize / bufferSize) * bufferSize;
- final long minimumDiskSize = (512L * 1024L * 1024L / bufferSize) * bufferSize;
- final long reservedDiskSize = (50L * 1024L * 1024L / bufferSize) * bufferSize;
- if ( diskSizeTarget < minimumDiskSize ) {
- diskSizeTarget = minimumDiskSize;
- }
- if (diskSizeTarget > freeDisk) {
- Log.i(TAG, "Free disk size " + freeDisk + " too small");
- return 0;
- }
- if ((freeDisk - diskSizeTarget) < reservedDiskSize) {
- diskSizeTarget -= reservedDiskSize;
- }
- return diskSizeTarget;
- }
-
- /**
- *
- * @param context
- * @param dirName
- * @param report
- * @param fileSize
- * @param bufferSize should be power of two
- * @throws IOException
- */
- public static void doRandomReadTest(Context context, String dirName, ReportLog report,
- long fileSize, int bufferSize) throws Exception {
- File file = FileUtil.createNewFilledFile(context,
- dirName, fileSize);
-
- final byte[] data = FileUtil.generateRandomData(bufferSize);
- Random random = new Random(0);
- final int totalReadCount = (int)(fileSize / bufferSize);
- final int[] readOffsets = new int[totalReadCount];
- for (int i = 0; i < totalReadCount; i++) {
- // align in buffer size
- readOffsets[i] = (int)(random.nextFloat() * (fileSize - bufferSize)) &
- ~(bufferSize - 1);
- }
- final int runsInOneGo = 16;
- final int readsInOneMeasure = totalReadCount / runsInOneGo;
-
- final RandomAccessFile randomFile = new RandomAccessFile(file, "rw"); // do not need O_SYNC
- double[] rdAmount = new double[runsInOneGo];
- double[] wrAmount = new double[runsInOneGo];
- double[] times = FileUtil.measureIO(runsInOneGo, rdAmount, wrAmount, new MeasureRun() {
-
- @Override
- public void run(int i) throws IOException {
- Log.i(TAG, "starting " + i + " -th round");
- int start = i * readsInOneMeasure;
- int end = (i + 1) * readsInOneMeasure;
- for (int j = start; j < end; j++) {
- randomFile.seek(readOffsets[j]);
- randomFile.read(data);
- }
- }
- });
- randomFile.close();
- double[] mbps = ReportLog.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
- times);
- report.printArray("read throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
- // This is just the amount of IO returned from kernel. So this is performance neutral.
- report.printArray("read amount", rdAmount, ResultType.NEUTRAL, ResultUnit.BYTE);
- Stat.StatResult stat = Stat.getStat(mbps);
-
- report.printSummary("read throughput", stat.mAverage, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
- }
-
- /**
- *
- * @param context
- * @param dirName
- * @param report
- * @param fileSize
- * @param bufferSize should be power of two
- * @throws IOException
- */
- public static void doRandomWriteTest(Context context, String dirName, ReportLog report,
- long fileSize, int bufferSize) throws Exception {
- File file = FileUtil.createNewFilledFile(context,
- dirName, fileSize);
- final byte[] data = FileUtil.generateRandomData(bufferSize);
- Random random = new Random(0);
- final int totalWriteCount = (int)(fileSize / bufferSize);
- final int[] writeOffsets = new int[totalWriteCount];
- for (int i = 0; i < totalWriteCount; i++) {
- writeOffsets[i] = (int)(random.nextFloat() * (fileSize - bufferSize)) &
- ~(bufferSize - 1);
- }
- final int runsInOneGo = 16;
- final int writesInOneMeasure = totalWriteCount / runsInOneGo;
-
- final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
- double[] rdAmount = new double[runsInOneGo];
- double[] wrAmount = new double[runsInOneGo];
- double[] times = FileUtil.measureIO(runsInOneGo, rdAmount, wrAmount, new MeasureRun() {
-
- @Override
- public void run(int i) throws IOException {
- Log.i(TAG, "starting " + i + " -th round");
- int start = i * writesInOneMeasure;
- int end = (i + 1) * writesInOneMeasure;
- for (int j = start; j < end; j++) {
- randomFile.seek(writeOffsets[j]);
- randomFile.write(data);
- }
- }
- });
- randomFile.close();
- double[] mbps = ReportLog.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
- times);
- report.printArray("write throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
- report.printArray("write amount", wrAmount, ResultType.NEUTRAL,
- ResultUnit.BYTE);
- Stat.StatResult stat = Stat.getStat(mbps);
-
- report.printSummary("write throughput", stat.mAverage, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
- }
-
- /**
- *
- * @param context
- * @param dirName
- * @param report
- * @param fileSize fileSize should be multiple of bufferSize.
- * @param bufferSize
- * @param numberRepetition
- * @throws IOException
- */
- public static void doSequentialUpdateTest(Context context, String dirName, ReportLog report,
- long fileSize, int bufferSize, int numberRepetition) throws Exception {
- File file = FileUtil.createNewFilledFile(context,
- dirName, fileSize);
- final byte[] data = FileUtil.generateRandomData(bufferSize);
- int numberRepeatInOneRun = (int)(fileSize / bufferSize);
- double[] mbpsAll = new double[numberRepetition * numberRepeatInOneRun];
- for (int i = 0; i < numberRepetition; i++) {
- Log.i(TAG, "starting " + i + " -th round");
- final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
- randomFile.seek(0L);
- double[] times = MeasureTime.measure(numberRepeatInOneRun, new MeasureRun() {
-
- @Override
- public void run(int i) throws IOException {
- randomFile.write(data);
- }
- });
- randomFile.close();
- double[] mbps = ReportLog.calcRatePerSecArray((double)bufferSize / 1024 / 1024,
- times);
- report.printArray(i + "-th round throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
- ReportLog.copyArray(mbps, mbpsAll, i * numberRepeatInOneRun);
- }
- Stat.StatResult stat = Stat.getStat(mbpsAll);
- report.printSummary("update throughput", stat.mAverage, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
- }
-}
diff --git a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/RandomRWTest.java b/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/RandomRWTest.java
deleted file mode 100644
index 6ad927b..0000000
--- a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/RandomRWTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.filesystemperf;
-
-import android.cts.util.CtsAndroidTestCase;
-import com.android.cts.util.TimeoutReq;
-
-public class RandomRWTest extends CtsAndroidTestCase {
- private static final String DIR_RANDOM_WR = "RANDOM_WR";
- private static final String DIR_RANDOM_RD = "RANDOM_RD";
-
- @Override
- protected void tearDown() throws Exception {
- FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_WR);
- FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_RD);
- super.tearDown();
- }
-
- @TimeoutReq(minutes = 60)
- public void testRandomRead() throws Exception {
- final int READ_BUFFER_SIZE = 4 * 1024;
- final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), READ_BUFFER_SIZE);
- if (fileSize == 0) { // not enough space, give up
- return;
- }
- FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, getReportLog(), fileSize,
- READ_BUFFER_SIZE);
- }
-
- // It is taking too long in some device, and thus cannot run multiple times
- @TimeoutReq(minutes = 60)
- public void testRandomUpdate() throws Exception {
- final int WRITE_BUFFER_SIZE = 4 * 1024;
- final long fileSize = 256 * 1024 * 1024;
- FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, getReportLog(), fileSize,
- WRITE_BUFFER_SIZE);
- }
-}
diff --git a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/SequentialRWTest.java b/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/SequentialRWTest.java
deleted file mode 100644
index d369ce8..0000000
--- a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/SequentialRWTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.filesystemperf;
-
-import android.cts.util.CtsAndroidTestCase;
-import com.android.cts.util.MeasureRun;
-import com.android.cts.util.MeasureTime;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.Stat;
-import com.android.cts.util.TimeoutReq;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-public class SequentialRWTest extends CtsAndroidTestCase {
- private static final String DIR_SEQ_WR = "SEQ_WR";
- private static final String DIR_SEQ_UPDATE = "SEQ_UPDATE";
- private static final String DIR_SEQ_RD = "SEQ_RD";
- private static final int BUFFER_SIZE = 10 * 1024 * 1024;
-
- @Override
- protected void tearDown() throws Exception {
- FileUtil.removeFileOrDir(getContext(), DIR_SEQ_WR);
- FileUtil.removeFileOrDir(getContext(), DIR_SEQ_UPDATE);
- FileUtil.removeFileOrDir(getContext(), DIR_SEQ_RD);
- super.tearDown();
- }
-
- @TimeoutReq(minutes = 30)
- public void testSingleSequentialWrite() throws Exception {
- final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
- if (fileSize == 0) { // not enough space, give up
- return;
- }
- final int numberOfFiles =(int)(fileSize / BUFFER_SIZE);
- getReportLog().printValue("files", numberOfFiles, ResultType.NEUTRAL,
- ResultUnit.COUNT);
- final byte[] data = FileUtil.generateRandomData(BUFFER_SIZE);
- final File[] files = FileUtil.createNewFiles(getContext(), DIR_SEQ_WR,
- numberOfFiles);
- double[] rdAmount = new double[numberOfFiles];
- double[] wrAmount = new double[numberOfFiles];
- double[] times = FileUtil.measureIO(numberOfFiles, rdAmount, wrAmount, new MeasureRun() {
-
- @Override
- public void run(int i) throws IOException {
- FileUtil.writeFile(files[i], data, false);
- }
- });
- double[] mbps = ReportLog.calcRatePerSecArray((double)BUFFER_SIZE / 1024 / 1024, times);
- getReportLog().printArray("write throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
- getReportLog().printArray("write amount", wrAmount, ResultType.NEUTRAL,
- ResultUnit.BYTE);
- Stat.StatResult stat = Stat.getStat(mbps);
- getReportLog().printSummary("write throughput", stat.mAverage, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
- }
-
- @TimeoutReq(minutes = 60)
- public void testSingleSequentialUpdate() throws Exception {
- final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
- if (fileSize == 0) { // not enough space, give up
- return;
- }
- final int NUMBER_REPETITION = 6;
- FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, getReportLog(), fileSize,
- BUFFER_SIZE, NUMBER_REPETITION);
- }
-
- @TimeoutReq(minutes = 30)
- public void testSingleSequentialRead() throws Exception {
- final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
- if (fileSize == 0) { // not enough space, give up
- return;
- }
- long start = System.currentTimeMillis();
- final File file = FileUtil.createNewFilledFile(getContext(),
- DIR_SEQ_RD, fileSize);
- long finish = System.currentTimeMillis();
- getReportLog().printValue("write throughput for test file of length " + fileSize,
- ReportLog.calcRatePerSec((double)fileSize / 1024 / 1024, finish - start),
- ResultType.HIGHER_BETTER, ResultUnit.MBPS);
-
- final int NUMBER_READ = 10;
-
- final byte[] data = new byte[BUFFER_SIZE];
- double[] times = MeasureTime.measure(NUMBER_READ, new MeasureRun() {
-
- @Override
- public void run(int i) throws IOException {
- final FileInputStream in = new FileInputStream(file);
- long read = 0;
- while (read < fileSize) {
- in.read(data);
- read += BUFFER_SIZE;
- }
- in.close();
- }
- });
- double[] mbps = ReportLog.calcRatePerSecArray((double)fileSize / 1024 / 1024, times);
- getReportLog().printArray("read throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
- Stat.StatResult stat = Stat.getStat(mbps);
- getReportLog().printSummary("read throughput", stat.mAverage, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
- }
-}
diff --git a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/TestTest.java b/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/TestTest.java
deleted file mode 100644
index 052c054..0000000
--- a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/TestTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-
-// code for testing, will be removed / moved before release
-
-package com.android.cts.filesystemperf;
-
-import android.cts.util.CtsAndroidTestCase;
-
-/**
- * This class is for testing CTS logging. Will be disabled in release.
- *
- */
-public class TestTest extends CtsAndroidTestCase {
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-/* code for testing CTS logging. Disabled.
- @TimeoutReq(minutes = 15)
- public void testPass() {
- double[] array = new double[] {1.0, 2.0, 3.0};
- getReportLog().printArray(" ", array, true);
- getReportLog().printArray(" ", array, false);
- getReportLog().printValue(" ", 1.0);
- getReportLog().printValue(" ", 2.0);
- getReportLog().printSummary("This should be shown", 0, 0);
- }
-
- @TimeoutReq(minutes = 10)
- public void testFail() throws Exception {
- getReportLog().printValue(" ", 1.0);
- getReportLog().printValue(" ", 2.0);
- getReportLog().printSummary("This should not be shown", 0, 0);
- throw new Exception("failed");
- }
-*/
-}
diff --git a/suite/cts/deviceTests/jank2/Android.mk b/suite/cts/deviceTests/jank2/Android.mk
deleted file mode 100644
index 346297e..0000000
--- a/suite/cts/deviceTests/jank2/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsJankTestCases
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ub-uiautomator ub-janktesthelper
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/suite/cts/deviceTests/jank2/AndroidManifest.xml b/suite/cts/deviceTests/jank2/AndroidManifest.xml
deleted file mode 100644
index a4c8337..0000000
--- a/suite/cts/deviceTests/jank2/AndroidManifest.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.cts.jank">
-
- <application>
- <uses-library android:name="android.test.runner"/>
- </application>
-
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.cts.jank"
- android:label="Jank tests">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
diff --git a/suite/cts/deviceTests/jank2/AndroidTest.xml b/suite/cts/deviceTests/jank2/AndroidTest.xml
deleted file mode 100644
index 2fbbac7..0000000
--- a/suite/cts/deviceTests/jank2/AndroidTest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?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.
--->
-<configuration description="CTS Jank test config">
- <include name="common-config" />
- <option name="cts-apk-installer:test-file-name" value="CtsDeviceUi.apk" />
-</configuration>
diff --git a/suite/cts/deviceTests/jank2/src/android/cts/jank/CtsJankTestBase.java b/suite/cts/deviceTests/jank2/src/android/cts/jank/CtsJankTestBase.java
deleted file mode 100644
index cb5c122..0000000
--- a/suite/cts/deviceTests/jank2/src/android/cts/jank/CtsJankTestBase.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank;
-
-import android.cts.util.DeviceReportLog;
-import android.os.Bundle;
-import android.support.test.jank.JankTestBase;
-import android.support.test.jank.WindowContentFrameStatsMonitor;
-import android.support.test.uiautomator.UiDevice;
-
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-
-public abstract class CtsJankTestBase extends JankTestBase {
-
- private UiDevice mDevice;
- private DeviceReportLog mLog;
-
- @Override
- public void afterTest(Bundle metrics) {
- String source = String.format("%s#%s", getClass().getCanonicalName(), getName());
- mLog.printValue(source, WindowContentFrameStatsMonitor.KEY_AVG_FPS,
- metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_FPS),
- ResultType.HIGHER_BETTER, ResultUnit.FPS);
- mLog.printValue(source, WindowContentFrameStatsMonitor.KEY_AVG_LONGEST_FRAME,
- metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_LONGEST_FRAME),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- mLog.printValue(source, WindowContentFrameStatsMonitor.KEY_MAX_NUM_JANKY,
- metrics.getInt(WindowContentFrameStatsMonitor.KEY_MAX_NUM_JANKY),
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- mLog.printSummary(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY,
- metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY),
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mLog = new DeviceReportLog();
- // fix device orientation
- mDevice = UiDevice.getInstance(getInstrumentation());
- mDevice.setOrientationNatural();
- }
-
- @Override
- protected void tearDown() throws Exception {
- mLog.deliverReportToHost(getInstrumentation());
- // restore device orientation
- mDevice.unfreezeRotation();
- super.tearDown();
- }
-
- protected UiDevice getUiDevice() {
- return mDevice;
- }
-}
diff --git a/suite/cts/deviceTests/jank2/src/android/cts/jank/ui/CtsDeviceJankUi.java b/suite/cts/deviceTests/jank2/src/android/cts/jank/ui/CtsDeviceJankUi.java
deleted file mode 100644
index 884f83c..0000000
--- a/suite/cts/deviceTests/jank2/src/android/cts/jank/ui/CtsDeviceJankUi.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank.ui;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.cts.jank.CtsJankTestBase;
-import android.os.SystemClock;
-import android.support.test.jank.JankTest;
-import android.support.test.jank.WindowContentFrameStatsMonitor;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.Direction;
-import android.support.test.uiautomator.Until;
-import android.widget.ListView;
-
-import java.io.IOException;
-
-public class CtsDeviceJankUi extends CtsJankTestBase {
- private final static int NUM_ELEMENTS = 1000;
- private static final long DEFAULT_ANIMATION_TIME = 2 * 1000;
- private static final long POST_SCROLL_IDLE_TIME = 2 *1000;
- private final static String PACKAGE = "com.android.cts.ui";
- private final static String CLASS = PACKAGE + ".ScrollingActivity";
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // launch the activity as part of the set up
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setComponent(new ComponentName(PACKAGE, CLASS));
- intent.putExtra("num_elements", NUM_ELEMENTS);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getInstrumentation().getTargetContext().startActivity(intent);
- getUiDevice().wait(Until.hasObject(By.pkg(PACKAGE)), DEFAULT_ANIMATION_TIME);
- }
-
- @Override
- protected void tearDown() throws Exception {
- getUiDevice().pressHome();
- super.tearDown();
- }
-
- @JankTest(expectedFrames=50, defaultIterationCount=5)
- @WindowContentFrameStatsMonitor
- public void testScrolling() throws IOException {
- getUiDevice().findObject(By.clazz(ListView.class)).fling(Direction.DOWN);
- SystemClock.sleep(POST_SCROLL_IDLE_TIME);
- }
-}
diff --git a/suite/cts/deviceTests/opengl/Android.mk b/suite/cts/deviceTests/opengl/Android.mk
deleted file mode 100644
index 0708efb..0000000
--- a/suite/cts/deviceTests/opengl/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# Include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_JNI_SHARED_LIBRARIES := libctsopengl_jni
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceOpenGl
-
-LOCAL_SDK_VERSION := 16
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/cts/deviceTests/opengl/AndroidManifest.xml b/suite/cts/deviceTests/opengl/AndroidManifest.xml
deleted file mode 100644
index 05fb5be..0000000
--- a/suite/cts/deviceTests/opengl/AndroidManifest.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.opengl"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="16"
- android:targetSdkVersion="17" />
-
- <uses-feature
- android:glEsVersion="0x00020000"
- android:required="true" />
-
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-
- <application android:allowBackup="false" >
- <uses-library android:name="android.test.runner" />
-
- <activity
- android:name=".primitive.GLPrimitiveActivity"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <activity
- android:name=".reference.GLReferenceActivity"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <activity
- android:name=".reference.GLGameActivity"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
- </activity>
- </application>
-
- <instrumentation
- android:name="android.support.test.runner.AndroidJUnitRunner"
- android:label="OpenGL ES 2.0 Benchmark"
- android:targetPackage="com.android.cts.opengl" />
-
-</manifest>
\ No newline at end of file
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/GLUtils.cpp b/suite/cts/deviceTests/opengl/jni/graphics/GLUtils.cpp
deleted file mode 100644
index ea166a1..0000000
--- a/suite/cts/deviceTests/opengl/jni/graphics/GLUtils.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "GLUtils.h"
-#include <stdlib.h>
-#include <sys/time.h>
-
-#include <android/asset_manager_jni.h>
-
-#define LOG_TAG "CTS_OPENGL"
-#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-static JNIEnv* sEnv = NULL;
-static jobject sAssetManager = NULL;
-
-void GLUtils::setEnvAndAssetManager(JNIEnv* env, jobject assetManager) {
- sEnv = env;
- sAssetManager = assetManager;
-}
-
-static AAsset* loadAsset(const char* path) {
- AAssetManager* nativeManager = AAssetManager_fromJava(sEnv, sAssetManager);
- if (nativeManager == NULL) {
- return NULL;
- }
- return AAssetManager_open(nativeManager, path, AASSET_MODE_UNKNOWN);;
-}
-
-char* GLUtils::openTextFile(const char* path) {
- AAsset* asset = loadAsset(path);
- if (asset == NULL) {
- ALOGE("Couldn't load %s", path);
- return NULL;
- }
- off_t length = AAsset_getLength(asset);
- char* buffer = new char[length + 1];
- int num = AAsset_read(asset, buffer, length);
- AAsset_close(asset);
- if (num != length) {
- ALOGE("Couldn't read %s", path);
- delete[] buffer;
- return NULL;
- }
- buffer[length] = '\0';
- return buffer;
-}
-
-GLuint GLUtils::loadTexture(const char* path) {
- GLuint textureId = 0;
- jclass activityClass = sEnv->FindClass("com/android/cts/opengl/reference/GLGameActivity");
- if (activityClass == NULL) {
- ALOGE("Couldn't find activity class");
- return -1;
- }
- jmethodID loadTexture = sEnv->GetStaticMethodID(activityClass, "loadTexture",
- "(Landroid/content/res/AssetManager;Ljava/lang/String;)I");
- if (loadTexture == NULL) {
- ALOGE("Couldn't find loadTexture method");
- return -1;
- }
- jstring pathStr = sEnv->NewStringUTF(path);
- textureId = sEnv->CallStaticIntMethod(activityClass, loadTexture, sAssetManager, pathStr);
- sEnv->DeleteLocalRef(pathStr);
- return textureId;
-}
-
-static int readInt(char* b) {
- unsigned char* ub = (unsigned char*) b;
- return (((int) ub[0]) << 24) | (((int) ub[1]) << 16) | (((int) ub[2]) << 8) | ((int) ub[3]);
-}
-
-static float readFloat(char* b) {
- union {
- int input;
- float output;
- } data;
- data.input = readInt(b);
- return data.output;
-}
-
-Mesh* GLUtils::loadMesh(const char* path) {
- char* buffer = openTextFile(path);
- if (buffer == NULL) {
- return NULL;
- }
- int index = 0;
- int numVertices = readInt(buffer + index);
- index += 4;
- float* vertices = new float[numVertices * 3];
- float* normals = new float[numVertices * 3];
- float* texCoords = new float[numVertices * 2];
- for (int i = 0; i < numVertices; i++) {
- // Vertices
- int vIndex = i * 3;
- vertices[vIndex + 0] = readFloat(buffer + index);
- index += 4;
- vertices[vIndex + 1] = readFloat(buffer + index);
- index += 4;
- vertices[vIndex + 2] = readFloat(buffer + index);
- index += 4;
- // Normals
- normals[vIndex + 0] = readFloat(buffer + index);
- index += 4;
- normals[vIndex + 1] = readFloat(buffer + index);
- index += 4;
- normals[vIndex + 2] = readFloat(buffer + index);
- index += 4;
- // Texture Coordinates
- int tIndex = i * 2;
- texCoords[tIndex + 0] = readFloat(buffer + index);
- index += 4;
- texCoords[tIndex + 1] = readFloat(buffer + index);
- index += 4;
- }
- return new Mesh(vertices, normals, texCoords, numVertices);
-}
-
-// Loads the given source code as a shader of the given type.
-static GLuint loadShader(GLenum shaderType, const char** source) {
- GLuint shader = glCreateShader(shaderType);
- if (shader) {
- glShaderSource(shader, 1, source, NULL);
- glCompileShader(shader);
- GLint compiled = 0;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- GLint infoLen = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
- if (infoLen > 0) {
- char* infoLog = (char*) malloc(sizeof(char) * infoLen);
- glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
- ALOGE("Error compiling shader:\n%s\n", infoLog);
- free(infoLog);
- }
- glDeleteShader(shader);
- shader = 0;
- }
- }
- return shader;
-}
-
-GLuint GLUtils::createProgram(const char** vertexSource, const char** fragmentSource) {
- GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource);
- if (!vertexShader) {
- return 0;
- }
-
- GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
- if (!fragmentShader) {
- return 0;
- }
-
- GLuint program = glCreateProgram();
- if (program) {
- glAttachShader(program, vertexShader);
- glAttachShader(program, fragmentShader);
-
- GLint linkStatus;
- glLinkProgram(program);
- glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
-
- if (!linkStatus) {
- GLint infoLen = 0;
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
- if (infoLen > 0) {
- char* infoLog = (char*) malloc(sizeof(char) * infoLen);
- glGetProgramInfoLog(program, infoLen, NULL, infoLog);
- ALOGE("Error linking program:\n%s\n", infoLog);
- free(infoLog);
- }
- glDeleteProgram(program);
- program = 0;
- }
- }
- return program;
-}
-
-double GLUtils::currentTimeMillis() {
- struct timeval tv;
- gettimeofday(&tv, (struct timezone *) NULL);
- return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
-}
-
-// Rounds a number up to the smallest power of 2 that is greater than or equal to x.
-int GLUtils::roundUpToSmallestPowerOf2(int x) {
- if (x < 0) {
- return 0;
- }
- --x;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
- return x + 1;
-}
-
-GLuint GLUtils::genTexture(int texWidth, int texHeight, int fill) {
- GLuint textureId = 0;
- int w = roundUpToSmallestPowerOf2(texWidth);
- int h = roundUpToSmallestPowerOf2(texHeight);
- uint32_t* m = new uint32_t[w * h];
- if (m != NULL) {
- uint32_t* d = m;
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- if (fill == RANDOM_FILL) {
- *d = 0xff000000 | ((y & 0xff) << 16) | ((x & 0xff) << 8) | ((x + y) & 0xff);
- } else {
- *d = 0xff000000 | fill;
- }
- d++;
- }
- }
- glGenTextures(1, &textureId);
- glBindTexture(GL_TEXTURE_2D, textureId);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, m);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- delete[] m;
- return textureId;
-}
diff --git a/suite/cts/deviceTests/opengl/jni/primitive/GLPrimitive.cpp b/suite/cts/deviceTests/opengl/jni/primitive/GLPrimitive.cpp
deleted file mode 100644
index 856da1e..0000000
--- a/suite/cts/deviceTests/opengl/jni/primitive/GLPrimitive.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-#include <jni.h>
-
-#include <stdlib.h>
-
-#include <android/native_window.h>
-#include <android/native_window_jni.h>
-
-#include <graphics/GLUtils.h>
-#include <graphics/Renderer.h>
-
-#include "fullpipeline/FullPipelineRenderer.h"
-#include "pixeloutput/PixelOutputRenderer.h"
-#include "shaderperf/ShaderPerfRenderer.h"
-#include "contextswitch/ContextSwitchRenderer.h"
-
-// Holds the current benchmark's renderer.
-Renderer* gRenderer = NULL;
-ANativeWindow* gNativeWindow = NULL;
-
-enum {
- FULL_PIPELINE_BENCHMARK = 0,
- PIXEL_OUTPUT_BENCHMARK = 1,
- SHADER_PERF_BENCHMARK = 2,
- CONTEXT_SWITCH_BENCHMARK = 3
-};
-
-extern "C" JNIEXPORT jboolean JNICALL
-Java_com_android_cts_opengl_primitive_GLPrimitiveActivity_startBenchmark(
- JNIEnv* env, jclass /*clazz*/, jint workload, jint numFrames, jdoubleArray frameTimes) {
- if (gRenderer == NULL) {
- return false;
- }
-
- // Sets up the renderer.
- bool success = gRenderer->setUp(workload);
-
- // Records the start time.
- double start = GLUtils::currentTimeMillis();
-
- // Offscreen renders 100 tiles per frame so reduce the number of frames to render.
- if (gRenderer->mOffscreen) {
- numFrames /= Renderer::OFFSCREEN_INNER_FRAMES;
- }
-
- // Draw off the screen.
- for (int i = 0; i < numFrames && success; i++) {
- // Draw a frame.
- success = gRenderer->draw();
- }
-
- // Records the end time.
- double end = GLUtils::currentTimeMillis();
-
- // Sets the times in the Java array.
- double times[] = {start, end};
- env->SetDoubleArrayRegion(frameTimes, 0, 2, times);
-
- success = gRenderer->tearDown() && success;
- return success;
-}
-
-// The following functions create the renderers for the various benchmarks.
-extern "C" JNIEXPORT void JNICALL
-Java_com_android_cts_opengl_primitive_GLPrimitiveActivity_setupBenchmark(
- JNIEnv* env, jclass /*clazz*/, jobject surface, jint benchmark,
- jboolean offscreen) {
- gNativeWindow = ANativeWindow_fromSurface(env, surface);
- switch (benchmark) {
- case FULL_PIPELINE_BENCHMARK:
- gRenderer = new FullPipelineRenderer(gNativeWindow, offscreen);
- break;
- case PIXEL_OUTPUT_BENCHMARK:
- gRenderer = new PixelOutputRenderer(gNativeWindow, offscreen);
- break;
- case SHADER_PERF_BENCHMARK:
- gRenderer = new ShaderPerfRenderer(gNativeWindow, offscreen);
- break;
- case CONTEXT_SWITCH_BENCHMARK:
- gRenderer = new ContextSwitchRenderer(gNativeWindow, offscreen);
- break;
- default:
- ALOGE("Unknown benchmark '%d'", benchmark);
- ANativeWindow_release(gNativeWindow);
- gNativeWindow = NULL;
- return;
- }
-
- // Set up call will log error conditions
- if (!gRenderer->eglSetUp()) {
- delete gRenderer;
- gRenderer = NULL;
-
- ANativeWindow_release(gNativeWindow);
- gNativeWindow = NULL;
- }
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_com_android_cts_opengl_primitive_GLPrimitiveActivity_tearDownBenchmark(
- JNIEnv* /*env*/, jclass /*clazz*/) {
- if (gRenderer == NULL) {
- return;
- }
- gRenderer->eglTearDown();
- delete gRenderer;
- gRenderer = NULL;
-
- ANativeWindow_release(gNativeWindow);
- gNativeWindow = NULL;
-}
diff --git a/suite/cts/deviceTests/opengl/jni/reference/GLReference.cpp b/suite/cts/deviceTests/opengl/jni/reference/GLReference.cpp
deleted file mode 100644
index dc0b4e2..0000000
--- a/suite/cts/deviceTests/opengl/jni/reference/GLReference.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-#include <jni.h>
-
-#include <android/native_window.h>
-#include <android/native_window_jni.h>
-
-#include <graphics/GLUtils.h>
-#include <graphics/Renderer.h>
-
-#include "ReferenceRenderer.h"
-
-extern "C" JNIEXPORT jboolean JNICALL
-Java_com_android_cts_opengl_reference_GLGameActivity_startBenchmark(
- JNIEnv* env, jclass /*clazz*/, jobject assetManager, jobject surface, jint numFrames,
- jdoubleArray setUpTimes, jdoubleArray updateTimes, jdoubleArray renderTimes) {
-
- GLUtils::setEnvAndAssetManager(env, assetManager);
-
- if (numFrames > (ReferenceRenderer::FRAMES_PER_SCENE * ReferenceRenderer::NUM_SCENES)) {
- return false;
- }
-
- ANativeWindow* nativeWindow = ANativeWindow_fromSurface(env, surface);
- ReferenceRenderer* renderer = new ReferenceRenderer(nativeWindow);
- bool success = renderer->eglSetUp();
- success = renderer->setUp(0) && success;
- env->SetDoubleArrayRegion(
- setUpTimes, 0, ReferenceRenderer::NUM_SETUP_TIMES, renderer->mSetUpTimes);
-
- double updates[numFrames];
- double renders[numFrames];
- for (int i = 0; i < numFrames && success; i++) {
- double t0 = GLUtils::currentTimeMillis();
- success = renderer->update(i);
- double t1 = GLUtils::currentTimeMillis();
- success = success && renderer->draw();
- double t2 = GLUtils::currentTimeMillis();
- updates[i] = t1 - t0;
- renders[i] = t2 - t1;
- }
-
- env->SetDoubleArrayRegion(updateTimes, 0, numFrames, updates);
- env->SetDoubleArrayRegion(renderTimes, 0, numFrames, renders);
-
- success = renderer->tearDown() && success;
- renderer->eglTearDown();
- delete renderer;
- renderer = NULL;
-
- ANativeWindow_release(nativeWindow);
-
- return success;
-}
diff --git a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/GLActivityIntentKeys.java b/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/GLActivityIntentKeys.java
deleted file mode 100644
index 9a29caf..0000000
--- a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/GLActivityIntentKeys.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.opengl;
-
-public class GLActivityIntentKeys {
- /**
- * Holds the name of the benchmark to run.
- */
- public final static String INTENT_EXTRA_BENCHMARK_NAME = "benchmark_name";
- /**
- * Holds whether or not the benchmark is to be run offscreen.
- */
- public final static String INTENT_EXTRA_OFFSCREEN = "offscreen";
- /**
- * The number of frames to render for each workload.
- */
- public final static String INTENT_EXTRA_NUM_FRAMES = "num_frames";
- /**
- * The number of iterations to run, the workload increases with each iteration.
- */
- public final static String INTENT_EXTRA_NUM_ITERATIONS = "num_iterations";
- /**
- * The number of milliseconds to wait before timing out.
- */
- public final static String INTENT_EXTRA_TIMEOUT = "timeout";
-}
diff --git a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/BenchmarkName.java b/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/BenchmarkName.java
deleted file mode 100644
index a6bd6db..0000000
--- a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/BenchmarkName.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.opengl.primitive;
-
-/**
- * Represents the different primitive benchmarks.
- */
-public enum BenchmarkName {
- FullPipeline,
- PixelOutput,
- ShaderPerf,
- ContextSwitch;
-}
diff --git a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveActivity.java b/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveActivity.java
deleted file mode 100644
index 6defdb7..0000000
--- a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveActivity.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.opengl.primitive;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.cts.util.WatchDog;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.Surface;
-
-import com.android.cts.opengl.GLActivityIntentKeys;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Semaphore;
-
-public class GLPrimitiveActivity extends Activity {
-
- public final static String TAG = "GLPrimitiveActivity";
-
- private volatile Exception mException;
- private volatile Surface mSurface = null;
- private CountDownLatch mStartSignal = new CountDownLatch(1);
- private Semaphore mSemaphore = new Semaphore(0);
-
- private BenchmarkName mBenchmark;
- private boolean mOffscreen;
- private int mNumFrames;
- private int mNumIterations;
- private int mTimeout;
- public double[] mFpsValues;
-
- @Override
- public void onCreate(Bundle data) {
- super.onCreate(data);
- System.loadLibrary("ctsopengl_jni");
- Intent intent = getIntent();
- mBenchmark = BenchmarkName.valueOf(
- intent.getStringExtra(GLActivityIntentKeys.INTENT_EXTRA_BENCHMARK_NAME));
- mOffscreen = intent.getBooleanExtra(GLActivityIntentKeys.INTENT_EXTRA_OFFSCREEN, false);
- mNumFrames = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, 0);
- mNumIterations = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_ITERATIONS, 0);
- mTimeout = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, 0);
- mFpsValues = new double[mNumIterations];
-
- Log.i(TAG, "Benchmark: " + mBenchmark);
- Log.i(TAG, "Offscreen: " + mOffscreen);
- Log.i(TAG, "Num Frames: " + mNumFrames);
- Log.i(TAG, "Num Iterations: " + mNumIterations);
- Log.i(TAG, "Time Out: " + mTimeout);
-
- SurfaceView surfaceView = new SurfaceView(this);
- surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- mSurface = holder.getSurface();
- mStartSignal.countDown();
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {}
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {}
- });
- setContentView(surfaceView);
- // Spawns a worker to run the benchmark.
- Worker worker = new Worker();
- worker.start();
- }
-
- public void waitForCompletion() throws Exception {
- // Wait for semiphore.
- mSemaphore.acquire();
- if (mException != null) {
- throw mException;
- }
- }
-
- private void complete() {
- // Release semiphore.
- mSemaphore.release();
- finish();
- }
-
- private synchronized void setException(Exception e) {
- if (mException == null) {
- mException = e;
- }
- }
-
- private static native boolean setupBenchmark(
- Surface surface, int benchmark, boolean offscreen);
-
- private static native boolean startBenchmark(int workload, int numFrames, double[] frameTimes);
-
- private static native void tearDownBenchmark();
-
- /**
- * This thread runs the benchmarks, freeing the UI thread.
- */
- private class Worker extends Thread implements WatchDog.TimeoutCallback {
-
- private WatchDog watchDog;
- private volatile boolean success = true;
-
- @Override
- public void run() {
- try {
- mStartSignal.await();
- } catch (InterruptedException e) {
- setException(e);
- complete();
- return;
- }
- Log.i(TAG, mBenchmark + " Benchmark Started");
- // Creates a watchdog to ensure a iteration doesn't exceed the timeout.
- watchDog = new WatchDog(mTimeout, this);
- // Used to record the start and end time of the iteration.
- double[] times = new double[2];
- try {
- // Setup the benchmark.
- setupBenchmark(mSurface, mBenchmark.ordinal(), mOffscreen);
- for (int i = 0; i < mNumIterations && success; i++) {
- // The workload to use for this iteration.
- int workload = i + 1;
- watchDog.start();
- // Start benchmark.
- success = startBenchmark(workload, mNumFrames, times);
- watchDog.stop();
- if (!success) {
- setException(new Exception("Benchmark failed to run"));
- } else {
- // Calculate FPS.
- mFpsValues[i] = mNumFrames * 1000.0f / (times[1] - times[0]);
- }
- }
- }
- finally
- {
- tearDownBenchmark();
- }
-
- complete();
- Log.i(TAG, mBenchmark + " Benchmark Completed");
- }
-
- public void onTimeout() {
- setException(new Exception("Benchmark timed out"));
- complete();
- }
-
- }
-}
diff --git a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveBenchmark.java b/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveBenchmark.java
deleted file mode 100644
index c177129..0000000
--- a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveBenchmark.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.opengl.primitive;
-
-import com.android.cts.opengl.GLActivityIntentKeys;
-import android.cts.util.CtsActivityInstrumentationTestCase2;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-
-import android.content.Intent;
-import com.android.cts.util.TimeoutReq;
-
-/**
- * Runs the Primitive OpenGL ES 2.0 Benchmarks.
- */
-public class GLPrimitiveBenchmark extends CtsActivityInstrumentationTestCase2<GLPrimitiveActivity> {
-
- private static final int NUM_FRAMES = 100;
- private static final int NUM_ITERATIONS = 8;
- private static final int TIMEOUT = 1000000;
-
- public GLPrimitiveBenchmark() {
- super(GLPrimitiveActivity.class);
- }
-
- /**
- * Runs the full OpenGL ES 2.0 pipeline test offscreen.
- */
- @TimeoutReq(minutes = 100)
- public void testFullPipelineOffscreen() throws Exception {
- runBenchmark(BenchmarkName.FullPipeline, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
- }
-
- /**
- * Runs the full OpenGL ES 2.0 pipeline test onscreen.
- */
- @TimeoutReq(minutes = 100)
- public void testFullPipelineOnscreen() throws Exception {
- runBenchmark(BenchmarkName.FullPipeline, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
- }
-
- /**
- * Runs the pixel output test offscreen.
- */
- @TimeoutReq(minutes = 100)
- public void testPixelOutputOffscreen() throws Exception {
- runBenchmark(BenchmarkName.PixelOutput, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
- }
-
- /**
- * Runs the pixel output test onscreen.
- */
- @TimeoutReq(minutes = 100)
- public void testPixelOutputOnscreen() throws Exception {
- runBenchmark(BenchmarkName.PixelOutput, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
- }
-
- /**
- * Runs the shader performance test offscreen.
- */
- @TimeoutReq(minutes = 100)
- public void testShaderPerfOffscreen() throws Exception {
- runBenchmark(BenchmarkName.ShaderPerf, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
- }
-
- /**
- * Runs the shader performance test onscreen.
- */
- @TimeoutReq(minutes = 100)
- public void testShaderPerfOnscreen() throws Exception {
- runBenchmark(BenchmarkName.ShaderPerf, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
- }
-
- /**
- * Runs the context switch overhead test offscreen.
- */
- @TimeoutReq(minutes = 100)
- public void testContextSwitchOffscreen() throws Exception {
- runBenchmark(BenchmarkName.ContextSwitch, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
- }
-
- /**
- * Runs the context switch overhead test onscreen.
- */
- @TimeoutReq(minutes = 100)
- public void testContextSwitchOnscreen() throws Exception {
- runBenchmark(BenchmarkName.ContextSwitch, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
- }
-
- /**
- * Runs the specified test.
- *
- * @param benchmark An enum representing the benchmark to run.
- * @param offscreen Whether to render to an offscreen framebuffer rather than the screen.
- * @param numFrames The number of frames to render.
- * @param numIterations The number of iterations to run, each iteration has a bigger workload.
- * @param timeout The milliseconds to wait for an iteration of the benchmark before timing out.
- * @throws Exception If the benchmark could not be run.
- */
- private void runBenchmark(BenchmarkName benchmark, boolean offscreen, int numFrames,
- int numIterations, int timeout) throws Exception {
- String benchmarkName = benchmark.toString();
- Intent intent = new Intent();
- intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_BENCHMARK_NAME, benchmarkName);
- intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_OFFSCREEN, offscreen);
- intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, numFrames);
- intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_ITERATIONS, numIterations);
- intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, timeout);
-
- setActivityIntent(intent);
- GLPrimitiveActivity activity = getActivity();
- if (activity != null) {
- activity.waitForCompletion();
- double[] fpsValues = activity.mFpsValues;
- double score = 0;
- for (double d : fpsValues) {
- score += d;
- }
- score /= numIterations;// Average.
-
- // TODO: maybe standard deviation / RMSE will be useful?
-
- getReportLog().printArray(
- "Fps Values", fpsValues, ResultType.HIGHER_BETTER, ResultUnit.FPS);
- getReportLog().printSummary(
- "Average Frames Per Second", score, ResultType.HIGHER_BETTER,
- ResultUnit.SCORE);
- }
- }
-}
diff --git a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/reference/GLGameActivity.java b/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/reference/GLGameActivity.java
deleted file mode 100644
index 3b310f9..0000000
--- a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/reference/GLGameActivity.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.opengl.reference;
-
-import com.android.cts.opengl.GLActivityIntentKeys;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.res.AssetManager;
-import android.cts.util.WatchDog;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.opengl.GLES20;
-import android.opengl.GLUtils;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.concurrent.CountDownLatch;
-
-public class GLGameActivity extends Activity {
-
- public final static String SET_UP_TIME = "set_up_time";
- public final static String UPDATE_TIMES = "update_times";
- public final static String RENDER_TIMES = "render_times";
-
- private int mNumFrames;
- private int mTimeout;
- private double[] mSetUpTimes;
- private double[] mUpdateTimes;
- private double[] mRenderTimes;
- private volatile Surface mSurface = null;
- private CountDownLatch mStartSignal = new CountDownLatch(1);
-
- @Override
- public void onCreate(Bundle data) {
- super.onCreate(data);
- System.loadLibrary("ctsopengl_jni");
-
- Intent intent = getIntent();
- mNumFrames = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, 1000);
- mTimeout = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, 1000000);
-
- SurfaceView surfaceView = new SurfaceView(this);
- surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- mSurface = holder.getSurface();
- mStartSignal.countDown();
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {}
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {}
- });
- setContentView(surfaceView);
-
- // Spawns a worker.
- Worker worker = new Worker(new Handler() {
- public void handleMessage(Message msg) {
- Intent intent = new Intent();
- intent.putExtra(SET_UP_TIME, mSetUpTimes);
- intent.putExtra(UPDATE_TIMES, mUpdateTimes);
- intent.putExtra(RENDER_TIMES, mRenderTimes);
- setResult((msg.what == 1) ? RESULT_OK : RESULT_CANCELED, intent);
- finish();
- }
- });
- worker.start();
- }
-
- private static native boolean startBenchmark(AssetManager manager,
- Surface surface,
- int numFrames,
- double[] setUpTimes,
- double[] updateTimes,
- double[] renderTimes);
-
- /**
- * This thread renderers the benchmarks, freeing the UI thread.
- */
- private class Worker extends Thread implements WatchDog.TimeoutCallback {
-
- private WatchDog watchDog;
- private Handler mHandler;
-
- public Worker(Handler handler) {
- mHandler = handler;
- }
-
- @Override
- public void run() {
- try {
- mStartSignal.await();
- } catch (InterruptedException e) {
- mHandler.sendEmptyMessage(0);
- return;
- }
- // Creates a watchdog to ensure a iteration doesn't exceed the timeout.
- watchDog = new WatchDog(mTimeout, this);
- watchDog.start();
-
- // Used to record the time taken to setup (GL, context, textures, meshes).
- mSetUpTimes = new double[4];
- // Used to record the times taken to update.
- mUpdateTimes = new double[mNumFrames];
- // Used to record the times taken to render.
- mRenderTimes = new double[mNumFrames];
- boolean success = startBenchmark(getAssets(),
- mSurface,
- mNumFrames,
- mSetUpTimes,
- mUpdateTimes,
- mRenderTimes);
-
- watchDog.stop();
- mHandler.sendEmptyMessage((success) ? 1 : 0);
- }
-
- public void onTimeout() {
- mHandler.sendEmptyMessage(0);
- }
-
- }
-
- public static int loadTexture(AssetManager manager, String path) {
- InputStream in = null;
- try {
- in = manager.open(path);
- } catch (IOException e) {
- e.printStackTrace();
- return -1;
- }
- BitmapFactory.Options op = new BitmapFactory.Options();
- op.inPreferredConfig = Bitmap.Config.ARGB_8888;
- Bitmap bmp = BitmapFactory.decodeStream(in, null, op);
- // generate textureID
- int[] textures = new int[1];
- GLES20.glGenTextures(1, textures, 0);
- int textureID = textures[0];
-
- // create texture
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
- GLES20.glTexParameteri(
- GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
- GLES20.glTexParameteri(
- GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
- GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
- GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
- GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
-
- // clean up
- try {
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- bmp.recycle();
- }
- return textureID;
- }
-}
diff --git a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/reference/GLReferenceActivity.java b/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/reference/GLReferenceActivity.java
deleted file mode 100644
index 8d34535..0000000
--- a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/reference/GLReferenceActivity.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.opengl.reference;
-
-import com.android.cts.opengl.GLActivityIntentKeys;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-
-import java.util.concurrent.Semaphore;
-
-public class GLReferenceActivity extends Activity {
-
- private final static int GAME_ACTIVITY_CODE = 1;
-
- private volatile Exception mException;
- private int mNumFrames;
- private int mTimeout;
-
- public double[] mSetUpTimes;
- public double[] mUpdateTimes;
- public double[] mRenderTimes;
-
- private Semaphore mSemaphore = new Semaphore(0);
-
- @Override
- public void onCreate(Bundle data) {
- super.onCreate(data);
- Intent intent = getIntent();
- mNumFrames = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, 0);
- mTimeout = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, 0);
-
- // Start benchmark
- intent = new Intent(this, GLGameActivity.class);
- intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, mNumFrames);
- intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, mTimeout);
- startActivityForResult(intent, GAME_ACTIVITY_CODE);
- }
-
- public void waitForCompletion() throws Exception {
- // Wait for semiphore.
- mSemaphore.acquire();
- if (mException != null) {
- throw mException;
- }
- }
-
- private synchronized void setException(Exception e) {
- if (mException == null) {
- mException = e;
- }
- }
-
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == GAME_ACTIVITY_CODE) {
- if (resultCode == RESULT_OK) {
- // Benchmark passed
- mSetUpTimes = data.getDoubleArrayExtra(GLGameActivity.SET_UP_TIME);
- mUpdateTimes = data.getDoubleArrayExtra(GLGameActivity.UPDATE_TIMES);
- mRenderTimes = data.getDoubleArrayExtra(GLGameActivity.RENDER_TIMES);
- } else {
- setException(new Exception("Benchmark failed to run"));
- }
- // Release semiphore.
- mSemaphore.release();
- finish();
- }
- }
-
-}
diff --git a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/reference/GLReferenceBenchmark.java b/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/reference/GLReferenceBenchmark.java
deleted file mode 100644
index fdea916..0000000
--- a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/reference/GLReferenceBenchmark.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.opengl.reference;
-
-import com.android.cts.opengl.GLActivityIntentKeys;
-
-import android.cts.util.CtsActivityInstrumentationTestCase2;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.TimeoutReq;
-
-import android.content.Intent;
-
-/**
- * Runs the Reference OpenGL ES 2.0 Benchmark.
- */
-public class GLReferenceBenchmark extends CtsActivityInstrumentationTestCase2<GLReferenceActivity> {
-
- private static final int NUM_FRAMES_PER_SCENE = 500;
- private static final int NUM_SCENES = 2;
- private static final int NUM_FRAMES = NUM_FRAMES_PER_SCENE * NUM_SCENES;
- private static final int TIMEOUT = 1000000;
-
- public GLReferenceBenchmark() {
- super(GLReferenceActivity.class);
- }
-
- /**
- * Runs the reference benchmark.
- */
- @TimeoutReq(minutes = 30)
- public void testReferenceBenchmark() throws Exception {
- Intent intent = new Intent();
- intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, NUM_FRAMES);
- intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, TIMEOUT);
-
- GLReferenceActivity activity = null;
- setActivityIntent(intent);
- activity = getActivity();
- if (activity != null) {
- activity.waitForCompletion();
- double totalTime = 0;
- double[] setUpTimes = activity.mSetUpTimes;
- double[] updateTimes = activity.mUpdateTimes;
- double[] renderTimes = activity.mRenderTimes;
-
- // Calculate update and render average.
- double updateSum = updateTimes[0];
- double renderSum = renderTimes[0];
- for (int i = 0; i < NUM_FRAMES - 1; i++) {
- updateSum += updateTimes[i + 1];
- renderSum += renderTimes[i + 1];
- }
- double updateAverage = updateSum / NUM_FRAMES;
- double renderAverage = renderSum / NUM_FRAMES;
-
- getReportLog().printArray(
- "Set Up Times", setUpTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- getReportLog().printArray(
- "Update Times", updateTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- getReportLog().printValue(
- "Update Time Average", updateAverage, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- getReportLog().printArray(
- "Render Times", renderTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- getReportLog().printValue(
- "Render Time Average", renderAverage, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- totalTime = setUpTimes[0] + setUpTimes[1] + setUpTimes[2] +
- setUpTimes[3] + updateAverage + renderAverage;
- getReportLog().printSummary(
- "Total Time", totalTime, ResultType.LOWER_BETTER, ResultUnit.MS);
- }
- }
-}
diff --git a/suite/cts/deviceTests/simplecpu/Android.mk b/suite/cts/deviceTests/simplecpu/Android.mk
deleted file mode 100644
index 17e7506..0000000
--- a/suite/cts/deviceTests/simplecpu/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# Include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_JNI_SHARED_LIBRARIES := libctscpu_jni
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceSimpleCpu
-
-LOCAL_SDK_VERSION := 16
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/cts/deviceTests/simplecpu/AndroidManifest.xml b/suite/cts/deviceTests/simplecpu/AndroidManifest.xml
deleted file mode 100644
index e5c1c2b..0000000
--- a/suite/cts/deviceTests/simplecpu/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.simplecpu">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.simplecpu"
- android:label="Very simple CPU benchmarking" />
-</manifest>
diff --git a/suite/cts/deviceTests/simplecpu/jni/CpuNativeJni.cpp b/suite/cts/deviceTests/simplecpu/jni/CpuNativeJni.cpp
deleted file mode 100644
index e0be7f3..0000000
--- a/suite/cts/deviceTests/simplecpu/jni/CpuNativeJni.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#include <jni.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-
-/* Code from now to qsort_local all copied from bionic source.
- * The code is duplicated here to remove dependency on optimized bionic
- */
-static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
-static __inline void swapfunc(char *, char *, int, int);
-
-#define min(a, b) (a) < (b) ? a : b
-
-/*
- * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
- */
-#define swapcode(TYPE, parmi, parmj, n) { \
- long i = (n) / sizeof (TYPE); \
- TYPE *pi = (TYPE *) (parmi); \
- TYPE *pj = (TYPE *) (parmj); \
- do { \
- TYPE t = *pi; \
- *pi++ = *pj; \
- *pj++ = t; \
- } while (--i > 0); \
-}
-
-#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
- es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
-
-static __inline void
-swapfunc(char *a, char *b, int n, int swaptype)
-{
- if (swaptype <= 1)
- swapcode(long, a, b, n)
- else
- swapcode(char, a, b, n)
-}
-
-#define swap(a, b) \
- if (swaptype == 0) { \
- long t = *(long *)(a); \
- *(long *)(a) = *(long *)(b); \
- *(long *)(b) = t; \
- } else \
- swapfunc(a, b, es, swaptype)
-
-#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
-
-static __inline char *
-med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
-{
- return cmp(a, b) < 0 ?
- (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
- :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
-}
-
-void
-qsort_local(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
-{
- char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
- int d, r, swaptype, swap_cnt;
- char *a = (char*)aa;
-
-loop: SWAPINIT(a, es);
- swap_cnt = 0;
- if (n < 7) {
- for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
- for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
- pl -= es)
- swap(pl, pl - es);
- return;
- }
- pm = (char *)a + (n / 2) * es;
- if (n > 7) {
- pl = (char *)a;
- pn = (char *)a + (n - 1) * es;
- if (n > 40) {
- d = (n / 8) * es;
- pl = med3(pl, pl + d, pl + 2 * d, cmp);
- pm = med3(pm - d, pm, pm + d, cmp);
- pn = med3(pn - 2 * d, pn - d, pn, cmp);
- }
- pm = med3(pl, pm, pn, cmp);
- }
- swap(a, pm);
- pa = pb = (char *)a + es;
-
- pc = pd = (char *)a + (n - 1) * es;
- for (;;) {
- while (pb <= pc && (r = cmp(pb, a)) <= 0) {
- if (r == 0) {
- swap_cnt = 1;
- swap(pa, pb);
- pa += es;
- }
- pb += es;
- }
- while (pb <= pc && (r = cmp(pc, a)) >= 0) {
- if (r == 0) {
- swap_cnt = 1;
- swap(pc, pd);
- pd -= es;
- }
- pc -= es;
- }
- if (pb > pc)
- break;
- swap(pb, pc);
- swap_cnt = 1;
- pb += es;
- pc -= es;
- }
- if (swap_cnt == 0) { /* Switch to insertion sort */
- for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
- for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
- pl -= es)
- swap(pl, pl - es);
- return;
- }
-
- pn = (char *)a + n * es;
- r = min(pa - (char *)a, pb - pa);
- vecswap(a, pb - r, r);
- r = min(pd - pc, pn - pd - (int)es);
- vecswap(pb, pn - r, r);
- if ((r = pb - pa) > (int)es)
- qsort_local(a, r / es, es, cmp);
- if ((r = pd - pc) > (int)es) {
- /* Iterate rather than recurse to save stack space */
- a = pn - r;
- n = r / es;
- goto loop;
- }
- /* qsort(pn - r, r / es, es, cmp); */
-}
-
-/* code duplication ends here */
-
-/**
- * Util for getting time stamp
- */
-double currentTimeMillis()
-{
- struct timeval tv;
- gettimeofday(&tv, (struct timezone *) NULL);
- return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
-}
-
-/**
- * Initialize given array randomly for the given seed
- */
-template <typename T> void randomInitArray(T* array, int len, unsigned int seed)
-{
- srand(seed);
- for (int i = 0; i < len; i++) {
- array[i] = (T) rand();
- }
-}
-
-/**
- * comparison function for int, for qsort
- */
-int cmpint(const void* p1, const void* p2)
-{
- return *(int*)p1 - *(int*)p2;
-}
-
-extern "C" JNIEXPORT jdouble JNICALL Java_com_android_cts_simplecpu_CpuNative_runSort(JNIEnv* env,
- jclass clazz, jint numberElements, jint repetition)
-{
- int* data = new int[numberElements];
- if (data == NULL) {
- env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "No memory");
- return -1;
- }
- double totalTime = 0;
- for (int i = 0; i < repetition; i++) {
- randomInitArray<int>(data, numberElements, 0);
- double start = currentTimeMillis();
- qsort_local(data, numberElements, sizeof(int), cmpint);
- double end = currentTimeMillis();
- totalTime += (end - start);
- }
- delete[] data;
- return totalTime;
-}
-
-
-/**
- * Do matrix multiplication, C = A x B with all matrices having dimension of n x n
- * The implementation is not in the most efficient, but it is good enough for benchmarking purpose.
- * @param n should be multiple of 8
- */
-void doMatrixMultiplication(float* A, float* B, float* C, int n)
-{
- // batch size
- const int M = 8;
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j += M) {
- float sum[M];
- for (int k = 0; k < M; k++) {
- sum[k] = 0;
- }
- // re-use the whole cache line for accessing B.
- // otherwise, the whole line will be read and only one value will be used.
-
- for (int k = 0; k < n; k++) {
- float a = A[i * n + k];
- sum[0] += a * B[k * n + j];
- sum[1] += a * B[k * n + j + 1];
- sum[2] += a * B[k * n + j + 2];
- sum[3] += a * B[k * n + j + 3];
- sum[4] += a * B[k * n + j + 4];
- sum[5] += a * B[k * n + j + 5];
- sum[6] += a * B[k * n + j + 6];
- sum[7] += a * B[k * n + j + 7];
- }
- for (int k = 0; k < M; k++) {
- C[i * n + j + k] = sum[k];
- }
- }
- }
-}
-
-extern "C" JNIEXPORT jdouble JNICALL Java_com_android_cts_simplecpu_CpuNative_runMatrixMultiplication(
- JNIEnv* env, jclass clazz, jint n, jint repetition)
-{
- // C = A x B
- float* A = new float[n * n];
- float* B = new float[n * n];
- float* C = new float[n * n];
- if ((A == NULL) || (B == NULL) || (C == NULL)) {
- delete[] A;
- delete[] B;
- delete[] C;
- env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "No memory");
- return -1;
- }
- double totalTime = 0;
- for (int i = 0; i < repetition; i++) {
- randomInitArray<float>(A, n * n, 0);
- randomInitArray<float>(B, n * n, 1);
- double start = currentTimeMillis();
- doMatrixMultiplication(A, B, C, n);
- double end = currentTimeMillis();
- totalTime += (end - start);
- }
- delete[] A;
- delete[] B;
- delete[] C;
- return totalTime;
-}
-
diff --git a/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/CpuNative.java b/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/CpuNative.java
deleted file mode 100644
index 8b48623..0000000
--- a/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/CpuNative.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.simplecpu;
-
-public class CpuNative {
- static {
- System.loadLibrary("ctscpu_jni");
- }
- /**
- * run qsort for given number of repetition
- * with each having the size of bufferSize.
- * @param numberElements
- * @param repeatition
- * @return time taken for computation, added for all repetition in ms
- */
- public static native double runSort(int numberElements, int repetition);
-
- /**
- * run matrix multiplication of (n x n) x (n x n)
- *
- * @param n dimension, should be multiple of 8
- * @param repetition
- * @return time taken for computation, added for all repetition in ms
- */
- public static native double runMatrixMultiplication(int n, int repetition);
-}
diff --git a/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/SimpleCpuTest.java b/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/SimpleCpuTest.java
deleted file mode 100644
index ce0feac..0000000
--- a/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/SimpleCpuTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.simplecpu;
-
-import android.util.Log;
-
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import android.cts.util.CtsAndroidTestCase;
-import com.android.cts.util.Stat;
-import com.android.cts.util.TimeoutReq;
-
-/**
- * Very simple CPU benchmarking to check the basic capability of CPU.
- * Cases include
- * qsort
- * matrix multiplication (for floating point performance)
- */
-public class SimpleCpuTest extends CtsAndroidTestCase {
- private static final String TAG = "BandwidthTest";
- private static final int KB = 1024;
- private static final int MB = 1024 * 1024;
- private static final int NUMBER_REPEAT = 20;
- // reject data outside +/- this value * median
- private static final double OUTLIER_THRESHOLD = 0.1;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- warmUpCpu();
- }
-
- public void testSort004KB() {
- doTestSort(NUMBER_REPEAT, 4 * KB);
- }
-
- public void testSort128KB() {
- doTestSort(NUMBER_REPEAT, 128 * KB);
- }
-
- public void testSort001MB() {
- doTestSort(NUMBER_REPEAT, 1 * MB);
- }
-
- // will fit into L1
- public void testMatrixMultiplication032() {
- doMatrixMultiplication(NUMBER_REPEAT, 32);
- }
-
- // mostly fit into L2
- public void testMatrixMultiplication128() {
- doMatrixMultiplication(NUMBER_REPEAT, 128);
- }
-
- // may fit into L2
- public void testMatrixMultiplication200() {
- doMatrixMultiplication(NUMBER_REPEAT, 200);
- }
-
- public void testMatrixMultiplication400() {
- doMatrixMultiplication(NUMBER_REPEAT, 400);
- }
-
- // will exceed L2
- @TimeoutReq(minutes = 30)
- public void testMatrixMultiplication600() {
- doMatrixMultiplication(NUMBER_REPEAT, 600);
- }
-
- /**
- * run some code to force full CPU freq.
- */
- private void warmUpCpu() {
- CpuNative.runSort(1 * MB, 10);
- }
-
- /**
- * qsort test
- * @param numberRepeat
- * @param arrayLength
- */
- private void doTestSort(int numberRepeat, int arrayLength) {
- final int numberRepeatInEachCall = 10;
- double[] result = new double[numberRepeat];
- for (int i = 0; i < numberRepeat; i++) {
- result[i] = CpuNative.runSort(arrayLength, numberRepeatInEachCall);
- }
- getReportLog().printArray("sorting time", result, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- Stat.StatResult stat = Stat.getStatWithOutlierRejection(result, OUTLIER_THRESHOLD);
- if (stat.mDataCount != result.length) {
- Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
- }
- getReportLog().printSummary("sorting time", stat.mAverage, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- }
-
- /**
- * Matrix multiplication test, nxn matrix multiplication
- * @param numberRepeat
- * @param n should be multiple of 8
- */
- private void doMatrixMultiplication(int numberRepeat, int n) {
- assertTrue(n % 8 == 0);
- final int numberRepeatInEachCall = 10;
- double[] result = new double[numberRepeat];
- for (int i = 0; i < numberRepeat; i++) {
- result[i] = CpuNative.runMatrixMultiplication(n, numberRepeatInEachCall);
- }
- getReportLog().printArray("matrix mutiplication time", result, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- Stat.StatResult stat = Stat.getStatWithOutlierRejection(result, OUTLIER_THRESHOLD);
- if (stat.mDataCount != result.length) {
- Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
- }
- getReportLog().printSummary("matrix mutiplication time", stat.mAverage,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- }
-
-}
diff --git a/suite/cts/deviceTests/tvproviderperf/Android.mk b/suite/cts/deviceTests/tvproviderperf/Android.mk
deleted file mode 100644
index e268955..0000000
--- a/suite/cts/deviceTests/tvproviderperf/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2014 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceTvProviderPerf
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
-
diff --git a/suite/cts/deviceTests/tvproviderperf/AndroidManifest.xml b/suite/cts/deviceTests/tvproviderperf/AndroidManifest.xml
deleted file mode 100644
index d345ab2..0000000
--- a/suite/cts/deviceTests/tvproviderperf/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.tvproviderperf">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
- <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.tvproviderperf"
- android:label="TvProvider performance measurement" />
-</manifest>
diff --git a/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java b/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
deleted file mode 100644
index 8eef86d..0000000
--- a/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.cts.tvproviderperf;
-
-import android.content.ComponentName;
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.OperationApplicationException;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.cts.util.CtsAndroidTestCase;
-import android.media.tv.TvContract;
-import android.media.tv.TvContract.Channels;
-import android.media.tv.TvContract.Programs;
-import android.net.Uri;
-import android.os.RemoteException;
-
-import com.android.cts.util.MeasureRun;
-import com.android.cts.util.MeasureTime;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.TimeoutReq;
-import com.android.cts.util.Stat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Test performance of TvProvider on a device. TvProvider typically handles hundreds of
- * thousands of records periodically, so it is desirable to have performance under a reasonable
- * bar.
- */
-public class TvProviderPerfTest extends CtsAndroidTestCase {
- private static final int TRANSACTION_RUNS = 100;
- private static final int QUERY_RUNS = 10;
-
- private ContentResolver mContentResolver;
- private String mInputId;
- private boolean mHasTvInputFramework;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mHasTvInputFramework = getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_LIVE_TV);
- if (!mHasTvInputFramework) return;
- mContentResolver = getContext().getContentResolver();
- mInputId = TvContract.buildInputId(new ComponentName(getContext(), getClass()));
- }
-
- @Override
- protected void tearDown() throws Exception {
- try {
- if (!mHasTvInputFramework) return;
- mContentResolver.delete(Programs.CONTENT_URI, null, null);
- mContentResolver.delete(Channels.CONTENT_URI, null, null);
- } finally {
- super.tearDown();
- }
- }
-
- @TimeoutReq(minutes = 8)
- public void testChannels() throws Exception {
- if (!mHasTvInputFramework) return;
- double[] averages = new double[5];
-
- // Insert
- final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
- final int TRANSACTION_SIZE = 1000;
- double[] applyBatchTimes = MeasureTime.measure(TRANSACTION_RUNS, new MeasureRun() {
- @Override
- public void run(int i) {
- operations.clear();
- for (int j = 0; j < TRANSACTION_SIZE; ++j) {
- ContentValues values = new ContentValues();
- values.put(Channels.COLUMN_INPUT_ID, mInputId);
- values.put(Channels.COLUMN_SERVICE_TYPE,
- Channels.SERVICE_TYPE_AUDIO_VIDEO);
- values.put(Channels.COLUMN_TYPE, Channels.TYPE_OTHER);
- operations.add(
- ContentProviderOperation.newInsert(Channels.CONTENT_URI)
- .withValues(values).build());
- }
- try {
- mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
- } catch (OperationApplicationException | RemoteException e) {
- throw new RuntimeException(e);
- }
- }
- });
- getReportLog().printArray("Elapsed time for insert: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[0] = Stat.getAverage(applyBatchTimes);
-
- // Update
- final String[] projection = { Channels._ID };
- try (final Cursor cursor = mContentResolver.query(Channels.CONTENT_URI,
- projection, null, null, null)) {
- applyBatchTimes = MeasureTime.measure(TRANSACTION_RUNS, new MeasureRun() {
- @Override
- public void run(int i) {
- operations.clear();
- for (int j = 0; j < TRANSACTION_SIZE && cursor.moveToNext(); ++j) {
- Uri channelUri = TvContract.buildChannelUri(cursor.getLong(0));
- String number = Integer.toString(i * TRANSACTION_SIZE + j);
- operations.add(
- ContentProviderOperation.newUpdate(channelUri)
- .withValue(Channels.COLUMN_DISPLAY_NUMBER, number)
- .build());
- }
- try {
- mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
- } catch (OperationApplicationException | RemoteException e) {
- throw new RuntimeException(e);
- }
- }
- });
- }
- getReportLog().printArray("Elapsed time for update: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[1] = Stat.getAverage(applyBatchTimes);
-
- // Query channels
- applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
- @Override
- public void run(int i) {
- try (Cursor cursor = mContentResolver.query(Channels.CONTENT_URI, null, null,
- null, null)) {
- while (cursor.moveToNext()) {
- // Do nothing. Just iterate all the items.
- }
- }
- }
- });
- getReportLog().printArray("Elapsed time for query (channels): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[2] = Stat.getAverage(applyBatchTimes);
-
- // Query a channel
- try (final Cursor cursor = mContentResolver.query(Channels.CONTENT_URI,
- projection, null, null, null)) {
- applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
- @Override
- public void run(int i) {
- assertTrue(cursor.moveToNext());
- try (Cursor c = mContentResolver.query(TvContract.buildChannelUri(
- cursor.getLong(0)), null, null, null, null)) {
- while (c.moveToNext()) {
- // Do nothing. Just iterate all the items.
- }
- }
- }
- });
- }
- getReportLog().printArray("Elapsed time for query (a channel): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[3] = Stat.getAverage(applyBatchTimes);
-
- // Delete
- applyBatchTimes = MeasureTime.measure(1, new MeasureRun() {
- @Override
- public void run(int i) {
- mContentResolver.delete(TvContract.buildChannelsUriForInput(mInputId), null, null);
- }
- });
- getReportLog().printArray("Elapsed time for delete: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[4] = Stat.getAverage(applyBatchTimes);
-
- getReportLog().printArray("Average elapsed time for insert, update, query (channels), "
- + "query (a channel), delete: ",
- averages, ResultType.LOWER_BETTER, ResultUnit.MS);
- }
-
- @TimeoutReq(minutes = 12)
- public void testPrograms() throws Exception {
- if (!mHasTvInputFramework) return;
- double[] averages = new double[7];
-
- // Prepare (insert channels)
- final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
- final int TRANSACTION_SIZE = 1000;
- final int NUM_CHANNELS = 100;
- final List<Uri> channelUris = new ArrayList<>();
-
- operations.clear();
- for (int i = 0; i < NUM_CHANNELS; ++i) {
- ContentValues values = new ContentValues();
- values.put(Channels.COLUMN_INPUT_ID, mInputId);
- values.put(Channels.COLUMN_SERVICE_TYPE,
- Channels.SERVICE_TYPE_AUDIO_VIDEO);
- values.put(Channels.COLUMN_TYPE, Channels.TYPE_OTHER);
- operations.add(
- ContentProviderOperation.newInsert(Channels.CONTENT_URI)
- .withValues(values).build());
- }
- try {
- ContentProviderResult[] results =
- mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
- for (ContentProviderResult result : results) {
- channelUris.add(result.uri);
- }
- } catch (OperationApplicationException | RemoteException e) {
- throw new RuntimeException(e);
- }
-
- // Insert
- double[] applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
- @Override
- public void run(int i) {
- operations.clear();
- Uri channelUri = channelUris.get(i);
- long channelId = ContentUris.parseId(channelUri);
- for (int j = 0; j < TRANSACTION_SIZE; ++j) {
- ContentValues values = new ContentValues();
- values.put(Programs.COLUMN_CHANNEL_ID, channelId);
- operations.add(
- ContentProviderOperation.newInsert(Programs.CONTENT_URI)
- .withValues(values).build());
- }
- try {
- mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
- } catch (OperationApplicationException | RemoteException e) {
- throw new RuntimeException(e);
- }
- }
- });
- getReportLog().printArray("Elapsed time for insert: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[0] = Stat.getAverage(applyBatchTimes);
-
- // Update
- final long PROGRAM_DURATION_MS = 60 * 1000;
- final String[] projection = { Programs._ID };
- applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
- @Override
- public void run(int i) {
- Uri channelUri = channelUris.get(i);
- operations.clear();
- try (Cursor cursor = mContentResolver.query(
- TvContract.buildProgramsUriForChannel(channelUri),
- projection, null, null, null)) {
- long startTimeMs = 0;
- long endTimeMs = 0;
- while (cursor.moveToNext()) {
- Uri programUri = TvContract.buildProgramUri(cursor.getLong(0));
- endTimeMs += PROGRAM_DURATION_MS;
- operations.add(
- ContentProviderOperation.newUpdate(programUri)
- .withValue(Programs.COLUMN_START_TIME_UTC_MILLIS, startTimeMs)
- .withValue(Programs.COLUMN_END_TIME_UTC_MILLIS, endTimeMs)
- .build());
- startTimeMs = endTimeMs;
- }
- }
- try {
- mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
- } catch (OperationApplicationException | RemoteException e) {
- throw new RuntimeException(e);
- }
- }
- });
- getReportLog().printArray("Elapsed time for update: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[1] = Stat.getAverage(applyBatchTimes);
-
- // Query programs
- applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
- @Override
- public void run(int i) {
- try (Cursor cursor = mContentResolver.query(Programs.CONTENT_URI, null, null,
- null, null)) {
- while (cursor.moveToNext()) {
- // Do nothing. Just iterate all the items.
- }
- }
- }
- });
- getReportLog().printArray("Elapsed time for query (programs): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[2] = Stat.getAverage(applyBatchTimes);
-
- // Query programs with selection
- applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
- @Override
- public void run(int i) {
- Uri channelUri = channelUris.get(i);
- try (Cursor cursor = mContentResolver.query(
- TvContract.buildProgramsUriForChannel(
- channelUri, 0,
- PROGRAM_DURATION_MS * TRANSACTION_SIZE / 2),
- null, null, null, null)) {
- while (cursor.moveToNext()) {
- // Do nothing. Just iterate all the items.
- }
- }
- }
- });
- getReportLog().printArray("Elapsed time for query (programs with selection): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[3] = Stat.getAverage(applyBatchTimes);
-
- // Query a program
- try (final Cursor cursor = mContentResolver.query(Programs.CONTENT_URI,
- projection, null, null, null)) {
- applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
- @Override
- public void run(int i) {
- assertTrue(cursor.moveToNext());
- try (Cursor c = mContentResolver.query(TvContract.buildProgramUri(
- cursor.getLong(0)), null, null, null, null)) {
- while (c.moveToNext()) {
- // Do nothing. Just iterate all the items.
- }
- }
- }
- });
- }
- getReportLog().printArray("Elapsed time for query (a program): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[4] = Stat.getAverage(applyBatchTimes);
-
- // Delete programs
- applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
- @Override
- public void run(int i) {
- Uri channelUri = channelUris.get(i);
- mContentResolver.delete(
- TvContract.buildProgramsUriForChannel(
- channelUri,
- PROGRAM_DURATION_MS * TRANSACTION_SIZE / 2,
- PROGRAM_DURATION_MS * TRANSACTION_SIZE),
- null, null);
- }
- });
- getReportLog().printArray("Elapsed time for delete programs: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[5] = Stat.getAverage(applyBatchTimes);
-
- // Delete channels
- applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
- @Override
- public void run(int i) {
- Uri channelUri = channelUris.get(i);
- mContentResolver.delete(channelUri, null, null);
- }
- });
- getReportLog().printArray("Elapsed time for delete channels: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- averages[6] = Stat.getAverage(applyBatchTimes);
-
- getReportLog().printArray("Average elapsed time for insert, update, query (programs), "
- + "query (programs with selection), query (a channel), delete (channels), "
- + "delete (programs): ",
- averages, ResultType.LOWER_BETTER, ResultUnit.MS);
- }
-}
diff --git a/suite/cts/deviceTests/ui/Android.mk b/suite/cts/deviceTests/ui/Android.mk
deleted file mode 100644
index ee52172..0000000
--- a/suite/cts/deviceTests/ui/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceUi
-
-LOCAL_SDK_VERSION := 16
-
-include $(BUILD_CTS_PACKAGE)
-
-
diff --git a/suite/cts/deviceTests/ui/AndroidManifest.xml b/suite/cts/deviceTests/ui/AndroidManifest.xml
deleted file mode 100644
index b41008e7..0000000
--- a/suite/cts/deviceTests/ui/AndroidManifest.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2012 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.ui" >
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <application>
- <uses-library android:name="android.test.runner" />
-
- <activity
- android:name=".ScrollingActivity"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
- <instrumentation
- android:name="android.support.test.runner.AndroidJUnitRunner"
- android:label="UI Latency measurement"
- android:targetPackage="com.android.cts.ui" >
- <meta-data
- android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
diff --git a/suite/cts/deviceTests/ui/src/com/android/cts/ui/ScrollingActivity.java b/suite/cts/deviceTests/ui/src/com/android/cts/ui/ScrollingActivity.java
deleted file mode 100644
index 2229e97..0000000
--- a/suite/cts/deviceTests/ui/src/com/android/cts/ui/ScrollingActivity.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.ui;
-
-import android.app.ListActivity;
-import android.os.Bundle;
-import android.widget.AbsListView;
-import android.widget.AbsListView.OnScrollListener;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Activity for measuring scrolling time of long list.
- */
-public class ScrollingActivity extends ListActivity implements OnScrollListener {
- static final String TAG = "ScrollingActivity";
- private static final String NUM_ELEMENTS_EXTRA = "num_elements";
- private static final int NUM_ELEMENTS_DEFAULT = 10000;
- private static final int SCROLL_TIME_IN_MS = 1;
- private static final int WAIT_TIMEOUT_IN_SECS = 5 * 60;
- private String[] mItems;
- private CountDownLatch mLatchStop = null;
- private int mTargetLoc;
- private int mNumElements;
-
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- mNumElements = getIntent().getIntExtra(NUM_ELEMENTS_EXTRA, NUM_ELEMENTS_DEFAULT);
- mItems = new String[mNumElements];
- for (int i = 0; i < mNumElements; i++) {
- mItems[i] = Integer.toString(i);
- }
- setListAdapter(new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1, mItems));
- ListView view = getListView();
- view.setOnScrollListener(this);
- }
-
- public boolean scrollToTop() {
- return doScroll(0);
- }
- public boolean scrollToBottom() {
- return doScroll(mNumElements - 1);
- }
-
- private boolean doScroll(final int loc) {
- mLatchStop = new CountDownLatch(1);
- mTargetLoc = loc;
- final ListView view = getListView();
- runOnUiThread( new Runnable() {
- @Override
- public void run() {
- view.smoothScrollToPositionFromTop(loc, 0, SCROLL_TIME_IN_MS);
- }
- });
- boolean result = false;
- try {
- result = mLatchStop.await(WAIT_TIMEOUT_IN_SECS, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- // ignore
- }
- mLatchStop = null;
- return result;
- }
-
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
-
- }
-
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem,
- int visibleItemCount, int totalItemCount) {
- //Log.i(TAG, "onScroll " + firstVisibleItem + " " + visibleItemCount);
- if ((mTargetLoc >= firstVisibleItem) &&
- (mTargetLoc <= (firstVisibleItem + visibleItemCount))) {
- if (mLatchStop != null) {
- mLatchStop.countDown();
- }
- }
- }
-}
diff --git a/suite/cts/deviceTests/ui/src/com/android/cts/ui/ScrollingTest.java b/suite/cts/deviceTests/ui/src/com/android/cts/ui/ScrollingTest.java
deleted file mode 100644
index b5b40e4..0000000
--- a/suite/cts/deviceTests/ui/src/com/android/cts/ui/ScrollingTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.ui;
-
-import com.android.cts.util.MeasureRun;
-import com.android.cts.util.MeasureTime;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import android.cts.util.CtsActivityInstrumentationTestCase2;
-import com.android.cts.util.Stat;
-import com.android.cts.util.TimeoutReq;
-
-import java.io.IOException;
-
-public class ScrollingTest extends CtsActivityInstrumentationTestCase2<ScrollingActivity> {
- private ScrollingActivity mActivity;
-
- public ScrollingTest() {
- super(ScrollingActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mActivity = getActivity();
- getInstrumentation().waitForIdleSync();
- try {
- runTestOnUiThread(new Runnable() {
- public void run() {
- }
- });
- } catch (Throwable e) {
- e.printStackTrace();
- fail();
- }
- }
-
- @Override
- protected void tearDown() throws Exception {
- mActivity = null;
- super.tearDown();
- }
-
- @TimeoutReq(minutes = 30)
- public void testFullScrolling() throws Exception {
- final int NUMBER_REPEAT = 10;
- final ScrollingActivity activity = mActivity;
- double[] results = MeasureTime.measure(NUMBER_REPEAT, new MeasureRun() {
-
- @Override
- public void run(int i) throws IOException {
- assertTrue(activity.scrollToBottom());
- assertTrue(activity.scrollToTop());
- }
- });
- getReportLog().printArray("scrolling time", results, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- Stat.StatResult stat = Stat.getStat(results);
- getReportLog().printSummary("scrolling time", stat.mAverage, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- }
-}
diff --git a/suite/cts/deviceTests/videoperf/Android.mk b/suite/cts/deviceTests/videoperf/Android.mk
deleted file mode 100644
index 4b825c5..0000000
--- a/suite/cts/deviceTests/videoperf/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-# include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil ctstestrunner
-
-LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libnativehelper_compat_libc++
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceVideoPerf
-
-LOCAL_SDK_VERSION := current
-
-cts_runtime_hint := 50
-
-include $(BUILD_CTS_PACKAGE)
-
diff --git a/suite/cts/deviceTests/videoperf/AndroidManifest.xml b/suite/cts/deviceTests/videoperf/AndroidManifest.xml
deleted file mode 100644
index ca01298b..0000000
--- a/suite/cts/deviceTests/videoperf/AndroidManifest.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.videoperf">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.videoperf"
- android:label="UI Latency measurement" >
- <meta-data
- android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-</manifest>
diff --git a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/CodecInfo.java b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/CodecInfo.java
deleted file mode 100644
index ccb3126..0000000
--- a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/CodecInfo.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.videoperf;
-
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaCodecInfo.CodecProfileLevel;
-import android.media.MediaCodecInfo.VideoCapabilities;
-import android.media.MediaCodecList;
-import android.media.MediaFormat;
-import android.util.Log;
-import android.util.Range;
-
-import java.io.IOException;
-
-/**
- * Utility class for getting codec information like bit rate, fps, and etc.
- * Uses public member variables instead of methods as this code is only for video benchmarking.
- */
-public class CodecInfo {
- /** bit rate in bps */
- public int mBitRate = 0;
- /** Frame rate */
- public int mFps = 0;
- /** if codec is supporting YUV semiplanar format */
- public boolean mSupportSemiPlanar = false;
- /** if codec is supporting YUV planar format */
- public boolean mSupportPlanar = false;
-
- private static final String TAG = "CodecInfo";
- private static final String VIDEO_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
- /**
- * Check if given codec with given (w,h) is supported.
- * @param codecName codec name
- * @param mimeType codec type in mime format like MediaFormat.MIMETYPE_VIDEO_AVC
- * @param w video width
- * @param h video height
- * @return null if the configuration is not supported.
- */
- public static CodecInfo getSupportedFormatInfo(
- String codecName, String mimeType, int w, int h) {
- MediaCodec codec;
- try {
- codec = MediaCodec.createByCodecName(codecName);
- } catch (IOException e) {
- return null;
- }
-
- CodecCapabilities cap = codec.getCodecInfo().getCapabilitiesForType(mimeType);
- if (cap.colorFormats.length == 0) {
- Log.w(TAG, "no supported color format");
- codec.release();
- return null;
- }
-
- CodecInfo info = new CodecInfo();
- for (int color : cap.colorFormats) {
- if (color == CodecCapabilities.COLOR_FormatYUV420SemiPlanar) {
- info.mSupportSemiPlanar = true;
- }
- if (color == CodecCapabilities.COLOR_FormatYUV420Planar) {
- info.mSupportPlanar = true;
- }
- }
- printIntArray("supported colors", cap.colorFormats);
-
- VideoCapabilities vidCap = cap.getVideoCapabilities();
- try {
- info.mFps = vidCap.getSupportedFrameRatesFor(w, h).getUpper().intValue();
- } catch (IllegalArgumentException e) {
- Log.w(TAG, "unsupported size");
- codec.release();
- return null;
- }
- info.mBitRate = vidCap.getBitrateRange().getUpper();
- Log.i(TAG, "test bit rate " + info.mBitRate + " fps " + info.mFps);
- codec.release();
- return info;
- }
-
- // for debugging
- private static void printIntArray(String msg, int[] data) {
- StringBuilder builder = new StringBuilder();
- builder.append(msg);
- builder.append(":");
- for (int e : data) {
- builder.append(Integer.toHexString(e));
- builder.append(",");
- }
- builder.deleteCharAt(builder.length() - 1);
- Log.i(TAG, builder.toString());
- }
-}
diff --git a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
deleted file mode 100644
index 39f3cb4..0000000
--- a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
+++ /dev/null
@@ -1,1260 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.videoperf;
-
-import android.cts.util.MediaUtils;
-import android.cts.util.DeviceReportLog;
-import android.graphics.ImageFormat;
-import android.graphics.Point;
-import android.media.cts.CodecImage;
-import android.media.cts.CodecUtils;
-import android.media.Image;
-import android.media.Image.Plane;
-import android.media.MediaCodec;
-import android.media.MediaCodec.BufferInfo;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaCodecList;
-import android.media.MediaFormat;
-import android.util.Log;
-import android.util.Pair;
-import android.util.Range;
-import android.util.Size;
-
-import android.cts.util.CtsAndroidTestCase;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.Stat;
-import com.android.cts.util.TimeoutReq;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.lang.System;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Random;
-import java.util.Vector;
-
-/**
- * This tries to test video encoder / decoder performance by running encoding / decoding
- * without displaying the raw data. To make things simpler, encoder is used to encode synthetic
- * data and decoder is used to decode the encoded video. This approach does not work where
- * there is only decoder. Performance index is total time taken for encoding and decoding
- * the whole frames.
- * To prevent sacrificing quality for faster encoding / decoding, randomly selected pixels are
- * compared with the original image. As the pixel comparison can slow down the decoding process,
- * only some randomly selected pixels are compared. As there can be only one performance index,
- * error above certain threshold in pixel value will be treated as an error.
- */
-public class VideoEncoderDecoderTest extends CtsAndroidTestCase {
- private static final String TAG = "VideoEncoderDecoderTest";
- // this wait time affects fps as too big value will work as a blocker if device fps
- // is not very high.
- private static final long VIDEO_CODEC_WAIT_TIME_US = 5000;
- private static final boolean VERBOSE = false;
- private static final String VIDEO_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
- private static final String VIDEO_VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
- private static final String VIDEO_H263 = MediaFormat.MIMETYPE_VIDEO_H263;
- private static final String VIDEO_MPEG4 = MediaFormat.MIMETYPE_VIDEO_MPEG4;
- private int mCurrentTestRound = 0;
- private double[][] mEncoderFrameTimeDiff = null;
- private double[][] mDecoderFrameTimeDiff = null;
- // i frame interval for encoder
- private static final int KEY_I_FRAME_INTERVAL = 5;
- private static final int MOVING_AVERAGE_NUM = 10;
-
- private static final int Y_CLAMP_MIN = 16;
- private static final int Y_CLAMP_MAX = 235;
- private static final int YUV_PLANE_ADDITIONAL_LENGTH = 200;
- private ByteBuffer mYBuffer, mYDirectBuffer;
- private ByteBuffer mUVBuffer, mUVDirectBuffer;
- private int mSrcColorFormat;
- private int mDstColorFormat;
- private int mBufferWidth;
- private int mBufferHeight;
- private int mVideoWidth;
- private int mVideoHeight;
- private int mFrameRate;
-
- private MediaFormat mEncInputFormat;
- private MediaFormat mEncOutputFormat;
- private MediaFormat mDecOutputFormat;
-
- private LinkedList<Pair<ByteBuffer, BufferInfo>> mEncodedOutputBuffer;
- // check this many pixels per each decoded frame
- // checking too many points decreases decoder frame rates a lot.
- private static final int PIXEL_CHECK_PER_FRAME = 1000;
- // RMS error in pixel values above this will be treated as error.
- private static final double PIXEL_RMS_ERROR_MARGAIN = 20.0;
- private double mRmsErrorMargain = PIXEL_RMS_ERROR_MARGAIN;
- private Random mRandom;
-
- private class TestConfig {
- public boolean mTestPixels = true;
- public boolean mTestResult = false;
- public boolean mReportFrameTime = false;
- public int mTotalFrames = 300;
- public int mMaxTimeMs = 120000; // 2 minutes
- public int mNumberOfRepeat = 10;
- }
-
- private TestConfig mTestConfig;
-
- private DeviceReportLog mReportLog;
-
- @Override
- protected void setUp() throws Exception {
- mEncodedOutputBuffer = new LinkedList<Pair<ByteBuffer, BufferInfo>>();
- // Use time as a seed, hoping to prevent checking pixels in the same pattern
- long now = System.currentTimeMillis();
- mRandom = new Random(now);
- mTestConfig = new TestConfig();
- mReportLog = new DeviceReportLog();
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- mEncodedOutputBuffer.clear();
- mEncodedOutputBuffer = null;
- mYBuffer = null;
- mUVBuffer = null;
- mYDirectBuffer = null;
- mUVDirectBuffer = null;
- mRandom = null;
- mTestConfig = null;
- mReportLog.deliverReportToHost(getInstrumentation());
- super.tearDown();
- }
-
- private String getEncoderName(String mime) {
- return getCodecName(mime, true /* isEncoder */);
- }
-
- private String getDecoderName(String mime) {
- return getCodecName(mime, false /* isEncoder */);
- }
-
- private String getCodecName(String mime, boolean isEncoder) {
- MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- for (MediaCodecInfo info : mcl.getCodecInfos()) {
- if (info.isEncoder() != isEncoder) {
- continue;
- }
- CodecCapabilities caps = null;
- try {
- caps = info.getCapabilitiesForType(mime);
- } catch (IllegalArgumentException e) { // mime is not supported
- continue;
- }
- return info.getName();
- }
- return null;
- }
-
- private String[] getEncoderName(String mime, boolean isGoog) {
- return getCodecName(mime, isGoog, true /* isEncoder */);
- }
-
- private String[] getDecoderName(String mime, boolean isGoog) {
- return getCodecName(mime, isGoog, false /* isEncoder */);
- }
-
- private String[] getCodecName(String mime, boolean isGoog, boolean isEncoder) {
- MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- ArrayList<String> result = new ArrayList<String>();
- for (MediaCodecInfo info : mcl.getCodecInfos()) {
- if (info.isEncoder() != isEncoder
- || info.getName().toLowerCase().startsWith("omx.google.") != isGoog) {
- continue;
- }
- CodecCapabilities caps = null;
- try {
- caps = info.getCapabilitiesForType(mime);
- } catch (IllegalArgumentException e) { // mime is not supported
- continue;
- }
- result.add(info.getName());
- }
- return result.toArray(new String[result.size()]);
- }
-
- public void testAvc0176x0144() throws Exception {
- doTestDefault(VIDEO_AVC, 176, 144);
- }
-
- public void testAvc0352x0288() throws Exception {
- doTestDefault(VIDEO_AVC, 352, 288);
- }
-
- public void testAvc0720x0480() throws Exception {
- doTestDefault(VIDEO_AVC, 720, 480);
- }
-
- public void testAvc1280x0720() throws Exception {
- doTestDefault(VIDEO_AVC, 1280, 720);
- }
-
- /**
- * resolution intentionally set to 1072 not 1080
- * as 1080 is not multiple of 16, and it requires additional setting like stride
- * which is not specified in API documentation.
- */
- public void testAvc1920x1072() throws Exception {
- doTestDefault(VIDEO_AVC, 1920, 1072);
- }
-
- // Avc tests
- public void testAvc0320x0240Other() throws Exception {
- doTestOther(VIDEO_AVC, 320, 240);
- }
-
- public void testAvc0320x0240Goog() throws Exception {
- doTestGoog(VIDEO_AVC, 320, 240);
- }
-
- public void testAvc0720x0480Other() throws Exception {
- doTestOther(VIDEO_AVC, 720, 480);
- }
-
- public void testAvc0720x0480Goog() throws Exception {
- doTestGoog(VIDEO_AVC, 720, 480);
- }
-
- @TimeoutReq(minutes = 10)
- public void testAvc1280x0720Other() throws Exception {
- doTestOther(VIDEO_AVC, 1280, 720);
- }
-
- @TimeoutReq(minutes = 10)
- public void testAvc1280x0720Goog() throws Exception {
- doTestGoog(VIDEO_AVC, 1280, 720);
- }
-
- @TimeoutReq(minutes = 10)
- public void testAvc1920x1080Other() throws Exception {
- doTestOther(VIDEO_AVC, 1920, 1080);
- }
-
- @TimeoutReq(minutes = 10)
- public void testAvc1920x1080Goog() throws Exception {
- doTestGoog(VIDEO_AVC, 1920, 1080);
- }
-
- // Vp8 tests
- public void testVp80320x0180Other() throws Exception {
- doTestOther(VIDEO_VP8, 320, 180);
- }
-
- public void testVp80320x0180Goog() throws Exception {
- doTestGoog(VIDEO_VP8, 320, 180);
- }
-
- public void testVp80640x0360Other() throws Exception {
- doTestOther(VIDEO_VP8, 640, 360);
- }
-
- public void testVp80640x0360Goog() throws Exception {
- doTestGoog(VIDEO_VP8, 640, 360);
- }
-
- @TimeoutReq(minutes = 10)
- public void testVp81280x0720Other() throws Exception {
- doTestOther(VIDEO_VP8, 1280, 720);
- }
-
- @TimeoutReq(minutes = 10)
- public void testVp81280x0720Goog() throws Exception {
- doTestGoog(VIDEO_VP8, 1280, 720);
- }
-
- @TimeoutReq(minutes = 10)
- public void testVp81920x1080Other() throws Exception {
- doTestOther(VIDEO_VP8, 1920, 1080);
- }
-
- @TimeoutReq(minutes = 10)
- public void testVp81920x1080Goog() throws Exception {
- doTestGoog(VIDEO_VP8, 1920, 1080);
- }
-
- // H263 tests
- public void testH2630176x0144Other() throws Exception {
- doTestOther(VIDEO_H263, 176, 144);
- }
-
- public void testH2630176x0144Goog() throws Exception {
- doTestGoog(VIDEO_H263, 176, 144);
- }
-
- public void testH2630352x0288Other() throws Exception {
- doTestOther(VIDEO_H263, 352, 288);
- }
-
- public void testH2630352x0288Goog() throws Exception {
- doTestGoog(VIDEO_H263, 352, 288);
- }
-
- // Mpeg4 tests
- public void testMpeg40176x0144Other() throws Exception {
- doTestOther(VIDEO_MPEG4, 176, 144);
- }
-
- public void testMpeg40176x0144Goog() throws Exception {
- doTestGoog(VIDEO_MPEG4, 176, 144);
- }
-
- public void testMpeg40352x0288Other() throws Exception {
- doTestOther(VIDEO_MPEG4, 352, 288);
- }
-
- public void testMpeg40352x0288Goog() throws Exception {
- doTestGoog(VIDEO_MPEG4, 352, 288);
- }
-
- public void testMpeg40640x0480Other() throws Exception {
- doTestOther(VIDEO_MPEG4, 640, 480);
- }
-
- public void testMpeg40640x0480Goog() throws Exception {
- doTestGoog(VIDEO_MPEG4, 640, 480);
- }
-
- @TimeoutReq(minutes = 10)
- public void testMpeg41280x0720Other() throws Exception {
- doTestOther(VIDEO_MPEG4, 1280, 720);
- }
-
- @TimeoutReq(minutes = 10)
- public void testMpeg41280x0720Goog() throws Exception {
- doTestGoog(VIDEO_MPEG4, 1280, 720);
- }
-
- private boolean isSrcSemiPlanar() {
- return mSrcColorFormat == CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
- }
-
- private boolean isSrcFlexYUV() {
- return mSrcColorFormat == CodecCapabilities.COLOR_FormatYUV420Flexible;
- }
-
- private boolean isDstSemiPlanar() {
- return mDstColorFormat == CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
- }
-
- private boolean isDstFlexYUV() {
- return mDstColorFormat == CodecCapabilities.COLOR_FormatYUV420Flexible;
- }
-
- private static int getColorFormat(CodecInfo info) {
- if (info.mSupportSemiPlanar) {
- return CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
- } else if (info.mSupportPlanar) {
- return CodecCapabilities.COLOR_FormatYUV420Planar;
- } else {
- // FlexYUV must be supported
- return CodecCapabilities.COLOR_FormatYUV420Flexible;
- }
- }
-
- private void doTestGoog(String mimeType, int w, int h) throws Exception {
- mTestConfig.mTestPixels = false;
- mTestConfig.mTestResult = true;
- mTestConfig.mTotalFrames = 3000;
- mTestConfig.mNumberOfRepeat = 2;
- doTest(true /* isGoog */, mimeType, w, h);
- }
-
- private void doTestOther(String mimeType, int w, int h) throws Exception {
- mTestConfig.mTestPixels = false;
- mTestConfig.mTestResult = true;
- mTestConfig.mTotalFrames = 3000;
- mTestConfig.mNumberOfRepeat = 2;
- doTest(false /* isGoog */, mimeType, w, h);
- }
-
- private void doTestDefault(String mimeType, int w, int h) throws Exception {
- String encoderName = getEncoderName(mimeType);
- if (encoderName == null) {
- Log.i(TAG, "Encoder for " + mimeType + " not found");
- return;
- }
-
- String decoderName = getDecoderName(mimeType);
- if (decoderName == null) {
- Log.i(TAG, "Encoder for " + mimeType + " not found");
- return;
- }
-
- doTestByName(encoderName, decoderName, mimeType, w, h);
- }
-
- /**
- * Run encoding / decoding test for given mimeType of codec
- * @param isGoog test google or non-google codec.
- * @param mimeType like video/avc
- * @param w video width
- * @param h video height
- */
- private void doTest(boolean isGoog, String mimeType, int w, int h)
- throws Exception {
- String[] encoderNames = getEncoderName(mimeType, isGoog);
- if (encoderNames.length == 0) {
- Log.i(TAG, isGoog ? "Google " : "Non-google "
- + "encoder for " + mimeType + " not found");
- return;
- }
-
- String[] decoderNames = getDecoderName(mimeType, isGoog);
- if (decoderNames.length == 0) {
- Log.i(TAG, isGoog ? "Google " : "Non-google "
- + "decoder for " + mimeType + " not found");
- return;
- }
-
- for (String encoderName: encoderNames) {
- for (String decoderName: decoderNames) {
- doTestByName(encoderName, decoderName, mimeType, w, h);
- }
- }
- }
-
- private void doTestByName(
- String encoderName, String decoderName, String mimeType, int w, int h)
- throws Exception {
- CodecInfo infoEnc = CodecInfo.getSupportedFormatInfo(encoderName, mimeType, w, h);
- if (infoEnc == null) {
- Log.i(TAG, "Encoder " + mimeType + " with " + w + "," + h + " not supported");
- return;
- }
- CodecInfo infoDec = CodecInfo.getSupportedFormatInfo(decoderName, mimeType, w, h);
- assertNotNull(infoDec);
- mVideoWidth = w;
- mVideoHeight = h;
-
- mSrcColorFormat = getColorFormat(infoEnc);
- mDstColorFormat = getColorFormat(infoDec);
- Log.i(TAG, "Testing video resolution " + w + "x" + h +
- ": enc format " + mSrcColorFormat +
- ", dec format " + mDstColorFormat);
-
- initYUVPlane(w + YUV_PLANE_ADDITIONAL_LENGTH, h + YUV_PLANE_ADDITIONAL_LENGTH);
- mEncoderFrameTimeDiff =
- new double[mTestConfig.mNumberOfRepeat][mTestConfig.mTotalFrames - 1];
- mDecoderFrameTimeDiff =
- new double[mTestConfig.mNumberOfRepeat][mTestConfig.mTotalFrames - 1];
- double[] encoderFpsResults = new double[mTestConfig.mNumberOfRepeat];
- double[] decoderFpsResults = new double[mTestConfig.mNumberOfRepeat];
- double[] totalFpsResults = new double[mTestConfig.mNumberOfRepeat];
- double[] decoderRmsErrorResults = new double[mTestConfig.mNumberOfRepeat];
- boolean success = true;
- for (int i = 0; i < mTestConfig.mNumberOfRepeat && success; i++) {
- mCurrentTestRound = i;
- MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, mimeType);
- format.setInteger(MediaFormat.KEY_BIT_RATE, infoEnc.mBitRate);
- format.setInteger(MediaFormat.KEY_WIDTH, w);
- format.setInteger(MediaFormat.KEY_HEIGHT, h);
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT, mSrcColorFormat);
- format.setInteger(MediaFormat.KEY_FRAME_RATE, infoEnc.mFps);
- mFrameRate = infoEnc.mFps;
- format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, KEY_I_FRAME_INTERVAL);
-
- double encodingTime = runEncoder(encoderName, format, mTestConfig.mTotalFrames);
- // re-initialize format for decoder
- format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, mimeType);
- format.setInteger(MediaFormat.KEY_WIDTH, w);
- format.setInteger(MediaFormat.KEY_HEIGHT, h);
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT, mDstColorFormat);
- double[] decoderResult = runDecoder(decoderName, format);
- if (decoderResult == null) {
- success = false;
- } else {
- double decodingTime = decoderResult[0];
- decoderRmsErrorResults[i] = decoderResult[1];
- encoderFpsResults[i] = (double)mTestConfig.mTotalFrames / encodingTime * 1000.0;
- decoderFpsResults[i] = (double)mTestConfig.mTotalFrames / decodingTime * 1000.0;
- totalFpsResults[i] =
- (double)mTestConfig.mTotalFrames / (encodingTime + decodingTime) * 1000.0;
- }
-
- // clear things for re-start
- mEncodedOutputBuffer.clear();
- // it will be good to clean everything to make every run the same.
- System.gc();
- }
- mReportLog.printArray("encoder", encoderFpsResults, ResultType.HIGHER_BETTER,
- ResultUnit.FPS);
- mReportLog.printArray("rms error", decoderRmsErrorResults, ResultType.LOWER_BETTER,
- ResultUnit.NONE);
- mReportLog.printArray("decoder", decoderFpsResults, ResultType.HIGHER_BETTER,
- ResultUnit.FPS);
- mReportLog.printArray("encoder decoder", totalFpsResults, ResultType.HIGHER_BETTER,
- ResultUnit.FPS);
- mReportLog.printValue(mimeType + " encoder average fps for " + w + "x" + h,
- Stat.getAverage(encoderFpsResults), ResultType.HIGHER_BETTER, ResultUnit.FPS);
- mReportLog.printValue(mimeType + " decoder average fps for " + w + "x" + h,
- Stat.getAverage(decoderFpsResults), ResultType.HIGHER_BETTER, ResultUnit.FPS);
- mReportLog.printSummary("encoder decoder", Stat.getAverage(totalFpsResults),
- ResultType.HIGHER_BETTER, ResultUnit.FPS);
-
- boolean encTestPassed = false;
- boolean decTestPassed = false;
- double[] measuredFps = new double[mTestConfig.mNumberOfRepeat];
- String[] resultRawData = new String[mTestConfig.mNumberOfRepeat];
- for (int i = 0; i < mTestConfig.mNumberOfRepeat; i++) {
- // make sure that rms error is not too big.
- if (decoderRmsErrorResults[i] >= mRmsErrorMargain) {
- fail("rms error is bigger than the limit "
- + decoderRmsErrorResults[i] + " vs " + mRmsErrorMargain);
- }
-
- if (mTestConfig.mReportFrameTime) {
- mReportLog.printValue(
- "encodertest#" + i + ": " + Arrays.toString(mEncoderFrameTimeDiff[i]),
- 0, ResultType.NEUTRAL, ResultUnit.NONE);
- mReportLog.printValue(
- "decodertest#" + i + ": " + Arrays.toString(mDecoderFrameTimeDiff[i]),
- 0, ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (mTestConfig.mTestResult) {
- double[] avgs = MediaUtils.calculateMovingAverage(
- mEncoderFrameTimeDiff[i], MOVING_AVERAGE_NUM);
- double encMin = Stat.getMin(avgs);
- double encMax = Stat.getMax(avgs);
- double encAvg = MediaUtils.getAverage(mEncoderFrameTimeDiff[i]);
- double encStdev = MediaUtils.getStdev(avgs);
- String prefix = "codec=" + encoderName + " round=" + i +
- " EncInputFormat=" + mEncInputFormat +
- " EncOutputFormat=" + mEncOutputFormat;
- String result =
- MediaUtils.logResults(mReportLog, prefix, encMin, encMax, encAvg, encStdev);
- double measuredEncFps = 1000000000 / encMin;
- resultRawData[i] = result;
- measuredFps[i] = measuredEncFps;
- if (!encTestPassed) {
- encTestPassed = MediaUtils.verifyResults(
- encoderName, mimeType, w, h, measuredEncFps);
- }
-
- avgs = MediaUtils.calculateMovingAverage(
- mDecoderFrameTimeDiff[i], MOVING_AVERAGE_NUM);
- double decMin = Stat.getMin(avgs);
- double decMax = Stat.getMax(avgs);
- double decAvg = MediaUtils.getAverage(mDecoderFrameTimeDiff[i]);
- double decStdev = MediaUtils.getStdev(avgs);
- prefix = "codec=" + decoderName + " size=" + w + "x" + h + " round=" + i +
- " DecOutputFormat=" + mDecOutputFormat;
- MediaUtils.logResults(mReportLog, prefix, decMin, decMax, decAvg, decStdev);
- double measuredDecFps = 1000000000 / decMin;
- if (!decTestPassed) {
- decTestPassed = MediaUtils.verifyResults(
- decoderName, mimeType, w, h, measuredDecFps);
- }
- }
- }
-
- if (mTestConfig.mTestResult) {
- if (!encTestPassed) {
- Range<Double> reportedRange =
- MediaUtils.getAchievableFrameRatesFor(encoderName, mimeType, w, h);
- String failMessage =
- MediaUtils.getErrorMessage(reportedRange, measuredFps, resultRawData);
- fail(failMessage);
- }
- // Decoder result will be verified in VideoDecoderPerfTest
- // if (!decTestPassed) {
- // fail("Measured fps for " + decoderName +
- // " doesn't match with reported achievable frame rates.");
- // }
- }
- measuredFps = null;
- resultRawData = null;
- }
-
- /**
- * run encoder benchmarking
- * @param encoderName encoder name
- * @param format format of media to encode
- * @param totalFrames total number of frames to encode
- * @return time taken in ms to encode the frames. This does not include initialization time.
- */
- private double runEncoder(String encoderName, MediaFormat format, int totalFrames) {
- MediaCodec codec = null;
- try {
- codec = MediaCodec.createByCodecName(encoderName);
- codec.configure(
- format,
- null /* surface */,
- null /* crypto */,
- MediaCodec.CONFIGURE_FLAG_ENCODE);
- } catch (IllegalStateException e) {
- Log.e(TAG, "codec '" + encoderName + "' failed configuration.");
- codec.release();
- assertTrue("codec '" + encoderName + "' failed configuration.", false);
- } catch (IOException | NullPointerException e) {
- Log.i(TAG, "could not find codec for " + format);
- return Double.NaN;
- }
- codec.start();
- mEncInputFormat = codec.getInputFormat();
- ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
-
- int numBytesSubmitted = 0;
- int numBytesDequeued = 0;
- int inFramesCount = 0;
- long lastOutputTimeNs = 0;
- long start = System.currentTimeMillis();
- while (true) {
- int index;
-
- if (inFramesCount < totalFrames) {
- index = codec.dequeueInputBuffer(VIDEO_CODEC_WAIT_TIME_US /* timeoutUs */);
- if (index != MediaCodec.INFO_TRY_AGAIN_LATER) {
- int size;
- boolean eos = (inFramesCount == (totalFrames - 1));
- if (!eos && ((System.currentTimeMillis() - start) > mTestConfig.mMaxTimeMs)) {
- eos = true;
- }
- // when encoder only supports flexYUV, use Image only; otherwise,
- // use ByteBuffer & Image each on half of the frames to test both
- if (isSrcFlexYUV() || inFramesCount % 2 == 0) {
- Image image = codec.getInputImage(index);
- // image should always be available
- assertTrue(image != null);
- size = queueInputImageEncoder(
- codec, image, index, inFramesCount,
- eos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
- } else {
- ByteBuffer buffer = codec.getInputBuffer(index);
- size = queueInputBufferEncoder(
- codec, buffer, index, inFramesCount,
- eos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
- }
- inFramesCount++;
- numBytesSubmitted += size;
- if (VERBOSE) {
- Log.d(TAG, "queued " + size + " bytes of input data, frame " +
- (inFramesCount - 1));
- }
-
- }
- }
- MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
- index = codec.dequeueOutputBuffer(info, VIDEO_CODEC_WAIT_TIME_US /* timeoutUs */);
- if (index == MediaCodec.INFO_TRY_AGAIN_LATER) {
- } else if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- mEncOutputFormat = codec.getOutputFormat();
- } else if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
- codecOutputBuffers = codec.getOutputBuffers();
- } else if (index >= 0) {
- if (lastOutputTimeNs > 0) {
- int pos = mEncodedOutputBuffer.size() - 1;
- if (pos < mEncoderFrameTimeDiff[mCurrentTestRound].length) {
- long diff = System.nanoTime() - lastOutputTimeNs;
- mEncoderFrameTimeDiff[mCurrentTestRound][pos] = diff;
- }
- }
- lastOutputTimeNs = System.nanoTime();
-
- dequeueOutputBufferEncoder(codec, codecOutputBuffers, index, info);
- numBytesDequeued += info.size;
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- if (VERBOSE) {
- Log.d(TAG, "dequeued output EOS.");
- }
- break;
- }
- if (VERBOSE) {
- Log.d(TAG, "dequeued " + info.size + " bytes of output data.");
- }
- }
- }
- long finish = System.currentTimeMillis();
- int validDataNum = Math.min(mEncodedOutputBuffer.size() - 1,
- mEncoderFrameTimeDiff[mCurrentTestRound].length);
- mEncoderFrameTimeDiff[mCurrentTestRound] =
- Arrays.copyOf(mEncoderFrameTimeDiff[mCurrentTestRound], validDataNum);
- if (VERBOSE) {
- Log.d(TAG, "queued a total of " + numBytesSubmitted + "bytes, "
- + "dequeued " + numBytesDequeued + " bytes.");
- }
- codec.stop();
- codec.release();
- codec = null;
- return (double)(finish - start);
- }
-
- /**
- * Fills input buffer for encoder from YUV buffers.
- * @return size of enqueued data.
- */
- private int queueInputBufferEncoder(
- MediaCodec codec, ByteBuffer buffer, int index, int frameCount, int flags) {
- buffer.clear();
-
- Point origin = getOrigin(frameCount);
- // Y color first
- int srcOffsetY = origin.x + origin.y * mBufferWidth;
- final byte[] yBuffer = mYBuffer.array();
- for (int i = 0; i < mVideoHeight; i++) {
- buffer.put(yBuffer, srcOffsetY, mVideoWidth);
- srcOffsetY += mBufferWidth;
- }
- if (isSrcSemiPlanar()) {
- int srcOffsetU = origin.y / 2 * mBufferWidth + origin.x / 2 * 2;
- final byte[] uvBuffer = mUVBuffer.array();
- for (int i = 0; i < mVideoHeight / 2; i++) {
- buffer.put(uvBuffer, srcOffsetU, mVideoWidth);
- srcOffsetU += mBufferWidth;
- }
- } else {
- int srcOffsetU = origin.y / 2 * mBufferWidth / 2 + origin.x / 2;
- int srcOffsetV = srcOffsetU + mBufferWidth / 2 * mBufferHeight / 2;
- final byte[] uvBuffer = mUVBuffer.array();
- for (int i = 0; i < mVideoHeight / 2; i++) { //U only
- buffer.put(uvBuffer, srcOffsetU, mVideoWidth / 2);
- srcOffsetU += mBufferWidth / 2;
- }
- for (int i = 0; i < mVideoHeight / 2; i++) { //V only
- buffer.put(uvBuffer, srcOffsetV, mVideoWidth / 2);
- srcOffsetV += mBufferWidth / 2;
- }
- }
- int size = mVideoHeight * mVideoWidth * 3 / 2;
- long ptsUsec = computePresentationTime(frameCount);
-
- codec.queueInputBuffer(index, 0 /* offset */, size, ptsUsec /* timeUs */, flags);
- if (VERBOSE && (frameCount == 0)) {
- printByteArray("Y ", mYBuffer.array(), 0, 20);
- printByteArray("UV ", mUVBuffer.array(), 0, 20);
- printByteArray("UV ", mUVBuffer.array(), mBufferWidth * 60, 20);
- }
- return size;
- }
-
- class YUVImage extends CodecImage {
- private final int mImageWidth;
- private final int mImageHeight;
- private final Plane[] mPlanes;
-
- YUVImage(
- Point origin,
- int imageWidth, int imageHeight,
- int arrayWidth, int arrayHeight,
- boolean semiPlanar,
- ByteBuffer bufferY, ByteBuffer bufferUV) {
- mImageWidth = imageWidth;
- mImageHeight = imageHeight;
- ByteBuffer dupY = bufferY.duplicate();
- ByteBuffer dupUV = bufferUV.duplicate();
- mPlanes = new Plane[3];
-
- int srcOffsetY = origin.x + origin.y * arrayWidth;
-
- mPlanes[0] = new YUVPlane(
- mImageWidth, mImageHeight, arrayWidth, 1,
- dupY, srcOffsetY);
-
- if (semiPlanar) {
- int srcOffsetUV = origin.y / 2 * arrayWidth + origin.x / 2 * 2;
-
- mPlanes[1] = new YUVPlane(
- mImageWidth / 2, mImageHeight / 2, arrayWidth, 2,
- dupUV, srcOffsetUV);
- mPlanes[2] = new YUVPlane(
- mImageWidth / 2, mImageHeight / 2, arrayWidth, 2,
- dupUV, srcOffsetUV + 1);
- } else {
- int srcOffsetU = origin.y / 2 * arrayWidth / 2 + origin.x / 2;
- int srcOffsetV = srcOffsetU + arrayWidth / 2 * arrayHeight / 2;
-
- mPlanes[1] = new YUVPlane(
- mImageWidth / 2, mImageHeight / 2, arrayWidth / 2, 1,
- dupUV, srcOffsetU);
- mPlanes[2] = new YUVPlane(
- mImageWidth / 2, mImageHeight / 2, arrayWidth / 2, 1,
- dupUV, srcOffsetV);
- }
- }
-
- @Override
- public int getFormat() {
- return ImageFormat.YUV_420_888;
- }
-
- @Override
- public int getWidth() {
- return mImageWidth;
- }
-
- @Override
- public int getHeight() {
- return mImageHeight;
- }
-
- @Override
- public long getTimestamp() {
- return 0;
- }
-
- @Override
- public Plane[] getPlanes() {
- return mPlanes;
- }
-
- @Override
- public void close() {
- mPlanes[0] = null;
- mPlanes[1] = null;
- mPlanes[2] = null;
- }
-
- class YUVPlane extends CodecImage.Plane {
- private final int mRowStride;
- private final int mPixelStride;
- private final ByteBuffer mByteBuffer;
-
- YUVPlane(int w, int h, int rowStride, int pixelStride,
- ByteBuffer buffer, int offset) {
- mRowStride = rowStride;
- mPixelStride = pixelStride;
-
- // only safe to access length bytes starting from buffer[offset]
- int length = (h - 1) * rowStride + (w - 1) * pixelStride + 1;
-
- buffer.position(offset);
- mByteBuffer = buffer.slice();
- mByteBuffer.limit(length);
- }
-
- @Override
- public int getRowStride() {
- return mRowStride;
- }
-
- @Override
- public int getPixelStride() {
- return mPixelStride;
- }
-
- @Override
- public ByteBuffer getBuffer() {
- return mByteBuffer;
- }
- }
- }
-
- /**
- * Fills input image for encoder from YUV buffers.
- * @return size of enqueued data.
- */
- private int queueInputImageEncoder(
- MediaCodec codec, Image image, int index, int frameCount, int flags) {
- assertTrue(image.getFormat() == ImageFormat.YUV_420_888);
-
-
- Point origin = getOrigin(frameCount);
-
- // Y color first
- CodecImage srcImage = new YUVImage(
- origin,
- mVideoWidth, mVideoHeight,
- mBufferWidth, mBufferHeight,
- isSrcSemiPlanar(),
- mYDirectBuffer, mUVDirectBuffer);
-
- CodecUtils.copyFlexYUVImage(image, srcImage);
-
- int size = mVideoHeight * mVideoWidth * 3 / 2;
- long ptsUsec = computePresentationTime(frameCount);
-
- codec.queueInputBuffer(index, 0 /* offset */, size, ptsUsec /* timeUs */, flags);
- if (VERBOSE && (frameCount == 0)) {
- printByteArray("Y ", mYBuffer.array(), 0, 20);
- printByteArray("UV ", mUVBuffer.array(), 0, 20);
- printByteArray("UV ", mUVBuffer.array(), mBufferWidth * 60, 20);
- }
- return size;
- }
-
- /**
- * Dequeue encoded data from output buffer and store for later usage.
- */
- private void dequeueOutputBufferEncoder(
- MediaCodec codec, ByteBuffer[] outputBuffers,
- int index, MediaCodec.BufferInfo info) {
- ByteBuffer output = outputBuffers[index];
- int l = info.size;
- ByteBuffer copied = ByteBuffer.allocate(l);
- output.get(copied.array(), 0, l);
- BufferInfo savedInfo = new BufferInfo();
- savedInfo.set(0, l, info.presentationTimeUs, info.flags);
- mEncodedOutputBuffer.addLast(Pair.create(copied, savedInfo));
- codec.releaseOutputBuffer(index, false /* render */);
- }
-
- /**
- * run decoder benchmarking with encoded stream stored from encoding phase
- * @param decoderName decoder name
- * @param format format of media to decode
- * @return returns length-2 array with 0: time for decoding, 1 : rms error of pixels
- */
- private double[] runDecoder(String decoderName, MediaFormat format) {
- MediaCodec codec = null;
- try {
- codec = MediaCodec.createByCodecName(decoderName);
- } catch (IOException | NullPointerException e) {
- Log.i(TAG, "could not find decoder for " + format);
- return null;
- }
- codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
- codec.start();
- ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
-
- double totalErrorSquared = 0;
-
- MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
- boolean sawOutputEOS = false;
- int inputLeft = mEncodedOutputBuffer.size();
- int inputBufferCount = 0;
- int outFrameCount = 0;
- YUVValue expected = new YUVValue();
- YUVValue decoded = new YUVValue();
- long lastOutputTimeNs = 0;
- long start = System.currentTimeMillis();
- while (!sawOutputEOS) {
- if (inputLeft > 0) {
- int inputBufIndex = codec.dequeueInputBuffer(VIDEO_CODEC_WAIT_TIME_US);
-
- if (inputBufIndex >= 0) {
- ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
- dstBuf.clear();
- ByteBuffer src = mEncodedOutputBuffer.get(inputBufferCount).first;
- BufferInfo srcInfo = mEncodedOutputBuffer.get(inputBufferCount).second;
- int writeSize = src.capacity();
- dstBuf.put(src.array(), 0, writeSize);
-
- int flags = srcInfo.flags;
- if ((System.currentTimeMillis() - start) > mTestConfig.mMaxTimeMs) {
- flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
- }
-
- codec.queueInputBuffer(
- inputBufIndex,
- 0 /* offset */,
- writeSize,
- srcInfo.presentationTimeUs,
- flags);
- inputLeft --;
- inputBufferCount ++;
- }
- }
-
- int res = codec.dequeueOutputBuffer(info, VIDEO_CODEC_WAIT_TIME_US);
- if (res >= 0) {
- int outputBufIndex = res;
-
- // only do YUV compare on EOS frame if the buffer size is none-zero
- if (info.size > 0) {
- if (lastOutputTimeNs > 0) {
- int pos = outFrameCount - 1;
- if (pos < mDecoderFrameTimeDiff[mCurrentTestRound].length) {
- long diff = System.nanoTime() - lastOutputTimeNs;
- mDecoderFrameTimeDiff[mCurrentTestRound][pos] = diff;
- }
- }
- lastOutputTimeNs = System.nanoTime();
-
- if (mTestConfig.mTestPixels) {
- Point origin = getOrigin(outFrameCount);
- int i;
-
- // if decoder supports planar or semiplanar, check output with
- // ByteBuffer & Image each on half of the points
- int pixelCheckPerFrame = PIXEL_CHECK_PER_FRAME;
- if (!isDstFlexYUV()) {
- pixelCheckPerFrame /= 2;
- ByteBuffer buf = codec.getOutputBuffer(outputBufIndex);
- if (VERBOSE && (outFrameCount == 0)) {
- printByteBuffer("Y ", buf, 0, 20);
- printByteBuffer("UV ", buf, mVideoWidth * mVideoHeight, 20);
- printByteBuffer("UV ", buf,
- mVideoWidth * mVideoHeight + mVideoWidth * 60, 20);
- }
- for (i = 0; i < pixelCheckPerFrame; i++) {
- int w = mRandom.nextInt(mVideoWidth);
- int h = mRandom.nextInt(mVideoHeight);
- getPixelValuesFromYUVBuffers(origin.x, origin.y, w, h, expected);
- getPixelValuesFromOutputBuffer(buf, w, h, decoded);
- if (VERBOSE) {
- Log.i(TAG, outFrameCount + "-" + i + "- th round: ByteBuffer:"
- + " expected "
- + expected.mY + "," + expected.mU + "," + expected.mV
- + " decoded "
- + decoded.mY + "," + decoded.mU + "," + decoded.mV);
- }
- totalErrorSquared += expected.calcErrorSquared(decoded);
- }
- }
-
- Image image = codec.getOutputImage(outputBufIndex);
- assertTrue(image != null);
- for (i = 0; i < pixelCheckPerFrame; i++) {
- int w = mRandom.nextInt(mVideoWidth);
- int h = mRandom.nextInt(mVideoHeight);
- getPixelValuesFromYUVBuffers(origin.x, origin.y, w, h, expected);
- getPixelValuesFromImage(image, w, h, decoded);
- if (VERBOSE) {
- Log.i(TAG, outFrameCount + "-" + i + "- th round: FlexYUV:"
- + " expcted "
- + expected.mY + "," + expected.mU + "," + expected.mV
- + " decoded "
- + decoded.mY + "," + decoded.mU + "," + decoded.mV);
- }
- totalErrorSquared += expected.calcErrorSquared(decoded);
- }
- }
- outFrameCount++;
- }
- codec.releaseOutputBuffer(outputBufIndex, false /* render */);
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- Log.d(TAG, "saw output EOS.");
- sawOutputEOS = true;
- }
- } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- mDecOutputFormat = codec.getOutputFormat();
- Log.d(TAG, "output format has changed to " + mDecOutputFormat);
- int colorFormat = mDecOutputFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
- if (colorFormat == CodecCapabilities.COLOR_FormatYUV420SemiPlanar
- || colorFormat == CodecCapabilities.COLOR_FormatYUV420Planar) {
- mDstColorFormat = colorFormat;
- } else {
- mDstColorFormat = CodecCapabilities.COLOR_FormatYUV420Flexible;
- Log.w(TAG, "output format changed to unsupported one " +
- Integer.toHexString(colorFormat) + ", using FlexYUV");
- }
- }
- }
- long finish = System.currentTimeMillis();
- int validDataNum = Math.min(outFrameCount - 1,
- mDecoderFrameTimeDiff[mCurrentTestRound].length);
- mDecoderFrameTimeDiff[mCurrentTestRound] =
- Arrays.copyOf(mDecoderFrameTimeDiff[mCurrentTestRound], validDataNum);
- codec.stop();
- codec.release();
- codec = null;
-
- // divide by 3 as sum is done for Y, U, V.
- double errorRms = Math.sqrt(totalErrorSquared / PIXEL_CHECK_PER_FRAME / outFrameCount / 3);
- double[] result = { (double) finish - start, errorRms };
- return result;
- }
-
- /**
- * returns origin in the absolute frame for given frame count.
- * The video scene is moving by moving origin per each frame.
- */
- private Point getOrigin(int frameCount) {
- if (frameCount < 100) {
- return new Point(2 * frameCount, 0);
- } else if (frameCount < 200) {
- return new Point(200, (frameCount - 100) * 2);
- } else {
- if (frameCount > 300) { // for safety
- frameCount = 300;
- }
- return new Point(600 - frameCount * 2, 600 - frameCount * 2);
- }
- }
-
- /**
- * initialize reference YUV plane
- * @param w This should be YUV_PLANE_ADDITIONAL_LENGTH pixels bigger than video resolution
- * to allow movements
- * @param h This should be YUV_PLANE_ADDITIONAL_LENGTH pixels bigger than video resolution
- * to allow movements
- * @param semiPlanarEnc
- * @param semiPlanarDec
- */
- private void initYUVPlane(int w, int h) {
- int bufferSizeY = w * h;
- mYBuffer = ByteBuffer.allocate(bufferSizeY);
- mUVBuffer = ByteBuffer.allocate(bufferSizeY / 2);
- mYDirectBuffer = ByteBuffer.allocateDirect(bufferSizeY);
- mUVDirectBuffer = ByteBuffer.allocateDirect(bufferSizeY / 2);
- mBufferWidth = w;
- mBufferHeight = h;
- final byte[] yArray = mYBuffer.array();
- final byte[] uvArray = mUVBuffer.array();
- for (int i = 0; i < h; i++) {
- for (int j = 0; j < w; j++) {
- yArray[i * w + j] = clampY((i + j) & 0xff);
- }
- }
- if (isSrcSemiPlanar()) {
- for (int i = 0; i < h/2; i++) {
- for (int j = 0; j < w/2; j++) {
- uvArray[i * w + 2 * j] = (byte) (i & 0xff);
- uvArray[i * w + 2 * j + 1] = (byte) (j & 0xff);
- }
- }
- } else { // planar, U first, then V
- int vOffset = bufferSizeY / 4;
- for (int i = 0; i < h/2; i++) {
- for (int j = 0; j < w/2; j++) {
- uvArray[i * w/2 + j] = (byte) (i & 0xff);
- uvArray[i * w/2 + vOffset + j] = (byte) (j & 0xff);
- }
- }
- }
- mYDirectBuffer.put(yArray);
- mUVDirectBuffer.put(uvArray);
- mYDirectBuffer.rewind();
- mUVDirectBuffer.rewind();
- }
-
- /**
- * class to store pixel values in YUV
- *
- */
- public class YUVValue {
- public byte mY;
- public byte mU;
- public byte mV;
- public YUVValue() {
- }
-
- public boolean equalTo(YUVValue other) {
- return (mY == other.mY) && (mU == other.mU) && (mV == other.mV);
- }
-
- public double calcErrorSquared(YUVValue other) {
- double yDelta = mY - other.mY;
- double uDelta = mU - other.mU;
- double vDelta = mV - other.mV;
- return yDelta * yDelta + uDelta * uDelta + vDelta * vDelta;
- }
- }
-
- /**
- * Read YUV values from given position (x,y) for given origin (originX, originY)
- * The whole data is already available from YBuffer and UVBuffer.
- * @param result pass the result via this. This is for avoiding creating / destroying too many
- * instances
- */
- private void getPixelValuesFromYUVBuffers(int originX, int originY, int x, int y,
- YUVValue result) {
- result.mY = mYBuffer.get((originY + y) * mBufferWidth + (originX + x));
- if (isSrcSemiPlanar()) {
- int index = (originY + y) / 2 * mBufferWidth + (originX + x) / 2 * 2;
- //Log.d(TAG, "YUV " + originX + "," + originY + "," + x + "," + y + "," + index);
- result.mU = mUVBuffer.get(index);
- result.mV = mUVBuffer.get(index + 1);
- } else {
- int vOffset = mBufferWidth * mBufferHeight / 4;
- int index = (originY + y) / 2 * mBufferWidth / 2 + (originX + x) / 2;
- result.mU = mUVBuffer.get(index);
- result.mV = mUVBuffer.get(vOffset + index);
- }
- }
-
- /**
- * Read YUV pixels from decoded output buffer for give (x, y) position
- * Output buffer is composed of Y parts followed by U/V
- * @param result pass the result via this. This is for avoiding creating / destroying too many
- * instances
- */
- private void getPixelValuesFromOutputBuffer(ByteBuffer buffer, int x, int y, YUVValue result) {
- result.mY = buffer.get(y * mVideoWidth + x);
- if (isDstSemiPlanar()) {
- int index = mVideoWidth * mVideoHeight + y / 2 * mVideoWidth + x / 2 * 2;
- //Log.d(TAG, "Decoded " + x + "," + y + "," + index);
- result.mU = buffer.get(index);
- result.mV = buffer.get(index + 1);
- } else {
- int vOffset = mVideoWidth * mVideoHeight / 4;
- int index = mVideoWidth * mVideoHeight + y / 2 * mVideoWidth / 2 + x / 2;
- result.mU = buffer.get(index);
- result.mV = buffer.get(index + vOffset);
- }
- }
-
- private void getPixelValuesFromImage(Image image, int x, int y, YUVValue result) {
- assertTrue(image.getFormat() == ImageFormat.YUV_420_888);
-
- Plane[] planes = image.getPlanes();
- assertTrue(planes.length == 3);
-
- result.mY = getPixelFromPlane(planes[0], x, y);
- result.mU = getPixelFromPlane(planes[1], x / 2, y / 2);
- result.mV = getPixelFromPlane(planes[2], x / 2, y / 2);
- }
-
- private byte getPixelFromPlane(Plane plane, int x, int y) {
- ByteBuffer buf = plane.getBuffer();
- return buf.get(y * plane.getRowStride() + x * plane.getPixelStride());
- }
-
- /**
- * Y cannot have full range. clamp it to prevent invalid value.
- */
- private byte clampY(int y) {
- if (y < Y_CLAMP_MIN) {
- y = Y_CLAMP_MIN;
- } else if (y > Y_CLAMP_MAX) {
- y = Y_CLAMP_MAX;
- }
- return (byte) (y & 0xff);
- }
-
- // for debugging
- private void printByteArray(String msg, byte[] data, int offset, int len) {
- StringBuilder builder = new StringBuilder();
- builder.append(msg);
- builder.append(":");
- for (int i = offset; i < offset + len; i++) {
- builder.append(Integer.toHexString(data[i]));
- builder.append(",");
- }
- builder.deleteCharAt(builder.length() - 1);
- Log.i(TAG, builder.toString());
- }
-
- // for debugging
- private void printByteBuffer(String msg, ByteBuffer data, int offset, int len) {
- StringBuilder builder = new StringBuilder();
- builder.append(msg);
- builder.append(":");
- for (int i = offset; i < offset + len; i++) {
- builder.append(Integer.toHexString(data.get(i)));
- builder.append(",");
- }
- builder.deleteCharAt(builder.length() - 1);
- Log.i(TAG, builder.toString());
- }
-
- /**
- * Generates the presentation time for frame N, in microseconds.
- */
- private long computePresentationTime(int frameIndex) {
- return 132 + frameIndex * 1000000L / mFrameRate;
- }
-}
diff --git a/suite/cts/hostTests/Android.mk b/suite/cts/hostTests/Android.mk
deleted file mode 100644
index c141484..0000000
--- a/suite/cts/hostTests/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright (C) 2012 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.
-#
-
-include $(call all-subdir-makefiles)
diff --git a/suite/cts/hostTests/jank/Android.mk b/suite/cts/hostTests/jank/Android.mk
deleted file mode 100644
index 8f1be07..0000000
--- a/suite/cts/hostTests/jank/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := CtsHostJank
-
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_CTS_TEST_PACKAGE := com.android.cts.jank
-
-LOCAL_DEVICE_JAR_ := CtsDeviceJank
-cts_library_jar_ := $(CTS_TESTCASES_OUT)/$(LOCAL_DEVICE_JAR_).jar
-
-$(cts_library_jar_): $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_DEVICE_JAR_))/javalib.jar | $(ACP)
- $(hide) mkdir -p $(CTS_TESTCASES_OUT)
- $(hide) $(ACP) -fp $< $@
-
-$(CTS_TESTCASES_OUT)/CtsHostJank.xml: $(cts_library_jar_)
-
-include $(BUILD_CTS_HOST_JAVA_LIBRARY)
-
-# Build the library using its own makefile
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/cts/hostTests/jank/app/Android.mk b/suite/cts/hostTests/jank/app/Android.mk
deleted file mode 100644
index 8f4fce6..0000000
--- a/suite/cts/hostTests/jank/app/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := CtsDeviceJank
-LOCAL_DEX_PREOPT := false
-
-LOCAL_JAVA_LIBRARIES := uiautomator.core
-
-LOCAL_STATIC_JAVA_LIBRARIES := com.android.uiautomator.platform.common
-
-include $(BUILD_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/suite/cts/hostTests/jank/app/src/com/android/cts/jank/CtsJankTestBase.java b/suite/cts/hostTests/jank/app/src/com/android/cts/jank/CtsJankTestBase.java
deleted file mode 100644
index 6d5162b..0000000
--- a/suite/cts/hostTests/jank/app/src/com/android/cts/jank/CtsJankTestBase.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.jank;
-
-import android.os.Bundle;
-import android.util.Log;
-
-import com.android.uiautomator.platform.JankTestBase;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Scanner;
-
-public class CtsJankTestBase extends JankTestBase {
- private final static String TAG = CtsJankTestBase.class.getName();
- protected final static String START_CMD = "am start -W -a android.intent.action.MAIN -n %s";
- protected final static String STOP_CMD = "am force-stop %s";
- protected final static String INTENT_STRING_EXTRA = " --es %s %s";
- protected final static String INTENT_BOOLEAN_EXTRA = " --ez %s %b";
- protected final static String INTENT_INTEGER_EXTRA = " --ei %s %d";
- protected static long SLEEP_TIME = 2000; // 2 seconds
- protected static int NUM_ITERATIONS = 5;
- protected static int TRACE_TIME = 5;
-
- @Override
- protected String getPropertyString(Bundle params, String key)
- throws FileNotFoundException, IOException {
- if (key.equals("iteration")) {
- return NUM_ITERATIONS + "";
- }
- if (key.equals("tracetime")) {
- return TRACE_TIME + "";
- }
- return super.getPropertyString(params, key);
- }
-
- protected void runShellCommand(String command) throws Exception {
- Process p = null;
- Scanner out = null;
- Scanner err = null;
- try {
- p = Runtime.getRuntime().exec(command);
-
- StringBuilder outStr = new StringBuilder();
- StringBuilder errStr = new StringBuilder();
- out = new Scanner(p.getInputStream());
- err = new Scanner(p.getErrorStream());
- boolean read = true;
- while (read) {
- if (out.hasNextLine()) {
- outStr.append(out.nextLine());
- outStr.append("\n");
- } else if (err.hasNextLine()) {
- errStr.append(err.nextLine());
- errStr.append("\n");
- } else {
- read = false;
- }
- }
- Log.i(TAG, command);
- if (outStr.length() > 0) {
- Log.i(TAG, outStr.toString());
- }
- if (errStr.length() > 0) {
- Log.e(TAG, errStr.toString());
- }
- } finally {
- if (p != null) {
- int status = p.waitFor();
- if (status != 0) {
- throw new RuntimeException(
- String.format("Run shell command: %s, status: %s", command, status));
- }
- p.destroy();
- p = null;
- }
- if (out != null) {
- out.close();
- }
- if (err != null) {
- err.close();
- }
- }
- }
-}
diff --git a/suite/cts/hostTests/jank/app/src/com/android/cts/jank/opengl/CtsDeviceJankOpenGl.java b/suite/cts/hostTests/jank/app/src/com/android/cts/jank/opengl/CtsDeviceJankOpenGl.java
deleted file mode 100755
index 5ba0613..0000000
--- a/suite/cts/hostTests/jank/app/src/com/android/cts/jank/opengl/CtsDeviceJankOpenGl.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.jank.opengl;
-
-import android.util.Log;
-
-import com.android.cts.jank.CtsJankTestBase;
-import com.android.uiautomator.platform.SurfaceFlingerHelper;
-
-public class CtsDeviceJankOpenGl extends CtsJankTestBase {
- private final static String TAG = CtsDeviceJankOpenGl.class.getName();
- private final static String PACKAGE = "com.android.cts.opengl";
- private final static String COMPONENT =
- PACKAGE + "/" + PACKAGE + ".primitive.GLPrimitiveActivity";
- private static String APP_WINDOW_NAME = "SurfaceView";
-
- /**
- * Runs the full OpenGL ES 2.0 pipeline test.
- */
- public void testFullPipeline() throws Exception {
- runBenchmark("FullPipeline");
- }
-
- /**
- * Runs the pixel output test.
- */
- public void testPixelOutput() throws Exception {
- runBenchmark("PixelOutput");
- }
-
- /**
- * Runs the shader performance test.
- */
- public void testShaderPerf() throws Exception {
- runBenchmark("ShaderPerf");
- }
-
- /**
- * Runs the context switch overhead test.
- */
- public void testContextSwitch() throws Exception {
- runBenchmark("ContextSwitch");
- }
-
- /**
- * Runs the benchhmark for jank test.
- */
- public void runBenchmark(String benchmark) throws Exception {
- // Start activity command
- final StringBuilder sb = new StringBuilder();
- sb.append(String.format(START_CMD, COMPONENT));
- sb.append(String.format(INTENT_STRING_EXTRA, "benchmark_name", benchmark));
- sb.append(String.format(INTENT_BOOLEAN_EXTRA, "offscreen", false));
- sb.append(String.format(INTENT_INTEGER_EXTRA, "num_frames", 1000));
- sb.append(String.format(INTENT_INTEGER_EXTRA, "num_iterations", 1));
- sb.append(String.format(INTENT_INTEGER_EXTRA, "timeout", 10000));
- final String startCommand = sb.toString();
- final String stopCommand = String.format(STOP_CMD, PACKAGE);
-
- Log.i(TAG, "Start command: " + startCommand);
- Log.i(TAG, "Stop command: " + stopCommand);
-
- setIteration(NUM_ITERATIONS);
- for (int i = 0; i < NUM_ITERATIONS; i++) {
- // Stop any existing instances
- runShellCommand(stopCommand);
- // Start activity
- runShellCommand(startCommand);
-
- // Wait for the activity to start
- sleep(SLEEP_TIME / 2);
-
- // Start systrace
- startTrace(mTestCaseName, i);
-
- // Clear SurfaceFlinger buffer
- Log.i(TAG, "Clearing SurfaceFlinger buffer");
- SurfaceFlingerHelper.clearBuffer(APP_WINDOW_NAME);
-
- // This is where user interactions would go, in this case just sleep
- sleep(SLEEP_TIME);
-
- // Dump SurfaceFlinger buffer
- Log.i(TAG, "Dumping SurfaceFlinger buffer");
- boolean result = SurfaceFlingerHelper.dumpFrameLatency(APP_WINDOW_NAME, true);
- assertTrue("SurfaceFlingerHelper could not get timestamps", result);
-
- // Stop systrace
- endTrace();
-
- // Record results
- recordResults(mTestCaseName, i);
- }
- // Save aggregated results
- saveResults(mTestCaseName);
- // Stop any remaining instances
- runShellCommand(stopCommand);
- }
-}
diff --git a/suite/cts/hostTests/jank/src/com/android/cts/jank/CtsHostJankTest.java b/suite/cts/hostTests/jank/src/com/android/cts/jank/CtsHostJankTest.java
deleted file mode 100644
index e196bfb..0000000
--- a/suite/cts/hostTests/jank/src/com/android/cts/jank/CtsHostJankTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.jank;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.tradefed.util.HostReportLog;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.ddmlib.IShellOutputReceiver;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Scanner;
-
-public class CtsHostJankTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
-
- private static final String TAG = CtsHostJankTest.class.getSimpleName();
- private static final String DEVICE_LOCATION = "/data/local/tmp/";
- // FIXME uiautomator is deprecated and does not support --abi flag
- private static final String RUN_UI_AUTOMATOR_CMD = "uiautomator runtest %s -c %s";
- private final String mHostTestClass;
- private final String mDeviceTestClass;
- private final String mJarName;
- private final String mJarPath;
- protected ITestDevice mDevice;
- protected CtsBuildHelper mBuild;
- protected IAbi mAbi;
-
- public CtsHostJankTest(String jarName, String deviceTestClass, String hostTestClass) {
- this.mHostTestClass = hostTestClass;
- this.mDeviceTestClass = deviceTestClass;
- this.mJarName = jarName;
- this.mJarPath = DEVICE_LOCATION + jarName;
- }
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mDevice = getDevice();
- // Push jar to device.
- File jarFile = mBuild.getTestApp(mJarName);
- boolean result = mDevice.pushFile(jarFile, mJarPath);
- assertTrue("Failed to push file to " + mJarPath, result);
- }
-
- @Override
- protected void tearDown() throws Exception {
- // Delete jar from device.
- mDevice.executeShellCommand("rm " + mJarPath);
- super.tearDown();
- }
-
- public void runUiAutomatorTest(String testName) throws Exception {
- // Delete any existing result files
- mDevice.executeShellCommand("rm -r " + DEVICE_LOCATION + "*.txt");
-
- // Run ui automator test.
- mDevice.executeShellCommand(
- String.format(RUN_UI_AUTOMATOR_CMD, mJarName, mDeviceTestClass + "#" + testName),
- new IShellOutputReceiver() {
- private StringBuilder sb = new StringBuilder();
-
- @Override
- public void addOutput(byte[] data, int offset, int length) {
- byte[] raw = new byte[length];
- for (int i = 0; i < length; i++) {
- raw[i] = data[i + offset];
- }
- sb.append(new String(raw));
- }
-
- @Override
- public void flush() {
- Log.logAndDisplay(LogLevel.INFO, TAG, sb.toString());
- }
-
- @Override
- public boolean isCancelled() {
- return false;
- }
- });
-
- // Pull result file across
- File result = mDevice.pullFile(DEVICE_LOCATION + "UiJankinessTestsOutput.txt");
- assertNotNull("Couldn't get result file", result);
- // Parse result file
- Scanner in = new Scanner(result);
- HashMap<String, Double> results = new HashMap<String, Double>(4);
- while (in.hasNextLine()) {
- String[] parts = in.nextLine().split(":");
- if (parts.length == 2) {
- results.put(parts[0], Double.parseDouble(parts[1]));
- }
- }
- in.close();
- Log.logAndDisplay(LogLevel.INFO, TAG, "Results: " + results);
- assertEquals("Could not parse the results file: ", 4, results.size());
-
- double avgNumJanks = results.get("average number of jankiness");
- double maxNumJanks = results.get("max number of jankiness");
- double avgFrameRate = results.get("average frame rate");
- double avgMaxAccFrames = results.get("average of max accumulated frames");
-
- // Create and deliver the report.
- HostReportLog report = new HostReportLog(mDevice.getSerialNumber(), mAbi.getName(),
- mHostTestClass + "#" + testName);
- report.printValue(
- "Average Frame Rate", avgFrameRate, ResultType.HIGHER_BETTER, ResultUnit.COUNT);
- report.printValue("Average of Maximum Accumulated Frames", avgMaxAccFrames,
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- report.printValue(
- "Maximum Number of Janks", maxNumJanks, ResultType.LOWER_BETTER, ResultUnit.COUNT);
- report.printSummary(
- "Average Number of Janks", avgNumJanks, ResultType.LOWER_BETTER, ResultUnit.SCORE);
- report.deliverReportToHost();
- }
-
-}
diff --git a/suite/cts/hostTests/jank/src/com/android/cts/jank/opengl/CtsHostJankOpenGl.java b/suite/cts/hostTests/jank/src/com/android/cts/jank/opengl/CtsHostJankOpenGl.java
deleted file mode 100644
index 2942ecf..0000000
--- a/suite/cts/hostTests/jank/src/com/android/cts/jank/opengl/CtsHostJankOpenGl.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.jank.opengl;
-
-import com.android.cts.jank.CtsHostJankTest;
-import com.android.cts.util.AbiUtils;
-import java.io.File;
-
-public class CtsHostJankOpenGl extends CtsHostJankTest {
-
- private static final String APK_PACKAGE = "com.android.cts";
- private static final String APK = "CtsDeviceOpenGl.apk";
- private static final String PACKAGE = "com.android.cts.jank.opengl";
- private static final String HOST_CLASS = CtsHostJankOpenGl.class.getName();
- private static final String DEVICE_CLASS = PACKAGE + ".CtsDeviceJankOpenGl";
- private static final String JAR_NAME = "CtsDeviceJank.jar";
-
- public CtsHostJankOpenGl() {
- super(JAR_NAME, DEVICE_CLASS, HOST_CLASS);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // Install the app.
- mDevice.uninstallPackage(APK_PACKAGE);
- File app = mBuild.getTestApp(APK);
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- mDevice.installPackage(app, false, options);
- }
-
- @Override
- protected void tearDown() throws Exception {
- // Uninstall the app.
- mDevice.uninstallPackage(APK_PACKAGE);
- super.tearDown();
- }
-
- public void testFullPipeline() throws Exception {
- runUiAutomatorTest("testFullPipeline");
- }
-
- public void testPixelOutput() throws Exception {
- runUiAutomatorTest("testPixelOutput");
- }
-
- public void testShaderPerf() throws Exception {
- runUiAutomatorTest("testShaderPerf");
- }
-
- public void testContextSwitch() throws Exception {
- runUiAutomatorTest("testContextSwitch");
- }
-}
diff --git a/suite/cts/hostTests/uihost/.gitignore b/suite/cts/hostTests/uihost/.gitignore
deleted file mode 100644
index 5e56e04..0000000
--- a/suite/cts/hostTests/uihost/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/bin
diff --git a/suite/cts/hostTests/uihost/Android.mk b/suite/cts/hostTests/uihost/Android.mk
deleted file mode 100644
index 67ebcbb..0000000
--- a/suite/cts/hostTests/uihost/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE := CtsHostUi
-
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_CTS_TEST_PACKAGE := com.android.cts.uihost
-
-include $(BUILD_CTS_HOST_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/cts/hostTests/uihost/appA/Android.mk b/suite/cts/hostTests/uihost/appA/Android.mk
deleted file mode 100644
index 17f076f..0000000
--- a/suite/cts/hostTests/uihost/appA/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceTaskswitchingAppA
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/suite/cts/hostTests/uihost/appA/AndroidManifest.xml b/suite/cts/hostTests/uihost/appA/AndroidManifest.xml
deleted file mode 100644
index b97325c..0000000
--- a/suite/cts/hostTests/uihost/appA/AndroidManifest.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2012 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.taskswitching.appa" >
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-
- <application>
- <activity
- android:name=".AppAActivity"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
- android:screenOrientation="portrait" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
-</manifest>
\ No newline at end of file
diff --git a/suite/cts/hostTests/uihost/appA/src/com/android/cts/taskswitching/appa/AppAActivity.java b/suite/cts/hostTests/uihost/appA/src/com/android/cts/taskswitching/appa/AppAActivity.java
deleted file mode 100644
index a4207a0..0000000
--- a/suite/cts/hostTests/uihost/appA/src/com/android/cts/taskswitching/appa/AppAActivity.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.taskswitching.appa;
-
-
-import android.app.ListActivity;
-import android.content.Intent;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.view.WindowManager;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-/**
- * Simple activity to notify completion via broadcast after onResume.
- * This is for measuring taskswitching time between two apps.
- */
-public class AppAActivity extends ListActivity {
- static final String TAG = "AppAActivity";
- private static final int NUMBER_ELEMENTS = 1000;
- private static final String TASKSWITCHING_INTENT = "com.android.cts.taskswitching.appa";
- private Handler mHandler;
-
- private String[] mItems = new String[NUMBER_ELEMENTS];
-
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
- for (int i = 0; i < NUMBER_ELEMENTS; i++) {
- mItems[i] = "A" + Integer.toString(i);
- }
- setListAdapter(new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1, mItems));
- ListView view = getListView();
- mHandler = new Handler();
- }
-
- public void onResume() {
- super.onResume();
- mHandler.post(new Runnable() {
-
- @Override
- public void run() {
- Intent intent = new Intent(TASKSWITCHING_INTENT);
- sendBroadcast(intent);
- }
- });
- }
-}
diff --git a/suite/cts/hostTests/uihost/appB/Android.mk b/suite/cts/hostTests/uihost/appB/Android.mk
deleted file mode 100644
index ebb36d2..0000000
--- a/suite/cts/hostTests/uihost/appB/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceTaskswitchingAppB
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/suite/cts/hostTests/uihost/appB/AndroidManifest.xml b/suite/cts/hostTests/uihost/appB/AndroidManifest.xml
deleted file mode 100644
index b96afe5..0000000
--- a/suite/cts/hostTests/uihost/appB/AndroidManifest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.taskswitching.appb">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-
- <application>
- <activity
- android:name=".AppBActivity"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
- android:screenOrientation="portrait" >
-
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
-</manifest>
diff --git a/suite/cts/hostTests/uihost/appB/src/com/android/cts/taskswitching/appb/AppBActivity.java b/suite/cts/hostTests/uihost/appB/src/com/android/cts/taskswitching/appb/AppBActivity.java
deleted file mode 100644
index 4df5e98..0000000
--- a/suite/cts/hostTests/uihost/appB/src/com/android/cts/taskswitching/appb/AppBActivity.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.taskswitching.appb;
-
-import android.app.ListActivity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.view.WindowManager;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-/**
- * Simple activity to notify completion via broadcast after onResume.
- * This is for measuring taskswitching time between two apps.
- */
-public class AppBActivity extends ListActivity {
- static final String TAG = "AppBActivity";
- private static final int NUMBER_ELEMENTS = 1000;
- private static final String TASKSWITCHING_INTENT = "com.android.cts.taskswitching.appb";
- private Handler mHandler;
-
- private String[] mItems = new String[NUMBER_ELEMENTS];
-
- public void onCreate(Bundle icicle)
- {
- super.onCreate(icicle);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
- for (int i = 0; i < NUMBER_ELEMENTS; i++) {
- mItems[i] = "B" + Integer.toString(i);
- }
- setListAdapter(new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1, mItems));
- ListView view = getListView();
- mHandler = new Handler();
- }
-
- public void onResume()
- {
- super.onResume();
- mHandler.post(new Runnable() {
-
- @Override
- public void run() {
- Intent intent = new Intent(TASKSWITCHING_INTENT);
- sendBroadcast(intent);
- }
- });
- }
-}
diff --git a/suite/cts/hostTests/uihost/control/Android.mk b/suite/cts/hostTests/uihost/control/Android.mk
deleted file mode 100644
index 4de9ae8..0000000
--- a/suite/cts/hostTests/uihost/control/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceTaskswitchingControl
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/suite/cts/hostTests/uihost/control/AndroidManifest.xml b/suite/cts/hostTests/uihost/control/AndroidManifest.xml
deleted file mode 100644
index e4b10f2..0000000
--- a/suite/cts/hostTests/uihost/control/AndroidManifest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.taskswitching.control">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation
- android:targetPackage="com.android.cts.taskswitching.control"
- android:name="android.support.test.runner.AndroidJUnitRunner" >
- <meta-data
- android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-</manifest>
diff --git a/suite/cts/hostTests/uihost/control/src/com/android/cts/taskswitching/control/TaskswitchingDeviceTest.java b/suite/cts/hostTests/uihost/control/src/com/android/cts/taskswitching/control/TaskswitchingDeviceTest.java
deleted file mode 100644
index bdb3132..0000000
--- a/suite/cts/hostTests/uihost/control/src/com/android/cts/taskswitching/control/TaskswitchingDeviceTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.taskswitching.control;
-
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-
-import com.android.cts.util.MeasureRun;
-import com.android.cts.util.MeasureTime;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import android.cts.util.CtsAndroidTestCase;
-import com.android.cts.util.Stat;
-
-
-/**
- * Device test which actually launches two apps sequentially and
- * measure time for switching.
- * Completion of launch is notified via broadcast.
- */
-public class TaskswitchingDeviceTest extends CtsAndroidTestCase {
- private static final String PKG_A = "com.android.cts.taskswitching.appa";
- private static final String PKG_B = "com.android.cts.taskswitching.appb";
- private static final String ACTIVITY_A = "AppAActivity";
- private static final String ACTIVITY_B = "AppBActivity";
- private static final long TASK_SWITCHING_WAIT_TIME = 5;
- private final AppBroadcastReceiver mReceiverA = new AppBroadcastReceiver();
- private final AppBroadcastReceiver mReceiverB = new AppBroadcastReceiver();
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- startActivity(PKG_A, ACTIVITY_A);
- startActivity(PKG_B, ACTIVITY_B);
- IntentFilter filterA = new IntentFilter();
- filterA.addAction(PKG_A);
- IntentFilter filterB = new IntentFilter();
- filterB.addAction(PKG_B);
- getContext().registerReceiver(mReceiverA, filterA);
- getContext().registerReceiver(mReceiverB, filterB);
- }
-
- @Override
- protected void tearDown() throws Exception {
- getContext().unregisterReceiver(mReceiverA);
- getContext().unregisterReceiver(mReceiverB);
- super.tearDown();
- }
-
- public void testMeasureTaskSwitching() throws Exception {
- final int NUMBER_REPEAT = 10;
- final int SWITCHING_PER_ONE_TRY = 10;
-
- double[] results = MeasureTime.measure(NUMBER_REPEAT, new MeasureRun() {
-
- @Override
- public void run(int i) throws Exception {
- for (int j = 0; j < SWITCHING_PER_ONE_TRY; j++) {
- startActivity(PKG_A, ACTIVITY_A);
- assertTrue(mReceiverA.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
- startActivity(PKG_B, ACTIVITY_B);
- assertTrue(mReceiverB.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
- }
- }
- });
- getReportLog().printArray("taskswitching time", results, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- Stat.StatResult stat = Stat.getStat(results);
- getReportLog().printSummary("taskswitching time", stat.mAverage,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- }
-
- private void startActivity(String packageName, String activityName) {
- Context context = getContext();
- Intent intent = new Intent();
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addCategory(Intent.CATEGORY_LAUNCHER);
- intent.setComponent(new ComponentName(packageName, packageName + "." + activityName));
- context.startActivity(intent);
- }
-
- class AppBroadcastReceiver extends BroadcastReceiver {
- private final Semaphore mSemaphore = new Semaphore(0);
-
- public boolean waitForBroadcast(long timeoutInSec) throws InterruptedException {
- return mSemaphore.tryAcquire(timeoutInSec, TimeUnit.SECONDS);
- }
- @Override
- public void onReceive(Context context, Intent intent) {
- mSemaphore.release();
- }
- }
-}
diff --git a/suite/cts/hostTests/uihost/src/com/android/cts/uihost/InstallTimeTest.java b/suite/cts/hostTests/uihost/src/com/android/cts/uihost/InstallTimeTest.java
deleted file mode 100644
index 75a2e92..0000000
--- a/suite/cts/hostTests/uihost/src/com/android/cts/uihost/InstallTimeTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uihost;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.tradefed.util.HostReportLog;
-import com.android.cts.util.AbiUtils;
-import com.android.cts.util.MeasureRun;
-import com.android.cts.util.MeasureTime;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.Stat;
-import com.android.ddmlib.Log;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.io.File;
-
-
-/**
- * Test to measure installation time of a APK.
- */
-public class InstallTimeTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
- private CtsBuildHelper mBuild;
- private ITestDevice mDevice;
- private IAbi mAbi;
-
- private static final String TAG = "InstallTimeTest";
- static final String PACKAGE = "com.replica.replicaisland";
- static final String APK = "com.replica.replicaisland.apk";
- private static final double OUTLIER_THRESHOLD = 0.1;
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mDevice = getDevice();
- }
-
-
- @Override
- protected void tearDown() throws Exception {
- mDevice.uninstallPackage(PACKAGE);
- super.tearDown();
- }
-
- public void testInstallTime() throws Exception {
- HostReportLog report = new HostReportLog(mDevice.getSerialNumber(), mAbi.getName(),
- ReportLog.getClassMethodNames());
- final int NUMBER_REPEAT = 10;
- final CtsBuildHelper build = mBuild;
- final ITestDevice device = mDevice;
- double[] result = MeasureTime.measure(NUMBER_REPEAT, new MeasureRun() {
- @Override
- public void prepare(int i) throws Exception {
- device.uninstallPackage(PACKAGE);
- }
- @Override
- public void run(int i) throws Exception {
- File app = build.getTestApp(APK);
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- device.installPackage(app, false, options);
- }
- });
- report.printArray("install time", result, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- Stat.StatResult stat = Stat.getStatWithOutlierRejection(result, OUTLIER_THRESHOLD);
- if (stat.mDataCount != result.length) {
- Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
- }
- report.printSummary("install time", stat.mAverage, ResultType.LOWER_BETTER,
- ResultUnit.MS);
- report.deliverReportToHost();
- }
-
-}
diff --git a/suite/cts/hostTests/uihost/src/com/android/cts/uihost/TaskSwitchingTest.java b/suite/cts/hostTests/uihost/src/com/android/cts/uihost/TaskSwitchingTest.java
deleted file mode 100644
index 2d33436..0000000
--- a/suite/cts/hostTests/uihost/src/com/android/cts/uihost/TaskSwitchingTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uihost;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.tradefed.util.CtsHostStore;
-import com.android.cts.tradefed.util.HostReportLog;
-import com.android.cts.util.AbiUtils;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.TimeoutReq;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestRunResult;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.io.File;
-import java.util.Map;
-
-
-/**
- * Measure time to taskswitching between two Apps: A & B
- * Actual test is done in device, but this host side code installs all necessary APKs
- * and starts device test which is in CtsDeviceTaskswitchingControl.
- */
-public class TaskSwitchingTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
- private static final String TAG = "TaskSwitchingTest";
- private final static String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
- private CtsBuildHelper mBuild;
- private ITestDevice mDevice;
- private String mCtsReport = null;
- private IAbi mAbi;
-
- static final String[] PACKAGES = {
- "com.android.cts.taskswitching.control",
- "com.android.cts.taskswitching.appa",
- "com.android.cts.taskswitching.appb"
- };
- static final String[] APKS = {
- "CtsDeviceTaskswitchingControl.apk",
- "CtsDeviceTaskswitchingAppA.apk",
- "CtsDeviceTaskswitchingAppB.apk"
- };
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mDevice = getDevice();
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- for (int i = 0; i < PACKAGES.length; i++) {
- mDevice.uninstallPackage(PACKAGES[i]);
- File app = mBuild.getTestApp(APKS[i]);
- mDevice.installPackage(app, false, options);
- }
- }
-
-
- @Override
- protected void tearDown() throws Exception {
- for (int i = 0; i < PACKAGES.length; i++) {
- mDevice.uninstallPackage(PACKAGES[i]);
- }
- super.tearDown();
- }
-
- @TimeoutReq(minutes = 30)
- public void testTaskswitching() throws Exception {
- // TODO is this used?
- HostReportLog report = new HostReportLog(mDevice.getSerialNumber(), mAbi.getName(),
- ReportLog.getClassMethodNames());
- RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(PACKAGES[0], RUNNER,
- mDevice.getIDevice());
- LocalListener listener = new LocalListener();
- mDevice.runInstrumentationTests(testRunner, listener);
- TestRunResult result = listener.getCurrentRunResults();
- if (result.isRunFailure()) {
- fail(result.getRunFailureMessage());
- }
- assertNotNull("no performance data", mCtsReport);
- CtsHostStore.storeCtsResult(mDevice.getSerialNumber(), mAbi.getName(),
- ReportLog.getClassMethodNames(), mCtsReport);
-
- }
-
- public class LocalListener extends CollectingTestListener {
- @Override
- public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
- // necessary as testMetrics passed from CollectingTestListerner is empty
- if (testMetrics.containsKey("CTS_TEST_RESULT")) {
- mCtsReport = testMetrics.get("CTS_TEST_RESULT");
- }
- super.testEnded(test, testMetrics);
- }
- }
-}
diff --git a/test_defs.sh b/test_defs.sh
new file mode 100644
index 0000000..5d5090d
--- /dev/null
+++ b/test_defs.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# 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.
+
+# Common tools for running unit tests of the compatibility libs
+
+JAR_DIR=${ANDROID_HOST_OUT}/framework
+TF_CONSOLE=com.android.tradefed.command.Console
+
+COMMON_JARS="
+ ddmlib-prebuilt\
+ hosttestlib\
+ tradefed-prebuilt"
+
+checkFile() {
+ if [ ! -f "$1" ]; then
+ echo "Unable to locate $1"
+ exit
+ fi;
+}
+
+build_jar_path() {
+ JAR_PATH=
+ for JAR in ${2} ${COMMON_JARS}; do
+ checkFile ${1}/${JAR}.jar
+ JAR_PATH=${JAR_PATH}:${1}/${JAR}.jar
+ done
+}
+
+run_tests() {
+ build_jar_path "${JAR_DIR}" "${2}"
+ for CLASS in ${1}; do
+ java $RDBG_FLAG -cp ${JAR_PATH} ${TF_CONSOLE} run singleCommand host -n --class ${CLASS} ${3}
+ done
+}
diff --git a/tests/JobScheduler/Android.mk b/tests/JobScheduler/Android.mk
index 499abded..fe5865d 100755
--- a/tests/JobScheduler/Android.mk
+++ b/tests/JobScheduler/Android.mk
@@ -26,8 +26,11 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# Must match the package name in CtsTestCaseList.mk
-LOCAL_PACKAGE_NAME := CtsJobSchedulerDeviceTestCases
+LOCAL_PACKAGE_NAME := CtsJobSchedulerTestCases
LOCAL_SDK_VERSION := current
diff --git a/tests/JobScheduler/AndroidManifest.xml b/tests/JobScheduler/AndroidManifest.xml
index 17cf399..2078978 100755
--- a/tests/JobScheduler/AndroidManifest.xml
+++ b/tests/JobScheduler/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.jobscheduler.cts.deviceside">
+ package="android.jobscheduler.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -35,7 +35,7 @@
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"
android:label="JobScheduler device-side tests"
- android:targetPackage="android.jobscheduler.cts.deviceside" >
+ android:targetPackage="android.jobscheduler.cts" >
<meta-data
android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/JobScheduler/AndroidTest.xml b/tests/JobScheduler/AndroidTest.xml
new file mode 100644
index 0000000..57a2f30
--- /dev/null
+++ b/tests/JobScheduler/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Job Scheduler test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsJobSchedulerTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.jobscheduler.cts" />
+ <option name="runtime-hint" value="2m" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/acceleration/Android.mk b/tests/acceleration/Android.mk
index f36b64b..87aa7c5 100644
--- a/tests/acceleration/Android.mk
+++ b/tests/acceleration/Android.mk
@@ -24,10 +24,15 @@
LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := CtsAccelerationTestStubs
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsAccelerationTestCases
LOCAL_SDK_VERSION := current
-include $(BUILD_CTS_SUPPORT_PACKAGE)
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/acceleration/AndroidManifest.xml b/tests/acceleration/AndroidManifest.xml
index f92b736..1a21554 100644
--- a/tests/acceleration/AndroidManifest.xml
+++ b/tests/acceleration/AndroidManifest.xml
@@ -15,15 +15,25 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.acceleration.stub">
+ package="android.acceleration.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application android:hardwareAccelerated="true">
- <activity android:name="android.acceleration.cts.HardwareAcceleratedActivity" />
- <activity android:name="android.acceleration.cts.SoftwareAcceleratedActivity"
+ <uses-library android:name="android.test.runner" />
+ <activity android:name="android.acceleration.HardwareAcceleratedActivity" />
+ <activity android:name="android.acceleration.SoftwareAcceleratedActivity"
android:hardwareAccelerated="false" />
- <activity android:name="android.acceleration.cts.WindowFlagHardwareAcceleratedActivity"
+ <activity android:name="android.acceleration.WindowFlagHardwareAcceleratedActivity"
android:hardwareAccelerated="false" />
</application>
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.acceleration.cts"
+ android:label="Tests for the Hardware Acceleration APIs." >
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
</manifest>
diff --git a/tests/acceleration/AndroidTest.xml b/tests/acceleration/AndroidTest.xml
new file mode 100644
index 0000000..1786c8e
--- /dev/null
+++ b/tests/acceleration/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Acceleration test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAccelerationTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.acceleration.cts" />
+ </test>
+</configuration>
diff --git a/tests/acceleration/res/layout/acceleration.xml b/tests/acceleration/res/layout/acceleration.xml
index 8dc027a..5127507 100644
--- a/tests/acceleration/res/layout/acceleration.xml
+++ b/tests/acceleration/res/layout/acceleration.xml
@@ -18,25 +18,25 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
- <android.acceleration.cts.AcceleratedView android:id="@+id/hardware_accelerated_view"
+ <android.acceleration.AcceleratedView android:id="@+id/hardware_accelerated_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layerType="hardware"
/>
- <android.acceleration.cts.AcceleratedView android:id="@+id/software_accelerated_view"
+ <android.acceleration.AcceleratedView android:id="@+id/software_accelerated_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layerType="software"
/>
<!-- Acceleration will be set via manual setLayerType calls from the activity. -->
- <android.acceleration.cts.AcceleratedView android:id="@+id/manual_hardware_accelerated_view"
+ <android.acceleration.AcceleratedView android:id="@+id/manual_hardware_accelerated_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
- <android.acceleration.cts.AcceleratedView android:id="@+id/manual_software_accelerated_view"
+ <android.acceleration.AcceleratedView android:id="@+id/manual_software_accelerated_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
diff --git a/tests/acceleration/src/android/acceleration/AcceleratedView.java b/tests/acceleration/src/android/acceleration/AcceleratedView.java
new file mode 100644
index 0000000..7134a76
--- /dev/null
+++ b/tests/acceleration/src/android/acceleration/AcceleratedView.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 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.acceleration;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class AcceleratedView extends View {
+
+ private final CountDownLatch mDrawLatch = new CountDownLatch(1);
+
+ private boolean mIsHardwareAccelerated;
+
+ public AcceleratedView(Context context) {
+ super(context);
+ }
+
+ public AcceleratedView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AcceleratedView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ synchronized (this) {
+ mIsHardwareAccelerated = canvas.isHardwareAccelerated();
+ }
+ mDrawLatch.countDown();
+ }
+
+ public boolean isCanvasHardwareAccelerated() {
+ try {
+ if (mDrawLatch.await(1, TimeUnit.SECONDS)) {
+ synchronized (this) {
+ return mIsHardwareAccelerated;
+ }
+ } else {
+ throw new IllegalStateException("View was not drawn...");
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/tests/acceleration/src/android/acceleration/BaseAcceleratedActivity.java b/tests/acceleration/src/android/acceleration/BaseAcceleratedActivity.java
new file mode 100644
index 0000000..262b43e
--- /dev/null
+++ b/tests/acceleration/src/android/acceleration/BaseAcceleratedActivity.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011 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.acceleration;
+
+import android.acceleration.cts.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+public abstract class BaseAcceleratedActivity extends Activity {
+
+ private AcceleratedView mHardwareAcceleratedView;
+ private AcceleratedView mSoftwareAcceleratedView;
+
+ private AcceleratedView mManualHardwareAcceleratedView;
+ private AcceleratedView mManualSoftwareAcceleratedView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.acceleration);
+
+ mHardwareAcceleratedView = (AcceleratedView) findViewById(R.id.hardware_accelerated_view);
+ mSoftwareAcceleratedView = (AcceleratedView) findViewById(R.id.software_accelerated_view);
+
+ mManualHardwareAcceleratedView =
+ (AcceleratedView) findViewById(R.id.manual_hardware_accelerated_view);
+ mManualSoftwareAcceleratedView =
+ (AcceleratedView) findViewById(R.id.manual_software_accelerated_view);
+
+ mManualHardwareAcceleratedView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ mManualSoftwareAcceleratedView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ }
+
+ public AcceleratedView getHardwareAcceleratedView() {
+ return mHardwareAcceleratedView;
+ }
+
+ public AcceleratedView getSoftwareAcceleratedView() {
+ return mSoftwareAcceleratedView;
+ }
+
+ public AcceleratedView getManualHardwareAcceleratedView() {
+ return mManualHardwareAcceleratedView;
+ }
+
+ public AcceleratedView getManualSoftwareAcceleratedView() {
+ return mManualSoftwareAcceleratedView;
+ }
+}
diff --git a/tests/acceleration/src/android/acceleration/HardwareAcceleratedActivity.java b/tests/acceleration/src/android/acceleration/HardwareAcceleratedActivity.java
new file mode 100644
index 0000000..9122565
--- /dev/null
+++ b/tests/acceleration/src/android/acceleration/HardwareAcceleratedActivity.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2011 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.acceleration;
+
+public class HardwareAcceleratedActivity extends BaseAcceleratedActivity {
+}
diff --git a/tests/acceleration/src/android/acceleration/SoftwareAcceleratedActivity.java b/tests/acceleration/src/android/acceleration/SoftwareAcceleratedActivity.java
new file mode 100644
index 0000000..7555862
--- /dev/null
+++ b/tests/acceleration/src/android/acceleration/SoftwareAcceleratedActivity.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2011 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.acceleration;
+
+public class SoftwareAcceleratedActivity extends BaseAcceleratedActivity {
+}
diff --git a/tests/acceleration/src/android/acceleration/WindowFlagHardwareAcceleratedActivity.java b/tests/acceleration/src/android/acceleration/WindowFlagHardwareAcceleratedActivity.java
new file mode 100644
index 0000000..d448334
--- /dev/null
+++ b/tests/acceleration/src/android/acceleration/WindowFlagHardwareAcceleratedActivity.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 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.acceleration;
+
+import android.os.Bundle;
+import android.view.WindowManager;
+
+public class WindowFlagHardwareAcceleratedActivity extends BaseAcceleratedActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+ }
+}
diff --git a/tests/acceleration/src/android/acceleration/cts/AcceleratedView.java b/tests/acceleration/src/android/acceleration/cts/AcceleratedView.java
deleted file mode 100644
index 7d749a1..0000000
--- a/tests/acceleration/src/android/acceleration/cts/AcceleratedView.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2011 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.acceleration.cts;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.view.View;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-public class AcceleratedView extends View {
-
- private final CountDownLatch mDrawLatch = new CountDownLatch(1);
-
- private boolean mIsHardwareAccelerated;
-
- public AcceleratedView(Context context) {
- super(context);
- }
-
- public AcceleratedView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public AcceleratedView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- synchronized (this) {
- mIsHardwareAccelerated = canvas.isHardwareAccelerated();
- }
- mDrawLatch.countDown();
- }
-
- public boolean isCanvasHardwareAccelerated() {
- try {
- if (mDrawLatch.await(1, TimeUnit.SECONDS)) {
- synchronized (this) {
- return mIsHardwareAccelerated;
- }
- } else {
- throw new IllegalStateException("View was not drawn...");
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/tests/acceleration/src/android/acceleration/cts/BaseAcceleratedActivity.java b/tests/acceleration/src/android/acceleration/cts/BaseAcceleratedActivity.java
deleted file mode 100644
index 8ef6a8e..0000000
--- a/tests/acceleration/src/android/acceleration/cts/BaseAcceleratedActivity.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2011 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.acceleration.cts;
-
-import com.android.cts.acceleration.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.View;
-
-abstract class BaseAcceleratedActivity extends Activity {
-
- private AcceleratedView mHardwareAcceleratedView;
- private AcceleratedView mSoftwareAcceleratedView;
-
- private AcceleratedView mManualHardwareAcceleratedView;
- private AcceleratedView mManualSoftwareAcceleratedView;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.acceleration);
-
- mHardwareAcceleratedView = (AcceleratedView) findViewById(R.id.hardware_accelerated_view);
- mSoftwareAcceleratedView = (AcceleratedView) findViewById(R.id.software_accelerated_view);
-
- mManualHardwareAcceleratedView =
- (AcceleratedView) findViewById(R.id.manual_hardware_accelerated_view);
- mManualSoftwareAcceleratedView =
- (AcceleratedView) findViewById(R.id.manual_software_accelerated_view);
-
- mManualHardwareAcceleratedView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- mManualSoftwareAcceleratedView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- }
-
- public AcceleratedView getHardwareAcceleratedView() {
- return mHardwareAcceleratedView;
- }
-
- public AcceleratedView getSoftwareAcceleratedView() {
- return mSoftwareAcceleratedView;
- }
-
- public AcceleratedView getManualHardwareAcceleratedView() {
- return mManualHardwareAcceleratedView;
- }
-
- public AcceleratedView getManualSoftwareAcceleratedView() {
- return mManualSoftwareAcceleratedView;
- }
-}
diff --git a/tests/acceleration/src/android/acceleration/cts/BaseAccelerationTest.java b/tests/acceleration/src/android/acceleration/cts/BaseAccelerationTest.java
new file mode 100644
index 0000000..c6e94ec
--- /dev/null
+++ b/tests/acceleration/src/android/acceleration/cts/BaseAccelerationTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 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.acceleration.cts;
+
+import android.acceleration.AcceleratedView;
+import android.acceleration.BaseAcceleratedActivity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FeatureInfo;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.View;
+
+abstract class BaseAccelerationTest<B extends BaseAcceleratedActivity>
+ extends ActivityInstrumentationTestCase2<B> {
+
+ protected B mActivity;
+
+ /** View with android:layerType="hardware" set */
+ protected AcceleratedView mHardwareView;
+
+ /** View with android:layerType="software" set */
+ protected AcceleratedView mSoftwareView;
+
+ /** View with setLayerType(HARDWARE) called */
+ protected AcceleratedView mManualHardwareView;
+
+ /** View with setLayerType(SOFTWARE) called */
+ protected AcceleratedView mManualSoftwareView;
+
+ BaseAccelerationTest(Class<B> clazz) {
+ super(clazz);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ mHardwareView = mActivity.getHardwareAcceleratedView();
+ mSoftwareView = mActivity.getSoftwareAcceleratedView();
+ mManualHardwareView = mActivity.getManualHardwareAcceleratedView();
+ mManualSoftwareView = mActivity.getManualSoftwareAcceleratedView();
+ }
+
+ public void testNotAttachedView() {
+ // Views that are not attached can't be attached to an accelerated window.
+ View view = new View(mActivity);
+ assertFalse(view.isHardwareAccelerated());
+ }
+
+ protected static int getGlEsVersion(Context context) {
+ ActivityManager activityManager =
+ (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
+ if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) {
+ return getMajorVersion(configInfo.reqGlEsVersion);
+ } else {
+ return 1; // Lack of property means OpenGL ES version 1
+ }
+ }
+
+ /** @see FeatureInfo#getGlEsVersion() */
+ private static int getMajorVersion(int glEsVersion) {
+ return ((glEsVersion & 0xffff0000) >> 16);
+ }
+}
diff --git a/tests/acceleration/src/android/acceleration/cts/HardwareAcceleratedActivity.java b/tests/acceleration/src/android/acceleration/cts/HardwareAcceleratedActivity.java
deleted file mode 100644
index bb26202..0000000
--- a/tests/acceleration/src/android/acceleration/cts/HardwareAcceleratedActivity.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2011 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.acceleration.cts;
-
-public class HardwareAcceleratedActivity extends BaseAcceleratedActivity {
-}
diff --git a/tests/acceleration/src/android/acceleration/cts/HardwareAccelerationTest.java b/tests/acceleration/src/android/acceleration/cts/HardwareAccelerationTest.java
new file mode 100644
index 0000000..94089cc
--- /dev/null
+++ b/tests/acceleration/src/android/acceleration/cts/HardwareAccelerationTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 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.acceleration.cts;
+
+import android.acceleration.HardwareAcceleratedActivity;
+
+/**
+ * Test that uses an Activity with hardware acceleration enabled.
+ */
+public class HardwareAccelerationTest
+ extends BaseAccelerationTest<HardwareAcceleratedActivity> {
+
+ public HardwareAccelerationTest() {
+ super(HardwareAcceleratedActivity.class);
+ }
+
+ public void testIsHardwareAccelerated() {
+ // Hardware acceleration should be available on devices with GL ES 2 or higher...
+ if (getGlEsVersion(mActivity) >= 2) {
+ // Both of the views are attached to a hardware accelerated window
+ assertTrue(mHardwareView.isHardwareAccelerated());
+ assertTrue(mSoftwareView.isHardwareAccelerated());
+ assertTrue(mManualHardwareView.isHardwareAccelerated());
+ assertTrue(mManualSoftwareView.isHardwareAccelerated());
+
+ assertTrue(mHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
+ assertTrue(mManualHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
+ } else {
+ assertFalse(mHardwareView.isHardwareAccelerated());
+ assertFalse(mSoftwareView.isHardwareAccelerated());
+ assertFalse(mManualHardwareView.isHardwareAccelerated());
+ assertFalse(mManualSoftwareView.isHardwareAccelerated());
+
+ assertFalse(mHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
+ assertFalse(mManualHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
+ }
+ }
+}
diff --git a/tests/acceleration/src/android/acceleration/cts/SoftwareAcceleratedActivity.java b/tests/acceleration/src/android/acceleration/cts/SoftwareAcceleratedActivity.java
deleted file mode 100644
index 0a6a3df..0000000
--- a/tests/acceleration/src/android/acceleration/cts/SoftwareAcceleratedActivity.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2011 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.acceleration.cts;
-
-public class SoftwareAcceleratedActivity extends BaseAcceleratedActivity {
-}
diff --git a/tests/acceleration/src/android/acceleration/cts/SoftwareAccelerationTest.java b/tests/acceleration/src/android/acceleration/cts/SoftwareAccelerationTest.java
new file mode 100644
index 0000000..4e12c1e
--- /dev/null
+++ b/tests/acceleration/src/android/acceleration/cts/SoftwareAccelerationTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 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.acceleration.cts;
+
+import android.acceleration.SoftwareAcceleratedActivity;
+
+/**
+ * Test that uses an Activity with hardware acceleration explicitly disabled
+ * and makes sure that all views are rendered using software acceleration.
+ */
+public class SoftwareAccelerationTest
+ extends BaseAccelerationTest<SoftwareAcceleratedActivity> {
+
+ public SoftwareAccelerationTest() {
+ super(SoftwareAcceleratedActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ }
+
+ public void testIsHardwareAccelerated() {
+ // Both of the views are not attached to a hardware accelerated window
+ assertFalse(mHardwareView.isHardwareAccelerated());
+ assertFalse(mSoftwareView.isHardwareAccelerated());
+ assertFalse(mManualHardwareView.isHardwareAccelerated());
+ assertFalse(mManualSoftwareView.isHardwareAccelerated());
+
+ assertFalse(mHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
+ assertFalse(mManualHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
+ }
+}
diff --git a/tests/acceleration/src/android/acceleration/cts/WindowFlagHardwareAcceleratedActivity.java b/tests/acceleration/src/android/acceleration/cts/WindowFlagHardwareAcceleratedActivity.java
deleted file mode 100644
index 9def8b7..0000000
--- a/tests/acceleration/src/android/acceleration/cts/WindowFlagHardwareAcceleratedActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2011 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.acceleration.cts;
-
-import android.os.Bundle;
-import android.view.WindowManager;
-
-public class WindowFlagHardwareAcceleratedActivity extends BaseAcceleratedActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
- }
-}
diff --git a/tests/acceleration/src/android/acceleration/cts/WindowFlagHardwareAccelerationTest.java b/tests/acceleration/src/android/acceleration/cts/WindowFlagHardwareAccelerationTest.java
new file mode 100644
index 0000000..2070666
--- /dev/null
+++ b/tests/acceleration/src/android/acceleration/cts/WindowFlagHardwareAccelerationTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 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.acceleration.cts;
+
+import android.acceleration.WindowFlagHardwareAcceleratedActivity;
+
+/**
+ * Test that uses an Activity with hardware acceleration enabled.
+ */
+public class WindowFlagHardwareAccelerationTest
+ extends BaseAccelerationTest<WindowFlagHardwareAcceleratedActivity> {
+
+ public WindowFlagHardwareAccelerationTest() {
+ super(WindowFlagHardwareAcceleratedActivity.class);
+ }
+
+ public void testIsHardwareAccelerated() {
+ // Hardware acceleration should be available on devices with GL ES 2 or higher...
+ if (getGlEsVersion(mActivity) >= 2) {
+ // Both of the views are attached to a hardware accelerated window
+ assertTrue(mHardwareView.isHardwareAccelerated());
+ assertTrue(mSoftwareView.isHardwareAccelerated());
+ assertTrue(mManualHardwareView.isHardwareAccelerated());
+ assertTrue(mManualSoftwareView.isHardwareAccelerated());
+
+ assertTrue(mHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
+ assertTrue(mManualHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
+ } else {
+ assertFalse(mHardwareView.isHardwareAccelerated());
+ assertFalse(mSoftwareView.isHardwareAccelerated());
+ assertFalse(mManualHardwareView.isHardwareAccelerated());
+ assertFalse(mManualSoftwareView.isHardwareAccelerated());
+
+ assertFalse(mHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
+ assertFalse(mManualHardwareView.isCanvasHardwareAccelerated());
+ assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
+ }
+ }
+}
diff --git a/tests/accessibility/Android.mk b/tests/accessibility/Android.mk
index bddbb58..f324ad9 100644
--- a/tests/accessibility/Android.mk
+++ b/tests/accessibility/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 The Android Open Source Project
+# Copyright (C) 2012 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.
@@ -18,14 +18,21 @@
LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := CtsSomeAccessibilityServices
+LOCAL_PACKAGE_NAME := CtsAccessibilityTestCases
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
LOCAL_SDK_VERSION := current
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+include $(BUILD_CTS_PACKAGE)
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/accessibility/AndroidManifest.xml b/tests/accessibility/AndroidManifest.xml
index dde1de8..69c6479 100644
--- a/tests/accessibility/AndroidManifest.xml
+++ b/tests/accessibility/AndroidManifest.xml
@@ -17,30 +17,19 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.view.accessibility.services">
+ package="android.view.accessibility.cts">
- <application>
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <service android:name=".SpeakingAccessibilityService"
- android:label="@string/title_speaking_accessibility_service"
- android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
- <intent-filter>
- <action android:name="android.accessibilityservice.AccessibilityService"/>
- </intent-filter>
- <meta-data android:name="android.accessibilityservice"
- android:resource="@xml/speaking_accessibilityservice" />
- </service>
+ <application android:theme="@android:style/Theme.Holo.NoActionBar" >
+ <uses-library android:name="android.test.runner"/>
+ </application>
- <service android:name=".VibratingAccessibilityService"
- android:label="@string/title_vibrating_accessibility_service"
- android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
- <intent-filter>
- <action android:name="android.accessibilityservice.AccessibilityService"/>
- </intent-filter>
- <meta-data android:name="android.accessibilityservice"
- android:resource="@xml/vibrating_accessibilityservice" />
- </service>
-
- </application>
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.view.accessibility.cts"
+ android:label="Tests for the accessibility APIs.">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
</manifest>
diff --git a/tests/accessibility/AndroidTest.xml b/tests/accessibility/AndroidTest.xml
new file mode 100644
index 0000000..7c7c480
--- /dev/null
+++ b/tests/accessibility/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<configuration description="Config for CTS Accessibility test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAccessibilityTestCases.apk" />
+ <option name="test-file-name" value="CtsSomeAccessibilityServices.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer" >
+ <option name="run-command" value="settings --user cur put secure enabled_accessibility_services android.view.accessibility.services/.SpeakingAccessibilityService:android.view.accessibility.services/.VibratingAccessibilityService" />
+ <option name="run-command" value="settings --user cur put secure touch_exploration_granted_accessibility_services android.view.accessibility.services/.SpeakingAccessibilityService:android.view.accessibility.services/.VibratingAccessibilityService" />
+ <option name="run-command" value="settings --user cur put secure accessibility_enabled 1" />
+ <option name="teardown-command" value="settings --user cur put secure enabled_accessibility_services """ />
+ <option name="teardown-command" value="settings --user cur put secure touch_exploration_granted_accessibility_services """ />
+ <option name="teardown-command" value="settings --user cur put secure accessibility_enabled 0" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.view.accessibility.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/accessibility/OldAndroidTest.xml b/tests/accessibility/OldAndroidTest.xml
new file mode 100644
index 0000000..d127319
--- /dev/null
+++ b/tests/accessibility/OldAndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Base config for CTS package preparer">
+ <include name="common-config" />
+ <option name="run-command:run-command" value="settings --user cur put secure enabled_accessibility_services android.view.accessibility.services/.SpeakingAccessibilityService:android.view.accessibility.services/.VibratingAccessibilityService" />
+ <option name="run-command:run-command" value="settings --user cur put secure touch_exploration_granted_accessibility_services android.view.accessibility.services/.SpeakingAccessibilityService:android.view.accessibility.services/.VibratingAccessibilityService" />
+ <option name="run-command:run-command" value="settings --user cur put secure accessibility_enabled 1" />
+ <option name="run-command:teardown-command" value="settings --user cur put secure enabled_accessibility_services """ />
+ <option name="run-command:teardown-command" value="settings --user cur put secure touch_exploration_granted_accessibility_services """ />
+ <option name="run-command:teardown-command" value="settings --user cur put secure accessibility_enabled 0" />
+ <option name="cts-apk-installer:test-file-name" value="CtsSomeAccessibilityServices.apk" />
+</configuration>
diff --git a/tests/tests/accessibility/res/values/ids.xml b/tests/accessibility/res/values/ids.xml
similarity index 100%
rename from tests/tests/accessibility/res/values/ids.xml
rename to tests/accessibility/res/values/ids.xml
diff --git a/tests/accessibility/service/Android.mk b/tests/accessibility/service/Android.mk
new file mode 100644
index 0000000..b0ba086
--- /dev/null
+++ b/tests/accessibility/service/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2010 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSomeAccessibilityServices
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/accessibility/service/AndroidManifest.xml b/tests/accessibility/service/AndroidManifest.xml
new file mode 100644
index 0000000..dde1de8
--- /dev/null
+++ b/tests/accessibility/service/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2012 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.view.accessibility.services">
+
+ <application>
+
+ <service android:name=".SpeakingAccessibilityService"
+ android:label="@string/title_speaking_accessibility_service"
+ android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+ <intent-filter>
+ <action android:name="android.accessibilityservice.AccessibilityService"/>
+ </intent-filter>
+ <meta-data android:name="android.accessibilityservice"
+ android:resource="@xml/speaking_accessibilityservice" />
+ </service>
+
+ <service android:name=".VibratingAccessibilityService"
+ android:label="@string/title_vibrating_accessibility_service"
+ android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+ <intent-filter>
+ <action android:name="android.accessibilityservice.AccessibilityService"/>
+ </intent-filter>
+ <meta-data android:name="android.accessibilityservice"
+ android:resource="@xml/vibrating_accessibilityservice" />
+ </service>
+
+ </application>
+
+</manifest>
diff --git a/tests/accessibility/res/values/strings.xml b/tests/accessibility/service/res/values/strings.xml
similarity index 100%
rename from tests/accessibility/res/values/strings.xml
rename to tests/accessibility/service/res/values/strings.xml
diff --git a/tests/accessibility/res/xml/speaking_accessibilityservice.xml b/tests/accessibility/service/res/xml/speaking_accessibilityservice.xml
similarity index 100%
rename from tests/accessibility/res/xml/speaking_accessibilityservice.xml
rename to tests/accessibility/service/res/xml/speaking_accessibilityservice.xml
diff --git a/tests/accessibility/res/xml/vibrating_accessibilityservice.xml b/tests/accessibility/service/res/xml/vibrating_accessibilityservice.xml
similarity index 100%
rename from tests/accessibility/res/xml/vibrating_accessibilityservice.xml
rename to tests/accessibility/service/res/xml/vibrating_accessibilityservice.xml
diff --git a/tests/accessibility/src/android/view/accessibility/services/SpeakingAccessibilityService.java b/tests/accessibility/service/src/android/view/accessibility/services/SpeakingAccessibilityService.java
similarity index 100%
rename from tests/accessibility/src/android/view/accessibility/services/SpeakingAccessibilityService.java
rename to tests/accessibility/service/src/android/view/accessibility/services/SpeakingAccessibilityService.java
diff --git a/tests/accessibility/src/android/view/accessibility/services/VibratingAccessibilityService.java b/tests/accessibility/service/src/android/view/accessibility/services/VibratingAccessibilityService.java
similarity index 100%
rename from tests/accessibility/src/android/view/accessibility/services/VibratingAccessibilityService.java
rename to tests/accessibility/service/src/android/view/accessibility/services/VibratingAccessibilityService.java
diff --git a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java
similarity index 100%
rename from tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java
rename to tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java
diff --git a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
similarity index 100%
rename from tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
rename to tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
new file mode 100644
index 0000000..30847a5
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2012 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.accessibility.cts;
+
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.accessibility.cts.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class for testing {@link AccessibilityNodeInfo}.
+ */
+public class AccessibilityNodeInfoTest extends AndroidTestCase {
+
+ /** The number of properties of the {@link AccessibilityNodeInfo} class. */
+ private static final int NON_STATIC_FIELD_COUNT = 30;
+
+ @SmallTest
+ public void testMarshaling() throws Exception {
+ // no new fields, so we are testing marshaling of all such
+ AccessibilityRecordTest.assertNoNewNonStaticFieldsAdded(AccessibilityNodeInfo.class,
+ NON_STATIC_FIELD_COUNT);
+
+ // fully populate the node info to marshal
+ AccessibilityNodeInfo sentInfo = AccessibilityNodeInfo.obtain(new View(getContext()));
+ fullyPopulateAccessibilityNodeInfo(sentInfo);
+
+ // marshal and unmarshal the node info
+ Parcel parcel = Parcel.obtain();
+ sentInfo.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ AccessibilityNodeInfo receivedInfo = AccessibilityNodeInfo.CREATOR.createFromParcel(parcel);
+
+ // make sure all fields properly marshaled
+ assertEqualsAccessibilityNodeInfo(sentInfo, receivedInfo);
+ }
+
+ /**
+ * Tests if {@link AccessibilityNodeInfo}s are properly reused.
+ */
+ @SmallTest
+ public void testReuse() {
+ AccessibilityEvent firstInfo = AccessibilityEvent.obtain();
+ firstInfo.recycle();
+ AccessibilityEvent secondInfo = AccessibilityEvent.obtain();
+ assertSame("AccessibilityNodeInfo not properly reused", firstInfo, secondInfo);
+ }
+
+ /**
+ * Tests if {@link AccessibilityNodeInfo} are properly recycled.
+ */
+ @SmallTest
+ public void testRecycle() {
+ // obtain and populate an node info
+ AccessibilityNodeInfo populatedInfo = AccessibilityNodeInfo.obtain();
+ fullyPopulateAccessibilityNodeInfo(populatedInfo);
+
+ // recycle and obtain the same recycled instance
+ populatedInfo.recycle();
+ AccessibilityNodeInfo recycledInfo = AccessibilityNodeInfo.obtain();
+
+ // check expectations
+ assertAccessibilityNodeInfoCleared(recycledInfo);
+ }
+
+ /**
+ * Tests whether the event describes its contents consistently.
+ */
+ @SmallTest
+ public void testDescribeContents() {
+ AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+ assertSame("Accessibility node infos always return 0 for this method.", 0,
+ info.describeContents());
+ fullyPopulateAccessibilityNodeInfo(info);
+ assertSame("Accessibility node infos always return 0 for this method.", 0,
+ info.describeContents());
+ }
+
+ /**
+ * Tests whether accessibility actions are properly added.
+ */
+ @SmallTest
+ public void testAddActions() {
+ List<AccessibilityAction> customActions = new ArrayList<AccessibilityAction>();
+ customActions.add(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo"));
+ customActions.add(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
+
+ AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+ info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
+ info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
+ for (AccessibilityAction customAction : customActions) {
+ info.addAction(customAction);
+ }
+
+ assertSame(info.getActions(), (AccessibilityNodeInfo.ACTION_FOCUS
+ | AccessibilityNodeInfo.ACTION_CLEAR_FOCUS));
+
+ List<AccessibilityAction> allActions = new ArrayList<AccessibilityAction>();
+ allActions.add(AccessibilityAction.ACTION_CLEAR_FOCUS);
+ allActions.addAll(customActions);
+ assertEquals(info.getActionList(), allActions);
+ }
+
+ /**
+ * Tests whether we catch addition of an action with invalid id.
+ */
+ @SmallTest
+ public void testCreateInvalidActionId() {
+ try {
+ new AccessibilityAction(3, null);
+ } catch (IllegalArgumentException iae) {
+ /* expected */
+ }
+ }
+
+ /**
+ * Tests whether accessibility actions are properly removed.
+ */
+ @SmallTest
+ public void testRemoveActions() {
+ AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+
+ info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
+ assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS);
+
+ info.removeAction(AccessibilityNodeInfo.ACTION_FOCUS);
+ assertSame(info.getActions(), 0);
+ assertTrue(info.getActionList().isEmpty());
+
+ AccessibilityAction customFocus = new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_FOCUS, "Foo");
+ info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
+ info.addAction(customFocus);
+ assertSame(info.getActionList().size(), 1);
+ assertEquals(info.getActionList().get(0), customFocus);
+ assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS);
+
+ info.removeAction(customFocus);
+ assertSame(info.getActions(), 0);
+ assertTrue(info.getActionList().isEmpty());
+ }
+
+ /**
+ * Fully populates the {@link AccessibilityNodeInfo} to marshal.
+ *
+ * @param info The node info to populate.
+ */
+ private void fullyPopulateAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ info.setParent(new View(getContext()));
+ info.setSource(new View(getContext()));
+ info.addChild(new View(getContext()));
+ info.addChild(new View(getContext()), 1);
+ info.setBoundsInParent(new Rect(1,1,1,1));
+ info.setBoundsInScreen(new Rect(2,2,2,2));
+ info.setClassName("foo.bar.baz.Class");
+ info.setContentDescription("content description");
+ info.setPackageName("foo.bar.baz");
+ info.setText("text");
+ info.setCheckable(true);
+ info.setChecked(true);
+ info.setClickable(true);
+ info.setEnabled(true);
+ info.setFocusable(true);
+ info.setFocused(true);
+ info.setLongClickable(true);
+ info.setContextClickable(true);
+ info.setPassword(true);
+ info.setScrollable(true);
+ info.setSelected(true);
+ info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
+ info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
+ info.addAction(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo"));
+ info.addAction(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
+ info.setAccessibilityFocused(true);
+ info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ info.setLabeledBy(new View(getContext()));
+ info.setLabelFor(new View(getContext()));
+ info.setViewIdResourceName("foo.bar:id/baz");
+ }
+
+ /**
+ * Compares all properties of the <code>expectedInfo</code> and the
+ * <code>receviedInfo</code> to verify that the received node info is
+ * the one that is expected.
+ */
+ public static void assertEqualsAccessibilityNodeInfo(AccessibilityNodeInfo expectedInfo,
+ AccessibilityNodeInfo receivedInfo) {
+ Rect expectedBounds = new Rect();
+ Rect receivedBounds = new Rect();
+ expectedInfo.getBoundsInParent(expectedBounds);
+ receivedInfo.getBoundsInParent(receivedBounds);
+ assertEquals("boundsInParent has incorrect value", expectedBounds, receivedBounds);
+ expectedInfo.getBoundsInScreen(expectedBounds);
+ receivedInfo.getBoundsInScreen(receivedBounds);
+ assertEquals("boundsInScreen has incorrect value", expectedBounds, receivedBounds);
+ assertEquals("className has incorrect value", expectedInfo.getClassName(),
+ receivedInfo.getClassName());
+ assertEquals("contentDescription has incorrect value", expectedInfo.getContentDescription(),
+ receivedInfo.getContentDescription());
+ assertEquals("packageName has incorrect value", expectedInfo.getPackageName(),
+ receivedInfo.getPackageName());
+ assertEquals("text has incorrect value", expectedInfo.getText(), receivedInfo.getText());
+ assertSame("checkable has incorrect value", expectedInfo.isCheckable(),
+ receivedInfo.isCheckable());
+ assertSame("checked has incorrect value", expectedInfo.isChecked(),
+ receivedInfo.isChecked());
+ assertSame("clickable has incorrect value", expectedInfo.isClickable(),
+ receivedInfo.isClickable());
+ assertSame("enabled has incorrect value", expectedInfo.isEnabled(),
+ receivedInfo.isEnabled());
+ assertSame("focusable has incorrect value", expectedInfo.isFocusable(),
+ receivedInfo.isFocusable());
+ assertSame("focused has incorrect value", expectedInfo.isFocused(),
+ receivedInfo.isFocused());
+ assertSame("longClickable has incorrect value", expectedInfo.isLongClickable(),
+ receivedInfo.isLongClickable());
+ assertSame("contextClickable has incorrect value", expectedInfo.isContextClickable(),
+ receivedInfo.isContextClickable());
+ assertSame("password has incorrect value", expectedInfo.isPassword(),
+ receivedInfo.isPassword());
+ assertSame("scrollable has incorrect value", expectedInfo.isScrollable(),
+ receivedInfo.isScrollable());
+ assertSame("selected has incorrect value", expectedInfo.isSelected(),
+ receivedInfo.isSelected());
+ assertSame("actions has incorrect value", expectedInfo.getActions(),
+ receivedInfo.getActions());
+ assertEquals("actionsSet has incorrect value", expectedInfo.getActionList(),
+ receivedInfo.getActionList());
+ assertSame("childCount has incorrect value", expectedInfo.getChildCount(),
+ receivedInfo.getChildCount());
+ assertSame("childCount has incorrect value", expectedInfo.getChildCount(),
+ receivedInfo.getChildCount());
+ assertSame("accessibilityFocused has incorrect value",
+ expectedInfo.isAccessibilityFocused(),
+ receivedInfo.isAccessibilityFocused());
+ assertSame("movementGranularities has incorrect value",
+ expectedInfo.getMovementGranularities(),
+ receivedInfo.getMovementGranularities());
+ assertEquals("viewId has incorrect value", expectedInfo.getViewIdResourceName(),
+ receivedInfo.getViewIdResourceName());
+ }
+
+ /**
+ * Asserts that an {@link AccessibilityNodeInfo} is cleared.
+ *
+ * @param info The node info to check.
+ */
+ public static void assertAccessibilityNodeInfoCleared(AccessibilityNodeInfo info) {
+ Rect bounds = new Rect();
+ info.getBoundsInParent(bounds);
+ assertTrue("boundsInParent not properly recycled", bounds.isEmpty());
+ info.getBoundsInScreen(bounds);
+ assertTrue("boundsInScreen not properly recycled", bounds.isEmpty());
+ assertNull("className not properly recycled", info.getClassName());
+ assertNull("contentDescription not properly recycled", info.getContentDescription());
+ assertNull("packageName not properly recycled", info.getPackageName());
+ assertNull("text not properly recycled", info.getText());
+ assertFalse("checkable not properly recycled", info.isCheckable());
+ assertFalse("checked not properly recycled", info.isChecked());
+ assertFalse("clickable not properly recycled", info.isClickable());
+ assertFalse("enabled not properly recycled", info.isEnabled());
+ assertFalse("focusable not properly recycled", info.isFocusable());
+ assertFalse("focused not properly recycled", info.isFocused());
+ assertFalse("longClickable not properly recycled", info.isLongClickable());
+ assertFalse("contextClickable not properly recycled", info.isContextClickable());
+ assertFalse("password not properly recycled", info.isPassword());
+ assertFalse("scrollable not properly recycled", info.isScrollable());
+ assertFalse("selected not properly recycled", info.isSelected());
+ assertSame("actions not properly recycled", 0, info.getActions());
+ assertFalse("accessibilityFocused not properly recycled", info.isAccessibilityFocused());
+ assertSame("movementGranularities not properly recycled", 0,
+ info.getMovementGranularities());
+ assertNull("viewId not properly recycled", info.getViewIdResourceName());
+ }
+}
diff --git a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java
similarity index 100%
rename from tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java
rename to tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java
diff --git a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
similarity index 100%
rename from tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
rename to tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
diff --git a/tests/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java
similarity index 100%
rename from tests/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java
rename to tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java
diff --git a/tests/accessibilityservice/Android.mk b/tests/accessibilityservice/Android.mk
new file mode 100644
index 0000000..6d757e1
--- /dev/null
+++ b/tests/accessibilityservice/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2010 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsAccessibilityServiceTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
new file mode 100644
index 0000000..f93e441
--- /dev/null
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2010 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.accessibilityservice.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+ <application android:theme="@android:style/Theme.Holo.NoActionBar" >
+
+ <uses-library android:name="android.test.runner"/>
+
+ <activity android:label="@string/accessibility_end_to_end_test_activity"
+ android:name=".AccessibilityEndToEndActivity"/>
+
+ <activity android:label="@string/accessibility_query_window_test_activity"
+ android:name=".AccessibilityWindowQueryActivity"/>
+
+ <activity android:label="@string/accessibility_view_tree_reporting_test_activity"
+ android:name=".AccessibilityViewTreeReportingActivity"/>
+
+ <activity android:label="@string/accessibility_focus_and_input_focus_sync_test_activity"
+ android:name=".AccessibilityFocusAndInputFocusSyncActivity"/>
+
+ <activity android:label="@string/accessibility_text_traversal_test_activity"
+ android:name=".AccessibilityTextTraversalActivity"/>
+
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.accessibilityservice.cts"
+ android:label="Tests for the accessibility APIs.">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
diff --git a/tests/accessibilityservice/AndroidTest.xml b/tests/accessibilityservice/AndroidTest.xml
new file mode 100644
index 0000000..db2707d
--- /dev/null
+++ b/tests/accessibilityservice/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Accessibility test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAccessibilityServiceTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.accessibilityservice.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/accessibilityservice/res/layout/accessibility_focus_and_input_focus_sync_test.xml b/tests/accessibilityservice/res/layout/accessibility_focus_and_input_focus_sync_test.xml
similarity index 100%
rename from tests/tests/accessibilityservice/res/layout/accessibility_focus_and_input_focus_sync_test.xml
rename to tests/accessibilityservice/res/layout/accessibility_focus_and_input_focus_sync_test.xml
diff --git a/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml b/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
similarity index 100%
rename from tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
rename to tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
diff --git a/tests/tests/accessibilityservice/res/layout/accessibility_view_tree_reporting_test.xml b/tests/accessibilityservice/res/layout/accessibility_view_tree_reporting_test.xml
similarity index 100%
rename from tests/tests/accessibilityservice/res/layout/accessibility_view_tree_reporting_test.xml
rename to tests/accessibilityservice/res/layout/accessibility_view_tree_reporting_test.xml
diff --git a/tests/tests/accessibilityservice/res/layout/end_to_end_test.xml b/tests/accessibilityservice/res/layout/end_to_end_test.xml
similarity index 100%
rename from tests/tests/accessibilityservice/res/layout/end_to_end_test.xml
rename to tests/accessibilityservice/res/layout/end_to_end_test.xml
diff --git a/tests/tests/accessibilityservice/res/layout/list_view_row.xml b/tests/accessibilityservice/res/layout/list_view_row.xml
similarity index 100%
rename from tests/tests/accessibilityservice/res/layout/list_view_row.xml
rename to tests/accessibilityservice/res/layout/list_view_row.xml
diff --git a/tests/tests/accessibilityservice/res/layout/query_window_test.xml b/tests/accessibilityservice/res/layout/query_window_test.xml
similarity index 100%
rename from tests/tests/accessibilityservice/res/layout/query_window_test.xml
rename to tests/accessibilityservice/res/layout/query_window_test.xml
diff --git a/tests/tests/accessibilityservice/res/values/ids.xml b/tests/accessibilityservice/res/values/ids.xml
similarity index 100%
rename from tests/tests/accessibilityservice/res/values/ids.xml
rename to tests/accessibilityservice/res/values/ids.xml
diff --git a/tests/tests/accessibilityservice/res/values/strings.xml b/tests/accessibilityservice/res/values/strings.xml
similarity index 100%
rename from tests/tests/accessibilityservice/res/values/strings.xml
rename to tests/accessibilityservice/res/values/strings.xml
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java
similarity index 100%
rename from tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java
rename to tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndActivity.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndActivity.java
new file mode 100644
index 0000000..9a26ac7
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndActivity.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 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.accessibilityservice.cts;
+
+import android.accessibilityservice.cts.R;
+
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+/**
+ * This class is an {@link android.app.Activity} used to perform end-to-end
+ * testing of the accessibility feature by interaction with the
+ * UI widgets.
+ */
+public class AccessibilityEndToEndActivity extends AccessibilityTestActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.end_to_end_test);
+
+ ListAdapter listAdapter = new BaseAdapter() {
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView textView = (TextView) View
+ .inflate(AccessibilityEndToEndActivity.this, R.layout.list_view_row, null);
+ textView.setText((String) getItem(position));
+ return textView;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public Object getItem(int position) {
+ if (position == 0) {
+ return AccessibilityEndToEndActivity.this.getString(R.string.first_list_item);
+ } else {
+ return AccessibilityEndToEndActivity.this.getString(R.string.second_list_item);
+ }
+ }
+
+ public int getCount() {
+ return 2;
+ }
+ };
+
+ ListView listView = (ListView) findViewById(R.id.listview);
+ listView.setAdapter(listAdapter);
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
new file mode 100644
index 0000000..1bd4e0a
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2010 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.accessibilityservice.cts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.app.UiAutomation;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+
+import android.accessibilityservice.cts.R;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This class performs end-to-end testing of the accessibility feature by
+ * creating an {@link Activity} and poking around so {@link AccessibilityEvent}s
+ * are generated and their correct dispatch verified.
+ */
+public class AccessibilityEndToEndTest extends
+ AccessibilityActivityTestCase<AccessibilityEndToEndActivity> {
+
+ private static final String LOG_TAG = "AccessibilityEndToEndTest";
+
+ /**
+ * Creates a new instance for testing {@link AccessibilityEndToEndActivity}.
+ */
+ public AccessibilityEndToEndTest() {
+ super(AccessibilityEndToEndActivity.class);
+ }
+
+ @MediumTest
+ public void testTypeViewSelectedAccessibilityEvent() throws Throwable {
+ // create and populate the expected event
+ final AccessibilityEvent expected = AccessibilityEvent.obtain();
+ expected.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ expected.setClassName(ListView.class.getName());
+ expected.setPackageName(getActivity().getPackageName());
+ expected.getText().add(getActivity().getString(R.string.second_list_item));
+ expected.setItemCount(2);
+ expected.setCurrentItemIndex(1);
+ expected.setEnabled(true);
+ expected.setScrollable(false);
+ expected.setFromIndex(0);
+ expected.setToIndex(1);
+
+ final ListView listView = (ListView) getActivity().findViewById(R.id.listview);
+
+ AccessibilityEvent awaitedEvent =
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+ new Runnable() {
+ @Override
+ public void run() {
+ // trigger the event
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ listView.setSelection(1);
+ }
+ });
+ }},
+ new UiAutomation.AccessibilityEventFilter() {
+ // check the received event
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return equalsAccessiblityEvent(event, expected);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+ assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
+ }
+
+ @MediumTest
+ public void testTypeViewClickedAccessibilityEvent() throws Throwable {
+ // create and populate the expected event
+ final AccessibilityEvent expected = AccessibilityEvent.obtain();
+ expected.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED);
+ expected.setClassName(Button.class.getName());
+ expected.setPackageName(getActivity().getPackageName());
+ expected.getText().add(getActivity().getString(R.string.button_title));
+ expected.setEnabled(true);
+
+ final Button button = (Button) getActivity().findViewById(R.id.button);
+
+ AccessibilityEvent awaitedEvent =
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+ new Runnable() {
+ @Override
+ public void run() {
+ // trigger the event
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ button.performClick();
+ }
+ });
+ }},
+ new UiAutomation.AccessibilityEventFilter() {
+ // check the received event
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return equalsAccessiblityEvent(event, expected);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+ assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
+ }
+
+ @MediumTest
+ public void testTypeViewLongClickedAccessibilityEvent() throws Throwable {
+ // create and populate the expected event
+ final AccessibilityEvent expected = AccessibilityEvent.obtain();
+ expected.setEventType(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
+ expected.setClassName(Button.class.getName());
+ expected.setPackageName(getActivity().getPackageName());
+ expected.getText().add(getActivity().getString(R.string.button_title));
+ expected.setEnabled(true);
+
+ final Button button = (Button) getActivity().findViewById(R.id.button);
+
+ AccessibilityEvent awaitedEvent =
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+ new Runnable() {
+ @Override
+ public void run() {
+ // trigger the event
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ button.performLongClick();
+ }
+ });
+ }},
+ new UiAutomation.AccessibilityEventFilter() {
+ // check the received event
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return equalsAccessiblityEvent(event, expected);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+ assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
+ }
+
+ @MediumTest
+ public void testTypeViewFocusedAccessibilityEvent() throws Throwable {
+ // create and populate the expected event
+ final AccessibilityEvent expected = AccessibilityEvent.obtain();
+ expected.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ expected.setClassName(Button.class.getName());
+ expected.setPackageName(getActivity().getPackageName());
+ expected.getText().add(getActivity().getString(R.string.button_title));
+ expected.setItemCount(3);
+ expected.setCurrentItemIndex(2);
+ expected.setEnabled(true);
+
+ final Button button = (Button) getActivity().findViewById(R.id.button);
+
+ AccessibilityEvent awaitedEvent =
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+ new Runnable() {
+ @Override
+ public void run() {
+ // trigger the event
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ button.requestFocus();
+ }
+ });
+ }},
+ new UiAutomation.AccessibilityEventFilter() {
+ // check the received event
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return equalsAccessiblityEvent(event, expected);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+ assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
+ }
+
+ @MediumTest
+ public void testTypeViewTextChangedAccessibilityEvent() throws Throwable {
+ // focus the edit text
+ final EditText editText = (EditText) getActivity().findViewById(R.id.edittext);
+
+ AccessibilityEvent awaitedFocusEvent =
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+ new Runnable() {
+ @Override
+ public void run() {
+ // trigger the event
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ editText.requestFocus();
+ }
+ });
+ }},
+ new UiAutomation.AccessibilityEventFilter() {
+ // check the received event
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED;
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+ assertNotNull("Did not receive expected focuss event.", awaitedFocusEvent);
+
+ final String beforeText = getActivity().getString(R.string.text_input_blah);
+ final String newText = getActivity().getString(R.string.text_input_blah_blah);
+ final String afterText = beforeText.substring(0, 3) + newText;
+
+ // create and populate the expected event
+ final AccessibilityEvent expected = AccessibilityEvent.obtain();
+ expected.setEventType(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
+ expected.setClassName(EditText.class.getName());
+ expected.setPackageName(getActivity().getPackageName());
+ expected.getText().add(afterText);
+ expected.setBeforeText(beforeText);
+ expected.setFromIndex(3);
+ expected.setAddedCount(9);
+ expected.setRemovedCount(1);
+ expected.setEnabled(true);
+
+ AccessibilityEvent awaitedTextChangeEvent =
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+ new Runnable() {
+ @Override
+ public void run() {
+ // trigger the event
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ editText.getEditableText().replace(3, 4, newText);
+ }
+ });
+ }},
+ new UiAutomation.AccessibilityEventFilter() {
+ // check the received event
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return equalsAccessiblityEvent(event, expected);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+ assertNotNull("Did not receive expected event: " + expected, awaitedTextChangeEvent);
+ }
+
+ @MediumTest
+ public void testTypeWindowStateChangedAccessibilityEvent() throws Throwable {
+ // create and populate the expected event
+ final AccessibilityEvent expected = AccessibilityEvent.obtain();
+ expected.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ expected.setClassName(AlertDialog.class.getName());
+ expected.setPackageName(getActivity().getPackageName());
+ expected.getText().add(getActivity().getString(R.string.alert_title));
+ expected.getText().add(getActivity().getString(R.string.alert_message));
+ expected.setEnabled(true);
+
+ AccessibilityEvent awaitedEvent =
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+ new Runnable() {
+ @Override
+ public void run() {
+ // trigger the event
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ (new AlertDialog.Builder(getActivity()).setTitle(R.string.alert_title)
+ .setMessage(R.string.alert_message)).create().show();
+ }
+ });
+ }},
+ new UiAutomation.AccessibilityEventFilter() {
+ // check the received event
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return equalsAccessiblityEvent(event, expected);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+ assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
+ }
+
+ @MediumTest
+ @SuppressWarnings("deprecation")
+ public void testTypeNotificationStateChangedAccessibilityEvent() throws Throwable {
+ // No notification UI on televisions.
+ if((getActivity().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
+ Log.i(LOG_TAG, "Skipping: testTypeNotificationStateChangedAccessibilityEvent" +
+ " - No notification UI on televisions.");
+ return;
+ }
+
+ String message = getActivity().getString(R.string.notification_message);
+
+ // create the notification to send
+ final int notificationId = 1;
+ final Notification notification = new Notification.Builder(getActivity())
+ .setSmallIcon(android.R.drawable.stat_notify_call_mute)
+ .setContentIntent(PendingIntent.getActivity(getActivity(), 0, new Intent(),
+ PendingIntent.FLAG_CANCEL_CURRENT))
+ .setTicker(message)
+ .setContentTitle("")
+ .setContentText("")
+ // Mark the notification as "interruptive" by specifying a vibration pattern. This
+ // ensures it's announced properly on watch-type devices.
+ .setVibrate(new long[] {})
+ .build();
+
+ // create and populate the expected event
+ final AccessibilityEvent expected = AccessibilityEvent.obtain();
+ expected.setEventType(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
+ expected.setClassName(Notification.class.getName());
+ expected.setPackageName(getActivity().getPackageName());
+ expected.getText().add(message);
+ expected.setParcelableData(notification);
+
+ AccessibilityEvent awaitedEvent =
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+ new Runnable() {
+ @Override
+ public void run() {
+ // trigger the event
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // trigger the event
+ NotificationManager notificationManager =
+ (NotificationManager) getActivity().getSystemService(
+ Service.NOTIFICATION_SERVICE);
+ notificationManager.notify(notificationId, notification);
+ getActivity().finish();
+ }
+ });
+ }},
+ new UiAutomation.AccessibilityEventFilter() {
+ // check the received event
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return equalsAccessiblityEvent(event, expected);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+ assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
+ }
+
+ /**
+ * Compares all properties of the <code>first</code> and the
+ * <code>second</code>.
+ */
+ private boolean equalsAccessiblityEvent(AccessibilityEvent first, AccessibilityEvent second) {
+ return first.getEventType() == second.getEventType()
+ && first.isChecked() == second.isChecked()
+ && first.getCurrentItemIndex() == second.getCurrentItemIndex()
+ && first.isEnabled() == second.isEnabled()
+ && first.getFromIndex() == second.getFromIndex()
+ && first.getItemCount() == second.getItemCount()
+ && first.isPassword() == second.isPassword()
+ && first.getRemovedCount() == second.getRemovedCount()
+ && first.isScrollable()== second.isScrollable()
+ && first.getToIndex() == second.getToIndex()
+ && first.getRecordCount() == second.getRecordCount()
+ && first.getScrollX() == second.getScrollX()
+ && first.getScrollY() == second.getScrollY()
+ && first.getAddedCount() == second.getAddedCount()
+ && TextUtils.equals(first.getBeforeText(), second.getBeforeText())
+ && TextUtils.equals(first.getClassName(), second.getClassName())
+ && TextUtils.equals(first.getContentDescription(), second.getContentDescription())
+ && equalsNotificationAsParcelableData(first, second)
+ && equalsText(first, second);
+ }
+
+ /**
+ * Compares the {@link android.os.Parcelable} data of the
+ * <code>first</code> and <code>second</code>.
+ */
+ private boolean equalsNotificationAsParcelableData(AccessibilityEvent first,
+ AccessibilityEvent second) {
+ Notification firstNotification = (Notification) first.getParcelableData();
+ Notification secondNotification = (Notification) second.getParcelableData();
+ if (firstNotification == null) {
+ return (secondNotification == null);
+ } else if (secondNotification == null) {
+ return false;
+ }
+ return TextUtils.equals(firstNotification.tickerText, secondNotification.tickerText);
+ }
+
+ /**
+ * Compares the text of the <code>first</code> and <code>second</code> text.
+ */
+ private boolean equalsText(AccessibilityEvent first, AccessibilityEvent second) {
+ List<CharSequence> firstText = first.getText();
+ List<CharSequence> secondText = second.getText();
+ if (firstText.size() != secondText.size()) {
+ return false;
+ }
+ Iterator<CharSequence> firstIterator = firstText.iterator();
+ Iterator<CharSequence> secondIterator = secondText.iterator();
+ for (int i = 0; i < firstText.size(); i++) {
+ if (!firstIterator.next().toString().equals(secondIterator.next().toString())) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncActivity.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncActivity.java
new file mode 100644
index 0000000..62831a4
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncActivity.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2012 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.accessibilityservice.cts;
+
+import android.os.Bundle;
+
+import android.accessibilityservice.cts.R;
+
+/**
+ * Activity for testing the accessibility focus APIs exposed to
+ * accessibility services. These APIs allow moving accessibility
+ * focus in the view tree from an AccessiiblityService. Specifically,
+ * this activity is for verifying the the sync between accessibility
+ * and input focus.
+ */
+public class AccessibilityFocusAndInputFocusSyncActivity extends AccessibilityTestActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.accessibility_focus_and_input_focus_sync_test);
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java
new file mode 100644
index 0000000..ec420de
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java
@@ -0,0 +1,229 @@
+/**
+ * Copyright (C) 2012 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.accessibilityservice.cts;
+
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
+
+import android.app.UiAutomation;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import android.accessibilityservice.cts.R;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * Test cases for testing the accessibility focus APIs exposed to accessibility
+ * services. These APIs allow moving accessibility focus in the view tree from
+ * an AccessiiblityService. Specifically, this activity is for verifying the the
+ * sync between accessibility and input focus.
+ */
+public class AccessibilityFocusAndInputFocusSyncTest
+ extends AccessibilityActivityTestCase<AccessibilityFocusAndInputFocusSyncActivity>{
+
+ public AccessibilityFocusAndInputFocusSyncTest() {
+ super(AccessibilityFocusAndInputFocusSyncActivity.class);
+ }
+
+ @MediumTest
+ public void testFindAccessibilityFocus() throws Exception {
+ // Get the view that has input and accessibility focus.
+ final AccessibilityNodeInfo expected = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.firstEditText)).get(0);
+ assertNotNull(expected);
+ assertFalse(expected.isAccessibilityFocused());
+ assertTrue(expected.isFocused());
+
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ // Perform a focus action and check for success.
+ assertTrue(expected.performAction(ACTION_ACCESSIBILITY_FOCUS));
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Get the second expected node info.
+ AccessibilityNodeInfo received = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
+ assertNotNull(received);
+ assertTrue(received.isAccessibilityFocused());
+
+ // Make sure we got the expected focusable.
+ assertEquals(expected, received);
+ }
+
+ @MediumTest
+ public void testInitialStateNoAccessibilityFocus() throws Exception {
+ // Get the root which is only accessibility focused.
+ AccessibilityNodeInfo focused = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
+ assertNull(focused);
+ }
+
+ @MediumTest
+ public void testActionAccessibilityFocus() throws Exception {
+ // Get the root linear layout info.
+ final AccessibilityNodeInfo rootLinearLayout = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.rootLinearLayout)).get(0);
+ assertNotNull(rootLinearLayout);
+ assertFalse(rootLinearLayout.isAccessibilityFocused());
+
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ // Perform a focus action and check for success.
+ assertTrue(rootLinearLayout.performAction(ACTION_ACCESSIBILITY_FOCUS));
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Get the node info again.
+ rootLinearLayout.refresh();
+
+ // Check if the node info is focused.
+ assertTrue(rootLinearLayout.isAccessibilityFocused());
+ }
+
+ @MediumTest
+ public void testActionClearAccessibilityFocus() throws Exception {
+ // Get the root linear layout info.
+ final AccessibilityNodeInfo rootLinearLayout = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.rootLinearLayout)).get(0);
+ assertNotNull(rootLinearLayout);
+
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ // Perform a focus action and check for success.
+ assertTrue(rootLinearLayout.performAction(ACTION_ACCESSIBILITY_FOCUS));
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Refresh the node info.
+ rootLinearLayout.refresh();
+
+ // Check if the node info is focused.
+ assertTrue(rootLinearLayout.isAccessibilityFocused());
+
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ // Perform a clear focus action and check for success.
+ assertTrue(rootLinearLayout.performAction(ACTION_CLEAR_ACCESSIBILITY_FOCUS));
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType()
+ == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Refresh the node info.
+ rootLinearLayout.refresh();
+
+ // Check if the node info is not focused.
+ assertFalse(rootLinearLayout.isAccessibilityFocused());
+ }
+
+ @MediumTest
+ public void testOnlyOneNodeHasAccessibilityFocus() throws Exception {
+ // Get the first not focused edit text.
+ final AccessibilityNodeInfo firstEditText = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.firstEditText)).get(0);
+ assertNotNull(firstEditText);
+ assertTrue(firstEditText.isFocusable());
+ assertTrue(firstEditText.isFocused());
+ assertFalse(firstEditText.isAccessibilityFocused());
+
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ // Perform a set focus action and check for success.
+ assertTrue(firstEditText.performAction(ACTION_ACCESSIBILITY_FOCUS));
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Get the second not focused edit text.
+ final AccessibilityNodeInfo secondEditText = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.secondEditText)).get(0);
+ assertNotNull(secondEditText);
+ assertTrue(secondEditText.isFocusable());
+ assertFalse(secondEditText.isFocused());
+ assertFalse(secondEditText.isAccessibilityFocused());
+
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ // Perform a set focus action and check for success.
+ assertTrue(secondEditText.performAction(ACTION_ACCESSIBILITY_FOCUS));
+
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Get the node info again.
+ secondEditText.refresh();
+
+ // Make sure no other node has accessibility focus.
+ AccessibilityNodeInfo root = getInstrumentation().getUiAutomation().getRootInActiveWindow();
+ Queue<AccessibilityNodeInfo> workQueue = new LinkedList<AccessibilityNodeInfo>();
+ workQueue.add(root);
+ while (!workQueue.isEmpty()) {
+ AccessibilityNodeInfo current = workQueue.poll();
+ if (current.isAccessibilityFocused() && !current.equals(secondEditText)) {
+ fail();
+ }
+ final int childCount = current.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ AccessibilityNodeInfo child = current.getChild(i);
+ if (child != null) {
+ workQueue.offer(child);
+ }
+ }
+ }
+ }
+}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
similarity index 100%
rename from tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
rename to tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java
similarity index 100%
rename from tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java
rename to tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTestActivity.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTestActivity.java
similarity index 100%
rename from tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTestActivity.java
rename to tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTestActivity.java
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalActivity.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalActivity.java
new file mode 100644
index 0000000..2b93a08
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalActivity.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2012 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.accessibilityservice.cts;
+
+import android.os.Bundle;
+
+import android.accessibilityservice.cts.R;
+
+/**
+ * Activity for testing the accessibility APIs for traversing the
+ * text content of a View at several granularities.
+ */
+public class AccessibilityTextTraversalActivity extends AccessibilityTestActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.accessibility_text_traversal_test);
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
new file mode 100644
index 0000000..f5958f9
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
@@ -0,0 +1,4646 @@
+/**
+ * Copyright (C) 2012 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.accessibilityservice.cts;
+
+import android.app.UiAutomation;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.Selection;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import android.accessibilityservice.cts.R;
+
+/**
+ * Test cases for testing the accessibility APIs for traversing the text content of
+ * a View at several granularities.
+ */
+public class AccessibilityTextTraversalTest
+ extends AccessibilityActivityTestCase<AccessibilityTextTraversalActivity>{
+
+ public AccessibilityTextTraversalTest() {
+ super(AccessibilityTextTraversalActivity.class);
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityCharacterOverContentDescription()
+ throws Exception {
+ final View view = getActivity().findViewById(R.id.view);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ view.setVisibility(View.VISIBLE);
+ view.setContentDescription(getString(R.string.a_b));
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.a_b)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
+ arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.a_b))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 1
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
+ arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.a_b))
+ && event.getFromIndex() == 1
+ && event.getToIndex() == 2
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
+ arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.a_b))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
+ arguments));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
+ arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.a_b))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
+ arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.a_b))
+ && event.getFromIndex() == 1
+ && event.getToIndex() == 2
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
+ arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.a_b))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 1
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityWordOverContentDescription()
+ throws Exception {
+ final View view = getActivity().findViewById(R.id.view);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ view.setVisibility(View.VISIBLE);
+ view.setContentDescription(getString(R.string.foo_bar_baz));
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.foo_bar_baz)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(View.class.getName())
+ && event.getContentDescription().toString().equals(
+ getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityCharacterOverText()
+ throws Exception {
+ final TextView textView = (TextView) getActivity().findViewById(R.id.text);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ textView.setVisibility(View.VISIBLE);
+ textView.setText(getString(R.string.a_b));
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.a_b)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 1
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(1, Selection.getSelectionStart(textView.getText()));
+ assertEquals(1, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 1
+ && event.getToIndex() == 2
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(textView.getText()));
+ assertEquals(2, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(textView.getText()));
+ assertEquals(3, Selection.getSelectionEnd(textView.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(textView.getText()));
+ assertEquals(3, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(textView.getText()));
+ assertEquals(2, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 1
+ && event.getToIndex() == 2
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(1, Selection.getSelectionStart(textView.getText()));
+ assertEquals(1, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 1
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(seventhExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(textView.getText()));
+ assertEquals(0, Selection.getSelectionEnd(textView.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(textView.getText()));
+ assertEquals(0, Selection.getSelectionEnd(textView.getText()));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityCharacterOverTextExtend()
+ throws Exception {
+ final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setVisibility(View.VISIBLE);
+ editText.setText(getString(R.string.a_b));
+ Selection.removeSelection(editText.getText());
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.a_b)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 1
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(1, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 1
+ && event.getToIndex() == 2
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(2, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(3, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(3, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(2, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 1
+ && event.getToIndex() == 2
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(1, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 1
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Focus the view so we can change selection.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setFocusable(true);
+ editText.requestFocus();
+ }
+ });
+
+ // Put selection at the end of the text.
+ Bundle setSelectionArgs = new Bundle();
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 3);
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 3);
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(editText.getText()));
+ assertEquals(3, Selection.getSelectionEnd(editText.getText()));
+
+ // Unfocus the view so we can get rid of the soft-keyboard.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.clearFocus();
+ editText.setFocusable(false);
+ }
+ });
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(seventhExpected);
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(editText.getText()));
+ assertEquals(2, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 1
+ && event.getToIndex() == 2
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eightExpected);
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(editText.getText()));
+ assertEquals(1, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 1
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(ninethExpected);
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 1
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(tenthExpected);
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(editText.getText()));
+ assertEquals(1, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 1
+ && event.getToIndex() == 2
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eleventhExpected);
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(editText.getText()));
+ assertEquals(2, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent twelvethExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.a_b))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(twelvethExpected);
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(editText.getText()));
+ assertEquals(3, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(editText.getText()));
+ assertEquals(3, Selection.getSelectionEnd(editText.getText()));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityWordOverText() throws Exception {
+ final TextView textView = (TextView) getActivity().findViewById(R.id.text);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ textView.setVisibility(View.VISIBLE);
+ textView.setText(getString(R.string.foo_bar_baz));
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.foo_bar_baz)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(3, Selection.getSelectionStart(textView.getText()));
+ assertEquals(3, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(7, Selection.getSelectionStart(textView.getText()));
+ assertEquals(7, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(textView.getText()));
+ assertEquals(11, Selection.getSelectionEnd(textView.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(textView.getText()));
+ assertEquals(11, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(8, Selection.getSelectionStart(textView.getText()));
+ assertEquals(8, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(4, Selection.getSelectionStart(textView.getText()));
+ assertEquals(4, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(textView.getText()));
+ assertEquals(0, Selection.getSelectionEnd(textView.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(textView.getText()));
+ assertEquals(0, Selection.getSelectionEnd(textView.getText()));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityWordOverEditTextWithContentDescription()
+ throws Exception {
+ final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setVisibility(View.VISIBLE);
+ editText.setText(getString(R.string.foo_bar_baz));
+ editText.setContentDescription(getString(R.string.android_wiki));
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.foo_bar_baz)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getContentDescription().equals(getString(R.string.android_wiki))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(3, editText.getSelectionStart());
+ assertEquals(3, editText.getSelectionEnd());
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getContentDescription().equals(getString(R.string.android_wiki))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(7, editText.getSelectionStart());
+ assertEquals(7, editText.getSelectionEnd());
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getContentDescription().equals(getString(R.string.android_wiki))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(11, editText.getSelectionStart());
+ assertEquals(11, editText.getSelectionEnd());
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(11, editText.getSelectionStart());
+ assertEquals(11, editText.getSelectionEnd());
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getContentDescription().equals(getString(R.string.android_wiki))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(8, editText.getSelectionStart());
+ assertEquals(8, editText.getSelectionEnd());
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getContentDescription().equals(getString(R.string.android_wiki))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(4, editText.getSelectionStart());
+ assertEquals(4, editText.getSelectionEnd());
+
+ // Move to the next character and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getContentDescription().equals(getString(R.string.android_wiki))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, editText.getSelectionStart());
+ assertEquals(0, editText.getSelectionEnd());
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, editText.getSelectionStart());
+ assertEquals(0, editText.getSelectionEnd());
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityWordOverTextExtend() throws Exception {
+ final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setVisibility(View.VISIBLE);
+ editText.setText(getString(R.string.foo_bar_baz));
+ Selection.removeSelection(editText.getText());
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.foo_bar_baz)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(3, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(7, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(11, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Move to the previous word and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(8, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous word and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(4, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Focus the view so we can change selection.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setFocusable(true);
+ editText.requestFocus();
+ }
+ });
+
+ // Put selection at the end of the text.
+ Bundle setSelectionArgs = new Bundle();
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 11);
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 11);
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(editText.getText()));
+ assertEquals(11, Selection.getSelectionEnd(editText.getText()));
+
+ // Unfocus the view so we can get rid of the soft-keyboard.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.clearFocus();
+ editText.setFocusable(false);
+ }
+ });
+
+ // Move to the previous word and wait for an event.
+ AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(seventhExpected);
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(editText.getText()));
+ assertEquals(8, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous word and wait for an event.
+ AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eightExpected);
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(editText.getText()));
+ assertEquals(4, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous character and wait for an event.
+ AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(ninethExpected);
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 3
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(tenthExpected);
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(editText.getText()));
+ assertEquals(3, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 4
+ && event.getToIndex() == 7
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eleventhExpected);
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(editText.getText()));
+ assertEquals(7, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next word and wait for an event.
+ AccessibilityEvent twelvthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+ && event.getFromIndex() == 8
+ && event.getToIndex() == 11
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(twelvthExpected);
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(editText.getText()));
+ assertEquals(11, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(11, Selection.getSelectionStart(editText.getText()));
+ assertEquals(11, Selection.getSelectionEnd(editText.getText()));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityLineOverText() throws Exception {
+ final TextView textView = (TextView) getActivity().findViewById(R.id.text);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ textView.setVisibility(View.VISIBLE);
+ textView.setText(getString(R.string.android_wiki_short));
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.android_wiki_short)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+
+ // Move to the next line and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 13
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(13, Selection.getSelectionStart(textView.getText()));
+ assertEquals(13, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next line and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 13
+ && event.getToIndex() == 25
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(25, Selection.getSelectionStart(textView.getText()));
+ assertEquals(25, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next line and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 25
+ && event.getToIndex() == 34
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(textView.getText()));
+ assertEquals(34, Selection.getSelectionEnd(textView.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(textView.getText()));
+ assertEquals(34, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the previous line and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 25
+ && event.getToIndex() == 34
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(25, Selection.getSelectionStart(textView.getText()));
+ assertEquals(25, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the previous line and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 13
+ && event.getToIndex() == 25
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(13, Selection.getSelectionStart(textView.getText()));
+ assertEquals(13, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the previous line and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(TextView.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 13
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(textView.getText()));
+ assertEquals(0, Selection.getSelectionEnd(textView.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(textView.getText()));
+ assertEquals(0, Selection.getSelectionEnd(textView.getText()));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityLineOverTextExtend() throws Exception {
+ final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setVisibility(View.VISIBLE);
+ editText.setText(getString(R.string.android_wiki_short));
+ Selection.removeSelection(editText.getText());
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.android_wiki_short)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
+
+ // Move to the next line and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 13
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(13, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next line and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 13
+ && event.getToIndex() == 25
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(25, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next line and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 25
+ && event.getToIndex() == 34
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(34, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous line and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 25
+ && event.getToIndex() == 34
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(25, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous line and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 13
+ && event.getToIndex() == 25
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(13, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous line and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 13
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Focus the view so we can change selection.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setFocusable(true);
+ editText.requestFocus();
+ }
+ });
+
+ // Put selection at the end of the text.
+ Bundle setSelectionArgs = new Bundle();
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 34);
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 34);
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(editText.getText()));
+ assertEquals(34, Selection.getSelectionEnd(editText.getText()));
+
+ // Unocus the view so we can hide the keyboard.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.clearFocus();
+ editText.setFocusable(false);
+ }
+ });
+
+ // Move to the previous line and wait for an event.
+ AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 25
+ && event.getToIndex() == 34
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(seventhExpected);
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(editText.getText()));
+ assertEquals(25, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous line and wait for an event.
+ AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 13
+ && event.getToIndex() == 25
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eightExpected);
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(editText.getText()));
+ assertEquals(13, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous line and wait for an event.
+ AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 13
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(ninethExpected);
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next line and wait for an event.
+ AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 13
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(tenthExpected);
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(editText.getText()));
+ assertEquals(13, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next line and wait for an event.
+ AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 13
+ && event.getToIndex() == 25
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eleventhExpected);
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(editText.getText()));
+ assertEquals(25, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next line and wait for an event.
+ AccessibilityEvent twelvethExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_short))
+ && event.getFromIndex() == 25
+ && event.getToIndex() == 34
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(twelvethExpected);
+
+ // Verify the selection position.
+ assertEquals(34, Selection.getSelectionStart(editText.getText()));
+ assertEquals(34, Selection.getSelectionEnd(editText.getText()));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityPageOverText() throws Exception {
+ final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setVisibility(View.VISIBLE);
+ editText.setText(getString(R.string.android_wiki));
+ Selection.removeSelection(editText.getText());
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.android_wiki)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ // Move to the next page and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 53
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(53, Selection.getSelectionStart(editText.getText()));
+ assertEquals(53, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next page and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 53
+ && event.getToIndex() == 103
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(103, Selection.getSelectionStart(editText.getText()));
+ assertEquals(103, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next page and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 103
+ && event.getToIndex() == 153
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(153, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(153, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous page and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 103
+ && event.getToIndex() == 153
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(103, Selection.getSelectionStart(editText.getText()));
+ assertEquals(103, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous page and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 53
+ && event.getToIndex() == 103
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(53, Selection.getSelectionStart(editText.getText()));
+ assertEquals(53, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous page and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 53
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityPageOverTextExtend() throws Exception {
+ final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setVisibility(View.VISIBLE);
+ editText.setText(getString(R.string.android_wiki));
+ Selection.removeSelection(editText.getText());
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.android_wiki)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
+
+ // Move to the next page and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 53
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(53, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next page and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 53
+ && event.getToIndex() == 103
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(103, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next page and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 103
+ && event.getToIndex() == 153
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(153, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Move to the previous page and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 103
+ && event.getToIndex() == 153
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(103, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous page and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 53
+ && event.getToIndex() == 103
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(53, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous page and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 53
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(0, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Focus the view so we can change selection.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setFocusable(true);
+ editText.requestFocus();
+ }
+ });
+
+ // Put selection at the end of the text.
+ Bundle setSelectionArgs = new Bundle();
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 153);
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 153);
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(153, Selection.getSelectionEnd(editText.getText()));
+
+ // Unfocus the view so we can hide the soft-keyboard.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.clearFocus();
+ editText.setFocusable(false);
+ }
+ });
+
+ // Move to the previous page and wait for an event.
+ AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 103
+ && event.getToIndex() == 153
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(seventhExpected);
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(103, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous page and wait for an event.
+ AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 53
+ && event.getToIndex() == 103
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eightExpected);
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(53, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous page and wait for an event.
+ AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 53
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(ninethExpected);
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next page and wait for an event.
+ AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 0
+ && event.getToIndex() == 53
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(tenthExpected);
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(53, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next page and wait for an event.
+ AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 53
+ && event.getToIndex() == 103
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eleventhExpected);
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(103, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next page and wait for an event.
+ AccessibilityEvent twelvethExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki))
+ && event.getFromIndex() == 103
+ && event.getToIndex() == 153
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(twelvethExpected);
+
+ // Verify the selection position.
+ assertEquals(153, Selection.getSelectionStart(editText.getText()));
+ assertEquals(153, Selection.getSelectionEnd(editText.getText()));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityParagraphOverText() throws Exception {
+ final TextView textView = (TextView) getActivity().findViewById(R.id.edit);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ textView.setVisibility(View.VISIBLE);
+ textView.setText(getString(R.string.android_wiki_paragraphs));
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.android_wiki_paragraphs)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+
+ // Move to the next paragraph and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 14
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(14, Selection.getSelectionStart(textView.getText()));
+ assertEquals(14, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next paragraph and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 16
+ && event.getToIndex() == 32
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(32, Selection.getSelectionStart(textView.getText()));
+ assertEquals(32, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the next paragraph and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 33
+ && event.getToIndex() == 47
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(textView.getText()));
+ assertEquals(47, Selection.getSelectionEnd(textView.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(textView.getText()));
+ assertEquals(47, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the previous paragraph and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 33
+ && event.getToIndex() == 47
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(33, Selection.getSelectionStart(textView.getText()));
+ assertEquals(33, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the previous paragraph and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 16
+ && event.getToIndex() == 32
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(16, Selection.getSelectionStart(textView.getText()));
+ assertEquals(16, Selection.getSelectionEnd(textView.getText()));
+
+ // Move to the previous paragraph and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 14
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(textView.getText()));
+ assertEquals(2, Selection.getSelectionEnd(textView.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(textView.getText()));
+ assertEquals(2, Selection.getSelectionEnd(textView.getText()));
+ }
+
+ @MediumTest
+ public void testActionNextAndPreviousAtGranularityParagraphOverTextExtend() throws Exception {
+ final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setVisibility(View.VISIBLE);
+ editText.setText(getString(R.string.android_wiki_paragraphs));
+ Selection.removeSelection(editText.getText());
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.android_wiki_paragraphs)).get(0);
+
+ final int granularities = text.getMovementGranularities();
+ assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+ final Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
+
+ // Move to the next paragraph and wait for an event.
+ AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 14
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(firstExpected);
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(editText.getText()));
+ assertEquals(14, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next paragraph and wait for an event.
+ AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 16
+ && event.getToIndex() == 32
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(secondExpected);
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(editText.getText()));
+ assertEquals(32, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next paragraph and wait for an event.
+ AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 33
+ && event.getToIndex() == 47
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(thirdExpected);
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(editText.getText()));
+ assertEquals(47, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(editText.getText()));
+ assertEquals(47, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous paragraph and wait for an event.
+ AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 33
+ && event.getToIndex() == 47
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fourthExpected);
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(editText.getText()));
+ assertEquals(33, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous paragraph and wait for an event.
+ AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 16
+ && event.getToIndex() == 32
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(fifthExpected);
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(editText.getText()));
+ assertEquals(16, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous paragraph and wait for an event.
+ AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 14
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(sixthExpected);
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(editText.getText()));
+ assertEquals(2, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(2, Selection.getSelectionStart(editText.getText()));
+ assertEquals(2, Selection.getSelectionEnd(editText.getText()));
+
+ // Focus the view so we can change selection.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setFocusable(true);
+ editText.requestFocus();
+ }
+ });
+
+ // Put selection at the end of the text.
+ Bundle setSelectionArgs = new Bundle();
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 47);
+ setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 47);
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(editText.getText()));
+ assertEquals(47, Selection.getSelectionEnd(editText.getText()));
+
+ // Unfocus the view so we can get rid of the soft-keyboard.
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.clearFocus();
+ editText.setFocusable(false);
+ }
+ });
+
+ // Move to the previous paragraph and wait for an event.
+ AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 33
+ && event.getToIndex() == 47
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(seventhExpected);
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(editText.getText()));
+ assertEquals(33, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous paragraph and wait for an event.
+ AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 16
+ && event.getToIndex() == 32
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eightExpected);
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(editText.getText()));
+ assertEquals(16, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the previous paragraph and wait for an event.
+ AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 14
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(ninethExpected);
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(editText.getText()));
+ assertEquals(2, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no previous.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(editText.getText()));
+ assertEquals(2, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next paragraph and wait for an event.
+ AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 2
+ && event.getToIndex() == 14
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(tenthExpected);
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(editText.getText()));
+ assertEquals(14, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next paragraph and wait for an event.
+ AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 16
+ && event.getToIndex() == 32
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(eleventhExpected);
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(editText.getText()));
+ assertEquals(32, Selection.getSelectionEnd(editText.getText()));
+
+ // Move to the next paragraph and wait for an event.
+ AccessibilityEvent twlevethExpected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return
+ (event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+ && event.getAction() ==
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ && event.getPackageName().equals(getActivity().getPackageName())
+ && event.getClassName().equals(EditText.class.getName())
+ && event.getText().size() > 0
+ && event.getText().get(0).toString().equals(getString(
+ R.string.android_wiki_paragraphs))
+ && event.getFromIndex() == 33
+ && event.getToIndex() == 47
+ && event.getMovementGranularity() ==
+ AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure we got the expected event.
+ assertNotNull(twlevethExpected);
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(editText.getText()));
+ assertEquals(47, Selection.getSelectionEnd(editText.getText()));
+
+ // Make sure there is no next.
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+ // Verify the selection position.
+ assertEquals(47, Selection.getSelectionStart(editText.getText()));
+ assertEquals(47, Selection.getSelectionEnd(editText.getText()));
+ }
+
+ @MediumTest
+ public void testTextEditingActions() throws Exception {
+ if (!getActivity().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_INPUT_METHODS)) {
+ return;
+ }
+
+ final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+ final String textContent = getString(R.string.foo_bar_baz);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ editText.setVisibility(View.VISIBLE);
+ editText.setFocusable(true);
+ editText.requestFocus();
+ editText.setText(getString(R.string.foo_bar_baz));
+ Selection.removeSelection(editText.getText());
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.foo_bar_baz)).get(0);
+
+ // Select all text.
+ Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT,
+ editText.getText().length());
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
+
+ // Copy the selected text.
+ text.performAction(AccessibilityNodeInfo.ACTION_COPY);
+
+ // Set selection at the end.
+ final int textLength = editText.getText().length();
+ // Verify the selection position.
+ assertEquals(textLength, Selection.getSelectionStart(editText.getText()));
+ assertEquals(textLength, Selection.getSelectionEnd(editText.getText()));
+
+ // Paste the selected text.
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_PASTE));
+
+ // Verify the content.
+ assertEquals(editText.getText().toString(), textContent + textContent);
+
+ // Select all text.
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT,
+ editText.getText().length());
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
+
+ // Cut the selected text.
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_CUT));
+
+ // Verify the content.
+ assertTrue(TextUtils.isEmpty(editText.getText()));
+ }
+
+ public void testSetSelectionInContentDescription() throws Exception {
+ final View view = getActivity().findViewById(R.id.view);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ view.setVisibility(View.VISIBLE);
+ view.setContentDescription(getString(R.string.foo_bar_baz));
+ }
+ });
+
+ AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.foo_bar_baz)).get(0);
+
+ // Set the cursor position.
+ Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 4);
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
+
+ // Try and fail to set the selection longer than zero.
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 5);
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
+ }
+
+ public void testSelectionPositionForNonEditableView() throws Exception {
+ final View view = getActivity().findViewById(R.id.view);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ view.setVisibility(View.VISIBLE);
+ view.setContentDescription(getString(R.string.foo_bar_baz));
+ }
+ });
+
+ final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.foo_bar_baz)).get(0);
+
+ // Check the initial node properties.
+ assertFalse(text.isEditable());
+ assertSame(text.getTextSelectionStart(), -1);
+ assertSame(text.getTextSelectionEnd(), -1);
+
+ // Set the cursor position.
+ getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 4);
+ assertTrue(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return (event.getEventType()
+ == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Refresh the node.
+ AccessibilityNodeInfo refreshedText = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.foo_bar_baz)).get(0);
+
+ // Check the related node properties.
+ assertFalse(refreshedText.isEditable());
+ assertSame(refreshedText.getTextSelectionStart(), 4);
+ assertSame(refreshedText.getTextSelectionEnd(), 4);
+
+ // Try to set to an invalid cursor position.
+ Bundle arguments = new Bundle();
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
+ arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 5);
+ assertFalse(text.performAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
+
+ // Refresh the node.
+ refreshedText = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.foo_bar_baz)).get(0);
+
+ // Check the related node properties.
+ assertFalse(refreshedText.isEditable());
+ assertSame(refreshedText.getTextSelectionStart(), 4);
+ assertSame(refreshedText.getTextSelectionEnd(), 4);
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingActivity.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingActivity.java
new file mode 100644
index 0000000..c28e7e8
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingActivity.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2012 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.accessibilityservice.cts;
+
+import android.os.Bundle;
+
+import android.accessibilityservice.cts.R;
+
+/**
+ * Activity for testing the accessibility focus APIs exposed to
+ * accessibility services. These APIs allow moving accessibility
+ * focus in the view tree from an AccessiiblityService. Specifically,
+ * this activity is for verifying the hierarchical movement of the
+ * accessibility focus.
+ */
+public class AccessibilityViewTreeReportingActivity extends AccessibilityTestActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.accessibility_view_tree_reporting_test);
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java
new file mode 100644
index 0000000..04a9d9d
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright (C) 2012 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.accessibilityservice.cts;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import android.accessibilityservice.cts.R;
+
+/**
+ * Test cases for testing the accessibility focus APIs exposed to accessibility
+ * services. This test checks how the view hierarchy is reported to accessibility
+ * services.
+ */
+public class AccessibilityViewTreeReportingTest
+ extends AccessibilityActivityTestCase<AccessibilityViewTreeReportingActivity>{
+
+ public AccessibilityViewTreeReportingTest() {
+ super(AccessibilityViewTreeReportingActivity.class);
+ }
+
+ @MediumTest
+ public void testDescendantsOfNotImportantViewReportedInOrder1() throws Exception {
+ AccessibilityNodeInfo firstFrameLayout = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.firstFrameLayout)).get(0);
+ assertNotNull(firstFrameLayout);
+ assertSame(3, firstFrameLayout.getChildCount());
+
+ // Check if the first child is the right one.
+ AccessibilityNodeInfo firstTextView = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.firstTextView)).get(0);
+ assertEquals(firstTextView, firstFrameLayout.getChild(0));
+
+ // Check if the second child is the right one.
+ AccessibilityNodeInfo firstEditText = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
+ R.string.firstEditText)).get(0);
+ assertEquals(firstEditText, firstFrameLayout.getChild(1));
+
+ // Check if the third child is the right one.
+ AccessibilityNodeInfo firstButton = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.firstButton)).get(0);
+ assertEquals(firstButton, firstFrameLayout.getChild(2));
+ }
+
+ @MediumTest
+ public void testDescendantsOfNotImportantViewReportedInOrder2() throws Exception {
+ AccessibilityNodeInfo secondFrameLayout = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.secondFrameLayout)).get(0);
+ assertNotNull(secondFrameLayout);
+ assertSame(3, secondFrameLayout.getChildCount());
+
+ // Check if the first child is the right one.
+ AccessibilityNodeInfo secondTextView = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.secondTextView)).get(0);
+ assertEquals(secondTextView, secondFrameLayout.getChild(0));
+
+ // Check if the second child is the right one.
+ AccessibilityNodeInfo secondEditText = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.secondEditText)).get(0);
+ assertEquals(secondEditText, secondFrameLayout.getChild(1));
+
+ // Check if the third child is the right one.
+ AccessibilityNodeInfo secondButton = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.secondButton)).get(0);
+ assertEquals(secondButton, secondFrameLayout.getChild(2));
+ }
+
+ @MediumTest
+ public void testDescendantsOfNotImportantViewReportedInOrder3() throws Exception {
+ AccessibilityNodeInfo rootLinearLayout = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.rootLinearLayout)).get(0);
+ assertNotNull(rootLinearLayout);
+ assertSame(4, rootLinearLayout.getChildCount());
+
+ // Check if the first child is the right one.
+ AccessibilityNodeInfo firstFrameLayout = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.firstFrameLayout)).get(0);
+ assertEquals(firstFrameLayout, rootLinearLayout.getChild(0));
+
+ // Check if the second child is the right one.
+ AccessibilityNodeInfo secondTextView = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.secondTextView)).get(0);
+ assertEquals(secondTextView, rootLinearLayout.getChild(1));
+
+ // Check if the third child is the right one.
+ AccessibilityNodeInfo secondEditText = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.secondEditText)).get(0);
+ assertEquals(secondEditText, rootLinearLayout.getChild(2));
+
+ // Check if the fourth child is the right one.
+ AccessibilityNodeInfo secondButton = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.secondButton)).get(0);
+ assertEquals(secondButton, rootLinearLayout.getChild(3));
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
new file mode 100644
index 0000000..9070a81
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2011 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.accessibilityservice.cts;
+
+import android.os.Bundle;
+import android.view.View;
+
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.accessibilityservice.cts.R;
+
+/**
+ * Activity for testing the accessibility APIs for querying of
+ * the screen content. These APIs allow exploring the screen and
+ * requesting an action to be performed on a given view from an
+ * AccessibilityService.
+ */
+public class AccessibilityWindowQueryActivity extends AccessibilityTestActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.query_window_test);
+
+ findViewById(R.id.button5).setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ /* do nothing */
+ }
+ });
+ findViewById(R.id.button5).setOnLongClickListener(new View.OnLongClickListener() {
+ public boolean onLongClick(View v) {
+ return true;
+ }
+ });
+
+ findViewById(R.id.button5).setAccessibilityDelegate(new View.AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ info.addAction(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ if (action == R.id.foo_custom_action) {
+ return true;
+ }
+ return super.performAccessibilityAction(host, action, args);
+ }
+ });
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
new file mode 100755
index 0000000..3f27cd7
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
@@ -0,0 +1,903 @@
+/*
+ * Copyright (C) 2012 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.accessibilityservice.cts;
+
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_FOCUS;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_SELECTION;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_SELECT;
+
+import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.UiAutomation;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.Gravity;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.accessibility.AccessibilityWindowInfo;
+
+import android.widget.Button;
+import android.accessibilityservice.cts.R;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Test cases for testing the accessibility APIs for querying of the screen content.
+ * These APIs allow exploring the screen and requesting an action to be performed
+ * on a given view from an AccessibilityService.
+ */
+public class AccessibilityWindowQueryTest
+ extends AccessibilityActivityTestCase<AccessibilityWindowQueryActivity> {
+
+ private static final long TIMEOUT_WINDOW_STATE_IDLE = 500;
+
+ public AccessibilityWindowQueryTest() {
+ super(AccessibilityWindowQueryActivity.class);
+ }
+
+ @MediumTest
+ public void testFindByText() throws Exception {
+ // find a view by text
+ List<AccessibilityNodeInfo> buttons = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText("b");
+ assertEquals(9, buttons.size());
+ }
+
+ @MediumTest
+ public void testFindByContentDescription() throws Exception {
+ // find a view by text
+ AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.contentDescription)).get(0);
+ assertNotNull(button);
+ }
+
+ @MediumTest
+ public void testTraverseWindow() throws Exception {
+ verifyNodesInAppWindow(getInstrumentation().getUiAutomation().getRootInActiveWindow());
+ }
+
+ @MediumTest
+ public void testNoWindowsAccessIfFlagNotSet() throws Exception {
+ // Make sure the windows cannot be accessed.
+ UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+ assertTrue(uiAutomation.getWindows().isEmpty());
+
+ // Find a button to click on.
+ final AccessibilityNodeInfo button1 = uiAutomation.getRootInActiveWindow()
+ .findAccessibilityNodeInfosByViewId(
+ "com.android.cts.accessibilityservice:id/button1").get(0);
+
+ // Argh...
+ final List<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();
+
+ // Click the button.
+ uiAutomation.executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ button1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+ }
+ },
+ new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
+ events.add(event);
+ return true;
+ }
+ return false;
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure the source window cannot be accessed.
+ AccessibilityEvent event = events.get(0);
+ assertNull(event.getSource().getWindow());
+ }
+
+ @MediumTest
+ public void testTraverseAllWindows() throws Exception {
+ setAccessInteractiveWindowsFlag();
+ try {
+ UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+ List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
+ Rect boundsInScreen = new Rect();
+
+ final int windowCount = windows.size();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = windows.get(i);
+
+ window.getBoundsInScreen(boundsInScreen);
+ assertFalse(boundsInScreen.isEmpty()); // Varies on screen size, emptiness check.
+ assertNull(window.getParent());
+ assertSame(0, window.getChildCount());
+ assertNull(window.getParent());
+ assertNotNull(window.getRoot());
+
+ if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) {
+ assertTrue(window.isFocused());
+ assertTrue(window.isActive());
+ verifyNodesInAppWindow(window.getRoot());
+ } else if (window.getType() == AccessibilityWindowInfo.TYPE_SYSTEM) {
+ assertFalse(window.isFocused());
+ assertFalse(window.isActive());
+ }
+ }
+ } finally {
+ clearAccessInteractiveWindowsFlag();
+ }
+ }
+
+ @MediumTest
+ public void testTraverseWindowFromEvent() throws Exception {
+ setAccessInteractiveWindowsFlag();
+ try {
+ UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+ // Find a button to click on.
+ final AccessibilityNodeInfo button1 = uiAutomation.getRootInActiveWindow()
+ .findAccessibilityNodeInfosByViewId(
+ "com.android.cts.accessibilityservice:id/button1").get(0);
+
+ // Argh...
+ final List<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();
+
+ // Click the button.
+ uiAutomation.executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ button1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+ }
+ },
+ new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
+ events.add(event);
+ return true;
+ }
+ return false;
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+
+ // Get the source window.
+ AccessibilityEvent event = events.get(0);
+ AccessibilityWindowInfo window = event.getSource().getWindow();
+
+ // Verify the application window.
+ Rect boundsInScreen = new Rect();
+ window.getBoundsInScreen(boundsInScreen);
+ assertFalse(boundsInScreen.isEmpty()); // Varies on screen size, so just emptiness check.
+ assertSame(window.getType(), AccessibilityWindowInfo.TYPE_APPLICATION);
+ assertTrue(window.isFocused());
+ assertTrue(window.isActive());
+ assertNull(window.getParent());
+ assertSame(0, window.getChildCount());
+ assertNotNull(window.getRoot());
+
+ // Verify the window content.
+ verifyNodesInAppWindow(window.getRoot());
+ } finally {
+ clearAccessInteractiveWindowsFlag();
+ }
+ }
+
+ @MediumTest
+ public void testInteractWithAppWindow() throws Exception {
+ setAccessInteractiveWindowsFlag();
+ try {
+ UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+ // Find a button to click on.
+ final AccessibilityNodeInfo button1 = uiAutomation.getRootInActiveWindow()
+ .findAccessibilityNodeInfosByViewId(
+ "com.android.cts.accessibilityservice:id/button1").get(0);
+
+ // Argh...
+ final List<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();
+
+ // Click the button.
+ uiAutomation.executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ button1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+ }
+ },
+ new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
+ events.add(event);
+ return true;
+ }
+ return false;
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+
+ // Get the source window.
+ AccessibilityEvent event = events.get(0);
+ AccessibilityWindowInfo window = event.getSource().getWindow();
+
+ // Find a another button from the event's window.
+ final AccessibilityNodeInfo button2 = window.getRoot()
+ .findAccessibilityNodeInfosByViewId(
+ "com.android.cts.accessibilityservice:id/button2").get(0);
+
+ // Click the second button.
+ uiAutomation.executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ button2.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+ }
+ },
+ new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED;
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+ } finally {
+ clearAccessInteractiveWindowsFlag();
+ }
+ }
+
+ @MediumTest
+ public void testSingleAccessibilityFocusAcrossWindows() throws Exception {
+ setAccessInteractiveWindowsFlag();
+ try {
+ // Add two more windows.
+ addTwoAppPanelWindows();
+
+ // Put accessibility focus in the first app window.
+ ensureAppWindowFocusedOrFail(0);
+ // Make sure there only one accessibility focus.
+ assertSingleAccessibilityFocus();
+
+ // Put accessibility focus in the second app window.
+ ensureAppWindowFocusedOrFail(1);
+ // Make sure there only one accessibility focus.
+ assertSingleAccessibilityFocus();
+
+ // Put accessibility focus in the third app window.
+ ensureAppWindowFocusedOrFail(2);
+ // Make sure there only one accessibility focus.
+ assertSingleAccessibilityFocus();
+ } finally {
+ ensureAccessibilityFocusCleared();
+ clearAccessInteractiveWindowsFlag();
+ }
+ }
+
+ @MediumTest
+ public void testPerformActionFocus() throws Exception {
+ // find a view and make sure it is not focused
+ AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.button5)).get(0);
+ assertFalse(button.isFocused());
+
+ // focus the view
+ assertTrue(button.performAction(ACTION_FOCUS));
+
+ // find the view again and make sure it is focused
+ button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
+ .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
+ assertTrue(button.isFocused());
+ }
+
+ @MediumTest
+ public void testPerformActionClearFocus() throws Exception {
+ // find a view and make sure it is not focused
+ AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.button5)).get(0);
+ assertFalse(button.isFocused());
+
+ // focus the view
+ assertTrue(button.performAction(ACTION_FOCUS));
+
+ // find the view again and make sure it is focused
+ button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
+ .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
+ assertTrue(button.isFocused());
+
+ // unfocus the view
+ assertTrue(button.performAction(ACTION_CLEAR_FOCUS));
+
+ // find the view again and make sure it is not focused
+ button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
+ .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
+ assertFalse(button.isFocused());
+ }
+
+ @MediumTest
+ public void testPerformActionSelect() throws Exception {
+ // find a view and make sure it is not selected
+ AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.button5)).get(0);
+ assertFalse(button.isSelected());
+
+ // select the view
+ assertTrue(button.performAction(ACTION_SELECT));
+
+ // find the view again and make sure it is selected
+ button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
+ .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
+ assertTrue(button.isSelected());
+ }
+
+ @MediumTest
+ public void testPerformActionClearSelection() throws Exception {
+ // find a view and make sure it is not selected
+ AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.button5)).get(0);
+ assertFalse(button.isSelected());
+
+ // select the view
+ assertTrue(button.performAction(ACTION_SELECT));
+
+ // find the view again and make sure it is selected
+ button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
+ .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
+
+ assertTrue(button.isSelected());
+
+ // unselect the view
+ assertTrue(button.performAction(ACTION_CLEAR_SELECTION));
+
+ // find the view again and make sure it is not selected
+ button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
+ .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
+ assertFalse(button.isSelected());
+ }
+
+ @MediumTest
+ public void testPerformActionClick() throws Exception {
+ // find a view and make sure it is not selected
+ final AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.button5)).get(0);
+ assertFalse(button.isSelected());
+
+ // Make an action and wait for an event.
+ AccessibilityEvent expected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ button.performAction(ACTION_CLICK);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure the expected event was received.
+ assertNotNull(expected);
+ }
+
+ @MediumTest
+ public void testPerformActionLongClick() throws Exception {
+ // find a view and make sure it is not selected
+ final AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.button5)).get(0);
+ assertFalse(button.isSelected());
+
+ // Make an action and wait for an event.
+ AccessibilityEvent expected = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ button.performAction(ACTION_LONG_CLICK);
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return (event.getEventType() == AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+
+ // Make sure the expected event was received.
+ assertNotNull(expected);
+ }
+
+
+ @MediumTest
+ public void testPerformCustomAction() throws Exception {
+ // find a view and make sure it is not selected
+ AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.button5)).get(0);
+
+ // find the custom action and perform it
+ List<AccessibilityAction> actions = button.getActionList();
+ final int actionCount = actions.size();
+ for (int i = 0; i < actionCount; i++) {
+ AccessibilityAction action = actions.get(i);
+ if (action.getId() == R.id.foo_custom_action) {
+ assertSame(action.getLabel(), "Foo");
+ // perform the action
+ assertTrue(button.performAction(action.getId()));
+ return;
+ }
+ }
+ }
+
+ @MediumTest
+ public void testGetEventSource() throws Exception {
+ // find a view and make sure it is not focused
+ final AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.button5)).get(0);
+ assertFalse(button.isSelected());
+
+ // focus and wait for the event
+ AccessibilityEvent awaitedEvent = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(
+ new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(button.performAction(ACTION_FOCUS));
+ }
+ },
+ new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ }
+ },
+ TIMEOUT_ASYNC_PROCESSING);
+
+ assertNotNull(awaitedEvent);
+
+ // check that last event source
+ AccessibilityNodeInfo source = awaitedEvent.getSource();
+ assertNotNull(source);
+
+ // bounds
+ Rect buttonBounds = new Rect();
+ button.getBoundsInParent(buttonBounds);
+ Rect sourceBounds = new Rect();
+ source.getBoundsInParent(sourceBounds);
+
+ assertEquals(buttonBounds.left, sourceBounds.left);
+ assertEquals(buttonBounds.right, sourceBounds.right);
+ assertEquals(buttonBounds.top, sourceBounds.top);
+ assertEquals(buttonBounds.bottom, sourceBounds.bottom);
+
+ // char sequence attributes
+ assertEquals(button.getPackageName(), source.getPackageName());
+ assertEquals(button.getClassName(), source.getClassName());
+ assertEquals(button.getText().toString(), source.getText().toString());
+ assertSame(button.getContentDescription(), source.getContentDescription());
+
+ // boolean attributes
+ assertSame(button.isFocusable(), source.isFocusable());
+ assertSame(button.isClickable(), source.isClickable());
+ assertSame(button.isEnabled(), source.isEnabled());
+ assertNotSame(button.isFocused(), source.isFocused());
+ assertSame(button.isLongClickable(), source.isLongClickable());
+ assertSame(button.isPassword(), source.isPassword());
+ assertSame(button.isSelected(), source.isSelected());
+ assertSame(button.isCheckable(), source.isCheckable());
+ assertSame(button.isChecked(), source.isChecked());
+ }
+
+ @MediumTest
+ public void testPerformGlobalActionBack() throws Exception {
+ assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_BACK));
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+ }
+
+ @MediumTest
+ public void testPerformGlobalActionHome() throws Exception {
+ assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_HOME));
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+ }
+
+ @MediumTest
+ public void testPerformGlobalActionRecents() throws Exception {
+ // Check whether the action succeeded.
+ assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_RECENTS));
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+
+ // This is a necessary since the back action does not
+ // dismiss recents until they stop animating. Sigh...
+ SystemClock.sleep(5000);
+
+ // Clean up.
+ getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_BACK);
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+ }
+
+ @MediumTest
+ public void testPerformGlobalActionNotifications() throws Exception {
+ // Perform the action under test
+ assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS));
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+
+ // Clean up.
+ assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_BACK));
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+ }
+
+ @MediumTest
+ public void testPerformGlobalActionQuickSettings() throws Exception {
+ // Check whether the action succeeded.
+ assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS));
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+
+ // Clean up.
+ getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_BACK);
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+ }
+
+ @MediumTest
+ public void testPerformGlobalActionPowerDialog() throws Exception {
+ // Check whether the action succeeded.
+ assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_POWER_DIALOG));
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+
+ // Clean up.
+ getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_BACK);
+
+ // Sleep a bit so the UI is settles.
+ waitForIdle();
+ }
+
+ @MediumTest
+ public void testObjectContract() throws Exception {
+ try {
+ AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
+ info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ getInstrumentation().getUiAutomation().setServiceInfo(info);
+
+ // find a view and make sure it is not focused
+ AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+ .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+ getString(R.string.button5)).get(0);
+ AccessibilityNodeInfo parent = button.getParent();
+ final int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ AccessibilityNodeInfo child = parent.getChild(i);
+ assertNotNull(child);
+ if (child.equals(button)) {
+ assertEquals("Equal objects must have same hasCode.", button.hashCode(),
+ child.hashCode());
+ return;
+ }
+ }
+ fail("Parent's children do not have the info whose parent is the parent.");
+ } finally {
+ AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
+ info.flags &= ~AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ getInstrumentation().getUiAutomation().setServiceInfo(info);
+ }
+ }
+
+ private void assertSingleAccessibilityFocus() {
+ UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+ List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
+ AccessibilityWindowInfo focused = null;
+
+ final int windowCount = windows.size();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = windows.get(i);
+
+ if (window.isAccessibilityFocused()) {
+ if (focused == null) {
+ focused = window;
+
+ AccessibilityNodeInfo root = window.getRoot();
+ assertEquals(uiAutomation.findFocus(
+ AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), root);
+ assertEquals(root.findFocus(
+ AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), root);
+ } else {
+ throw new AssertionError("Duplicate accessibility focus");
+ }
+ } else {
+ assertNull(window.getRoot().findFocus(
+ AccessibilityNodeInfo.FOCUS_ACCESSIBILITY));
+ }
+ }
+ }
+
+ private void ensureAppWindowFocusedOrFail(int appWindowIndex) throws TimeoutException {
+ UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+ List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
+ AccessibilityWindowInfo focusTareget = null;
+
+ int visitedAppWindows = -1;
+ final int windowCount = windows.size();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = windows.get(i);
+ if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) {
+ visitedAppWindows++;
+ if (appWindowIndex <= visitedAppWindows) {
+ focusTareget = window;
+ break;
+ }
+ }
+ }
+
+ if (focusTareget == null) {
+ throw new IllegalStateException("Couldn't find app window: " + appWindowIndex);
+ }
+
+ if (focusTareget.isAccessibilityFocused()) {
+ return;
+ }
+
+ final AccessibilityWindowInfo finalFocusTarget = focusTareget;
+ uiAutomation.executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(finalFocusTarget.getRoot().performAction(
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS));
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ windows = uiAutomation.getWindows();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = windows.get(i);
+ if (window.getId() == focusTareget.getId()) {
+ assertTrue(window.isAccessibilityFocused());
+ break;
+ }
+ }
+ }
+
+ private void addTwoAppPanelWindows() throws TimeoutException {
+ final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+ uiAutomation.waitForIdle(TIMEOUT_WINDOW_STATE_IDLE, TIMEOUT_ASYNC_PROCESSING);
+
+ // Add the first window.
+ uiAutomation.executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+ params.gravity = Gravity.TOP;
+ params.y = getStatusBarHeight();
+ params.width = WindowManager.LayoutParams.MATCH_PARENT;
+ params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ params.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ params.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+ params.token = getActivity().getWindow().getDecorView().getWindowToken();
+
+ Button button = new Button(getActivity());
+ button.setText(R.string.button1);
+ getActivity().getWindowManager().addView(button, params);
+ }
+ });
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+
+ // Add the second window.
+ uiAutomation.executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+ params.gravity = Gravity.BOTTOM;
+ params.width = WindowManager.LayoutParams.MATCH_PARENT;
+ params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ params.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ params.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+ params.token = getActivity().getWindow().getDecorView().getWindowToken();
+
+ Button button = new Button(getActivity());
+ button.setText(R.string.button2);
+ getActivity().getWindowManager().addView(button, params);
+ }
+ });
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+ }
+
+ private int getStatusBarHeight() {
+ final Rect rect = new Rect();
+ Window window = getActivity().getWindow();
+ window.getDecorView().getWindowVisibleDisplayFrame(rect);
+ return rect.top;
+ }
+
+ private void setAccessInteractiveWindowsFlag () {
+ UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+ AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
+ info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+ uiAutomation.setServiceInfo(info);
+ }
+
+ private void clearAccessInteractiveWindowsFlag () {
+ UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+ AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
+ info.flags &= ~AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+ uiAutomation.setServiceInfo(info);
+ }
+
+ private void ensureAccessibilityFocusCleared() {
+ try {
+ final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+ uiAutomation.executeAndWaitForEvent(new Runnable() {
+ @Override
+ public void run() {
+ List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
+ final int windowCount = windows.size();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = windows.get(i);
+ if (window.isAccessibilityFocused()) {
+ window.getRoot().performAction(
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ }
+ }
+ }
+ }, new UiAutomation.AccessibilityEventFilter() {
+ @Override
+ public boolean accept(AccessibilityEvent event) {
+ return event.getEventType() ==
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
+ }
+ }, TIMEOUT_ASYNC_PROCESSING);
+ } catch (TimeoutException te) {
+ /* ignore */
+ }
+ }
+
+ private void verifyNodesInAppWindow(AccessibilityNodeInfo root) throws Exception {
+ try {
+ AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
+ info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ getInstrumentation().getUiAutomation().setServiceInfo(info);
+
+ root.refresh();
+
+ // make list of expected nodes
+ List<String> classNameAndTextList = new ArrayList<String>();
+ classNameAndTextList.add("android.widget.LinearLayout");
+ classNameAndTextList.add("android.widget.LinearLayout");
+ classNameAndTextList.add("android.widget.LinearLayout");
+ classNameAndTextList.add("android.widget.LinearLayout");
+ classNameAndTextList.add("android.widget.ButtonB1");
+ classNameAndTextList.add("android.widget.ButtonB2");
+ classNameAndTextList.add("android.widget.ButtonB3");
+ classNameAndTextList.add("android.widget.ButtonB4");
+ classNameAndTextList.add("android.widget.ButtonB5");
+ classNameAndTextList.add("android.widget.ButtonB6");
+ classNameAndTextList.add("android.widget.ButtonB7");
+ classNameAndTextList.add("android.widget.ButtonB8");
+ classNameAndTextList.add("android.widget.ButtonB9");
+
+ String contentViewIdResName = "com.android.cts.accessibilityservice:id/added_content";
+ boolean verifyContent = false;
+
+ Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
+ fringe.add(root);
+
+ // do a BFS traversal and check nodes
+ while (!fringe.isEmpty()) {
+ AccessibilityNodeInfo current = fringe.poll();
+
+ if (!verifyContent
+ && contentViewIdResName.equals(current.getViewIdResourceName())) {
+ verifyContent = true;
+ }
+
+ if (verifyContent) {
+ CharSequence text = current.getText();
+ String receivedClassNameAndText = current.getClassName().toString()
+ + ((text != null) ? text.toString() : "");
+ String expectedClassNameAndText = classNameAndTextList.remove(0);
+
+ assertEquals("Did not get the expected node info",
+ expectedClassNameAndText, receivedClassNameAndText);
+ }
+
+ final int childCount = current.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ AccessibilityNodeInfo child = current.getChild(i);
+ fringe.add(child);
+ }
+ }
+ } finally {
+ AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
+ info.flags &= ~AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ getInstrumentation().getUiAutomation().setServiceInfo(info);
+ }
+ }
+
+ @Override
+ protected void scrubClass(Class<?> testCaseClass) {
+ /* intentionally do not scrub */
+ }
+}
diff --git a/tests/admin/Android.mk b/tests/admin/Android.mk
new file mode 100644
index 0000000..f42de8a
--- /dev/null
+++ b/tests/admin/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2011 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner mockito-target
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsAdminTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_INSTRUMENTATION_FOR := CtsAdminApp
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/admin/AndroidManifest.xml b/tests/admin/AndroidManifest.xml
new file mode 100644
index 0000000..d3467af
--- /dev/null
+++ b/tests/admin/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.admin.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.admin.app"
+ android:label="Tests for the admin APIs.">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
diff --git a/tests/admin/AndroidTest.xml b/tests/admin/AndroidTest.xml
new file mode 100644
index 0000000..6831d14
--- /dev/null
+++ b/tests/admin/AndroidTest.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+<configuration description="Config for the CTS device admin tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAdminApp.apk" />
+ <option name="test-file-name" value="CtsAdminTestCases.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="dpm set-active-admin --user cur android.admin.app/.CtsDeviceAdminReceiver" />
+ <option name="run-command" value="dpm set-active-admin --user cur android.admin.app/.CtsDeviceAdminReceiver2" />
+ <option name="run-command" value="dpm set-device-owner --user cur android.admin.app/.CtsDeviceAdminDeviceOwner" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.admin.cts" />
+ <option name="exclude-filter" value="android.admin.app.DeactivationTest" />
+ </test>
+
+ <!-- Instrument the app to clear the device admins so the apk can be uninstalled -->
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstrumentationPreparer">
+ <option name="apk" value="CtsAdminApp.apk" />
+ <option name="package" value="android.admin.app" />
+ <option name="include-filter" value="android.admin.app.DeactivationTest" />
+ <option name="when" value="after" />
+ </target_preparer>
+</configuration>
\ No newline at end of file
diff --git a/tests/admin/OldAndroidTest.xml b/tests/admin/OldAndroidTest.xml
new file mode 100644
index 0000000..0cfada8
--- /dev/null
+++ b/tests/admin/OldAndroidTest.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<configuration description="CTS device admin test config">
+ <include name="common-config" />
+ <option name="run-command:run-command" value="dpm set-active-admin --user cur android.admin.app/.CtsDeviceAdminReceiver" />
+ <option name="run-command:run-command" value="dpm set-active-admin --user cur android.admin.app/.CtsDeviceAdminReceiver2" />
+</configuration>
diff --git a/tests/admin/app/Android.mk b/tests/admin/app/Android.mk
new file mode 100644
index 0000000..bf49e39
--- /dev/null
+++ b/tests/admin/app/Android.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2011 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_JAVA_LIBRARIES := guava
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsAdminApp
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/admin/app/AndroidManifest.xml b/tests/admin/app/AndroidManifest.xml
new file mode 100644
index 0000000..0834579
--- /dev/null
+++ b/tests/admin/app/AndroidManifest.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.admin.app">
+ <application>
+
+ <uses-library android:name="android.test.runner"/>
+
+ <receiver android:name="android.admin.app.CtsDeviceAdminDeviceOwner"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="android.admin.app.CtsDeviceAdminReceiver"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="android.admin.app.CtsDeviceAdminReceiver2"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_2" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <!-- Device Admin that needs to be in the deactivated state in order
+ for tests to pass. -->
+ <receiver android:name="android.admin.app.CtsDeviceAdminDeactivatedReceiver"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <!-- Helper Activity used by Device Admin activation tests -->
+ <activity android:name="android.admin.app.CtsDeviceAdminActivationTestActivity"
+ android:label="Device Admin activation test" />
+
+ <!-- Broken device admin: meta-data missing -->
+ <receiver android:name="android.admin.app.CtsDeviceAdminBrokenReceiver"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <!-- Broken device admin: filter doesn't match an Intent with action
+ android.app.action.DEVICE_ADMIN_ENABLED and nothing else (e.g.,
+ data) set -->
+ <receiver android:name="android.admin.app.CtsDeviceAdminBrokenReceiver2"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ <data android:scheme="https" />
+ </intent-filter>
+ </receiver>
+
+ <!-- Broken device admin: meta-data element doesn't point to valid
+ Device Admin configuration/description -->
+ <receiver android:name="android.admin.app.CtsDeviceAdminBrokenReceiver3"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/broken_device_admin" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <!-- Broken device admin: filter doesn't match Intents with action
+ android.app.action.DEVICE_ADMIN_ENABLED -->
+ <receiver android:name="android.admin.app.CtsDeviceAdminBrokenReceiver4"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_DISABLED" />
+ </intent-filter>
+ </receiver>
+
+ <!-- Broken device admin: no intent-filter -->
+ <receiver android:name="android.admin.app.CtsDeviceAdminBrokenReceiver5"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin" />
+ </receiver>
+
+ </application>
+
+ <!-- self-instrumenting test package. -->
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:label="Deactivate Admins"
+ android:targetPackage="android.admin.app" >
+ </instrumentation>
+
+</manifest>
diff --git a/tests/deviceadmin/res/xml/broken_device_admin.xml b/tests/admin/app/res/xml/broken_device_admin.xml
similarity index 100%
rename from tests/deviceadmin/res/xml/broken_device_admin.xml
rename to tests/admin/app/res/xml/broken_device_admin.xml
diff --git a/tests/deviceadmin/res/xml/device_admin.xml b/tests/admin/app/res/xml/device_admin.xml
similarity index 100%
rename from tests/deviceadmin/res/xml/device_admin.xml
rename to tests/admin/app/res/xml/device_admin.xml
diff --git a/tests/deviceadmin/res/xml/device_admin_2.xml b/tests/admin/app/res/xml/device_admin_2.xml
similarity index 100%
rename from tests/deviceadmin/res/xml/device_admin_2.xml
rename to tests/admin/app/res/xml/device_admin_2.xml
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminActivationTestActivity.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminActivationTestActivity.java
new file mode 100644
index 0000000..9f46949
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminActivationTestActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 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.admin.app;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Helper {@link Activity} for CTS tests of Device Admin activation. The {@code Activity}
+ * enables tests to capture the invocations of its {@link #onActivityResult(int, int, Intent)} by
+ * providing a {@link OnActivityResultListener}.
+ */
+public class CtsDeviceAdminActivationTestActivity extends Activity {
+ public interface OnActivityResultListener {
+ void onActivityResult(int requestCode, int resultCode, Intent data);
+ }
+
+ private OnActivityResultListener mOnActivityResultListener;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Dismiss keyguard and keep screen on while this Activity is displayed.
+ // This is needed because on older platforms, when the keyguard is on, onActivityResult is
+ // not invoked when a Device Admin activation is rejected without user interaction.
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+ | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+
+ @VisibleForTesting
+ public void setOnActivityResultListener(OnActivityResultListener listener) {
+ mOnActivityResultListener = listener;
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (mOnActivityResultListener != null) {
+ mOnActivityResultListener.onActivityResult(requestCode, resultCode, data);
+ return;
+ }
+
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+}
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver.java
new file mode 100644
index 0000000..8aec34a
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.admin.app;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminBrokenReceiver extends DeviceAdminReceiver {
+}
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver2.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver2.java
new file mode 100644
index 0000000..9895716
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver2.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.admin.app;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminBrokenReceiver2 extends DeviceAdminReceiver {
+}
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver3.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver3.java
new file mode 100644
index 0000000..0c6d2cc
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver3.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.admin.app;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminBrokenReceiver3 extends DeviceAdminReceiver {
+}
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver4.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver4.java
new file mode 100644
index 0000000..20229c6
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver4.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.admin.app;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminBrokenReceiver4 extends DeviceAdminReceiver {
+}
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver5.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver5.java
new file mode 100644
index 0000000..709dd86
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminBrokenReceiver5.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.admin.app;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminBrokenReceiver5 extends DeviceAdminReceiver {
+}
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminDeactivatedReceiver.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminDeactivatedReceiver.java
new file mode 100644
index 0000000..fbafe0e
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminDeactivatedReceiver.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.admin.app;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminDeactivatedReceiver extends DeviceAdminReceiver {
+}
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminDeviceOwner.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminDeviceOwner.java
new file mode 100644
index 0000000..619f700
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminDeviceOwner.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+package android.admin.app;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminDeviceOwner extends DeviceAdminReceiver {
+
+}
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminReceiver.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminReceiver.java
new file mode 100644
index 0000000..737111f
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminReceiver.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011 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.admin.app;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminReceiver extends DeviceAdminReceiver {
+}
diff --git a/tests/admin/app/src/android/admin/app/CtsDeviceAdminReceiver2.java b/tests/admin/app/src/android/admin/app/CtsDeviceAdminReceiver2.java
new file mode 100644
index 0000000..9baf8b0
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/CtsDeviceAdminReceiver2.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011 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.admin.app;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminReceiver2 extends DeviceAdminReceiver {
+}
diff --git a/tests/admin/app/src/android/admin/app/DeactivationTest.java b/tests/admin/app/src/android/admin/app/DeactivationTest.java
new file mode 100644
index 0000000..d6a7bf8
--- /dev/null
+++ b/tests/admin/app/src/android/admin/app/DeactivationTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+package android.admin.app;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+/**
+ * Helper to deactivate Device Admins.
+ */
+public class DeactivationTest extends AndroidTestCase {
+ private static final String PACKAGE = CtsDeviceAdminReceiver.class.getPackage().getName();
+ private static final ComponentName RECEIVER1 = new ComponentName(PACKAGE,
+ CtsDeviceAdminReceiver.class.getName());
+ private static final ComponentName RECEIVER2 = new ComponentName(PACKAGE,
+ CtsDeviceAdminReceiver2.class.getName());
+
+ // Device admin we use to reset password. Note profile owner can do this too,
+ // but DPM.clearProfileOwner() is hidden, so we just use a device owner.
+ private static final ComponentName DEVICE_OWNER = new ComponentName(PACKAGE,
+ CtsDeviceAdminDeviceOwner.class.getName());
+
+ public void testDeactivateAdmins() throws Exception {
+ DevicePolicyManager manager = (DevicePolicyManager)
+ getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
+ assertNotNull(manager);
+
+ manager.clearDeviceOwnerApp(PACKAGE);
+
+ manager.removeActiveAdmin(RECEIVER1);
+ manager.removeActiveAdmin(RECEIVER2);
+ manager.removeActiveAdmin(DEVICE_OWNER);
+
+ for (int i = 0; i < 1000 && isActive(manager); i++) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ assertFalse(isActive(manager));
+ }
+
+ private boolean isActive(DevicePolicyManager manager) {
+ return manager.isAdminActive(RECEIVER1) ||
+ manager.isAdminActive(RECEIVER2) ||
+ manager.isAdminActive(DEVICE_OWNER);
+ }
+}
\ No newline at end of file
diff --git a/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java b/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java
new file mode 100644
index 0000000..e3b7c4b
--- /dev/null
+++ b/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2013 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.admin.cts;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.admin.app.CtsDeviceAdminBrokenReceiver;
+import android.admin.app.CtsDeviceAdminBrokenReceiver2;
+import android.admin.app.CtsDeviceAdminBrokenReceiver3;
+import android.admin.app.CtsDeviceAdminBrokenReceiver4;
+import android.admin.app.CtsDeviceAdminBrokenReceiver5;
+import android.admin.app.CtsDeviceAdminDeactivatedReceiver;
+import android.admin.app.CtsDeviceAdminActivationTestActivity;
+import android.admin.app.CtsDeviceAdminActivationTestActivity.OnActivityResultListener;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for the standard way of activating a Device Admin: by starting system UI via an
+ * {@link Intent} with {@link DevicePolicyManager#ACTION_ADD_DEVICE_ADMIN}. The test requires that
+ * the {@code CtsDeviceAdmin.apk} be installed.
+ */
+public class DeviceAdminActivationTest
+ extends ActivityInstrumentationTestCase2<CtsDeviceAdminActivationTestActivity> {
+
+ private static final String TAG = DeviceAdminActivationTest.class.getSimpleName();
+
+ // IMPLEMENTATION NOTE: Because Device Admin activation requires the use of
+ // Activity.startActivityForResult, this test creates an empty Activity which then invokes
+ // startActivityForResult.
+
+ private static final int REQUEST_CODE_ACTIVATE_ADMIN = 1;
+
+ /**
+ * Maximum duration of time (milliseconds) after which the effects of programmatic actions in
+ * this test should have affected the UI.
+ */
+ private static final int UI_EFFECT_TIMEOUT_MILLIS = 5000;
+
+ private boolean mDeviceAdmin;
+ @Mock private OnActivityResultListener mMockOnActivityResultListener;
+
+ public DeviceAdminActivationTest() {
+ super(CtsDeviceAdminActivationTestActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ getActivity().setOnActivityResultListener(mMockOnActivityResultListener);
+ mDeviceAdmin = getInstrumentation().getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_DEVICE_ADMIN);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ finishActivateDeviceAdminActivity();
+ } finally {
+ super.tearDown();
+ }
+ }
+
+ public void testActivateGoodReceiverDisplaysActivationUi() throws Exception {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testActivateGoodReceiverDisplaysActivationUi");
+ return;
+ }
+ assertDeviceAdminDeactivated(CtsDeviceAdminDeactivatedReceiver.class);
+ startAddDeviceAdminActivityForResult(CtsDeviceAdminDeactivatedReceiver.class);
+ assertWithTimeoutOnActivityResultNotInvoked();
+ // The UI is up and running. Assert that dismissing the UI returns the corresponding result
+ // to the test activity.
+ finishActivateDeviceAdminActivity();
+ assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminDeactivatedReceiver.class);
+ }
+
+ public void testActivateBrokenReceiverFails() throws Exception {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testActivateBrokenReceiverFails");
+ return;
+ }
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver.class);
+ startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver.class);
+ assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver.class);
+ }
+
+ public void testActivateBrokenReceiver2Fails() throws Exception {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testActivateBrokenReceiver2Fails");
+ return;
+ }
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver2.class);
+ startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver2.class);
+ assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver2.class);
+ }
+
+ public void testActivateBrokenReceiver3Fails() throws Exception {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testActivateBrokenReceiver3Fails");
+ return;
+ }
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver3.class);
+ startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver3.class);
+ assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver3.class);
+ }
+
+ public void testActivateBrokenReceiver4Fails() throws Exception {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testActivateBrokenReceiver4Fails");
+ return;
+ }
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver4.class);
+ startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver4.class);
+ assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver4.class);
+ }
+
+ public void testActivateBrokenReceiver5Fails() throws Exception {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testActivateBrokenReceiver5Fails");
+ return;
+ }
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver5.class);
+ startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver5.class);
+ assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver5.class);
+ }
+
+ private void startAddDeviceAdminActivityForResult(Class<?> receiverClass) {
+ getActivity().startActivityForResult(
+ getAddDeviceAdminIntent(receiverClass),
+ REQUEST_CODE_ACTIVATE_ADMIN);
+ }
+
+ private Intent getAddDeviceAdminIntent(Class<?> receiverClass) {
+ return new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
+ .putExtra(
+ DevicePolicyManager.EXTRA_DEVICE_ADMIN,
+ new ComponentName(
+ getInstrumentation().getTargetContext(),
+ receiverClass));
+ }
+
+ private void assertWithTimeoutOnActivityResultNotInvoked() {
+ SystemClock.sleep(UI_EFFECT_TIMEOUT_MILLIS);
+ Mockito.verify(mMockOnActivityResultListener, Mockito.never())
+ .onActivityResult(
+ Mockito.eq(REQUEST_CODE_ACTIVATE_ADMIN),
+ Mockito.anyInt(),
+ Mockito.any(Intent.class));
+ }
+
+ private void assertWithTimeoutOnActivityResultInvokedWithResultCode(int expectedResultCode) {
+ ArgumentCaptor<Integer> resultCodeCaptor = ArgumentCaptor.forClass(int.class);
+ Mockito.verify(mMockOnActivityResultListener, Mockito.timeout(UI_EFFECT_TIMEOUT_MILLIS))
+ .onActivityResult(
+ Mockito.eq(REQUEST_CODE_ACTIVATE_ADMIN),
+ resultCodeCaptor.capture(),
+ Mockito.any(Intent.class));
+ assertEquals(expectedResultCode, (int) resultCodeCaptor.getValue());
+ }
+
+ private void finishActivateDeviceAdminActivity() {
+ getActivity().finishActivity(REQUEST_CODE_ACTIVATE_ADMIN);
+ }
+
+ private void assertDeviceAdminDeactivated(Class<?> receiverClass) {
+ DevicePolicyManager devicePolicyManager =
+ (DevicePolicyManager) getActivity().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ assertFalse(devicePolicyManager.isAdminActive(
+ new ComponentName(getInstrumentation().getTargetContext(), receiverClass)));
+ }
+}
diff --git a/tests/admin/src/android/admin/cts/DeviceAdminInfoTest.java b/tests/admin/src/android/admin/cts/DeviceAdminInfoTest.java
new file mode 100644
index 0000000..ca1b340
--- /dev/null
+++ b/tests/admin/src/android/admin/cts/DeviceAdminInfoTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 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.admin.cts;
+
+import android.app.admin.DeviceAdminInfo;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+public class DeviceAdminInfoTest extends AndroidTestCase {
+
+ private static final String TAG = DeviceAdminInfoTest.class.getSimpleName();
+
+ private PackageManager mPackageManager;
+ private ComponentName mComponent;
+ private ComponentName mSecondComponent;
+ private boolean mDeviceAdmin;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mPackageManager = mContext.getPackageManager();
+ mComponent = getReceiverComponent();
+ mSecondComponent = getSecondReceiverComponent();
+ mDeviceAdmin =
+ mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
+ }
+
+ static ComponentName getReceiverComponent() {
+ return new ComponentName("android.admin.app", "android.admin.app.CtsDeviceAdminReceiver");
+ }
+
+ static ComponentName getSecondReceiverComponent() {
+ return new ComponentName("android.admin.app", "android.admin.app.CtsDeviceAdminReceiver2");
+ }
+
+ public void testDeviceAdminInfo() throws Exception {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testDeviceAdminInfo");
+ return;
+ }
+ ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.activityInfo = mPackageManager.getReceiverInfo(mComponent,
+ PackageManager.GET_META_DATA);
+
+ DeviceAdminInfo info = new DeviceAdminInfo(mContext, resolveInfo);
+ assertEquals(mComponent, info.getComponent());
+ assertEquals(mComponent.getPackageName(), info.getPackageName());
+ assertEquals(mComponent.getClassName(), info.getReceiverName());
+
+ assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_FORCE_LOCK));
+ assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD));
+ assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_RESET_PASSWORD));
+ assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_WATCH_LOGIN));
+ assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_WIPE_DATA));
+
+ assertEquals("force-lock",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_FORCE_LOCK));
+ assertEquals("limit-password",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD));
+ assertEquals("reset-password",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_RESET_PASSWORD));
+ assertEquals("watch-login",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_WATCH_LOGIN));
+ assertEquals("wipe-data",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_WIPE_DATA));
+ }
+
+ public void testDeviceAdminInfo2() throws Exception {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testDeviceAdminInfo2");
+ return;
+ }
+ ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.activityInfo = mPackageManager.getReceiverInfo(mSecondComponent,
+ PackageManager.GET_META_DATA);
+
+ DeviceAdminInfo info = new DeviceAdminInfo(mContext, resolveInfo);
+ assertEquals(mSecondComponent, info.getComponent());
+ assertEquals(mSecondComponent.getPackageName(), info.getPackageName());
+ assertEquals(mSecondComponent.getClassName(), info.getReceiverName());
+
+ assertFalse(info.usesPolicy(DeviceAdminInfo.USES_POLICY_FORCE_LOCK));
+ assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD));
+ assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_RESET_PASSWORD));
+ assertFalse(info.usesPolicy(DeviceAdminInfo.USES_POLICY_WATCH_LOGIN));
+ assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_WIPE_DATA));
+
+ assertEquals("force-lock",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_FORCE_LOCK));
+ assertEquals("limit-password",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD));
+ assertEquals("reset-password",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_RESET_PASSWORD));
+ assertEquals("watch-login",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_WATCH_LOGIN));
+ assertEquals("wipe-data",
+ info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_WIPE_DATA));
+ }
+}
diff --git a/tests/tests/admin/src/android/admin/cts/DeviceAdminReceiverTest.java b/tests/admin/src/android/admin/cts/DeviceAdminReceiverTest.java
similarity index 100%
rename from tests/tests/admin/src/android/admin/cts/DeviceAdminReceiverTest.java
rename to tests/admin/src/android/admin/cts/DeviceAdminReceiverTest.java
diff --git a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
new file mode 100644
index 0000000..2e79557
--- /dev/null
+++ b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -0,0 +1,1160 @@
+/*
+ * Copyright (C) 2011 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.admin.cts;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Build;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.Log;
+
+import java.util.List;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+
+/**
+ * TODO: Make sure DO APIs are not called by PO.
+ * Test that exercises {@link DevicePolicyManager}. The test requires that the
+ * CtsDeviceAdminReceiver be installed via the CtsDeviceAdmin.apk and be
+ * activated via "Settings > Location & security > Select device administrators".
+ */
+public class DevicePolicyManagerTest extends AndroidTestCase {
+
+ private static final String TAG = DevicePolicyManagerTest.class.getSimpleName();
+
+ private DevicePolicyManager mDevicePolicyManager;
+ private ComponentName mComponent;
+ private ComponentName mSecondComponent;
+ private boolean mDeviceAdmin;
+ private boolean mManagedProfiles;
+ private PackageManager mPackageManager;
+
+ private static final String TEST_CA_STRING1 =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICVzCCAgGgAwIBAgIJAMvnLHnnfO/IMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD\n" +
+ "VQQGEwJJTjELMAkGA1UECAwCQVAxDDAKBgNVBAcMA0hZRDEVMBMGA1UECgwMSU1G\n" +
+ "TCBQVlQgTFREMRAwDgYDVQQLDAdJTUZMIE9VMRIwEAYDVQQDDAlJTUZMLklORk8x\n" +
+ "HzAdBgkqhkiG9w0BCQEWEHJhbWVzaEBpbWZsLmluZm8wHhcNMTMwODI4MDk0NDA5\n" +
+ "WhcNMjMwODI2MDk0NDA5WjCBhjELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAkFQMQww\n" +
+ "CgYDVQQHDANIWUQxFTATBgNVBAoMDElNRkwgUFZUIExURDEQMA4GA1UECwwHSU1G\n" +
+ "TCBPVTESMBAGA1UEAwwJSU1GTC5JTkZPMR8wHQYJKoZIhvcNAQkBFhByYW1lc2hA\n" +
+ "aW1mbC5pbmZvMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ738cbTQlNIO7O6nV/f\n" +
+ "DJTMvWbPkyHYX8CQ7yXiAzEiZ5bzKJjDJmpRAkUrVinljKns2l6C4++l/5A7pFOO\n" +
+ "33kCAwEAAaNQME4wHQYDVR0OBBYEFOdbZP7LaMbgeZYPuds2CeSonmYxMB8GA1Ud\n" +
+ "IwQYMBaAFOdbZP7LaMbgeZYPuds2CeSonmYxMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" +
+ "hvcNAQEFBQADQQBdrk6J9koyylMtl/zRfiMAc2zgeC825fgP6421NTxs1rjLs1HG\n" +
+ "VcUyQ1/e7WQgOaBHi9TefUJi+4PSVSluOXon\n" +
+ "-----END CERTIFICATE-----";
+
+ private static final String MANAGED_PROVISIONING_PKG = "com.android.managedprovisioning";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevicePolicyManager = (DevicePolicyManager)
+ mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ mComponent = DeviceAdminInfoTest.getReceiverComponent();
+ mPackageManager = mContext.getPackageManager();
+ mSecondComponent = DeviceAdminInfoTest.getSecondReceiverComponent();
+ mDeviceAdmin = mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
+ mManagedProfiles = mDeviceAdmin
+ && mPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS);
+ setBlankPassword();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ setBlankPassword();
+ }
+
+ private void setBlankPassword() {
+ if (!mDeviceAdmin) {
+ return;
+ }
+ // Reset the password to nothing for future tests...
+ mDevicePolicyManager.setPasswordQuality(mComponent,
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+ mDevicePolicyManager.setPasswordMinimumLength(mComponent, 0);
+
+ // Note resetPassword() doesn't take "who", but because the caller package has
+ assertTrue(mDevicePolicyManager.resetPassword("", 0));
+ }
+
+ public void testGetActiveAdmins() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testGetActiveAdmins");
+ return;
+ }
+ List<ComponentName> activeAdmins = mDevicePolicyManager.getActiveAdmins();
+ assertFalse(activeAdmins.isEmpty());
+ assertTrue(activeAdmins.contains(mComponent));
+ assertTrue(mDevicePolicyManager.isAdminActive(mComponent));
+ }
+
+ public void testGetMaximumFailedPasswordsForWipe() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testGetMaximumFailedPasswordsForWipe");
+ return;
+ }
+ mDevicePolicyManager.setMaximumFailedPasswordsForWipe(mComponent, 3);
+ assertEquals(3, mDevicePolicyManager.getMaximumFailedPasswordsForWipe(mComponent));
+
+ mDevicePolicyManager.setMaximumFailedPasswordsForWipe(mComponent, 5);
+ assertEquals(5, mDevicePolicyManager.getMaximumFailedPasswordsForWipe(mComponent));
+ }
+
+ public void testPasswordQuality_something() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_something");
+ return;
+ }
+ mDevicePolicyManager.setPasswordQuality(mComponent,
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ assertEquals(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
+ mDevicePolicyManager.getPasswordQuality(mComponent));
+ assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
+
+ String caseDescription = "initial";
+ assertPasswordSucceeds("1234", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordSucceeds("abcd1234", caseDescription);
+
+ mDevicePolicyManager.setPasswordMinimumLength(mComponent, 10);
+ caseDescription = "minimum password length = 10";
+ assertEquals(10, mDevicePolicyManager.getPasswordMinimumLength(mComponent));
+ assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
+
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordFails("abcd1234", caseDescription);
+
+ mDevicePolicyManager.setPasswordMinimumLength(mComponent, 4);
+ caseDescription = "minimum password length = 4";
+ assertEquals(4, mDevicePolicyManager.getPasswordMinimumLength(
+ mComponent));
+ assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
+
+ assertPasswordSucceeds("1234", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordSucceeds("abcd1234", caseDescription);
+ }
+
+ public void testPasswordQuality_numeric() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_numeric");
+ return;
+ }
+ mDevicePolicyManager.setPasswordQuality(mComponent,
+ DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+ assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
+ mDevicePolicyManager.getPasswordQuality(mComponent));
+ assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
+
+ String caseDescription = "initial";
+ assertPasswordSucceeds("1234", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordSucceeds("abcd1234", caseDescription);
+
+ mDevicePolicyManager.setPasswordMinimumLength(mComponent, 10);
+ caseDescription = "minimum password length = 10";
+ assertEquals(10, mDevicePolicyManager.getPasswordMinimumLength(mComponent));
+ assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
+
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordFails("abcd1234", caseDescription);
+
+ mDevicePolicyManager.setPasswordMinimumLength(mComponent, 4);
+ caseDescription = "minimum password length = 4";
+ assertEquals(4, mDevicePolicyManager.getPasswordMinimumLength(
+ mComponent));
+ assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
+
+ assertPasswordSucceeds("1234", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordSucceeds("abcd1234", caseDescription);
+ }
+
+ public void testPasswordQuality_alphabetic() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_alphabetic");
+ return;
+ }
+ mDevicePolicyManager.setPasswordQuality(mComponent,
+ DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
+ assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
+ mDevicePolicyManager.getPasswordQuality(mComponent));
+ assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
+
+ String caseDescription = "initial";
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordSucceeds("abcd1234", caseDescription);
+
+ mDevicePolicyManager.setPasswordMinimumLength(mComponent, 10);
+ caseDescription = "minimum password length = 10";
+ assertEquals(10, mDevicePolicyManager.getPasswordMinimumLength(mComponent));
+ assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
+
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordFails("abcd1234", caseDescription);
+
+ mDevicePolicyManager.setPasswordMinimumLength(mComponent, 4);
+ caseDescription = "minimum password length = 4";
+ assertEquals(4, mDevicePolicyManager.getPasswordMinimumLength(
+ mComponent));
+ assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
+
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordSucceeds("abcd1234", caseDescription);
+ }
+
+ public void testPasswordQuality_alphanumeric() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_alphanumeric");
+ return;
+ }
+ mDevicePolicyManager.setPasswordQuality(mComponent,
+ DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC);
+ assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
+ mDevicePolicyManager.getPasswordQuality(mComponent));
+ assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
+
+ String caseDescription = "initial";
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordSucceeds("abcd1234", caseDescription);
+
+ mDevicePolicyManager.setPasswordMinimumLength(mComponent, 10);
+ caseDescription = "minimum password length = 10";
+ assertEquals(10, mDevicePolicyManager.getPasswordMinimumLength(mComponent));
+ assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
+
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordFails("abcd1234", caseDescription);
+
+ mDevicePolicyManager.setPasswordMinimumLength(mComponent, 4);
+ caseDescription = "minimum password length = 4";
+ assertEquals(4, mDevicePolicyManager.getPasswordMinimumLength(
+ mComponent));
+ assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
+
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordSucceeds("abcd1234", caseDescription);
+ }
+
+ public void testPasswordQuality_complexUpperCase() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_complexUpperCase");
+ return;
+ }
+
+ mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+ assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+ resetComplexPasswordRestrictions();
+
+ String caseDescription = "minimum UpperCase=0";
+ assertPasswordSucceeds("abc1", caseDescription);
+ assertPasswordSucceeds("aBc1", caseDescription);
+ assertPasswordSucceeds("ABC1", caseDescription);
+ assertPasswordSucceeds("ABCD", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumUpperCase(mComponent, 1);
+ assertEquals(1, mDevicePolicyManager.getPasswordMinimumUpperCase(mComponent));
+ caseDescription = "minimum UpperCase=1";
+ assertPasswordFails("abc1", caseDescription);
+ assertPasswordSucceeds("aBc1", caseDescription);
+ assertPasswordSucceeds("ABC1", caseDescription);
+ assertPasswordSucceeds("ABCD", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumUpperCase(mComponent, 3);
+ assertEquals(3, mDevicePolicyManager.getPasswordMinimumUpperCase(mComponent));
+ caseDescription = "minimum UpperCase=3";
+ assertPasswordFails("abc1", caseDescription);
+ assertPasswordFails("aBC1", caseDescription);
+ assertPasswordSucceeds("ABC1", caseDescription);
+ assertPasswordSucceeds("ABCD", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+ }
+
+ public void testPasswordQuality_complexLowerCase() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_complexLowerCase");
+ return;
+ }
+
+ mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+ assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+ resetComplexPasswordRestrictions();
+
+ String caseDescription = "minimum LowerCase=0";
+ assertPasswordSucceeds("ABCD", caseDescription);
+ assertPasswordSucceeds("aBC1", caseDescription);
+ assertPasswordSucceeds("abc1", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumLowerCase(mComponent, 1);
+ assertEquals(1, mDevicePolicyManager.getPasswordMinimumLowerCase(mComponent));
+ caseDescription = "minimum LowerCase=1";
+ assertPasswordFails("ABCD", caseDescription);
+ assertPasswordSucceeds("aBC1", caseDescription);
+ assertPasswordSucceeds("abc1", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumLowerCase(mComponent, 3);
+ assertEquals(3, mDevicePolicyManager.getPasswordMinimumLowerCase(mComponent));
+ caseDescription = "minimum LowerCase=3";
+ assertPasswordFails("ABCD", caseDescription);
+ assertPasswordFails("aBC1", caseDescription);
+ assertPasswordSucceeds("abc1", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+ }
+
+ public void testPasswordQuality_complexLetters() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_complexLetters");
+ return;
+ }
+
+ mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+ assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+ resetComplexPasswordRestrictions();
+
+ String caseDescription = "minimum Letters=0";
+ assertPasswordSucceeds("1234", caseDescription);
+ assertPasswordSucceeds("a123", caseDescription);
+ assertPasswordSucceeds("abc1", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumLetters(mComponent, 1);
+ assertEquals(1, mDevicePolicyManager.getPasswordMinimumLetters(mComponent));
+ caseDescription = "minimum Letters=1";
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordSucceeds("a123", caseDescription);
+ assertPasswordSucceeds("abc1", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumLetters(mComponent, 3);
+ assertEquals(3, mDevicePolicyManager.getPasswordMinimumLetters(mComponent));
+ caseDescription = "minimum Letters=3";
+ assertPasswordFails("1234", caseDescription);
+ assertPasswordFails("a123", caseDescription);
+ assertPasswordSucceeds("abc1", caseDescription);
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+ }
+
+ public void testPasswordQuality_complexNumeric() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_complexNumeric");
+ return;
+ }
+
+ mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+ assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+ resetComplexPasswordRestrictions();
+
+ String caseDescription = "minimum Numeric=0";
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordSucceeds("1abc", caseDescription);
+ assertPasswordSucceeds("123a", caseDescription);
+ assertPasswordSucceeds("1234", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumNumeric(mComponent, 1);
+ assertEquals(1, mDevicePolicyManager.getPasswordMinimumNumeric(mComponent));
+ caseDescription = "minimum Numeric=1";
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordSucceeds("1abc", caseDescription);
+ assertPasswordSucceeds("123a", caseDescription);
+ assertPasswordSucceeds("1234", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumNumeric(mComponent, 3);
+ assertEquals(3, mDevicePolicyManager.getPasswordMinimumNumeric(mComponent));
+ caseDescription = "minimum Numeric=3";
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordFails("1abc", caseDescription);
+ assertPasswordSucceeds("123a", caseDescription);
+ assertPasswordSucceeds("1234", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+ }
+
+ public void testPasswordQuality_complexSymbols() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_complexSymbols");
+ return;
+ }
+
+ mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+ assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+ resetComplexPasswordRestrictions();
+
+ String caseDescription = "minimum Symbols=0";
+ assertPasswordSucceeds("abcd", caseDescription);
+ assertPasswordSucceeds("_bc1", caseDescription);
+ assertPasswordSucceeds("@#!1", caseDescription);
+ assertPasswordSucceeds("_@#!", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumSymbols(mComponent, 1);
+ assertEquals(1, mDevicePolicyManager.getPasswordMinimumSymbols(mComponent));
+ caseDescription = "minimum Symbols=1";
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordSucceeds("_bc1", caseDescription);
+ assertPasswordSucceeds("@#!1", caseDescription);
+ assertPasswordSucceeds("_@#!", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumSymbols(mComponent, 3);
+ assertEquals(3, mDevicePolicyManager.getPasswordMinimumSymbols(mComponent));
+ caseDescription = "minimum Symbols=3";
+ assertPasswordFails("abcd", caseDescription);
+ assertPasswordFails("_bc1", caseDescription);
+ assertPasswordSucceeds("@#!1", caseDescription);
+ assertPasswordSucceeds("_@#!", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+ }
+
+ public void testPasswordQuality_complexNonLetter() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordQuality_complexNonLetter");
+ return;
+ }
+
+ mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+ assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+ resetComplexPasswordRestrictions();
+
+ String caseDescription = "minimum NonLetter=0";
+ assertPasswordSucceeds("Abcd", caseDescription);
+ assertPasswordSucceeds("_bcd", caseDescription);
+ assertPasswordSucceeds("3bcd", caseDescription);
+ assertPasswordSucceeds("_@3c", caseDescription);
+ assertPasswordSucceeds("_25!", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumNonLetter(mComponent, 1);
+ assertEquals(1, mDevicePolicyManager.getPasswordMinimumNonLetter(mComponent));
+ caseDescription = "minimum NonLetter=1";
+ assertPasswordFails("Abcd", caseDescription);
+ assertPasswordSucceeds("_bcd", caseDescription);
+ assertPasswordSucceeds("3bcd", caseDescription);
+ assertPasswordSucceeds("_@3c", caseDescription);
+ assertPasswordSucceeds("_25!", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+
+ mDevicePolicyManager.setPasswordMinimumNonLetter(mComponent, 3);
+ assertEquals(3, mDevicePolicyManager.getPasswordMinimumNonLetter(mComponent));
+ caseDescription = "minimum NonLetter=3";
+ assertPasswordFails("Abcd", caseDescription);
+ assertPasswordFails("_bcd", caseDescription);
+ assertPasswordFails("3bcd", caseDescription);
+ assertPasswordSucceeds("_@3c", caseDescription);
+ assertPasswordSucceeds("_25!", caseDescription);
+ assertPasswordFails("123", caseDescription); // too short
+ }
+
+ public void testPasswordHistoryLength() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordHistoryLength");
+ return;
+ }
+ // Password history length restriction is only imposed if password quality is at least
+ // numeric.
+ mDevicePolicyManager.setPasswordQuality(mComponent,
+ DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
+ int originalValue = mDevicePolicyManager.getPasswordHistoryLength(mComponent);
+ try {
+ mDevicePolicyManager.setPasswordHistoryLength(mComponent, 3);
+ assertEquals(3, mDevicePolicyManager.getPasswordHistoryLength(mComponent));
+ // Although it would make sense we cannot test if password history restrictions
+ // are enforced as DevicePolicyManagerService.resetPassword fails to do so at the
+ // moment. See b/17707820
+ } finally {
+ mDevicePolicyManager.setPasswordHistoryLength(mComponent, originalValue);
+ }
+ }
+
+ public void testPasswordExpirationTimeout() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testPasswordExpirationTimeout");
+ return;
+ }
+ long originalValue = mDevicePolicyManager.getPasswordExpirationTimeout(mComponent);
+ try {
+ for (long testLength : new long[] {
+ 0L, 864000000L /* ten days */, 8640000000L /* 100 days */}) {
+ mDevicePolicyManager.setPasswordExpirationTimeout(mComponent, testLength);
+ assertEquals(testLength,
+ mDevicePolicyManager.getPasswordExpirationTimeout(mComponent));
+ }
+ } finally {
+ mDevicePolicyManager.setPasswordExpirationTimeout(mComponent, originalValue);
+ }
+ }
+
+ public void testKeyguardDisabledFeatures() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testKeyguardDisabledFeatures");
+ return;
+ }
+ int originalValue = mDevicePolicyManager.getKeyguardDisabledFeatures(mComponent);
+ try {
+ for (int which = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+ which < 2 * DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT; ++which) {
+ mDevicePolicyManager.setKeyguardDisabledFeatures(mComponent, which);
+ assertEquals(which, mDevicePolicyManager.getKeyguardDisabledFeatures(mComponent));
+ }
+ } finally {
+ mDevicePolicyManager.setKeyguardDisabledFeatures(mComponent, originalValue);
+ }
+ }
+
+ public void testCreateUser_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testCreateUser_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.createUser(mComponent, "user name");
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testRemoveUser_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testRemoveUser_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.removeUser(mComponent, null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetApplicationHidden_failIfNotDeviceOrProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetApplicationHidden_failIfNotDeviceOrProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setApplicationHidden(mComponent, "com.google.anything", true);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testIsApplicationHidden_failIfNotDeviceOrProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testIsApplicationHidden_failIfNotDeviceOrProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.isApplicationHidden(mComponent, "com.google.anything");
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetGlobalSetting_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetGlobalSetting_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setGlobalSetting(mComponent,
+ Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, "1");
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetSecureSetting_failIfNotDeviceOrProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetSecureSetting_failIfNotDeviceOrProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setSecureSetting(mComponent,
+ Settings.Secure.INSTALL_NON_MARKET_APPS, "1");
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setMasterVolumeMuted(mComponent, true);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testIsMasterVolumeMuted_failIfNotDeviceOrProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.isMasterVolumeMuted(mComponent);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetRecommendedGlobalProxy_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetRecommendedGlobalProxy_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setRecommendedGlobalProxy(mComponent, null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetLockTaskPackages_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetLockTaskPackages_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setLockTaskPackages(mComponent, new String[] {"package"});
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ }
+ }
+
+ // This test registers itself as DO, so this is no longer testable. We do a positive test
+ // for clearDeviceOwnerApp()
+ @Suppress
+ public void testClearDeviceOwnerApp_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testClearDeviceOwnerApp_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.clearDeviceOwnerApp("android.admin.app");
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSwitchUser_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSwitchUser_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.switchUser(mComponent, null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testCreateAndInitializeUser_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testCreateAndInitializeUser_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.createAndInitializeUser(mComponent, "name", "admin name",
+ mComponent, null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testInstallCaCert_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testInstallCaCert_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.installCaCert(mComponent,
+ TEST_CA_STRING1.getBytes());
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testInstallCaCert_failIfNotCertInstaller() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testInstallCaCert_failIfNotCertInstaller");
+ return;
+ }
+ try {
+ // Delegated cert installer is identified by using null as the first argument.
+ mDevicePolicyManager.installCaCert(null, TEST_CA_STRING1.getBytes());
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ public void testUninstallCaCert_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testUninstallCaCert_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.uninstallCaCert(mComponent,
+ TEST_CA_STRING1.getBytes());
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testUninstallCaCert_failIfNotCertInstaller() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testUninstallCaCert_failIfNotCertInstaller");
+ return;
+ }
+ try {
+ // Delegated cert installer is identified by using null as the first argument.
+ mDevicePolicyManager.uninstallCaCert(null, TEST_CA_STRING1.getBytes());
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ public void testGetInstalledCaCerts_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testGetInstalledCaCerts_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.getInstalledCaCerts(mComponent);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testGetInstalledCaCerts_failIfNotCertInstaller() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testGetInstalledCaCerts_failIfNotCertInstaller");
+ return;
+ }
+ try {
+ // Delegated cert installer is identified by using null as the first argument.
+ mDevicePolicyManager.getInstalledCaCerts(null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ public void testHasCaCertInstalled_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testHasCaCertInstalled_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.hasCaCertInstalled(mComponent,
+ TEST_CA_STRING1.getBytes());
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testHasCaCertInstalled_failIfNotCertInstaller() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testHasCaCertInstalled_failIfNotCertInstaller");
+ return;
+ }
+ try {
+ // Delegated cert installer is identified by using null as the first argument.
+ mDevicePolicyManager.hasCaCertInstalled(null, TEST_CA_STRING1.getBytes());
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ public void testUninstallAllUserCaCerts_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testUninstallAllUserCaCerts_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.uninstallAllUserCaCerts(mComponent);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testUninstallAllUserCaCerts_failIfNotCertInstaller() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testUninstallAllUserCaCerts_failIfNotCertInstaller");
+ return;
+ }
+ try {
+ // Delegated cert installer is identified by using null as the first argument.
+ mDevicePolicyManager.uninstallAllUserCaCerts(null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ public void testSetScreenCaptureDisabled_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetScreenCaptureDisabled_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setScreenCaptureDisabled(mComponent, true);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetAutoTimeRequired_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetAutoTimeRequired_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setAutoTimeRequired(mComponent, true);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testAddPersistentPreferredActivity_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testAddPersistentPreferredActivity_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.addPersistentPreferredActivity(mComponent,
+ new IntentFilter(Intent.ACTION_MAIN),
+ new ComponentName("android.admin.cts", "dummy"));
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testClearPackagePersistentPreferredActivities_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testClearPackagePersistentPreferredActivities_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.clearPackagePersistentPreferredActivities(mComponent,
+ "android.admin.cts");
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetApplicationRestrictions_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetApplicationRestrictions_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setApplicationRestrictions(mComponent,
+ "android.admin.cts", null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testAddUserRestriction_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testAddUserRestriction_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.addUserRestriction(mComponent,
+ UserManager.DISALLOW_SMS);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetAccountManagementDisabled_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetAccountManagementDisabled_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setAccountManagementDisabled(mComponent,
+ "dummy", true);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetRestrictionsProvider_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetRestrictionsProvider_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setRestrictionsProvider(mComponent,
+ new ComponentName("android.admin.cts", "dummy"));
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetUninstallBlocked_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetUninstallBlocked_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setUninstallBlocked(mComponent,
+ "android.admin.cts", true);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetPermittedAccessibilityServices_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetPermittedAccessibilityServices_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setPermittedAccessibilityServices(mComponent, null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetBluetoothContactSharingDisabled_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetBluetoothContactSharingDisabled_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setBluetoothContactSharingDisabled(mComponent, true);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetPermittedInputMethods_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetPermittedInputMethods_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setPermittedInputMethods(mComponent, null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ /**
+ * Test whether the version of the pre-installed launcher is at least L. This is needed for
+ * managed profile support.
+ */
+ public void testLauncherVersionAtLeastL() throws Exception {
+ if (!mManagedProfiles) {
+ return;
+ }
+
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities(intent,
+ 0 /* default flags */);
+ assertFalse("No launcher present", resolveInfos.isEmpty());
+
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ ApplicationInfo launcherAppInfo = mPackageManager.getApplicationInfo(
+ resolveInfo.activityInfo.packageName, 0 /* default flags */);
+ if ((launcherAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 &&
+ launcherAppInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
+ return;
+ }
+ }
+ fail("No system launcher with version L+ present present on device.");
+ }
+
+ /**
+ * Test that managed provisioning is pre-installed if and only if the device declares the
+ * device admin feature.
+ */
+ public void testManagedProvisioningPreInstalled() throws Exception {
+ assertEquals(mDeviceAdmin, isPackageInstalledOnSystemImage(MANAGED_PROVISIONING_PKG));
+ }
+
+ private void assertDeviceOwnerMessage(String message) {
+ assertTrue("message is: "+ message, message.contains("does not own the device")
+ || message.contains("can only be called by the device owner"));
+ }
+
+ private void assertProfileOwnerMessage(String message) {
+ assertTrue("message is: "+ message,
+ message.contains("does not own the profile"));
+ }
+
+ private void resetComplexPasswordRestrictions() {
+ /**
+ * Not enough to reset only mComponent as
+ * {@link DevicePolicyManager#resetPassword(String, int)} checks restrictions across all
+ * admin components.
+ */
+ for (ComponentName adminComponent : new ComponentName[] {mComponent, mSecondComponent}) {
+ mDevicePolicyManager.setPasswordMinimumLength(adminComponent, 0);
+ mDevicePolicyManager.setPasswordMinimumUpperCase(adminComponent, 0);
+ mDevicePolicyManager.setPasswordMinimumLowerCase(adminComponent, 0);
+ mDevicePolicyManager.setPasswordMinimumLetters(adminComponent, 0);
+ mDevicePolicyManager.setPasswordMinimumNumeric(adminComponent, 0);
+ mDevicePolicyManager.setPasswordMinimumSymbols(adminComponent, 0);
+ mDevicePolicyManager.setPasswordMinimumNonLetter(adminComponent, 0);
+ }
+ }
+
+ private void assertPasswordFails(String password, String restriction) {
+ try {
+ boolean passwordResetResult = mDevicePolicyManager.resetPassword(password, /* flags= */0);
+ assertFalse("Password '" + password + "' should have failed on " + restriction,
+ passwordResetResult);
+ } catch (IllegalArgumentException e) {
+ // yesss, we have failed!
+ }
+ }
+
+ private void assertPasswordSucceeds(String password, String restriction) {
+ boolean passwordResetResult = mDevicePolicyManager.resetPassword(password, /* flags= */0);
+ assertTrue("Password '" + password + "' failed on " + restriction, passwordResetResult);
+ assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
+ }
+
+ public void testSetDelegatedCertInstaller_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetDelegatedCertInstaller_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setCertInstallerPackage(mComponent, "com.test.package");
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testGetDelegatedCertInstaller_failIfNotProfileOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testGetDelegatedCertInstaller_failIfNotProfileOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.getCertInstallerPackage(mComponent);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertProfileOwnerMessage(e.getMessage());
+ }
+ }
+
+ public void testSetSystemUpdatePolicy_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testSetSystemUpdatePolicy_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.setSystemUpdatePolicy(mComponent, null);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+ private boolean isPackageInstalledOnSystemImage(String packagename) {
+ try {
+ ApplicationInfo info = mPackageManager.getApplicationInfo(packagename,
+ 0 /* default flags */);
+ return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ public void testReboot_failIfNotDeviceOwner() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testReboot_failIfNotDeviceOwner");
+ return;
+ }
+ try {
+ mDevicePolicyManager.reboot(mComponent);
+ fail("did not throw expected SecurityException");
+ } catch (SecurityException e) {
+ assertDeviceOwnerMessage(e.getMessage());
+ }
+ }
+
+}
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
index f4f0a13..0acabaf 100644
--- a/tests/app/Android.mk
+++ b/tests/app/Android.mk
@@ -21,15 +21,23 @@
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_PROGUARD_ENABLED := disabled
-
LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common voip-common org.apache.http.legacy
LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
- src/android/app/cts/ISecondary.aidl
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := CtsAppTestStubs
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
-include $(BUILD_CTS_SUPPORT_PACKAGE)
+LOCAL_PACKAGE_NAME := CtsAppTestCases
+
+LOCAL_INSTRUMENTATION_FOR := CtsAppTestStubs
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/app/AndroidManifest.xml b/tests/app/AndroidManifest.xml
index 8d7729e..0a7216d 100644
--- a/tests/app/AndroidManifest.xml
+++ b/tests/app/AndroidManifest.xml
@@ -16,270 +16,22 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.app.stub">
+ package="android.app.cts">
- <permission android:name="android.app.cts.permission.TEST_GRANTED"
- android:protectionLevel="normal"
- android:label="@string/permlab_testGranted"
- android:description="@string/permdesc_testGranted">
- <meta-data android:name="android.app.cts.string" android:value="foo" />
- <meta-data android:name="android.app.cts.boolean" android:value="true" />
- <meta-data android:name="android.app.cts.integer" android:value="100" />
- <meta-data android:name="android.app.cts.color" android:value="#ff000000" />
- <meta-data android:name="android.app.cts.float" android:value="100.1" />
- <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
- </permission>
-
- <uses-permission android:name="android.app.cts.permission.TEST_GRANTED" />
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.WRITE_CONTACTS" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.CAMERA" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
- <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-sdk android:minSdkVersion="11" />
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.BODY_SENSORS" />
-
- <application android:label="Android TestCase"
- android:icon="@drawable/size_48x48"
- android:maxRecents="1"
- android:multiArch="true"
- android:name="android.app.cts.MockApplication"
- android:supportsRtl="true">
+ <application>
<uses-library android:name="android.test.runner" />
<uses-library android:name="org.apache.http.legacy" android:required="false" />
-
- <activity android:name="android.app.cts.ActionBarActivity" />
-
- <activity android:name="android.app.cts.DialogStubActivity"
- android:label="DialogStubActivity"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <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.cts.MockActivity" android:label="MockActivity">
- <meta-data android:name="android.app.alias"
- android:resource="@xml/alias" />
- <meta-data android:name="android.app.intent.filter"
- android:resource="@xml/intentfilter" />
- </activity>
-
- <activity android:name="android.app.cts.MockApplicationActivity"
- android:label="MockApplicationActivity">
- <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.cts.InstrumentationTestActivity"
- android:theme="@style/Theme_NoSwipeDismiss"
- android:label="InstrumentationTestActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.cursor.dir/person" />
- </intent-filter>
- </activity>
-
- <activity android:name="android.app.cts.AliasActivityStub">
- <meta-data android:name="android.app.alias"
- android:resource="@xml/alias" />
- </activity>
-
- <activity android:name="android.app.cts.ChildActivity"
- android:label="ChildActivity" />
-
- <receiver android:name="android.app.cts.MockReceiver">
- <intent-filter>
- <action android:name="android.app.cts.PendingIntentTest.TEST_RECEIVER" />
- </intent-filter>
- </receiver>
-
- <service android:name="android.app.cts.MockService" />
-
- <activity android:name="android.app.cts.SearchManagerStubActivity"
- android:label="SearchManagerStubActivity">
- <intent-filter>
- <action android:name="android.intent.action.SEARCH" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
- </activity>
-
- <service android:name="android.app.cts.LocalService">
- <intent-filter>
- <action android:name="android.app.cts.activity.SERVICE_LOCAL" />
- </intent-filter>
- <meta-data android:name="android.app.cts.string" android:value="foo" />
- <meta-data android:name="android.app.cts.boolean" android:value="true" />
- <meta-data android:name="android.app.cts.integer" android:value="100" />
- <meta-data android:name="android.app.cts.color" android:value="#ff000000" />
- <meta-data android:name="android.app.cts.float" android:value="100.1" />
- <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
- </service>
-
- <service android:name="android.app.cts.LocalGrantedService"
- android:permission="android.app.cts.permission.TEST_GRANTED">
- <intent-filter>
- <action android:name="android.app.cts.activity.SERVICE_LOCAL_GRANTED" />
- </intent-filter>
- </service>
-
- <service android:name="android.app.cts.LocalDeniedService"
- android:permission="android.app.cts.permission.TEST_DENIED">
- <intent-filter>
- <action android:name="android.app.cts.activity.SERVICE_LOCAL_DENIED" />
- </intent-filter>
- </service>
-
- <activity android:name="android.app.cts.TestedScreen"
- android:process=":remoteScreen">
- </activity>
- <activity android:name="android.app.cts.LocalScreen" android:multiprocess="true">
- </activity>
- <activity android:name="android.app.cts.ClearTop" android:multiprocess="true"
- android:launchMode="singleTop">
- </activity>
- <activity android:name="android.app.cts.LocalDialog" android:multiprocess="true"
- android:theme="@android:style/Theme.Dialog">
- </activity>
-
- <activity android:name="android.app.cts.PendingIntentStubActivity"
- android:label="PendingIntentStubActivity"/>
-
- <activity android:name="android.app.cts.LocalActivityManagerStubActivity"
- android:label="LocalActivityManagerStubActivity" />
-
- <activity android:name="android.app.cts.LocalActivityManagerTestHelper"
- android:label="LocalActivityManagerTestHelper" />
-
- <activity android:name="android.app.cts.LaunchpadTabActivity" android:multiprocess="true">
- </activity>
-
- <activity android:name="android.app.cts.LocalActivity" android:multiprocess="true">
- <meta-data android:name="android.app.cts.string" android:value="foo" />
- <meta-data android:name="android.app.cts.boolean" android:value="true" />
- <meta-data android:name="android.app.cts.integer" android:value="100" />
- <meta-data android:name="android.app.cts.color" android:value="#ff000000" />
- <meta-data android:name="android.app.cts.float" android:value="100.1" />
- <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
- </activity>
-
- <activity android:name="android.app.cts.TestedActivity"
- android:process=":remoteActivity">
- </activity>
-
- <activity android:name="android.app.cts.ExpandableListTestActivity"
- android:label="ExpandableListTestActivity">
- <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.cts.ChildTabActivity" android:label="ChildTabActivity" />
-
- <activity android:name="android.app.cts.LauncherActivityStub"
- android:label="LauncherActivityStub" >
- <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.cts.MockTabActivity" android:label="MockTabActivity" />
-
- <activity android:name="android.app.cts.AppStubActivity" android:label="AppStubActivity">
- <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.cts.DialogStubActivity"
- android:theme="@style/Theme_NoSwipeDismiss"
- android:label="DialogStubActivity">
- <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.cts.ActivityManagerStubFooActivity"
- android:label="ActivityManagerStubFooActivity">
- <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.cts.ActivityManagerRecentOneActivity"
- android:label="ActivityManagerRecentOneActivity"
- android:allowTaskReparenting="true"
- android:taskAffinity="android.app.cts.recentOne">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
- <activity android:name="android.app.cts.ActivityManagerRecentTwoActivity"
- android:label="ActivityManagerRecentTwoActivity"
- android:allowTaskReparenting="true"
- android:taskAffinity="android.app.cts.recentTwo">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
- <activity android:name="android.app.cts.ActivityManagerStubCrashActivity"
- android:label="ActivityManagerStubCrashActivity"
- android:multiprocess="true"
- android:process=":ActivityManagerStubCrashActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
- <service android:name="android.app.cts.StubRemoteService"
- android:process=":remote">
- <intent-filter>
- <action
- android:name="android.app.cts.ISecondary" />
- <action
- android:name="android.app.REMOTESERVICE" />
- </intent-filter>
- </service>
-
- <activity android:name="android.app.ActivityGroup"
- android:label="ActivityGroup" />
-
- <activity android:name="android.app.cts.KeyguardManagerActivity"
- android:label="KeyguardManagerActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <service android:name="android.app.cts.IntentServiceStub"/>
-
- <activity android:name="android.app.cts.LaunchpadActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:multiprocess="true">
- </activity>
-
- <activity android:name="android.app.cts.ActivityManagerMemoryClassLaunchActivity" />
-
- <activity android:name="android.app.cts.ActivityManagerMemoryClassTestActivity"
- android:process=":memoryclass" />
-
</application>
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.app.stubs"
+ android:label="CTS tests of android.app">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
</manifest>
diff --git a/tests/app/AndroidTest.xml b/tests/app/AndroidTest.xml
new file mode 100644
index 0000000..acbc9e7
--- /dev/null
+++ b/tests/app/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<configuration description="Config for CTS App test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSimpleApp.apk" />
+ <option name="test-file-name" value="CtsAppTestStubs.apk" />
+ <option name="test-file-name" value="CtsAppTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.app.cts" />
+ <option name="runtime-hint" value="3m8s" />
+ </test>
+
+</configuration>
diff --git a/tests/tests/app/AndroidTest.xml b/tests/app/OldAndroidTest.xml
similarity index 100%
rename from tests/tests/app/AndroidTest.xml
rename to tests/app/OldAndroidTest.xml
diff --git a/tests/app/app/Android.mk b/tests/app/app/Android.mk
new file mode 100644
index 0000000..a638b70
--- /dev/null
+++ b/tests/app/app/Android.mk
@@ -0,0 +1,38 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common voip-common org.apache.http.legacy
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+ src/android/app/stubs/ISecondary.aidl
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsAppTestStubs
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
new file mode 100644
index 0000000..c64e977
--- /dev/null
+++ b/tests/app/app/AndroidManifest.xml
@@ -0,0 +1,328 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.app.stubs">
+
+ <permission android:name="android.app.stubs.permission.TEST_GRANTED"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_testGranted"
+ android:description="@string/permdesc_testGranted">
+ <meta-data android:name="android.app.stubs.string" android:value="foo" />
+ <meta-data android:name="android.app.stubs.boolean" android:value="true" />
+ <meta-data android:name="android.app.stubs.integer" android:value="100" />
+ <meta-data android:name="android.app.stubs.color" android:value="#ff000000" />
+ <meta-data android:name="android.app.stubs.float" android:value="100.1" />
+ <meta-data android:name="android.app.stubs.reference" android:resource="@xml/metadata" />
+ </permission>
+
+ <uses-permission android:name="android.app.stubs.permission.TEST_GRANTED" />
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.BODY_SENSORS" />
+
+ <application android:label="Android TestCase"
+ android:icon="@drawable/size_48x48"
+ android:maxRecents="1"
+ android:multiArch="true"
+ android:name="android.app.stubs.MockApplication"
+ android:supportsRtl="true">
+ <uses-library android:name="android.test.runner" />
+ <uses-library android:name="org.apache.http.legacy" android:required="false" />
+
+ <activity android:name="android.app.stubs.ActionBarActivity" />
+
+ <activity android:name="android.app.stubs.DialogStubActivity"
+ android:label="DialogStubActivity"
+ android:configChanges="keyboardHidden|orientation|screenSize">
+ <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.stubs.MockActivity" android:label="MockActivity">
+ <meta-data android:name="android.app.alias"
+ android:resource="@xml/alias" />
+ <meta-data android:name="android.app.intent.filter"
+ android:resource="@xml/intentfilter" />
+ </activity>
+
+ <activity android:name="android.app.stubs.MockApplicationActivity"
+ android:label="MockApplicationActivity">
+ <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.stubs.InstrumentationTestActivity"
+ android:theme="@style/Theme_NoSwipeDismiss"
+ android:label="InstrumentationTestActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.dir/person" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.app.stubs.AliasActivityStub">
+ <meta-data android:name="android.app.alias"
+ android:resource="@xml/alias" />
+ </activity>
+
+ <activity android:name="android.app.stubs.ChildActivity"
+ android:label="ChildActivity" />
+
+ <receiver android:name="android.app.stubs.MockReceiver">
+ <intent-filter>
+ <action android:name="android.app.stubs.PendingIntentTest.TEST_RECEIVER" />
+ </intent-filter>
+ </receiver>
+
+ <service android:name="android.app.stubs.MockService" />
+
+ <activity android:name="android.app.stubs.SearchManagerStubActivity"
+ android:label="SearchManagerStubActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.SEARCH" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
+ </activity>
+
+ <service android:name="android.app.stubs.LocalService">
+ <intent-filter>
+ <action android:name="android.app.stubs.activity.SERVICE_LOCAL" />
+ </intent-filter>
+ <meta-data android:name="android.app.stubs.string" android:value="foo" />
+ <meta-data android:name="android.app.stubs.boolean" android:value="true" />
+ <meta-data android:name="android.app.stubs.integer" android:value="100" />
+ <meta-data android:name="android.app.stubs.color" android:value="#ff000000" />
+ <meta-data android:name="android.app.stubs.float" android:value="100.1" />
+ <meta-data android:name="android.app.stubs.reference" android:resource="@xml/metadata" />
+ </service>
+
+ <service android:name="android.app.stubs.LocalGrantedService"
+ android:permission="android.app.stubs.permission.TEST_GRANTED">
+ <intent-filter>
+ <action android:name="android.app.stubs.activity.SERVICE_LOCAL_GRANTED" />
+ </intent-filter>
+ </service>
+
+ <service android:name="android.app.stubs.LocalDeniedService"
+ android:permission="android.app.stubs.permission.TEST_DENIED">
+ <intent-filter>
+ <action android:name="android.app.stubs.activity.SERVICE_LOCAL_DENIED" />
+ </intent-filter>
+ </service>
+
+ <activity android:name="android.app.stubs.TestedScreen"
+ android:process=":remoteScreen">
+ </activity>
+ <activity android:name="android.app.stubs.LocalScreen" android:multiprocess="true">
+ </activity>
+ <activity android:name="android.app.stubs.ClearTop" android:multiprocess="true"
+ android:launchMode="singleTop">
+ </activity>
+ <activity android:name="android.app.stubs.LocalDialog" android:multiprocess="true"
+ android:theme="@android:style/Theme.Dialog">
+ </activity>
+
+ <activity android:name="android.app.stubs.PendingIntentStubActivity"
+ android:label="PendingIntentStubActivity"/>
+
+ <activity android:name="android.app.stubs.LocalActivityManagerStubActivity"
+ android:label="LocalActivityManagerStubActivity" />
+
+ <activity android:name="android.app.stubs.LocalActivityManagerTestHelper"
+ android:label="LocalActivityManagerTestHelper" />
+
+ <activity android:name="android.app.stubs.LaunchpadTabActivity" android:multiprocess="true">
+ </activity>
+
+ <activity android:name="android.app.stubs.LocalActivity" android:multiprocess="true">
+ <meta-data android:name="android.app.stubs.string" android:value="foo" />
+ <meta-data android:name="android.app.stubs.boolean" android:value="true" />
+ <meta-data android:name="android.app.stubs.integer" android:value="100" />
+ <meta-data android:name="android.app.stubs.color" android:value="#ff000000" />
+ <meta-data android:name="android.app.stubs.float" android:value="100.1" />
+ <meta-data android:name="android.app.stubs.reference" android:resource="@xml/metadata" />
+ </activity>
+
+ <activity android:name="android.app.stubs.TestedActivity"
+ android:process=":remoteActivity">
+ </activity>
+
+ <activity android:name="android.app.stubs.ExpandableListTestActivity"
+ android:label="ExpandableListTestActivity">
+ <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.stubs.FragmentTestActivity"
+ android:label="FragmentTestActivity">
+ <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.stubs.ChildTabActivity" android:label="ChildTabActivity" />
+
+ <activity android:name="android.app.stubs.LauncherActivityStub"
+ android:label="LauncherActivityStub" >
+ <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.stubs.MockTabActivity" android:label="MockTabActivity" />
+
+ <activity android:name="android.app.stubs.AppStubActivity" android:label="AppStubActivity">
+ <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.stubs.DialogStubActivity"
+ android:theme="@style/Theme_NoSwipeDismiss"
+ android:label="DialogStubActivity">
+ <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.stubs.ActivityManagerStubFooActivity"
+ android:label="ActivityManagerStubFooActivity">
+ <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.stubs.ActivityManagerRecentOneActivity"
+ android:label="ActivityManagerRecentOneActivity"
+ android:allowTaskReparenting="true"
+ android:taskAffinity="android.app.stubs.recentOne">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.app.stubs.ActivityManagerRecentTwoActivity"
+ android:label="ActivityManagerRecentTwoActivity"
+ android:allowTaskReparenting="true"
+ android:taskAffinity="android.app.stubs.recentTwo">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.app.stubs.ActivityManagerStubCrashActivity"
+ android:label="ActivityManagerStubCrashActivity"
+ android:multiprocess="true"
+ android:process=":ActivityManagerStubCrashActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+
+ <service android:name="android.app.stubs.StubRemoteService"
+ android:process=":remote">
+ <intent-filter>
+ <action
+ android:name="android.app.stubs.ISecondary" />
+ <action
+ android:name="android.app.REMOTESERVICE" />
+ </intent-filter>
+ </service>
+
+ <activity android:name="android.app.ActivityGroup"
+ android:label="ActivityGroup" />
+
+ <activity android:name="android.app.stubs.KeyguardManagerActivity"
+ android:label="KeyguardManagerActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <service android:name="android.app.stubs.IntentServiceStub"/>
+
+ <activity android:name="android.app.stubs.LaunchpadActivity"
+ android:configChanges="keyboardHidden|orientation|screenSize"
+ android:multiprocess="true">
+ </activity>
+
+ <activity android:name="android.app.stubs.ActivityManagerMemoryClassLaunchActivity" />
+
+ <activity android:name="android.app.stubs.ActivityManagerMemoryClassTestActivity"
+ android:process=":memoryclass" />
+
+ <activity android:name="android.app.stubs.PipActivity"
+ android:label="PipActivity"
+ android:resizeable="true"
+ android:supportsPictureInPicture="true"
+ android:configChanges="smallestScreenSize|orientation|screenSize">
+ <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.stubs.PipNotResizeableActivity"
+ android:label="PipNotResizeableActivity"
+ android:resizeable="false"
+ android:supportsPictureInPicture="true"
+ android:configChanges="smallestScreenSize|orientation|screenSize">
+ <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.stubs.PipNotSupportedActivity"
+ android:label="PipNotSupportedActivity"
+ android:resizeable="true"
+ android:supportsPictureInPicture="false"
+ android:configChanges="smallestScreenSize|orientation|screenSize">
+ <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.stubs.KeyboardShortcutsActivity" />
+
+ </application>
+
+</manifest>
+
diff --git a/tests/app/assets/noiseandchirps b/tests/app/app/assets/noiseandchirps
similarity index 100%
rename from tests/app/assets/noiseandchirps
rename to tests/app/app/assets/noiseandchirps
Binary files differ
diff --git a/tests/app/assets/noiseandchirps.mp3 b/tests/app/app/assets/noiseandchirps.mp3
similarity index 100%
rename from tests/app/assets/noiseandchirps.mp3
rename to tests/app/app/assets/noiseandchirps.mp3
Binary files differ
diff --git a/tests/app/assets/noiseandchirps.ogg b/tests/app/app/assets/noiseandchirps.ogg
similarity index 100%
rename from tests/app/assets/noiseandchirps.ogg
rename to tests/app/app/assets/noiseandchirps.ogg
Binary files differ
diff --git a/tests/app/assets/noiseandchirps.wrong b/tests/app/app/assets/noiseandchirps.wrong
similarity index 100%
rename from tests/app/assets/noiseandchirps.wrong
rename to tests/app/app/assets/noiseandchirps.wrong
Binary files differ
diff --git a/tests/app/res/drawable/icon_black.jpg b/tests/app/app/res/drawable/icon_black.jpg
similarity index 100%
rename from tests/app/res/drawable/icon_black.jpg
rename to tests/app/app/res/drawable/icon_black.jpg
Binary files differ
diff --git a/tests/app/res/drawable/icon_blue.jpg b/tests/app/app/res/drawable/icon_blue.jpg
similarity index 100%
rename from tests/app/res/drawable/icon_blue.jpg
rename to tests/app/app/res/drawable/icon_blue.jpg
Binary files differ
diff --git a/tests/app/res/drawable/icon_green.jpg b/tests/app/app/res/drawable/icon_green.jpg
similarity index 100%
rename from tests/app/res/drawable/icon_green.jpg
rename to tests/app/app/res/drawable/icon_green.jpg
Binary files differ
diff --git a/tests/app/res/drawable/icon_red.jpg b/tests/app/app/res/drawable/icon_red.jpg
similarity index 100%
rename from tests/app/res/drawable/icon_red.jpg
rename to tests/app/app/res/drawable/icon_red.jpg
Binary files differ
diff --git a/tests/app/res/drawable/icon_yellow.jpg b/tests/app/app/res/drawable/icon_yellow.jpg
similarity index 100%
rename from tests/app/res/drawable/icon_yellow.jpg
rename to tests/app/app/res/drawable/icon_yellow.jpg
Binary files differ
diff --git a/tests/app/res/drawable/ninepatch_0.9.png b/tests/app/app/res/drawable/ninepatch_0.9.png
similarity index 100%
rename from tests/app/res/drawable/ninepatch_0.9.png
rename to tests/app/app/res/drawable/ninepatch_0.9.png
Binary files differ
diff --git a/tests/app/res/drawable/ninepatch_1.9.png b/tests/app/app/res/drawable/ninepatch_1.9.png
similarity index 100%
rename from tests/app/res/drawable/ninepatch_1.9.png
rename to tests/app/app/res/drawable/ninepatch_1.9.png
Binary files differ
diff --git a/tests/app/res/drawable/pass.jpg b/tests/app/app/res/drawable/pass.jpg
similarity index 100%
rename from tests/app/res/drawable/pass.jpg
rename to tests/app/app/res/drawable/pass.jpg
Binary files differ
diff --git a/tests/app/res/drawable/robot.png b/tests/app/app/res/drawable/robot.png
similarity index 100%
rename from tests/app/res/drawable/robot.png
rename to tests/app/app/res/drawable/robot.png
Binary files differ
diff --git a/tests/app/res/drawable/size_48x48.jpg b/tests/app/app/res/drawable/size_48x48.jpg
similarity index 100%
rename from tests/app/res/drawable/size_48x48.jpg
rename to tests/app/app/res/drawable/size_48x48.jpg
Binary files differ
diff --git a/tests/app/app/res/layout/activity_content.xml b/tests/app/app/res/layout/activity_content.xml
new file mode 100644
index 0000000..8870e60
--- /dev/null
+++ b/tests/app/app/res/layout/activity_content.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
diff --git a/tests/app/res/layout/alert_dialog_text_entry.xml b/tests/app/app/res/layout/alert_dialog_text_entry.xml
similarity index 100%
rename from tests/app/res/layout/alert_dialog_text_entry.xml
rename to tests/app/app/res/layout/alert_dialog_text_entry.xml
diff --git a/tests/app/res/layout/alert_dialog_text_entry_2.xml b/tests/app/app/res/layout/alert_dialog_text_entry_2.xml
similarity index 100%
rename from tests/app/res/layout/alert_dialog_text_entry_2.xml
rename to tests/app/app/res/layout/alert_dialog_text_entry_2.xml
diff --git a/tests/app/res/layout/alertdialog_custom_title.xml b/tests/app/app/res/layout/alertdialog_custom_title.xml
similarity index 100%
rename from tests/app/res/layout/alertdialog_custom_title.xml
rename to tests/app/app/res/layout/alertdialog_custom_title.xml
diff --git a/tests/app/res/layout/app_activity.xml b/tests/app/app/res/layout/app_activity.xml
similarity index 100%
rename from tests/app/res/layout/app_activity.xml
rename to tests/app/app/res/layout/app_activity.xml
diff --git a/tests/app/res/layout/checkbox_layout.xml b/tests/app/app/res/layout/checkbox_layout.xml
similarity index 100%
rename from tests/app/res/layout/checkbox_layout.xml
rename to tests/app/app/res/layout/checkbox_layout.xml
diff --git a/tests/app/res/layout/dialog_stub_layout.xml b/tests/app/app/res/layout/dialog_stub_layout.xml
similarity index 100%
rename from tests/app/res/layout/dialog_stub_layout.xml
rename to tests/app/app/res/layout/dialog_stub_layout.xml
diff --git a/tests/app/app/res/layout/fragment_a.xml b/tests/app/app/res/layout/fragment_a.xml
new file mode 100644
index 0000000..38e0423
--- /dev/null
+++ b/tests/app/app/res/layout/fragment_a.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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/textA"
+ android:text="@string/hello"/>
+</LinearLayout>
diff --git a/tests/app/app/res/layout/fragment_b.xml b/tests/app/app/res/layout/fragment_b.xml
new file mode 100644
index 0000000..d8ed961
--- /dev/null
+++ b/tests/app/app/res/layout/fragment_b.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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/textB"
+ android:text="@string/hello"/>
+</LinearLayout>
diff --git a/tests/app/app/res/layout/fragment_c.xml b/tests/app/app/res/layout/fragment_c.xml
new file mode 100644
index 0000000..ed3c753
--- /dev/null
+++ b/tests/app/app/res/layout/fragment_c.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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/textC"
+ android:text="@string/hello"/>
+</LinearLayout>
diff --git a/tests/app/app/res/layout/fragment_end.xml b/tests/app/app/res/layout/fragment_end.xml
new file mode 100644
index 0000000..aa3d9e8
--- /dev/null
+++ b/tests/app/app/res/layout/fragment_end.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:transitionName="destination"
+ android:id="@+id/hello"
+ android:text="@string/hello"/>
+ <View android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="#0F0"
+ android:id="@+id/greenSquare"/>
+ <View android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="#F00"
+ android:id="@+id/redSquare"/>
+</LinearLayout>
diff --git a/tests/app/app/res/layout/fragment_start.xml b/tests/app/app/res/layout/fragment_start.xml
new file mode 100644
index 0000000..793e9b5
--- /dev/null
+++ b/tests/app/app/res/layout/fragment_start.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <View android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="#0F0"
+ android:id="@+id/greenSquare"/>
+ <View android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="#F00"
+ android:id="@+id/redSquare"/>
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:transitionName="source"
+ android:id="@+id/hello"
+ android:text="@string/hello"/>
+</LinearLayout>
diff --git a/tests/app/res/menu/browser.xml b/tests/app/app/res/menu/browser.xml
similarity index 100%
rename from tests/app/res/menu/browser.xml
rename to tests/app/app/res/menu/browser.xml
diff --git a/tests/app/res/values/arrays.xml b/tests/app/app/res/values/arrays.xml
similarity index 100%
rename from tests/app/res/values/arrays.xml
rename to tests/app/app/res/values/arrays.xml
diff --git a/tests/app/res/values/attrs.xml b/tests/app/app/res/values/attrs.xml
similarity index 100%
rename from tests/app/res/values/attrs.xml
rename to tests/app/app/res/values/attrs.xml
diff --git a/tests/app/res/values/colors.xml b/tests/app/app/res/values/colors.xml
similarity index 100%
rename from tests/app/res/values/colors.xml
rename to tests/app/app/res/values/colors.xml
diff --git a/tests/app/app/res/values/strings.xml b/tests/app/app/res/values/strings.xml
new file mode 100644
index 0000000..5e9e6d7
--- /dev/null
+++ b/tests/app/app/res/values/strings.xml
@@ -0,0 +1,180 @@
+<?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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="permlab_testGranted">Test Granted</string>
+ <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
+ where we have the permission.</string>
+ <string name="permlab_testDynamic">Test Dynamic</string>
+ <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
+ dynamic permissions.</string>
+ <string name="permlab_testDenied">Test Denied</string>
+ <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
+ where we do not have the permission.</string>
+ <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
+ else press failed button.</string>
+ <string name="text_view_hello">Hello! Text view!</string>
+ <string name="text_view_hello_two_lines">Hello! \nText view!</string>
+ <string name="text_view_simple_hint">This is a hint.</string>
+ <string name="text_view_hint">This is a string for testing hint of textview.</string>
+ <string name="activity_forwarding">App/Forwarding</string>
+ <string name="forwarding">$$$</string>
+ <string name="go">Go</string>
+ <string name="back">Back</string>
+ <string name="forward_target">
+ Press back button and notice we don\'t see the previous activity.
+ </string>
+ <string name="edit_text">testing</string>
+ <string name="text">DialogTest</string>
+ <string name="text_country">Country</string>
+ <string name="text_name">Name</string>
+ <string name="hello_world">Hello, World!</string>
+ <string name="hello_android">Hello, Android!</string>
+ <string name="alert_dialog_username">Name:</string>
+ <string name="alert_dialog_password">Password:</string>
+ <string name="alert_dialog_positive">Positive</string>
+ <string name="alert_dialog_negative">Negative</string>
+ <string name="alert_dialog_neutral">Neutral</string>
+ <string name="notify">Notify </string>
+ <string name="tabs_1">testing</string>
+ <string name="table_layout_first">first</string>
+ <string name="table_layout_second">second</string>
+ <string name="table_layout_third">third</string>
+ <string name="table_layout_long">Very long to make the string out of the screen</string>
+ <string name="chronometer_text">Test Chronometer</string>
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="viewgroup_test">ViewGroup test</string>
+ <string name="viewanimator_test">ViewAnimator test</string>
+ <string name="id_ok">OK</string>
+ <string name="id_cancel">Cancel</string>
+ <string name="context_test_string1">This is %s string.</string>
+ <string name="context_test_string2">This is test string.</string>
+ <string name="animationutils_test_instructions">Choose different animations</string>
+ <string name="animationutils_test_alpha">Alpha animation</string>
+ <string name="animationutils_test_scale">Scale animation</string>
+ <string name="animationutils_test_rotate">Rotate animation</string>
+ <string name="animationutils_test_translate">Translate animation</string>
+ <string name="animationutils_test_set">Animation set</string>
+ <string name="animationutils_test_layout">Layout animation</string>
+ <string name="animationutils_test_gridlayout">Grid layout animation</string>
+ <string name="twolinelistitem_test_text1">text1</string>
+ <string name="twolinelistitem_test_text2">text2</string>
+ <string name="metadata_text">metadata text</string>
+ <string name="horizontal_text_1">horizontal 1</string>
+ <string name="horizontal_text_2">horizontal 2</string>
+ <string name="horizontal_text_3">horizontal 3</string>
+ <string name="vertical_text_1">vertical 1</string>
+ <string name="vertical_text_2">vertical 2</string>
+ <string name="vertical_text_3">vertical 3</string>
+ <string name="reference">here</string>
+ <string name="coerceIntegerToString">100</string>
+ <string name="coerceBooleanToString">true</string>
+ <string name="coerceColorToString">#fff</string>
+ <string name="coerceFloatToString">100.0</string>
+ <string name="coerceDimensionToString">100px</string>
+ <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
+ <string name="formattedStringNone">Format[]</string>
+ <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
+ <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
+ <string name="checkboxpref_key">checkboxpref_key</string>
+ <string name="checkboxpref_title">title of preference</string>
+ <string name="checkboxpref_summary">summary of preference</string>
+ <string name="checkboxpref_summary_on">summary on of preference</string>
+ <string name="checkboxpref_summary_off">summary off of preference</string>
+ <string name="checkboxpref_depend">checkboxpref_depend</string>
+ <string name="checkboxpref_depend_title"> depend title of preference</string>
+ <string name="checkboxpref_depend_summary"> depend summary of preference</string>
+ <string name="edittextpref_key">edittextpref_key</string>
+ <string name="edittextpref_default_value">default value of preference</string>
+ <string name="edittextpref_title">title of edit text preference</string>
+ <string name="edittextpref_summary">summary of edit text preference</string>
+ <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
+ <string name="edittextpref_text">text of edit text preference</string>
+ <string name="listpref_key">listpref_key</string>
+ <string name="listpref_title">title of list preference</string>
+ <string name="listpref_summary">summary of list preference</string>
+ <string name="listpref_dialogtitle">dialog title of list preference</string>
+ <string name="easy">Easy</string>
+ <string name="medium">Medium</string>
+ <string name="hard">Hard</string>
+ <string name="footer_view">Footer view</string>
+ <string name="header_view">Header view</string>
+ <string name="dialogpref_title">title of dialog preference </string>
+ <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
+ <string name="dialogpref_key">dialogpref_key</string>
+ <string name="dialogpref_default_value">default value of dialog preference</string>
+ <string name="dialogpref_summary">summary of dialog preference</string>
+ <string name="dialogpref_message">message of dialog preference</string>
+ <string name="dialogpref_sure">Sure</string>
+ <string name="dialogpref_cancel">Cancel</string>
+ <string name="pref_key">pref_key</string>
+ <string name="pref_title">title of preference</string>
+ <string name="pref_summary">summary of preference</string>
+ <string name="pref_depend_key">pref_depend_key</string>
+ <string name="pref_depend_title"> depend title of preference</string>
+ <string name="pref_depend_summary"> depend summary of preference</string>
+ <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
+ <string name="def_pref_key">def_pref_key</string>
+ <string name="def_pref_title">default preference</string>
+ <string name="def_pref_summary">This is default preference of cts</string>
+ <string name="relative_view1">view 1</string>
+ <string name="relative_view2">view 2</string>
+ <string name="relative_view3">view 3</string>
+ <string name="relative_view4">view 4</string>
+ <string name="relative_view5">view 5</string>
+ <string name="relative_view6">view 6</string>
+ <string name="relative_view7">view 7</string>
+ <string name="relative_view8">view 8</string>
+ <string name="relative_view9">view 9</string>
+ <string name="relative_view10">view 10</string>
+ <string name="relative_view11">view 11</string>
+ <string name="relative_view12">view 12</string>
+ <string name="relative_view13">view 13</string>
+ <string name="country">Country:</string>
+ <string name="symbol">Symbol:</string>
+ <string name="country_warning">No such country registered</string>
+ <string name="version_cur">base</string>
+ <string name="version_old">base</string>
+ <string name="version_v3">base</string>
+ <string name="authenticator_label">Android CTS</string>
+ <string name="search_label">Android CTS</string>
+ <string name="tag1">tag 1</string>
+ <string name="tag2">tag 2</string>
+
+ <string name="button">Button</string>
+ <string name="holo_test">Holo Test</string>
+ <string name="holo_generator">Holo Generator</string>
+ <string name="holo_light_test">Holo Light Test</string>
+ <string name="holo_light_generator">Holo Light Generator</string>
+ <string name="reference_image">Reference Image: </string>
+ <string name="generated_image">Generated Image: </string>
+ <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.
+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!
+I think so, so how about double this string, like copy and paste!
+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!
+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>
+ <string name="hello">Hello World</string>
+</resources>
diff --git a/tests/app/res/values/styles.xml b/tests/app/app/res/values/styles.xml
similarity index 100%
rename from tests/app/res/values/styles.xml
rename to tests/app/app/res/values/styles.xml
diff --git a/tests/app/app/res/xml/alias.xml b/tests/app/app/res/xml/alias.xml
new file mode 100644
index 0000000..de3f557
--- /dev/null
+++ b/tests/app/app/res/xml/alias.xml
@@ -0,0 +1,27 @@
+<?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.
+ */
+-->
+
+<alias xmlns:android="http://schemas.android.com/apk/res/android">
+ <intent android:action="android.intent.action.MAIN"
+ android:targetPackage="android.app.stubs"
+ android:targetClass="android.app.stubs.ChildActivity"
+ android:data="http://www.google.com/">
+ </intent>
+</alias>
+
diff --git a/tests/app/res/xml/intentfilter.xml b/tests/app/app/res/xml/intentfilter.xml
similarity index 100%
rename from tests/app/res/xml/intentfilter.xml
rename to tests/app/app/res/xml/intentfilter.xml
diff --git a/tests/app/res/xml/metadata.xml b/tests/app/app/res/xml/metadata.xml
similarity index 100%
rename from tests/app/res/xml/metadata.xml
rename to tests/app/app/res/xml/metadata.xml
diff --git a/tests/app/res/xml/searchable.xml b/tests/app/app/res/xml/searchable.xml
similarity index 100%
rename from tests/app/res/xml/searchable.xml
rename to tests/app/app/res/xml/searchable.xml
diff --git a/tests/app/app/src/android/app/stubs/ActionBarActivity.java b/tests/app/app/src/android/app/stubs/ActionBarActivity.java
new file mode 100644
index 0000000..ec27b1b
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ActionBarActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 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.ActionBar;
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ActionBarActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActionBar bar = getActionBar();
+ if (bar != null) {
+ bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/ActivityManagerMemoryClassLaunchActivity.java b/tests/app/app/src/android/app/stubs/ActivityManagerMemoryClassLaunchActivity.java
new file mode 100644
index 0000000..d79467c
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ActivityManagerMemoryClassLaunchActivity.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011 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;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * {@link Activity} that just launches {@link ActivityManagerMemoryClassTestActivity} and
+ * returns the result of that activity.
+ */
+public class ActivityManagerMemoryClassLaunchActivity extends Activity {
+
+ public static final String MEMORY_CLASS_EXTRA = "activityMemoryClass";
+
+ private static final int TEST_ACTIVITY_REQUEST_CODE = 1337;
+
+ private final CountDownLatch mLatch = new CountDownLatch(1);
+
+ private int mChildResult = RESULT_CANCELED;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Start the activity that runs in a separate process to do the actual testing,
+ // since the test itself cannot start an activity in a separate process. A separate
+ // process is used to avoid including the overhead of the test instrumentation process.
+
+ Intent intent = getIntent();
+ int memoryClass = intent.getIntExtra(MEMORY_CLASS_EXTRA, -1);
+
+ Intent testIntent = new Intent(this, ActivityManagerMemoryClassTestActivity.class);
+ testIntent.putExtra(MEMORY_CLASS_EXTRA, memoryClass);
+ startActivityForResult(testIntent, TEST_ACTIVITY_REQUEST_CODE);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == 1337) {
+ synchronized (this) {
+ mChildResult = resultCode;
+ }
+ } else {
+ throw new IllegalStateException("Request code: " + requestCode);
+ }
+ }
+
+ public int getResult() throws InterruptedException {
+ mLatch.await(5, TimeUnit.SECONDS);
+ synchronized (this) {
+ return mChildResult;
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/ActivityManagerMemoryClassTestActivity.java b/tests/app/app/src/android/app/stubs/ActivityManagerMemoryClassTestActivity.java
new file mode 100644
index 0000000..09566aa
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ActivityManagerMemoryClassTestActivity.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 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.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * {@link Activity} that allocates arrays of 256k until reaching 75% of the specified memory class.
+ */
+public class ActivityManagerMemoryClassTestActivity extends Activity {
+
+ private static final String TAG = "ActivityManagerMemoryClassTest";
+
+ private static final double FREE_MEMORY_PERCENTAGE = 0.75;
+
+ private static final int ARRAY_BYTES_SIZE = 256 * 1024;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = getIntent();
+ int memoryClass =
+ intent.getIntExtra(ActivityManagerMemoryClassLaunchActivity.MEMORY_CLASS_EXTRA, -1);
+ new AllocateMemoryTask(memoryClass).execute();
+ }
+
+ private class AllocateMemoryTask extends AsyncTask<Void, Void, Void> {
+
+ private final int mMemoryClass;
+
+ AllocateMemoryTask(int memoryClass) {
+ this.mMemoryClass = memoryClass;
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ int targetMbs = (int) (mMemoryClass * FREE_MEMORY_PERCENTAGE);
+ int numArrays = targetMbs * 1024 * 1024 / ARRAY_BYTES_SIZE;
+ Log.i(TAG, "Memory class: " + mMemoryClass + "mb Target memory: "
+ + targetMbs + "mb Number of arrays: " + numArrays);
+
+ byte[][] arrays = new byte[numArrays][];
+ for (int i = 0; i < arrays.length; i++) {
+ Log.i(TAG, "Allocating array " + i + " of " + arrays.length
+ + " (" + (i * ARRAY_BYTES_SIZE / 1024 / 1024) + "mb)");
+ arrays[i] = new byte[ARRAY_BYTES_SIZE];
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ super.onPostExecute(result);
+ setResult(RESULT_OK);
+ finish();
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/ActivityManagerRecentOneActivity.java b/tests/app/app/src/android/app/stubs/ActivityManagerRecentOneActivity.java
new file mode 100644
index 0000000..41944bd
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ActivityManagerRecentOneActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+public class ActivityManagerRecentOneActivity extends Activity {
+}
diff --git a/tests/app/app/src/android/app/stubs/ActivityManagerRecentTwoActivity.java b/tests/app/app/src/android/app/stubs/ActivityManagerRecentTwoActivity.java
new file mode 100644
index 0000000..136e565
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ActivityManagerRecentTwoActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+public class ActivityManagerRecentTwoActivity extends Activity {
+}
diff --git a/tests/app/app/src/android/app/stubs/ActivityManagerStubCrashActivity.java b/tests/app/app/src/android/app/stubs/ActivityManagerStubCrashActivity.java
new file mode 100644
index 0000000..f6bef49
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ActivityManagerStubCrashActivity.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class ActivityManagerStubCrashActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ final TextView tv = new TextView(this);
+ tv.setText("Hello, Android but crash");
+ setContentView(tv);
+ die();
+ }
+
+ public void die() {
+ throw new NullPointerException("Expected NPE.");
+ }
+}
+
diff --git a/tests/app/app/src/android/app/stubs/ActivityManagerStubFooActivity.java b/tests/app/app/src/android/app/stubs/ActivityManagerStubFooActivity.java
new file mode 100644
index 0000000..5892e6b
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ActivityManagerStubFooActivity.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class ActivityManagerStubFooActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ final TextView tv = new TextView(this);
+ tv.setText("Hello, Android");
+ setContentView(tv);
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/ActivityTestsBase.java b/tests/app/app/src/android/app/stubs/ActivityTestsBase.java
new file mode 100644
index 0000000..12463b4
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ActivityTestsBase.java
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.test.AndroidTestCase;
+import android.test.PerformanceTestCase;
+
+public class ActivityTestsBase extends AndroidTestCase implements PerformanceTestCase,
+ LaunchpadActivity.CallingTest {
+ public static final String PERMISSION_GRANTED = "android.app.cts.permission.TEST_GRANTED";
+ public static final String PERMISSION_DENIED = "android.app.cts.permission.TEST_DENIED";
+
+ private static final int TIMEOUT_MS = 60 * 1000;
+
+ protected Intent mIntent;
+
+ private PerformanceTestCase.Intermediates mIntermediates;
+ private String mExpecting;
+
+ // Synchronization of activity result.
+ private boolean mFinished;
+ private int mResultCode = 0;
+ private Intent mData;
+ private RuntimeException mResultStack = null;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mIntent = new Intent(mContext, LaunchpadActivity.class);
+ mIntermediates = null;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mIntermediates = null;
+ super.tearDown();
+ }
+
+ public boolean isPerformanceOnly() {
+ return false;
+ }
+
+ public void setInternalIterations(int count) {
+ }
+
+ public void startTiming(boolean realTime) {
+ if (mIntermediates != null) {
+ mIntermediates.startTiming(realTime);
+ }
+ }
+
+ public void addIntermediate(String name) {
+ if (mIntermediates != null) {
+ mIntermediates.addIntermediate(name);
+ }
+ }
+
+ public void addIntermediate(String name, long timeInNS) {
+ if (mIntermediates != null) {
+ mIntermediates.addIntermediate(name, timeInNS);
+ }
+ }
+
+ public void finishTiming(boolean realTime) {
+ if (mIntermediates != null) {
+ mIntermediates.finishTiming(realTime);
+ }
+ }
+
+ public void activityFinished(int resultCode, Intent data, RuntimeException where) {
+ finishWithResult(resultCode, data, where);
+ }
+
+ public Intent editIntent() {
+ return mIntent;
+ }
+
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ public int startPerformance(Intermediates intermediates) {
+ mIntermediates = intermediates;
+ return 1;
+ }
+
+ public void finishGood() {
+ finishWithResult(Activity.RESULT_OK, null);
+ }
+
+ public void finishBad(String error) {
+ finishWithResult(Activity.RESULT_CANCELED, new Intent().setAction(error));
+ }
+
+ public void finishWithResult(int resultCode, Intent data) {
+ final RuntimeException where = new RuntimeException("Original error was here");
+ where.fillInStackTrace();
+ finishWithResult(resultCode, data, where);
+ }
+
+ public void finishWithResult(int resultCode, Intent data, RuntimeException where) {
+ synchronized (this) {
+ mResultCode = resultCode;
+ mData = data;
+ mResultStack = where;
+ mFinished = true;
+ notifyAll();
+ }
+ }
+
+ public int runLaunchpad(String action) {
+ startLaunchpadActivity(action);
+ return waitForResultOrThrow(TIMEOUT_MS);
+ }
+
+ private void startLaunchpadActivity(String action) {
+ LaunchpadActivity.setCallingTest(this);
+
+ synchronized (this) {
+ mIntent.setAction(action);
+ mFinished = false;
+ mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(mIntent);
+ }
+ }
+
+ public int waitForResultOrThrow(int timeoutMs) {
+ return waitForResultOrThrow(timeoutMs, null);
+ }
+
+ public int waitForResultOrThrow(int timeoutMs, String expected) {
+ final int res = waitForResult(timeoutMs, expected);
+
+ if (res == Activity.RESULT_CANCELED) {
+ if (mResultStack != null) {
+ throw new RuntimeException(mData != null ? mData.toString() : "Unable to launch",
+ mResultStack);
+ } else {
+ throw new RuntimeException(mData != null ? mData.toString() : "Unable to launch");
+ }
+ }
+ return res;
+ }
+
+ public int waitForResult(int timeoutMs, String expected) {
+ mExpecting = expected;
+
+ final long endTime = System.currentTimeMillis() + timeoutMs;
+
+ boolean timeout = false;
+ synchronized (this) {
+ while (!mFinished) {
+ final long delay = endTime - System.currentTimeMillis();
+ if (delay < 0) {
+ timeout = true;
+ break;
+ }
+
+ try {
+ wait(delay);
+ } catch (final java.lang.InterruptedException e) {
+ // do nothing
+ }
+ }
+ }
+
+ mFinished = false;
+
+ if (timeout) {
+ mResultCode = Activity.RESULT_CANCELED;
+ onTimeout();
+ }
+ return mResultCode;
+ }
+
+
+ public int getResultCode() {
+ return mResultCode;
+ }
+
+ public Intent getResultData() {
+ return mData;
+ }
+
+ public RuntimeException getResultStack() {
+ return mResultStack;
+ }
+
+ public void onTimeout() {
+ final String msg = mExpecting == null ? "Timeout" : "Timeout while expecting " + mExpecting;
+ finishWithResult(Activity.RESULT_CANCELED, new Intent().setAction(msg));
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/AliasActivityStub.java b/tests/app/app/src/android/app/stubs/AliasActivityStub.java
new file mode 100644
index 0000000..7d2d469
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/AliasActivityStub.java
@@ -0,0 +1,37 @@
+/*
+ * 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.AliasActivity;
+import android.os.Bundle;
+
+public class AliasActivityStub extends AliasActivity {
+
+ public static boolean isOnCreateCalled = false;
+ public static boolean isFinished = false;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ isOnCreateCalled = true;
+ }
+
+ @Override
+ public void finish() {
+ super.finish();
+ isFinished = true;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/AppStubActivity.java b/tests/app/app/src/android/app/stubs/AppStubActivity.java
new file mode 100644
index 0000000..1da2421
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/AppStubActivity.java
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+
+/**
+ * A minimal "Hello, World!" application.
+ */
+public class AppStubActivity extends Activity {
+ private Dialog mDialog;
+ public boolean mOnPrepareDialog;
+ public boolean mOnOptionsMenuClosedCalled;
+ public boolean mOnPrepareOptionsMenuCalled;
+ public boolean mOnOptionsItemSelectedCalled;
+ public boolean mOnCreateOptionsMenu;
+ public boolean mIndterminate = false;
+ public boolean mIndterminatevisibility = false;
+ public boolean mSecPro = false;
+ public boolean mOnContextItemSelectedCalled;
+ public boolean mOnCreateContextMenu;
+ public boolean mApplyResourceCalled;
+ public boolean mCreateContextMenuCalled;
+ public boolean mRequestWinFeatureRet = false;
+
+ public AppStubActivity() {
+
+ }
+
+ public void finalize() {
+ try {
+ super.finalize();
+ } catch (Throwable exception) {
+ System.err.print("exception!");
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+ mRequestWinFeatureRet = requestWindowFeature(1);
+ setContentView(R.layout.app_activity);
+ }
+
+ public Dialog getDialogById(int id) {
+ return mDialog;
+ }
+
+ @Override
+ public Dialog onCreateDialog(int id) {
+ super.onCreateDialog(id);
+ mDialog = new Dialog(this);
+ return mDialog;
+ }
+
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ super.onPrepareDialog(id, dialog);
+ mOnPrepareDialog = true;
+ }
+
+ @Override
+ public void onOptionsMenuClosed(Menu menu) {
+ super.onOptionsMenuClosed(menu);
+ mOnOptionsMenuClosedCalled = true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ mOnPrepareOptionsMenuCalled = true;
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ mOnCreateOptionsMenu = true;
+ if(menu != null)
+ menu.add(0, 0, 0, "Fake Item");
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ mOnOptionsItemSelectedCalled = true;
+ return super.onOptionsItemSelected(item);
+ }
+
+ public boolean setProBarIndeterminate(boolean indeterminate){
+ mIndterminate = indeterminate;
+ super.setProgressBarIndeterminate(indeterminate);
+ return mIndterminate;
+ }
+
+ public boolean setProBarIndeterminateVisibility(boolean visible){
+ mIndterminatevisibility = visible;
+ super.setProgressBarIndeterminateVisibility(visible);
+ return mIndterminatevisibility;
+ }
+
+ public boolean setSecPro(int secPro){
+ mSecPro = true;
+ super.setSecondaryProgress(secPro);
+ return mSecPro;
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item){
+ mOnContextItemSelectedCalled = true;
+ return super.onContextItemSelected(item);
+ }
+
+ @Override
+ public void onApplyThemeResource( Resources.Theme theme,
+ int resid,
+ boolean first){
+ super.onApplyThemeResource(theme,resid,first);
+ mApplyResourceCalled = true;
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu,v,menuInfo);
+ mCreateContextMenuCalled = true;
+ }
+}
+
diff --git a/tests/app/app/src/android/app/stubs/CTSActivityTestCaseBase.java b/tests/app/app/src/android/app/stubs/CTSActivityTestCaseBase.java
new file mode 100644
index 0000000..44ff6b2
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/CTSActivityTestCaseBase.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.cts.util.CTSResult;
+import android.test.InstrumentationTestCase;
+
+public class CTSActivityTestCaseBase extends InstrumentationTestCase implements CTSResult {
+
+ private Sync mSync;
+ static class Sync {
+ public boolean mHasNotify;
+ public int mResult;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mSync = new Sync();
+ }
+
+ public void setResult(int resultCode) {
+ synchronized (mSync) {
+ mSync.mHasNotify = true;
+ mSync.mResult = resultCode;
+ mSync.notify();
+ }
+ }
+
+ protected void waitForResult() throws InterruptedException {
+ synchronized (mSync) {
+ while (!mSync.mHasNotify) {
+ mSync.wait();
+ }
+ assertEquals(CTSResult.RESULT_OK, mSync.mResult);
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/ChildActivity.java b/tests/app/app/src/android/app/stubs/ChildActivity.java
new file mode 100644
index 0000000..559b101
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ChildActivity.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+public class ChildActivity extends Activity {
+
+ public static boolean isStarted = false;
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ isStarted = true;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/ChildTabActivity.java b/tests/app/app/src/android/app/stubs/ChildTabActivity.java
new file mode 100644
index 0000000..1f0fb37
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ChildTabActivity.java
@@ -0,0 +1,25 @@
+/*
+ * 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 {
+}
diff --git a/tests/app/app/src/android/app/stubs/ClearTop.java b/tests/app/app/src/android/app/stubs/ClearTop.java
new file mode 100644
index 0000000..94fcc57
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ClearTop.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class ClearTop extends Activity {
+ public static final String WAIT_CLEAR_TASK = "waitClearTask";
+ private static final String TAG = "ClearTop";
+ public ClearTop() {
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ final Intent intent = new Intent(getIntent()).setAction(LocalScreen.CLEAR_TASK).setClass(
+ this, LocalScreen.class);
+ startActivity(intent);
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ Log.i(TAG, "onNewIntent");
+ if (LocalScreen.CLEAR_TASK.equals(intent.getAction())) {
+ setResult(RESULT_OK);
+ } else {
+ setResult(RESULT_CANCELED, new Intent().setAction("New intent received " + intent
+ + ", expecting action " + TestedScreen.CLEAR_TASK));
+ }
+ finish();
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/DialogStubActivity.java b/tests/app/app/src/android/app/stubs/DialogStubActivity.java
new file mode 100644
index 0000000..d77b9a3
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/DialogStubActivity.java
@@ -0,0 +1,422 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.DatePickerDialog;
+import android.app.Dialog;
+import android.app.TimePickerDialog;
+import android.app.DatePickerDialog.OnDateSetListener;
+import android.app.TimePickerDialog.OnTimeSetListener;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.DialogInterface.OnCancelListener;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.DatePicker;
+import android.widget.TimePicker;
+
+/*
+ * Stub class for Dialog, AlertDialog, DatePickerDialog, TimePickerDialog etc.
+ */
+public class DialogStubActivity extends Activity {
+ public static final int TEST_DIALOG_WITHOUT_THEME = 0;
+ public static final int TEST_DIALOG_WITH_THEME = 1;
+ public static final int TEST_ALERTDIALOG = 2;
+ public static final int TEST_CUSTOM_ALERTDIALOG = 3;
+ public static final int TEST_DATEPICKERDIALOG = 4;
+ public static final int TEST_DATEPICKERDIALOG_WITH_THEME = 5;
+ public static final int TEST_TIMEPICKERDIALOG = 6;
+ public static final int TEST_TIMEPICKERDIALOG_WITH_THEME = 7;
+ public static final int TEST_ONSTART_AND_ONSTOP = 8;
+ public static final int TEST_ALERTDIALOG_DEPRECATED = 9;
+ public static final int TEST_ALERTDIALOG_CALLBACK = 10;
+ public static final int TEST_CUSTOM_ALERTDIALOG_VIEW = 11;
+ public static final int TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE = 12;
+ public static final int TEST_ALERTDIALOG_THEME = 13;
+ public static final int TEST_ALERTDIALOG_CANCELABLE = 14;
+ public static final int TEST_ALERTDIALOG_NOT_CANCELABLE = 15;
+ public static final int TEST_PROTECTED_CANCELABLE = 16;
+ public static final int TEST_PROTECTED_NOT_CANCELABLE = 17;
+
+ public static final int SPACING_LEFT = 10;
+ public static final int SPACING_TOP = 20;
+ public static final int SPACING_RIGHT = 30;
+ public static final int SPACING_BOTTOM = 40;
+ public static int buttonIndex;
+
+ public static final String DEFAULT_ALERTDIALOG_TITLE = "AlertDialog";
+ public static final String DEFAULT_ALERTDIALOG_MESSAGE = "AlertDialog message";
+ private static final String LOG_TAG = "DialogStubActivity";
+
+ public boolean isPositiveButtonClicked = false;
+ public boolean isNegativeButtonClicked = false;
+ public boolean isNeutralButtonClicked = false;
+ public boolean isCallBackCalled;
+ public boolean onCancelCalled;
+ public boolean onKeyDownCalled;
+ public boolean onKeyUpCalled;
+ public boolean onCreateCalled;
+ public boolean onCancelListenerCalled;
+ public boolean onClickCalled;
+ public static boolean onDateChangedCalled;
+ public static boolean onRestoreInstanceStateCalled;
+ public boolean onSaveInstanceStateCalled;
+ public int updatedYear;
+ public int updatedMonth;
+ public int updatedDay;
+
+ public final int INITIAL_YEAR = 2008;
+ public final int INITIAL_MONTH = 7;
+ public final int INITIAL_DAY_OF_MONTH = 27;
+ private final int INITIAL_HOUR = 10;
+ private final int INITIAL_MINUTE = 35;
+ private Dialog mDialog;
+ private AlertDialog mAlertDialog;
+ private OnDateSetListener mOnDateSetListener = new OnDateSetListener() {
+ public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
+ updatedYear = year;
+ updatedMonth = monthOfYear;
+ updatedDay = dayOfMonth;
+ }
+ };
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case TEST_DIALOG_WITHOUT_THEME:
+ mDialog = new Dialog(this);
+ mDialog.setTitle("Hello, Dialog");
+ break;
+
+ case TEST_DIALOG_WITH_THEME:
+ mDialog = new Dialog(this, 1);
+ break;
+
+ case TEST_ALERTDIALOG:
+ mDialog = getAlertDialogInstance(false);
+ break;
+
+ case TEST_CUSTOM_ALERTDIALOG:
+ mDialog = getCustomAlertDialogInstance(false);
+ break;
+
+ case TEST_CUSTOM_ALERTDIALOG_VIEW:
+ mDialog = getCustomAlertDialogInstance(true);
+ break;
+
+ case TEST_DATEPICKERDIALOG:
+ mDialog = new MockDatePickerDialog(this, mOnDateSetListener, INITIAL_YEAR,
+ INITIAL_MONTH, INITIAL_DAY_OF_MONTH);
+ break;
+
+ case TEST_DATEPICKERDIALOG_WITH_THEME:
+ mDialog = new MockDatePickerDialog(this,
+ com.android.internal.R.style.Theme_Translucent, mOnDateSetListener,
+ INITIAL_YEAR, INITIAL_MONTH, INITIAL_DAY_OF_MONTH);
+ break;
+
+ case TEST_TIMEPICKERDIALOG:
+ mDialog = new TimePickerDialog(this, new OnTimeSetListener() {
+ public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+ isCallBackCalled = true;
+ }
+ }, INITIAL_HOUR, INITIAL_MINUTE, true);
+ break;
+
+ case TEST_TIMEPICKERDIALOG_WITH_THEME:
+ mDialog = new TimePickerDialog(this,
+ com.android.internal.R.style.Theme_Translucent, null, INITIAL_HOUR,
+ INITIAL_MINUTE, true);
+ break;
+
+ case TEST_ONSTART_AND_ONSTOP:
+ mDialog = new TestDialog(this);
+ Log.i(LOG_TAG, "mTestDialog:" + mDialog);
+ return mDialog;
+
+ case TEST_ALERTDIALOG_DEPRECATED:
+ mDialog = getAlertDialogInstance(true);
+ break;
+
+ case TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE:
+ final Handler handler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ buttonIndex = msg.what;
+ super.handleMessage(msg);
+ }
+ };
+ final Message positiveMessage = Message.obtain();
+ positiveMessage.setTarget(handler);
+ positiveMessage.what = DialogInterface.BUTTON_POSITIVE;
+
+ final Message negativeMessage = Message.obtain();
+ negativeMessage.setTarget(handler);
+ negativeMessage.what = DialogInterface.BUTTON_NEGATIVE;
+
+ final Message neutralMessage = Message.obtain();
+ neutralMessage.setTarget(handler);
+ neutralMessage.what = DialogInterface.BUTTON_NEUTRAL;
+ mAlertDialog = getAlertDialogInstance(false);
+ mAlertDialog.setButton(getString(R.string.alert_dialog_positive), positiveMessage);
+ mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), negativeMessage);
+ mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), neutralMessage);
+ mDialog = mAlertDialog;
+ break;
+
+ case TEST_ALERTDIALOG_CALLBACK:
+ mDialog = new MockAlertDialog(this);
+ break;
+ case TEST_ALERTDIALOG_THEME:
+ mDialog = new MockAlertDialog(this, R.style.Theme_AlertDialog);
+ break;
+ case TEST_ALERTDIALOG_CANCELABLE:
+ mDialog = getAlertDialogCancelablInstance(true);
+ break;
+ case TEST_ALERTDIALOG_NOT_CANCELABLE:
+ mDialog = getAlertDialogCancelablInstance(false);
+ break;
+ case TEST_PROTECTED_CANCELABLE:
+ mDialog = new TestDialog(this, true, new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ onCancelListenerCalled = true;
+ }
+ });
+ break;
+ case TEST_PROTECTED_NOT_CANCELABLE:
+ mDialog = new TestDialog(this, false, new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ onCancelListenerCalled = true;
+ }
+ });
+ break;
+ default:
+ break;
+ }
+
+ Log.i(LOG_TAG, "mDialog:" + mDialog);
+ return mDialog;
+ }
+
+ private AlertDialog getAlertDialogCancelablInstance(boolean cancelable) {
+ OnCancelListener cancelListener = new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ onCancelCalled = true;
+ }
+ };
+ return new MockAlertDialog(this, cancelable, cancelListener);
+ }
+
+ @SuppressWarnings("deprecation")
+ private AlertDialog getAlertDialogInstance(boolean deprecated) {
+ mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create();
+ mAlertDialog.setIcon(R.drawable.pass);
+ mAlertDialog.setTitle(DEFAULT_ALERTDIALOG_TITLE);
+ mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE);
+ mAlertDialog.setInverseBackgroundForced(true);
+ final DialogInterface.OnClickListener positiveListener = new MockOnClickListener(
+ DialogInterface.BUTTON_POSITIVE);
+ final DialogInterface.OnClickListener netativeListener = new MockOnClickListener(
+ DialogInterface.BUTTON_NEGATIVE);
+ final DialogInterface.OnClickListener neutralListener = new MockOnClickListener(
+ DialogInterface.BUTTON_NEUTRAL);
+
+ if (deprecated) {
+ mAlertDialog.setButton(getString(R.string.alert_dialog_positive), positiveListener);
+ mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), netativeListener);
+ mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), neutralListener);
+ } else {
+ mAlertDialog.setButton(DialogInterface.BUTTON_POSITIVE,
+ getString(R.string.alert_dialog_positive), positiveListener);
+ mAlertDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
+ getString(R.string.alert_dialog_negative), netativeListener);
+ mAlertDialog.setButton(DialogInterface.BUTTON_NEUTRAL,
+ getString(R.string.alert_dialog_neutral), neutralListener);
+ }
+ return mAlertDialog;
+
+ }
+
+ private AlertDialog getCustomAlertDialogInstance(boolean withSpacing) {
+ final LayoutInflater inflate = getLayoutInflater();
+ final View customTitleViewCustom = inflate.inflate(R.layout.alertdialog_custom_title, null);
+ final View textEntryView = inflate.inflate(R.layout.alert_dialog_text_entry_2, null);
+ mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create();
+ mAlertDialog.setCustomTitle(customTitleViewCustom);
+ mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE);
+ if (withSpacing) {
+ mAlertDialog.setView(textEntryView, SPACING_LEFT, SPACING_TOP, SPACING_RIGHT,
+ SPACING_BOTTOM);
+ } else {
+ mAlertDialog.setView(textEntryView);
+ }
+
+ return mAlertDialog;
+
+ }
+
+ public Dialog getDialog() {
+ return mDialog;
+ }
+
+ public String getDialogTitle() {
+ return (String) mDialog.getWindow().getAttributes().getTitle();
+ }
+
+ private static final String TEST_DIALOG_NUMBER_EXTRA = "testDialogNumber";
+
+ public static <T extends Activity> T startDialogActivity(
+ ActivityInstrumentationTestCase2<T> testCase, int dialogNumber) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.putExtra(TEST_DIALOG_NUMBER_EXTRA, dialogNumber);
+ testCase.setActivityIntent(intent);
+ return testCase.getActivity();
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.dialog_stub_layout);
+
+ Intent intent = getIntent();
+ int dialogNum = intent.getIntExtra(TEST_DIALOG_NUMBER_EXTRA, -1);
+ if (dialogNum != -1) {
+ showDialog(dialogNum);
+ }
+ }
+
+ public void setUpTitle(final String title) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ getDialog().setTitle(title);
+ }
+ });
+ }
+
+ public void setUpTitle(final int id) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ getDialog().setTitle(id);
+ }
+ });
+ }
+
+ class MockAlertDialog extends AlertDialog {
+ public MockAlertDialog(Context context) {
+ super(context);
+ }
+
+ public MockAlertDialog(Context context, int theme) {
+ super(context, theme);
+ }
+
+ public MockAlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
+ super(context, cancelable, cancelListener);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ onKeyDownCalled = true;
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ onKeyUpCalled = true;
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ onCreateCalled = true;
+ super.onCreate(savedInstanceState);
+ }
+
+ }
+
+ class MockOnClickListener implements DialogInterface.OnClickListener {
+ private final int mId;
+
+ public MockOnClickListener(final int buttonId) {
+ mId = buttonId;
+ }
+
+ public void onClick(DialogInterface dialog, int which) {
+ switch (mId) {
+ case DialogInterface.BUTTON_POSITIVE:
+ isPositiveButtonClicked = true;
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ isNegativeButtonClicked = true;
+ break;
+ case DialogInterface.BUTTON_NEUTRAL:
+ isNeutralButtonClicked = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ class MockDatePickerDialog extends DatePickerDialog {
+ public MockDatePickerDialog(Context context, OnDateSetListener callBack, int year,
+ int monthOfYear, int dayOfMonth) {
+ super(context, callBack, year, monthOfYear, dayOfMonth);
+ }
+
+ public MockDatePickerDialog(Context context, int theme, OnDateSetListener callBack,
+ int year, int monthOfYear, int dayOfMonth) {
+ super(context, theme, callBack, year, monthOfYear, dayOfMonth);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ onClickCalled = true;
+ super.onClick(dialog, which);
+ }
+
+ @Override
+ public void onDateChanged(DatePicker view, int year, int month, int day) {
+ onDateChangedCalled = true;
+ super.onDateChanged(view, year, month, day);
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle savedInstanceState) {
+ onRestoreInstanceStateCalled = true;
+ super.onRestoreInstanceState(savedInstanceState);
+ }
+
+ @Override
+ public Bundle onSaveInstanceState() {
+ onSaveInstanceStateCalled = true;
+ return super.onSaveInstanceState();
+ }
+
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/ExpandableListTestActivity.java b/tests/app/app/src/android/app/stubs/ExpandableListTestActivity.java
new file mode 100644
index 0000000..ab377d9
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ExpandableListTestActivity.java
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+package android.app.stubs;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import android.app.ExpandableListActivity;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.MessageQueue;
+import android.view.ContextMenu;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.SimpleExpandableListAdapter;
+
+import com.android.internal.R;
+import com.android.internal.view.menu.ContextMenuBuilder;
+import com.google.android.collect.Lists;
+
+public class ExpandableListTestActivity extends ExpandableListActivity {
+ private static final String NAME = "NAME";
+ private static final String IS_EVEN = "IS_EVEN";
+ private boolean mOnContentChangedCalled = false;
+ private boolean mOnCreateContextMenuCalled = false;
+ private boolean mOnGroupCollapseCalled = false;
+ private boolean mOnGroupExpandCalled = false;
+ private ExpandableListAdapter mAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final List<Map<String, String>> groupData = Lists.newArrayList();
+ final List<List<Map<String, String>>> childData = Lists.newArrayList();
+ for (int i = 0; i < 20; i++) {
+ final Map<String, String> curGroupMap = new HashMap<String, String>();
+ groupData.add(curGroupMap);
+ curGroupMap.put(NAME, "Group " + i);
+ curGroupMap.put(IS_EVEN, (i % 2 == 0) ? "This group is even" : "This group is odd");
+
+ final List<Map<String, String>> children = Lists.newArrayList();
+ for (int j = 0; j < 15; j++) {
+ Map<String, String> curChildMap = new HashMap<String, String>();
+ children.add(curChildMap);
+ curChildMap.put(NAME, "Child " + j);
+ curChildMap.put(IS_EVEN, (j % 2 == 0) ? "This child is even" : "This child is odd");
+ }
+ childData.add(children);
+ }
+
+ // Set up our adapter
+ mAdapter = new SimpleExpandableListAdapter(this, groupData,
+ R.layout.simple_expandable_list_item_1,
+ new String[] { NAME, IS_EVEN }, new int[] { R.id.text1, R.id.text2 }, childData,
+ R.layout.simple_expandable_list_item_2,
+ new String[] { NAME, IS_EVEN }, new int[] { R.id.text1, R.id.text2 });
+ setListAdapter(mAdapter);
+
+ }
+
+ private int testCallback() {
+ final ExpandableListView v = getExpandableListView();
+ final ExpandableListAdapter a = getExpandableListAdapter();
+ final View convertView = new View(this);
+ final View gv = a.getGroupView(0, true, convertView, v);
+ v.setOnCreateContextMenuListener(this);
+ v.createContextMenu(new ContextMenuBuilder(this));
+ for (int i = 0; i < 20; i++) {
+ v.expandGroup(i);
+ v.performClick();
+ v.performLongClick();
+ for (int k = 0; k < 15; k++) {
+ v.performItemClick(gv, i, k);
+ }
+ v.collapseGroup(i);
+ }
+ if (mOnContentChangedCalled && mOnCreateContextMenuCalled
+ && mOnGroupCollapseCalled && mOnGroupExpandCalled)
+ return RESULT_OK;
+
+ return RESULT_CANCELED;
+ }
+
+ private int testView() {
+ final ExpandableListView currentView = getExpandableListView();
+ for (int i = 0; i < 20; i++) {
+ if (!currentView.expandGroup(i))
+ return RESULT_CANCELED;
+ if (!currentView.collapseGroup(i))
+ return RESULT_CANCELED;
+ }
+ final View otherView = findViewById(android.R.id.list);
+ setContentView(otherView);
+ if (!otherView.equals(getExpandableListView()))
+ return RESULT_CANCELED;
+ setContentView(currentView);
+ return RESULT_OK;
+ }
+
+ private int testSelecte() {
+ final ExpandableListView v = getExpandableListView();
+ for (int i = 0; i < 20; i++) {
+ v.expandGroup(i);
+ setSelectedGroup(i);
+ for (int k = 0; k < 15; k++) {
+ setSelectedChild(i, k, false);
+ if (ExpandableListView.getPackedPositionForChild(i, k) != getSelectedPosition())
+ return RESULT_CANCELED;
+ }
+
+ for (int k = 0; k < 15; k++) {
+ setSelectedChild(i, k, true);
+ if (ExpandableListView.getPackedPositionForChild(i, k) != getSelectedPosition())
+ return RESULT_CANCELED;
+ }
+ v.collapseGroup(i);
+ }
+ return RESULT_OK;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ final String action = getIntent().getAction();
+ if (LaunchpadActivity.EXPANDLIST_SELECT.equals(action)) {
+ setResult(testSelecte());
+ } else if (LaunchpadActivity.EXPANDLIST_VIEW.equals(action)) {
+ setResult(testView());
+ } else if (LaunchpadActivity.EXPANDLIST_CALLBACK.equals(action)) {
+ setResult(testCallback());
+ }
+ Looper.myQueue().addIdleHandler(new Idler());
+ }
+
+ protected void onRestoreInstanceState(Bundle state) {
+ super.onRestoreInstanceState(state);
+ }
+
+ @Override
+ public void onContentChanged() {
+ mOnContentChangedCalled = true;
+ super.onContentChanged();
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v,
+ ContextMenuInfo menuInfo) {
+ mOnCreateContextMenuCalled = true;
+ super.onCreateContextMenu(menu, v, menuInfo);
+ }
+
+ @Override
+ public void onGroupCollapse(int groupPosition) {
+ mOnGroupCollapseCalled = true;
+ super.onGroupCollapse(groupPosition);
+ }
+
+ @Override
+ public void onGroupExpand(int groupPosition) {
+ mOnGroupExpandCalled = true;
+ super.onGroupExpand(groupPosition);
+ }
+
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ }
+
+ protected void onStop() {
+ super.onStop();
+ }
+
+ private class Idler implements MessageQueue.IdleHandler {
+ public final boolean queueIdle() {
+ finish();
+ return false;
+ }
+ }
+
+}
diff --git a/tests/app/app/src/android/app/stubs/FragmentTestActivity.java b/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
new file mode 100644
index 0000000..65ba911
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2014 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.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.transition.Transition;
+import android.transition.Transition.TransitionListener;
+import android.transition.TransitionInflater;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * A simple activity used for Fragment Transitions
+ */
+public class FragmentTestActivity extends Activity {
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.activity_content);
+ }
+
+ public static class TestFragment extends Fragment {
+ public static final int ENTER = 0;
+ public static final int RETURN = 1;
+ public static final int EXIT = 2;
+ public static final int REENTER = 3;
+ public static final int SHARED_ELEMENT_ENTER = 4;
+ public static final int SHARED_ELEMENT_RETURN = 5;
+ private static final int TRANSITION_COUNT = 6;
+
+ private static final String LAYOUT_ID = "layoutId";
+ private static final String TRANSITION_KEY = "transition_";
+ private int mLayoutId = R.layout.fragment_start;
+ private final int[] mTransitionIds = new int[] {
+ android.R.transition.explode,
+ android.R.transition.explode,
+ android.R.transition.fade,
+ android.R.transition.fade,
+ android.R.transition.move,
+ android.R.transition.move,
+ };
+ private final TransitionCalledListener[] mListeners =
+ new TransitionCalledListener[TRANSITION_COUNT];
+ private OnTransitionListener mOnTransitionListener;
+
+ public TestFragment() {
+ for (int i = 0; i < TRANSITION_COUNT; i++) {
+ mListeners[i] = new TransitionCalledListener();
+ }
+ }
+
+ public TestFragment(int layoutId) {
+ this();
+ mLayoutId = layoutId;
+ }
+
+ public void clearTransitions() {
+ for (int i = 0; i < TRANSITION_COUNT; i++) {
+ mTransitionIds[i] = 0;
+ }
+ }
+
+ public void clearNotifications() {
+ for (int i = 0; i < TRANSITION_COUNT; i++) {
+ mListeners[i].transitionStarted = false;
+ mListeners[i].transitionEnded = false;
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (savedInstanceState != null) {
+ mLayoutId = savedInstanceState.getInt(LAYOUT_ID, mLayoutId);
+ for (int i = 0; i < TRANSITION_COUNT; i++) {
+ String key = TRANSITION_KEY + i;
+ mTransitionIds[i] = savedInstanceState.getInt(key, mTransitionIds[i]);
+ }
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(LAYOUT_ID, mLayoutId);
+ for (int i = 0; i < TRANSITION_COUNT; i++) {
+ String key = TRANSITION_KEY + i;
+ outState.putInt(key, mTransitionIds[i]);
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(mLayoutId, container, false);
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ setEnterTransition(loadTransition(ENTER));
+ setReenterTransition(loadTransition(REENTER));
+ setExitTransition(loadTransition(EXIT));
+ setReturnTransition(loadTransition(RETURN));
+ setSharedElementEnterTransition(loadTransition(SHARED_ELEMENT_ENTER));
+ setSharedElementReturnTransition(loadTransition(SHARED_ELEMENT_RETURN));
+ }
+
+ public void setOnTransitionListener(OnTransitionListener listener) {
+ mOnTransitionListener = listener;
+ }
+
+ public boolean wasStartCalled(int transitionKey) {
+ return mListeners[transitionKey].transitionStarted;
+ }
+
+ public boolean wasEndCalled(int transitionKey) {
+ return mListeners[transitionKey].transitionEnded;
+ }
+
+ private Transition loadTransition(int key) {
+ final int id = mTransitionIds[key];
+ if (id == 0) {
+ return null;
+ }
+ Transition transition = TransitionInflater.from(getActivity()).inflateTransition(id);
+ transition.addListener(mListeners[key]);
+ return transition;
+ }
+
+ private void notifyTransition() {
+ if (mOnTransitionListener != null) {
+ mOnTransitionListener.onTransition(this);
+ }
+ }
+
+ private class TransitionCalledListener implements TransitionListener {
+ public boolean transitionStarted;
+ public boolean transitionEnded;
+
+ public TransitionCalledListener() {
+ }
+
+ @Override
+ public void onTransitionStart(Transition transition) {
+ transitionStarted = true;
+ notifyTransition();
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ transitionEnded = true;
+ notifyTransition();
+ }
+
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionPause(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionResume(Transition transition) {
+ }
+ }
+ }
+
+ public interface OnTransitionListener {
+ void onTransition(TestFragment fragment);
+ }
+
+}
diff --git a/tests/app/app/src/android/app/stubs/ISecondary.aidl b/tests/app/app/src/android/app/stubs/ISecondary.aidl
new file mode 100644
index 0000000..2f3ec25
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ISecondary.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+interface ISecondary {
+
+ int getPid();
+
+ long getElapsedCpuTime();
+
+ String getTimeZoneID();
+}
diff --git a/tests/app/app/src/android/app/stubs/InstrumentationTestActivity.java b/tests/app/app/src/android/app/stubs/InstrumentationTestActivity.java
new file mode 100644
index 0000000..8e36beb
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/InstrumentationTestActivity.java
@@ -0,0 +1,365 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.TextView;
+
+public class InstrumentationTestActivity extends Activity {
+
+ private boolean mOnCreateCalled;
+ private boolean mOnDestroyCalled ;
+ private boolean mOnNewIntentCalled;
+ private boolean mOnPauseCalled;
+ private boolean mOnPostCreate;
+ private boolean mOnRestart;
+ private boolean mOnRestoreInstanceState;
+ private boolean mOnResume;
+ private boolean mOnSaveInstanceState;
+ private boolean mOnStart;
+ private boolean mOnStop;
+ private boolean mOnMenuOpened;
+ private boolean mOnLeave;
+ private int mMenuID;
+ private boolean mOnTouchEventCalled;
+ private int mKeyDownCode;
+ private int mKeyUpCode;
+ private MotionEvent mMotionEvent;
+ private Bundle mBundle;
+ private MockTextView mTextView;
+ private List<KeyEvent> mKeyDownList = new ArrayList<KeyEvent>();
+ private List<KeyEvent> mKeyUpList = new ArrayList<KeyEvent>();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mTextView = new MockTextView(this);
+ setContentView(mTextView);
+ mOnCreateCalled = true;
+ }
+
+ class MockTextView extends TextView {
+
+ public MockTextView(Context context) {
+ super(context);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return super.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ return super.onTrackballEvent(event);
+ }
+
+ @Override
+ public void getLocationOnScreen(int[] location) {
+ super.getLocationOnScreen(location);
+ location[0] = location[1] = 10;
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mOnDestroyCalled = true;
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ mOnNewIntentCalled = true;
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mOnPauseCalled = true;
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ mOnPostCreate = true;
+ }
+
+ @Override
+ protected void onRestart() {
+ super.onRestart();
+ mOnRestart = true;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ mOnRestoreInstanceState = true;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ mOnTouchEventCalled = true;
+ mMotionEvent = event;
+ return super.onTouchEvent(event);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mOnResume = true;
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mOnSaveInstanceState = true;
+ mBundle = outState;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mOnStart = true;
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mOnStop = true;
+ }
+
+ @Override
+ protected void onUserLeaveHint() {
+ super.onUserLeaveHint();
+ mOnLeave = true;
+ }
+
+ @Override
+ public boolean onMenuOpened(int featureId, Menu menu) {
+ mOnMenuOpened = true;
+ return super.onMenuOpened(featureId, menu);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.browser, menu);
+
+ menu.add("title");
+ mOnMenuOpened = true;
+ return true;
+ }
+
+ @Override
+ public boolean onCreatePanelMenu(int featureId, Menu menu) {
+ return super.onCreatePanelMenu(featureId, menu);
+ }
+
+ @Override
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {
+ mMenuID = item.getItemId();
+ return super.onMenuItemSelected(featureId, item);
+ }
+
+ @Override
+ public void openContextMenu(View view) {
+ super.openContextMenu(view);
+ }
+
+ @Override
+ public void openOptionsMenu() {
+ super.openOptionsMenu();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ mKeyDownList.add(event);
+ mKeyDownCode = keyCode;
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ mMotionEvent = event;
+ return super.onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ mKeyUpList.add(event);
+ mKeyUpCode = keyCode;
+ return super.onKeyUp(keyCode, event);
+ }
+
+ public boolean isOnCreateCalled() {
+ return mOnCreateCalled;
+ }
+
+ public void setOnCreateCalled(boolean onCreateCalled) {
+ mOnCreateCalled = onCreateCalled;
+ }
+
+ public boolean isOnDestroyCalled() {
+ return mOnDestroyCalled;
+ }
+
+ public void setOnDestroyCalled(boolean onDestroyCalled) {
+ mOnDestroyCalled = onDestroyCalled;
+ }
+
+ public boolean isOnNewIntentCalled() {
+ return mOnNewIntentCalled;
+ }
+
+ public void setOnNewIntentCalled(boolean onNewIntentCalled) {
+ mOnNewIntentCalled = onNewIntentCalled;
+ }
+
+ public boolean isOnPauseCalled() {
+ return mOnPauseCalled;
+ }
+
+ public void setOnPauseCalled(boolean onPauseCalled) {
+ mOnPauseCalled = onPauseCalled;
+ }
+
+ public boolean isOnPostCreate() {
+ return mOnPostCreate;
+ }
+
+ public void setOnPostCreate(boolean onPostCreate) {
+ mOnPostCreate = onPostCreate;
+ }
+
+ public boolean isOnRestart() {
+ return mOnRestart;
+ }
+
+ public void setOnRestart(boolean onRestart) {
+ mOnRestart = onRestart;
+ }
+
+ public boolean isOnRestoreInstanceState() {
+ return mOnRestoreInstanceState;
+ }
+
+ public void setOnRestoreInstanceState(boolean onRestoreInstanceState) {
+ mOnRestoreInstanceState = onRestoreInstanceState;
+ }
+
+ public boolean isOnResume() {
+ return mOnResume;
+ }
+
+ public void setOnResume(boolean onResume) {
+ mOnResume = onResume;
+ }
+
+ public boolean isOnSaveInstanceState() {
+ return mOnSaveInstanceState;
+ }
+
+ public void setOnSaveInstanceState(boolean onSaveInstanceState) {
+ mOnSaveInstanceState = onSaveInstanceState;
+ }
+
+ public boolean isOnStart() {
+ return mOnStart;
+ }
+
+ public void setOnStart(boolean onStart) {
+ mOnStart = onStart;
+ }
+
+ public boolean isOnStop() {
+ return mOnStop;
+ }
+
+ public boolean isOnLeave() {
+ return mOnLeave;
+ }
+
+ public void setOnStop(boolean onStop) {
+ mOnStop = onStop;
+ }
+
+ public boolean isMOnMenuOpened() {
+ return mOnMenuOpened;
+ }
+
+ public void setOnMenuOpened(boolean onMenuOpened) {
+ mOnMenuOpened = onMenuOpened;
+ }
+
+ public int getMenuID() {
+ return mMenuID;
+ }
+
+ public void setMenuID(int menuID) {
+ mMenuID = menuID;
+ }
+
+ public MotionEvent getMotionEvent() {
+ return mMotionEvent;
+ }
+
+ public Bundle getBundle() {
+ return mBundle;
+ }
+
+ public boolean isOnTouchEventCalled() {
+ return mOnTouchEventCalled;
+ }
+
+ public void setOnTouchEventCalled(boolean onTouchEventCalled) {
+ mOnTouchEventCalled = onTouchEventCalled;
+ }
+
+ public int getKeyUpCode() {
+ return mKeyUpCode;
+ }
+
+ public int getKeyDownCode() {
+ return mKeyDownCode;
+ }
+
+ public List<KeyEvent> getKeyUpList() {
+ return mKeyUpList;
+ }
+
+ public List<KeyEvent> getKeyDownList() {
+ return mKeyDownList;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/IntentServiceStub.java b/tests/app/app/src/android/app/stubs/IntentServiceStub.java
new file mode 100644
index 0000000..626e464
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/IntentServiceStub.java
@@ -0,0 +1,136 @@
+/*
+ * 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.IntentService;
+import android.content.Intent;
+import android.cts.util.PollingCheck;
+import android.os.Binder;
+import android.os.IBinder;
+
+public class IntentServiceStub extends IntentService {
+ public IntentServiceStub() {
+ super("IntentServiceStub");
+ }
+
+ public static final String ISS_ADD = "add";
+ public static final String ISS_VALUE = "value";
+
+ private static int onHandleIntentCalled;
+ private static boolean onBindCalled;
+ private static boolean onCreateCalled;
+ private static boolean onDestroyCalled;
+ private static boolean onStartCalled;
+ private static int accumulator;
+
+ private static Throwable throwable;
+
+ public synchronized static void reset() {
+ onHandleIntentCalled = 0;
+ onBindCalled = false;
+ onCreateCalled = false;
+ onDestroyCalled = false;
+ onStartCalled = false;
+ accumulator = 0;
+ throwable = null;
+ }
+
+ public static void waitToFinish(long timeout) throws Throwable {
+ new PollingCheck(timeout) {
+ @Override
+ protected boolean check() {
+ synchronized (IntentServiceStub.class) {
+ return IntentServiceStub.onDestroyCalled;
+ }
+ }
+ }.run();
+ if (throwable != null) {
+ throw throwable;
+ }
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ synchronized (IntentServiceStub.class) {
+ onHandleIntentCalled += 1;
+ try {
+ String action = intent.getAction();
+ if (action != null && action.equals(ISS_ADD)) {
+ accumulator += intent.getIntExtra(ISS_VALUE, 0);
+ }
+ } catch (Throwable t) {
+ throwable = t;
+ }
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ synchronized (IntentServiceStub.class) {
+ onBindCalled = true;
+ }
+ return new Binder();
+ }
+
+ @Override
+ public void onCreate() {
+ synchronized (IntentServiceStub.class) {
+ onCreateCalled = true;
+ }
+ super.onCreate();
+ }
+
+ @Override
+ public void onDestroy() {
+ synchronized (IntentServiceStub.class) {
+ onDestroyCalled = true;
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public void onStart(Intent intent, int startId) {
+ synchronized (IntentService.class) {
+ onStartCalled = true;
+ }
+ super.onStart(intent, startId);
+ }
+
+ public synchronized static int getOnHandleIntentCalledCount() {
+ return onHandleIntentCalled;
+ }
+
+ public synchronized static boolean isOnBindCalled() {
+ return onBindCalled;
+ }
+
+ public synchronized static boolean isOnCreateCalled() {
+ return onCreateCalled;
+ }
+
+ public synchronized static boolean isOnDestroyCalled() {
+ return onDestroyCalled;
+ }
+
+ public synchronized static boolean isOnStartCalled() {
+ return onStartCalled;
+ }
+
+ public synchronized static int getAccumulator() {
+ return accumulator;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/KeyboardShortcutsActivity.java b/tests/app/app/src/android/app/stubs/KeyboardShortcutsActivity.java
new file mode 100644
index 0000000..dd9d1dc
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/KeyboardShortcutsActivity.java
@@ -0,0 +1,32 @@
+/*
+ * 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.view.Menu;
+
+public class KeyboardShortcutsActivity extends Activity {
+
+ public static final String ITEM_1_NAME = "item 1";
+ public static final char ITEM_1_SHORTCUT = 'i';
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menu.add(ITEM_1_NAME).setAlphabeticShortcut(ITEM_1_SHORTCUT);
+ return true;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/KeyguardManagerActivity.java b/tests/app/app/src/android/app/stubs/KeyguardManagerActivity.java
new file mode 100644
index 0000000..e85938d
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/KeyguardManagerActivity.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package android.app.stubs;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+
+public class KeyguardManagerActivity extends Activity {
+ private static final String TAG = "KeyguardManagerActivity";
+ public static final boolean DEBUG = false;
+ private KeyguardManager mKeyguardManager;
+ private KeyguardManager.KeyguardLock mKeyLock;
+ public int keyCode;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+ mKeyLock = null;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (DEBUG) {
+ Log.d(TAG, "onResume");
+ }
+ if (mKeyLock == null) {
+ mKeyLock = mKeyguardManager.newKeyguardLock(TAG);
+ mKeyLock.disableKeyguard();
+ if (DEBUG) {
+ Log.d(TAG, "disableKeyguard");
+ }
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ this.keyCode = keyCode;
+ if (keyCode == KeyEvent.KEYCODE_0 && mKeyLock != null) {
+ mKeyLock.reenableKeyguard();
+ mKeyLock = null;
+ if (DEBUG) {
+ Log.d(TAG, "reenableKeyguard");
+ }
+ }
+ if (DEBUG) {
+ Log.d(TAG, "onKeyDown");
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/LauncherActivityStub.java b/tests/app/app/src/android/app/stubs/LauncherActivityStub.java
new file mode 100644
index 0000000..f309b04
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LauncherActivityStub.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.LauncherActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ListView;
+
+public class LauncherActivityStub extends LauncherActivity {
+ public boolean isOnCreateCalled = false;
+ public boolean isOnListItemClick = false;
+ // For testing LauncherActivity#getTargetIntent()
+ private Intent mSuperIntent;
+
+ public Intent getSuperIntent() {
+ return mSuperIntent;
+ }
+
+ @Override
+ protected Intent getTargetIntent() {
+ mSuperIntent = super.getTargetIntent();
+ Intent targetIntent = new Intent(Intent.ACTION_MAIN, null);
+ targetIntent.addCategory(Intent.CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST);
+ targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return targetIntent;
+ }
+
+ @Override
+ public Intent intentForPosition(int position) {
+ return super.intentForPosition(position);
+ }
+
+ public LauncherActivityStub() {
+ super();
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ isOnCreateCalled = true;
+ }
+
+ @Override
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ super.onListItemClick(l, v, position, id);
+ isOnListItemClick = true;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/LaunchpadActivity.java b/tests/app/app/src/android/app/stubs/LaunchpadActivity.java
new file mode 100644
index 0000000..16b1363
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LaunchpadActivity.java
@@ -0,0 +1,648 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.test.PerformanceTestCase;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+class MyBadParcelable implements Parcelable {
+ public MyBadParcelable() {
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString("I am bad");
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<MyBadParcelable> CREATOR =
+ new Parcelable.Creator<MyBadParcelable>() {
+ public MyBadParcelable createFromParcel(Parcel in) {
+ return new MyBadParcelable(in);
+ }
+
+ public MyBadParcelable[] newArray(int size) {
+ return new MyBadParcelable[size];
+ }
+ };
+
+ public MyBadParcelable(Parcel in) {
+ in.readString();
+ }
+}
+
+public class LaunchpadActivity extends Activity {
+ public interface CallingTest extends PerformanceTestCase.Intermediates {
+ public void startTiming(boolean realTime);
+
+ public void addIntermediate(String name);
+
+ public void addIntermediate(String name, long timeInNS);
+
+ public void finishTiming(boolean realTime);
+
+ public void activityFinished(int resultCode, Intent data, RuntimeException where);
+ }
+
+ // Also used as the Binder interface descriptor string in these tests
+ public static final String LAUNCH = "android.app.cts.activity.LAUNCH";
+
+ public static final String FORWARD_RESULT = "android.app.cts.activity.FORWARD_RESULT";
+ public static final String RETURNED_RESULT = "android.app.cts.activity.RETURNED_RESULT";
+
+ public static final String BAD_PARCELABLE = "android.app.cts.activity.BAD_PARCELABLE";
+
+ public static final int LAUNCHED_RESULT = 1;
+ public static final int FORWARDED_RESULT = 2;
+
+ public static final String LIFECYCLE_BASIC = "android.app.cts.activity.LIFECYCLE_BASIC";
+ public static final String LIFECYCLE_SCREEN = "android.app.cts.activity.LIFECYCLE_SCREEN";
+ public static final String LIFECYCLE_DIALOG = "android.app.cts.activity.LIFECYCLE_DIALOG";
+
+ public static final String BROADCAST_REGISTERED = "android.app.cts.activity.BROADCAST_REGISTERED";
+ public static final String BROADCAST_LOCAL = "android.app.cts.activity.BROADCAST_LOCAL";
+ public static final String BROADCAST_REMOTE = "android.app.cts.activity.BROADCAST_REMOTE";
+ public static final String BROADCAST_ALL = "android.app.cts.activity.BROADCAST_ALL";
+ public static final String BROADCAST_REPEAT = "android.app.cts.activity.BROADCAST_REPEAT";
+ public static final String BROADCAST_MULTI = "android.app.cts.activity.BROADCAST_MULTI";
+ public static final String BROADCAST_ABORT = "android.app.cts.activity.BROADCAST_ABORT";
+
+ public static final String EXPANDLIST_SELECT = "EXPANDLIST_SELECT";
+ public static final String EXPANDLIST_VIEW = "EXPANDLIST_VIEW";
+ public static final String EXPANDLIST_CALLBACK = "EXPANDLIST_CALLBACK";
+
+ public static final String BROADCAST_STICKY1 = "android.app.cts.activity.BROADCAST_STICKY1";
+ public static final String BROADCAST_STICKY2 = "android.app.cts.activity.BROADCAST_STICKY2";
+
+ public static final String ALIAS_ACTIVITY = "android.app.cts.activity.ALIAS_ACTIVITY";
+
+ public static final String RECEIVER_REG = "receiver-reg";
+ public static final String RECEIVER_LOCAL = "receiver-local";
+ public static final String RECEIVER_REMOTE = "receiver-remote";
+ public static final String RECEIVER_ABORT = "receiver-abort";
+
+ public static final String DATA_1 = "one";
+ public static final String DATA_2 = "two";
+
+ public static final String ON_START = "onStart";
+ public static final String ON_RESTART = "onRestart";
+ public static final String ON_RESUME = "onResume";
+ public static final String ON_FREEZE = "onSaveInstanceState";
+ public static final String ON_PAUSE = "onPause";
+
+ // ON_STOP and ON_DESTROY are not tested because they may not be called.
+
+ public static final String DO_FINISH = "finish";
+ public static final String DO_LOCAL_SCREEN = "local-screen";
+ public static final String DO_LOCAL_DIALOG = "local-dialog";
+
+ private static final String TAG = "LaunchpadActivity";
+
+ private boolean mBadParcelable = false;
+
+ private boolean mStarted = false;
+
+ private int mResultCode = RESULT_CANCELED;
+ private Intent mData = new Intent().setAction("No result received");
+ private RuntimeException mResultStack = null;
+
+ /** Index into the {@link #mNextLifecycle} array. */
+ private int mNextLifecycle;
+
+ /** Current lifecycle expected to be followed. */
+ private String[] mExpectedLifecycle;
+
+ /** Other possible lifecycles. Never includes the current {@link #mExpectedLifecycle}. */
+ private List<String[]> mOtherPossibleLifecycles = new ArrayList<String[]>(2);
+
+ /** Map from lifecycle arrays to debugging log names. */
+ private Map<String[], String> mLifecycleNames = new HashMap<String[], String>(2);
+
+ private String[] mExpectedReceivers = null;
+ private int mNextReceiver;
+
+ private String[] mExpectedData = null;
+ private boolean[] mReceivedData = null;
+
+ boolean mReceiverRegistered = false;
+
+ private static CallingTest sCallingTest = null;
+
+ public static void setCallingTest(CallingTest ct) {
+ sCallingTest = ct;
+ }
+
+ public LaunchpadActivity() {
+ }
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ resetLifecycles();
+
+ // ON_STOP and ON_DESTROY are not tested because they may not be called.
+
+ final String action = getIntent().getAction();
+ if (LIFECYCLE_BASIC.equals(action)) {
+ addPossibleLifecycle(LIFECYCLE_BASIC, new String[] {
+ ON_START, ON_RESUME, DO_FINISH, ON_PAUSE
+ });
+ } else if (LIFECYCLE_SCREEN.equals(action)) {
+ addPossibleLifecycle(LIFECYCLE_SCREEN + "_RESTART", new String[] {
+ ON_START, ON_RESUME, DO_LOCAL_SCREEN, ON_PAUSE,
+ ON_RESTART, ON_START, ON_RESUME, DO_FINISH, ON_PAUSE
+ });
+ addPossibleLifecycle(LIFECYCLE_SCREEN + "_RESUME", new String[] {
+ ON_START, ON_RESUME, DO_LOCAL_SCREEN, ON_PAUSE,
+ ON_RESUME, DO_FINISH, ON_PAUSE
+ });
+ } else if (LIFECYCLE_DIALOG.equals(action)) {
+ addPossibleLifecycle(LIFECYCLE_DIALOG + "_RESTART", new String[] {
+ ON_START, ON_RESUME, DO_LOCAL_DIALOG, ON_PAUSE,
+ ON_RESTART, ON_START, ON_RESUME, DO_FINISH, ON_PAUSE
+ });
+ addPossibleLifecycle(LIFECYCLE_DIALOG + "_RESUME", new String[] {
+ ON_START, ON_RESUME, DO_LOCAL_DIALOG, ON_PAUSE,
+ ON_RESUME, DO_FINISH, ON_PAUSE
+ });
+ }
+ }
+
+ private void resetLifecycles() {
+ mNextLifecycle = 0;
+ mExpectedLifecycle = null;
+ mOtherPossibleLifecycles.clear();
+ mLifecycleNames.clear();
+ }
+
+ /**
+ * Add a potential lifecycle that this activity may follow, since there
+ * are usually multiple valid lifecycles. For instance, sometimes onPause
+ * will lead to onResume rather than onStop when another activity is
+ * raised over the current one.
+ *
+ * @param debugName for the lifecycle shown in the logs
+ * @param lifecycle array containing tokens indicating the expected lifecycle
+ */
+ private void addPossibleLifecycle(String debugName, String[] lifecycle) {
+ mLifecycleNames.put(lifecycle, debugName);
+ if (mExpectedLifecycle == null) {
+ mExpectedLifecycle = lifecycle;
+ } else {
+ mOtherPossibleLifecycles.add(lifecycle);
+ }
+ }
+
+ /**
+ * Switch to the next possible lifecycle and return if switching was
+ * successful. Call this method when mExpectedLifecycle doesn't match
+ * the current lifecycle and you need to check another possible lifecycle.
+ *
+ * @return whether on not there was a lifecycle to switch to
+ */
+ private boolean switchToNextPossibleLifecycle() {
+ if (!mOtherPossibleLifecycles.isEmpty()) {
+ String[] newLifecycle = mOtherPossibleLifecycles.remove(0);
+ Log.w(TAG, "Switching expected lifecycles from "
+ + mLifecycleNames.get(mExpectedLifecycle) + " to "
+ + mLifecycleNames.get(newLifecycle));
+ mExpectedLifecycle = newLifecycle;
+ return true;
+ } else {
+ Log.w(TAG, "No more lifecycles after "
+ + mLifecycleNames.get(mExpectedLifecycle));
+ mExpectedLifecycle = null;
+ return false;
+ }
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ checkLifecycle(ON_START);
+ }
+
+ @Override
+ protected void onRestart() {
+ super.onStart();
+ checkLifecycle(ON_RESTART);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ checkLifecycle(ON_RESUME);
+
+ if (!mStarted) {
+ mStarted = true;
+
+ mHandler.postDelayed(mTimeout, 10 * 1000);
+
+ final String action = getIntent().getAction();
+
+ sCallingTest.startTiming(true);
+
+ if (LAUNCH.equals(action)) {
+ final Intent intent = getIntent();
+ intent.setFlags(0);
+ intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
+ startActivityForResult(intent, LAUNCHED_RESULT);
+
+ } else if (FORWARD_RESULT.equals(action)) {
+ final Intent intent = getIntent();
+ intent.setFlags(0);
+ intent.setClass(this, LocalScreen.class);
+ startActivityForResult(intent, FORWARDED_RESULT);
+ } else if (BAD_PARCELABLE.equals(action)) {
+ mBadParcelable = true;
+ final Intent intent = getIntent();
+ intent.setFlags(0);
+ intent.setClass(this, LocalScreen.class);
+ startActivityForResult(intent, LAUNCHED_RESULT);
+ } else if (BROADCAST_REGISTERED.equals(action)) {
+ setExpectedReceivers(new String[] {
+ RECEIVER_REG
+ });
+ registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED));
+ sCallingTest.addIntermediate("after-register");
+ sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED));
+ } else if (BROADCAST_LOCAL.equals(action)) {
+ setExpectedReceivers(new String[] {
+ RECEIVER_LOCAL
+ });
+ sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL));
+ } else if (BROADCAST_REMOTE.equals(action)) {
+ setExpectedReceivers(new String[] {
+ RECEIVER_REMOTE
+ });
+ sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE));
+ } else if (BROADCAST_ALL.equals(action)) {
+ setExpectedReceivers(new String[] {
+ RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL
+ });
+ registerMyReceiver(new IntentFilter(BROADCAST_ALL));
+ sCallingTest.addIntermediate("after-register");
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+ } else if (BROADCAST_MULTI.equals(action)) {
+ setExpectedReceivers(new String[] {
+ RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE,
+ RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE, RECEIVER_REG,
+ RECEIVER_LOCAL, RECEIVER_LOCAL, RECEIVER_REMOTE, RECEIVER_LOCAL,
+ RECEIVER_REMOTE, RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL,
+ RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE,
+ RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE, RECEIVER_LOCAL,
+ RECEIVER_REMOTE, RECEIVER_LOCAL
+ });
+ registerMyReceiver(new IntentFilter(BROADCAST_ALL));
+ sCallingTest.addIntermediate("after-register");
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REPEAT), null);
+ } else if (BROADCAST_ABORT.equals(action)) {
+ setExpectedReceivers(new String[] {
+ RECEIVER_REMOTE, RECEIVER_ABORT
+ });
+ registerMyReceiver(new IntentFilter(BROADCAST_ABORT));
+ sCallingTest.addIntermediate("after-register");
+ sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ABORT), null);
+ } else if (BROADCAST_STICKY1.equals(action)) {
+ setExpectedReceivers(new String[] {
+ RECEIVER_REG
+ });
+ setExpectedData(new String[] {
+ DATA_1
+ });
+ registerMyReceiver(new IntentFilter(BROADCAST_STICKY1));
+ sCallingTest.addIntermediate("after-register");
+ } else if (BROADCAST_STICKY2.equals(action)) {
+ setExpectedReceivers(new String[] {
+ RECEIVER_REG, RECEIVER_REG
+ });
+ setExpectedData(new String[] {
+ DATA_1, DATA_2
+ });
+ final IntentFilter filter = new IntentFilter(BROADCAST_STICKY1);
+ filter.addAction(BROADCAST_STICKY2);
+ registerMyReceiver(filter);
+ sCallingTest.addIntermediate("after-register");
+ } else if (ALIAS_ACTIVITY.equals(action)) {
+ final Intent intent = getIntent();
+ intent.setFlags(0);
+ intent.setClass(this, AliasActivityStub.class);
+ startActivityForResult(intent, LAUNCHED_RESULT);
+ } else if (EXPANDLIST_SELECT.equals(action)) {
+ final Intent intent = getIntent();
+ intent.setFlags(0);
+ intent.setAction(action);
+ intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
+ startActivityForResult(intent, LAUNCHED_RESULT);
+ } else if (EXPANDLIST_VIEW.equals(action)) {
+ final Intent intent = getIntent();
+ intent.setFlags(0);
+ intent.setAction(action);
+ intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
+ startActivityForResult(intent, LAUNCHED_RESULT);
+ } else if (EXPANDLIST_CALLBACK.equals(action)) {
+ final Intent intent = getIntent();
+ intent.setFlags(0);
+ intent.setAction(action);
+ intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
+ startActivityForResult(intent, LAUNCHED_RESULT);
+ }
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle icicle) {
+ super.onSaveInstanceState(icicle);
+ if (mBadParcelable) {
+ icicle.putParcelable("baddy", new MyBadParcelable());
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ checkLifecycle(ON_PAUSE);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ case LAUNCHED_RESULT:
+ sCallingTest.finishTiming(true);
+ finishWithResult(resultCode, data);
+ break;
+ case FORWARDED_RESULT:
+ sCallingTest.finishTiming(true);
+ if (RETURNED_RESULT.equals(data.getAction())) {
+ finishWithResult(resultCode, data);
+ } else {
+ finishWithResult(RESULT_CANCELED, new Intent().setAction("Bad data returned: "
+ + data));
+ }
+ break;
+ default:
+ sCallingTest.finishTiming(true);
+ finishWithResult(RESULT_CANCELED, new Intent()
+ .setAction("Unexpected request code: " + requestCode));
+ break;
+ }
+ }
+
+ private void checkLifecycle(String where) {
+ String action = getIntent().getAction();
+
+ if (mExpectedLifecycle == null) {
+ return;
+ }
+
+ if (mNextLifecycle >= mExpectedLifecycle.length) {
+ finishBad("Activity lifecycle for " + action + " incorrect: received " + where
+ + " but don't expect any more calls");
+ mExpectedLifecycle = null;
+ return;
+ }
+
+ do {
+ if (mExpectedLifecycle[mNextLifecycle].equals(where)) {
+ Log.w(TAG, "Matched: " + where);
+ break;
+ } else {
+ Log.w(TAG, "Expected " + mExpectedLifecycle[mNextLifecycle] + " but got " + where);
+ }
+ } while (switchToNextPossibleLifecycle());
+
+ if (mExpectedLifecycle == null) {
+ finishBad("Activity lifecycle for " + action + " incorrect: received " + where
+ + " at " + mNextLifecycle);
+ return;
+ }
+
+ mNextLifecycle++;
+
+ if (mNextLifecycle >= mExpectedLifecycle.length) {
+ finishGood();
+ return;
+ }
+
+ final String next = mExpectedLifecycle[mNextLifecycle];
+ if (next.equals(DO_FINISH)) {
+ mNextLifecycle++;
+ if (mNextLifecycle >= mExpectedLifecycle.length) {
+ setTestResult(RESULT_OK, null);
+ }
+ if (!isFinishing()) {
+ finish();
+ }
+ } else if (next.equals(DO_LOCAL_SCREEN)) {
+ mNextLifecycle++;
+ final Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH);
+ intent.setClass(this, LocalScreen.class);
+ startActivity(intent);
+ } else if (next.equals(DO_LOCAL_DIALOG)) {
+ mNextLifecycle++;
+ final Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH);
+ intent.setClass(this, LocalDialog.class);
+ startActivity(intent);
+ }
+ }
+
+ private void setExpectedReceivers(String[] receivers) {
+ mExpectedReceivers = receivers;
+ mNextReceiver = 0;
+ }
+
+ private void setExpectedData(String[] data) {
+ mExpectedData = data;
+ mReceivedData = new boolean[data.length];
+ }
+
+ @SuppressWarnings("deprecation")
+ private Intent makeBroadcastIntent(String action) {
+ final Intent intent = new Intent(action, null);
+ intent.putExtra("caller", mCallTarget);
+ return intent;
+ }
+
+ private void finishGood() {
+ finishWithResult(RESULT_OK, null);
+ }
+
+ private void finishBad(String error) {
+ finishWithResult(RESULT_CANCELED, new Intent().setAction(error));
+ }
+
+ private void finishWithResult(int resultCode, Intent data) {
+ setTestResult(resultCode, data);
+ finish();
+
+ // Member fields set by calling setTestResult above...
+ sCallingTest.activityFinished(mResultCode, mData, mResultStack);
+ }
+
+ private void setTestResult(int resultCode, Intent data) {
+ mHandler.removeCallbacks(mTimeout);
+ unregisterMyReceiver();
+ mResultCode = resultCode;
+ mData = data;
+ mResultStack = new RuntimeException("Original error was here");
+ mResultStack.fillInStackTrace();
+ }
+
+ private void registerMyReceiver(IntentFilter filter) {
+ mReceiverRegistered = true;
+ registerReceiver(mReceiver, filter);
+ }
+
+ private void unregisterMyReceiver() {
+ if (mReceiverRegistered) {
+ mReceiverRegistered = false;
+ unregisterReceiver(mReceiver);
+ }
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ }
+ };
+
+ static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
+ static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
+
+ private final Binder mCallTarget = new Binder() {
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
+ data.setDataPosition(0);
+ data.enforceInterface(LaunchpadActivity.LAUNCH);
+ if (code == GOT_RECEIVE_TRANSACTION) {
+ final String name = data.readString();
+ gotReceive(name, null);
+ return true;
+ } else if (code == ERROR_TRANSACTION) {
+ finishBad(data.readString());
+ return true;
+ }
+ return false;
+ }
+ };
+
+ private final void gotReceive(String name, Intent intent) {
+ synchronized (this) {
+
+ sCallingTest.addIntermediate(mNextReceiver + "-" + name);
+
+ if (mExpectedData != null) {
+ final int n = mExpectedData.length;
+ int i;
+ boolean prev = false;
+ for (i = 0; i < n; i++) {
+ if (mExpectedData[i].equals(intent.getStringExtra("test"))) {
+ if (mReceivedData[i]) {
+ prev = true;
+ continue;
+ }
+ mReceivedData[i] = true;
+ break;
+ }
+ }
+ if (i >= n) {
+ if (prev) {
+ finishBad("Receive got data too many times: "
+ + intent.getStringExtra("test"));
+ } else {
+ finishBad("Receive got unexpected data: " + intent.getStringExtra("test"));
+ }
+ return;
+ }
+ }
+
+ if (mNextReceiver >= mExpectedReceivers.length) {
+ finishBad("Got too many onReceiveIntent() calls!");
+ } else if (!mExpectedReceivers[mNextReceiver].equals(name)) {
+ finishBad("Receive out of order: got " + name + " but expected "
+ + mExpectedReceivers[mNextReceiver] + " at " + mNextReceiver);
+ } else {
+ mNextReceiver++;
+ if (mNextReceiver == mExpectedReceivers.length) {
+ mHandler.post(mUnregister);
+ }
+ }
+
+ }
+ }
+
+ private final Runnable mUnregister = new Runnable() {
+ public void run() {
+ if (mReceiverRegistered) {
+ sCallingTest.addIntermediate("before-unregister");
+ unregisterMyReceiver();
+ }
+ sCallingTest.finishTiming(true);
+ finishGood();
+ }
+ };
+
+ private final Runnable mTimeout = new Runnable() {
+ public void run() {
+ Log.i(TAG, "timeout");
+ String msg = "Timeout";
+ if (mExpectedReceivers != null && mNextReceiver < mExpectedReceivers.length) {
+ msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver];
+ }
+ finishBad(msg);
+ }
+ };
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ gotReceive(RECEIVER_REG, intent);
+ }
+ };
+}
diff --git a/tests/app/app/src/android/app/stubs/LaunchpadTabActivity.java b/tests/app/app/src/android/app/stubs/LaunchpadTabActivity.java
new file mode 100644
index 0000000..a63b384
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LaunchpadTabActivity.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.TabActivity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.TabHost;
+
+public class LaunchpadTabActivity extends TabActivity {
+ public LaunchpadTabActivity() {
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ final Intent tabIntent = new Intent(getIntent());
+ tabIntent.setComponent((ComponentName) tabIntent.getParcelableExtra("tab"));
+
+ final TabHost th = getTabHost();
+ final TabHost.TabSpec ts = th.newTabSpec("1");
+ ts.setIndicator("One");
+ ts.setContent(tabIntent);
+ th.addTab(ts);
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/LocalActivity.java b/tests/app/app/src/android/app/stubs/LocalActivity.java
new file mode 100644
index 0000000..b279d3b
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LocalActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+public class LocalActivity extends TestedActivity {
+ public LocalActivity() {
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/LocalActivityManagerStubActivity.java b/tests/app/app/src/android/app/stubs/LocalActivityManagerStubActivity.java
new file mode 100644
index 0000000..f7df9a3
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LocalActivityManagerStubActivity.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class LocalActivityManagerStubActivity extends Activity{
+
+ public static boolean sIsOnResumeCalled;
+ public static boolean sIsOnStopCalled;
+ public static boolean sIsOnPauseCalled;
+ public static boolean sIsOnDestroyCalled;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ sIsOnResumeCalled = true;
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ sIsOnStopCalled = true;
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ sIsOnPauseCalled = true;
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ sIsOnDestroyCalled = true;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/LocalActivityManagerTestHelper.java b/tests/app/app/src/android/app/stubs/LocalActivityManagerTestHelper.java
new file mode 100644
index 0000000..8e28ee4
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LocalActivityManagerTestHelper.java
@@ -0,0 +1,340 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+
+import android.app.Activity;
+import android.app.ActivityGroup;
+import android.app.LocalActivityManager;
+import android.content.Intent;
+import android.cts.util.CTSResult;
+import android.os.Bundle;
+import android.view.Window;
+
+public class LocalActivityManagerTestHelper extends ActivityGroup {
+
+ public static final String ACTION_DISPATCH_RESUME = "dispatchResume";
+ public static final String ACTION_START_ACTIVITY = "startActivity";
+ public static final String ACTION_DISPATCH_CREATE = "dispatchCreate";
+ public static final String ACTION_DISPATCH_STOP = "dispatchStop";
+ public static final String ACTION_DISPATCH_PAUSE_TRUE = "dispatchPauseTrue";
+ public static final String ACTION_DISPATCH_PAUSE_FALSE = "dispatchPauseFalse";
+ public static final String ACTION_SAVE_INSTANCE_STATE = "saveInstanceState";
+ public static final String ACTION_DISPATCH_DESTROY = "dispatchDestroy";
+ public static final String ACTION_REMOVE_ALL_ACTIVITY = "removeAllActivities";
+
+ private String mCurrentAction;
+ private LocalActivityManager mLocalActivityManager;
+
+ private static CTSResult sResult;
+
+ public static void setResult(CTSResult cr) {
+ sResult = cr;
+ }
+
+ public LocalActivityManagerTestHelper() {
+ super();
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mCurrentAction = getIntent().getAction();
+ mLocalActivityManager = getLocalActivityManager();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ }
+
+ protected void onResume() {
+ super.onResume();
+ if (mCurrentAction.equals(ACTION_DISPATCH_RESUME)) {
+ testDispatchResume();
+ } else if (mCurrentAction.equals(ACTION_START_ACTIVITY)) {
+ testStartActivity();
+ } else if (mCurrentAction.equals(ACTION_DISPATCH_CREATE)) {
+ testDispatchCreate();
+ } else if (mCurrentAction.equals(ACTION_DISPATCH_STOP)) {
+ testDispatchStop();
+ } else if (mCurrentAction.equals(ACTION_DISPATCH_PAUSE_TRUE)) {
+ testDispatchPauseTrue();
+ } else if (mCurrentAction.equals(ACTION_DISPATCH_PAUSE_FALSE)) {
+ testDispatchPauseFalse();
+ } else if (mCurrentAction.equals(ACTION_SAVE_INSTANCE_STATE)) {
+ testSaveInstanceState();
+ } else if (mCurrentAction.equals(ACTION_DISPATCH_DESTROY)) {
+ testDispatchDestroy();
+ } else if (mCurrentAction.equals(ACTION_REMOVE_ALL_ACTIVITY)) {
+ testRemoveAllActivity();
+ }
+ }
+
+ private void testRemoveAllActivity() {
+ final String id = "id_remove_activity";
+ final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mLocalActivityManager.startActivity(id, intent);
+
+ Activity activity = mLocalActivityManager.getActivity(id);
+ if (activity == null) {
+ fail();
+ return;
+ }
+
+ if (!activity.getClass().getName().equals("android.app.stubs."
+ + "LocalActivityManagerStubActivity")) {
+ fail();
+ return;
+ }
+
+ mLocalActivityManager.removeAllActivities();
+ activity = mLocalActivityManager.getActivity(id);
+ if (activity != null) {
+ fail();
+ return;
+ }
+ pass();
+ }
+
+ private void testDispatchDestroy() {
+ final String id1 = "id_dispatch_destroy1";
+ final String id2 = "id_dispatch_destroy2";
+ final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mLocalActivityManager.startActivity(id1, intent);
+
+ LocalActivityManagerStubActivity.sIsOnDestroyCalled = false;
+ mLocalActivityManager.dispatchDestroy(false);
+ if (mLocalActivityManager.getCurrentActivity().isFinishing()){
+ fail();
+ return;
+ }
+
+ if (!LocalActivityManagerStubActivity.sIsOnDestroyCalled) {
+ fail();
+ return;
+ }
+
+ mLocalActivityManager.startActivity(id2, intent);
+ LocalActivityManagerStubActivity.sIsOnDestroyCalled = false;
+ mLocalActivityManager.dispatchDestroy(true);
+
+ if (!LocalActivityManagerStubActivity.sIsOnDestroyCalled) {
+ fail();
+ return;
+ }
+
+ if (!mLocalActivityManager.getCurrentActivity().isFinishing()){
+ fail();
+ return;
+ }
+ pass();
+ }
+
+ private void testSaveInstanceState() {
+ final String key = "_id1";
+ mLocalActivityManager.dispatchCreate(null);
+ final Bundle bundle = mLocalActivityManager.saveInstanceState();
+ if (bundle != null) {
+ fail();
+ return;
+ }
+
+ final String id = "id_dispatch_pause";
+ final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mLocalActivityManager.startActivity(id, intent);
+
+ final Bundle savedBundle = new Bundle();
+ final Bundle bb = new Bundle();
+ savedBundle.putBundle(key, bb);
+
+ mLocalActivityManager.dispatchCreate(savedBundle);
+ final Bundle returnedBundle = mLocalActivityManager.saveInstanceState();
+ if (returnedBundle.getBundle(key) == null ) {
+ fail();
+ return;
+ }
+ pass();
+ }
+
+ private void testDispatchPauseFalse() {
+ final String id = "id_dispatch_pause";
+ final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mLocalActivityManager.startActivity(id, intent);
+ LocalActivityManagerStubActivity.sIsOnPauseCalled = false;
+ mLocalActivityManager.dispatchPause(false);
+ if (!LocalActivityManagerStubActivity.sIsOnPauseCalled) {
+ fail();
+ return;
+ }
+ pass();
+ }
+
+ private void testDispatchPauseTrue() {
+ final String id = "id_dispatch_pause";
+ final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mLocalActivityManager.startActivity(id, intent);
+ LocalActivityManagerStubActivity.sIsOnPauseCalled = false;
+ mLocalActivityManager.dispatchPause(true);
+ if (!LocalActivityManagerStubActivity.sIsOnPauseCalled) {
+ fail();
+ return;
+ }
+ pass();
+ }
+
+ private void testDispatchStop() {
+ final String id = "id_dispatch_stop";
+ final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mLocalActivityManager.startActivity(id, intent);
+ if (mLocalActivityManager.getCurrentActivity() == null) {
+ fail();
+ return;
+ }
+
+ LocalActivityManagerStubActivity.sIsOnStopCalled = false;
+ mLocalActivityManager.dispatchStop();
+
+ if (!LocalActivityManagerStubActivity.sIsOnStopCalled) {
+ fail();
+ return;
+ }
+ pass();
+ }
+
+ private void testDispatchCreate() {
+ final Bundle EXPECTED = new Bundle();
+ final String id = "id";
+
+ final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mLocalActivityManager.startActivity("_id" + System.currentTimeMillis(), intent);
+ final Bundle bundle = mLocalActivityManager.saveInstanceState();
+ if (bundle == null) {
+ fail();
+ return;
+ }
+
+ if (bundle.keySet().size() != 1) {
+ fail();
+ return;
+ }
+
+ bundle.putBundle(id, EXPECTED);
+ // test null parameter
+ mLocalActivityManager.dispatchCreate(null);
+
+ if (mLocalActivityManager.saveInstanceState().keySet().size() != 1) {
+ fail();
+ return;
+ }
+
+ mLocalActivityManager.dispatchCreate(bundle);
+
+ final Bundle b = mLocalActivityManager.saveInstanceState();
+ final Bundle bb = b.getBundle(id);
+ if (bb != EXPECTED) {
+ fail();
+ return;
+ }
+ pass();
+ }
+
+ private void testStartActivity() {
+ final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final String id = "_id_resume_test";
+ final Window w = mLocalActivityManager.startActivity(id, intent);
+ if (w == null) {
+ fail();
+ return;
+ }
+
+ Activity activity = mLocalActivityManager.getActivity(id);
+ if (activity == null) {
+ fail();
+ return;
+ }
+
+ // testing null id
+ activity = mLocalActivityManager.getActivity("null id");
+ if (activity != null) {
+ fail();
+ return;
+ }
+
+ if (!mLocalActivityManager.getCurrentId().equals(id)) {
+ fail();
+ return;
+ }
+
+ if (mLocalActivityManager.getActivity(id) != mLocalActivityManager
+ .getCurrentActivity()) {
+ fail();
+ return;
+ }
+
+ if (mLocalActivityManager.destroyActivity(id, true) == null) {
+ fail();
+ return;
+ }
+
+ if (mLocalActivityManager.startActivity(null, intent) == null) {
+ fail();
+ return;
+ }
+
+ try {
+ // test when calling startActivity with both null parameter.
+ mLocalActivityManager.startActivity(null, null);
+ fail();
+ return;
+ } catch (NullPointerException e) {
+ }
+ pass();
+ }
+
+ private void testDispatchResume() {
+ final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mLocalActivityManager.startActivity("_id_resume_test", intent);
+ mLocalActivityManager.dispatchStop();
+ LocalActivityManagerStubActivity.sIsOnResumeCalled = false;
+ mLocalActivityManager.dispatchResume();
+ if (LocalActivityManagerStubActivity.sIsOnResumeCalled) {
+ pass();
+ } else {
+ fail();
+ }
+ }
+
+ private void fail() {
+ sResult.setResult(CTSResult.RESULT_FAIL);
+ finish();
+ }
+
+ private void pass() {
+ sResult.setResult(CTSResult.RESULT_OK);
+ finish();
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/LocalDeniedService.java b/tests/app/app/src/android/app/stubs/LocalDeniedService.java
new file mode 100644
index 0000000..aaf4670
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LocalDeniedService.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+public class LocalDeniedService extends LocalService
+{
+}
+
diff --git a/tests/app/app/src/android/app/stubs/LocalDialog.java b/tests/app/app/src/android/app/stubs/LocalDialog.java
new file mode 100644
index 0000000..62c4824
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LocalDialog.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+public class LocalDialog extends TestedScreen {
+ public LocalDialog() {
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/LocalGrantedService.java b/tests/app/app/src/android/app/stubs/LocalGrantedService.java
new file mode 100644
index 0000000..c82d3fd
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LocalGrantedService.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+public class LocalGrantedService extends LocalService
+{
+}
+
diff --git a/tests/app/app/src/android/app/stubs/LocalScreen.java b/tests/app/app/src/android/app/stubs/LocalScreen.java
new file mode 100644
index 0000000..21026a1
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LocalScreen.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+public class LocalScreen extends TestedScreen {
+ public LocalScreen() {
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/LocalService.java b/tests/app/app/src/android/app/stubs/LocalService.java
new file mode 100644
index 0000000..01e098b
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LocalService.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Service;
+import android.content.Intent;
+import android.cts.util.IBinderParcelable;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+
+public class LocalService extends Service {
+ public static final String SERVICE_LOCAL =
+ "android.app.cts.activity.SERVICE_LOCAL";
+ public static final String SERVICE_LOCAL_GRANTED =
+ "android.app.cts.activity.SERVICE_LOCAL_GRANTED";
+ public static final String SERVICE_LOCAL_DENIED =
+ "android.app.cts.activity.SERVICE_LOCAL_DENIED";
+
+ public static final String REPORT_OBJ_NAME = "report";
+
+ public static final int STARTED_CODE = 1;
+ public static final int DESTROYED_CODE = 2;
+ public static final int SET_REPORTER_CODE = 3;
+ public static final int UNBIND_CODE = 4;
+ public static final int REBIND_CODE = 5;
+
+ private IBinder mReportObject;
+ private int mStartCount = 1;
+
+ private final IBinder mBinder = new Binder() {
+ @Override
+ protected boolean onTransact(int code, Parcel data, Parcel reply,
+ int flags) throws RemoteException {
+ if (code == SET_REPORTER_CODE) {
+ data.enforceInterface(SERVICE_LOCAL);
+ mReportObject = data.readStrongBinder();
+ return true;
+ } else {
+ return super.onTransact(code, data, reply, flags);
+ }
+ }
+ };
+
+
+ public LocalService() {
+ }
+
+ @Override
+ public void onStart(Intent intent, int startId) {
+ if (intent.getExtras() != null) {
+ IBinderParcelable parcelable
+ = (IBinderParcelable) intent.getExtras().getParcelable(REPORT_OBJ_NAME);
+ mReportObject = parcelable.binder;
+ if (mReportObject != null) {
+ bindAction(STARTED_CODE);
+ }
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mReportObject != null) {
+ bindAction(DESTROYED_CODE);
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ if (mReportObject != null) {
+ bindAction(UNBIND_CODE);
+ }
+ return true;
+ }
+
+ @Override
+ public void onRebind(Intent intent) {
+ if (mReportObject != null) {
+ bindAction(REBIND_CODE);
+ }
+ }
+
+ private void bindAction(final int bindCode) {
+ try {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(SERVICE_LOCAL);
+ if (bindCode == STARTED_CODE) {
+ data.writeInt(mStartCount);
+ mStartCount++;
+ }
+ mReportObject.transact(
+ bindCode, data, null, 0);
+ data.recycle();
+ } catch (RemoteException e) {
+ // fail
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/MockActivity.java b/tests/app/app/src/android/app/stubs/MockActivity.java
new file mode 100644
index 0000000..625263a
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/MockActivity.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+
+public class MockActivity extends Activity {
+
+}
diff --git a/tests/app/app/src/android/app/stubs/MockAlarmReceiver.java b/tests/app/app/src/android/app/stubs/MockAlarmReceiver.java
new file mode 100644
index 0000000..57374ef
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/MockAlarmReceiver.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+
+/**
+ * this class receive alarm from AlarmManagerTest
+ */
+public class MockAlarmReceiver extends BroadcastReceiver {
+ private final Object mSync = new Object();
+ public final String mTargetAction;
+
+ public volatile boolean alarmed = false;
+ public volatile long elapsedTime;
+ public volatile long rtcTime;
+
+ public MockAlarmReceiver(String targetAction) {
+ mTargetAction = targetAction;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(mTargetAction)) {
+ synchronized (mSync) {
+ alarmed = true;
+ elapsedTime = SystemClock.elapsedRealtime();
+ rtcTime = System.currentTimeMillis();
+ }
+ }
+ }
+
+ public void setAlarmedFalse() {
+ synchronized (mSync) {
+ alarmed = false;
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/MockApplication.java b/tests/app/app/src/android/app/stubs/MockApplication.java
new file mode 100644
index 0000000..4de2a95
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/MockApplication.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Application;
+import android.content.res.Configuration;
+
+
+public class MockApplication extends Application {
+
+ public boolean isOnCreateCalled;
+ public boolean isConstructorCalled;
+ public boolean isOnConfigurationChangedCalled;
+ public boolean isOnLowMemoryCalled;
+
+ public MockApplication() {
+ super();
+ isConstructorCalled = true;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ isOnCreateCalled = true;
+ }
+
+ @Override
+ public void onTerminate() {
+ super.onTerminate();
+ // The documentation states that one cannot rely on this method being called. No need to
+ // test it here.
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ isOnConfigurationChangedCalled = true;
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ isOnLowMemoryCalled = true;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/MockApplicationActivity.java b/tests/app/app/src/android/app/stubs/MockApplicationActivity.java
new file mode 100644
index 0000000..6df70d7
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/MockApplicationActivity.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class MockApplicationActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ TextView textView = new TextView(this);
+ textView.setText("Test");
+ setContentView(textView);
+ }
+
+}
diff --git a/tests/app/app/src/android/app/stubs/MockReceiver.java b/tests/app/app/src/android/app/stubs/MockReceiver.java
new file mode 100644
index 0000000..7704340
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/MockReceiver.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class MockReceiver extends BroadcastReceiver {
+
+ // PendingIntent may return same instance or new instance, so static variable is needed.
+ public static int sResultCode = 0;
+ public static final String MOCKACTION = "android.app.PendingIntentTest.TEST_RECEIVER";
+ public static String sAction;
+
+ /**
+ * set the result as true when received alarm
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ sAction = intent.getAction();
+ if (sAction.equals(MOCKACTION)) {
+ sResultCode = getResultCode();
+ }
+ }
+}
+
diff --git a/tests/app/app/src/android/app/stubs/MockService.java b/tests/app/app/src/android/app/stubs/MockService.java
new file mode 100644
index 0000000..7a8c001
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/MockService.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+
+public class MockService extends Service {
+ public static boolean result = false;
+ private final IBinder mBinder = new MockBinder();
+
+ public class MockBinder extends Binder {
+ MockService getService() {
+ return MockService.this;
+ }
+ }
+
+ /**
+ * set the result as true when service bind
+ */
+ @Override
+ public IBinder onBind(Intent intent) {
+ result = true;
+ return mBinder;
+ }
+
+ /**
+ * set the result as true when service start
+ */
+ @Override
+ public void onStart(Intent intent, int startId) {
+ super.onStart(intent, startId);
+ result = true;
+ }
+}
+
diff --git a/tests/app/app/src/android/app/stubs/MockTabActivity.java b/tests/app/app/src/android/app/stubs/MockTabActivity.java
new file mode 100644
index 0000000..247cfe0
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/MockTabActivity.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.app.TabActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.TabHost;
+
+public class MockTabActivity extends TabActivity {
+
+ private static final String TAB1 = "tab1";
+ private static final String TAB2 = "tab2";
+ private static final String TAB3 = "tab3";
+
+ public boolean isOnChildTitleChangedCalled;
+ public boolean isOnPostCreateCalled;
+ public boolean isOnSaveInstanceStateCalled;
+ public boolean isOnContentChangedCalled;
+ public static boolean isOnRestoreInstanceStateCalled;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final TabHost tabHost = getTabHost();
+
+ tabHost.addTab(tabHost.newTabSpec(TAB1).setIndicator(TAB1)
+ .setContent(new Intent(this, ChildTabActivity.class)));
+
+ tabHost.addTab(tabHost.newTabSpec(TAB2).setIndicator(TAB2)
+ .setContent(new Intent(this, MockActivity.class)));
+
+ tabHost.addTab(tabHost.newTabSpec(TAB3).setIndicator(TAB3).setContent(
+ new Intent(this, AppStubActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)));
+
+ }
+
+ @Override
+ protected void onChildTitleChanged(Activity childActivity, CharSequence title) {
+ super.onChildTitleChanged(childActivity, title);
+ isOnChildTitleChangedCalled = true;
+ }
+
+ @Override
+ protected void onPostCreate(Bundle icicle) {
+ super.onPostCreate(icicle);
+ isOnPostCreateCalled = true;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle state) {
+ super.onRestoreInstanceState(state);
+ isOnRestoreInstanceStateCalled = true;
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ isOnSaveInstanceStateCalled = true;
+ }
+
+ @Override
+ public void onContentChanged() {
+ super.onContentChanged();
+ isOnContentChangedCalled = true;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/OrientationTestUtils.java b/tests/app/app/src/android/app/stubs/OrientationTestUtils.java
new file mode 100644
index 0000000..4ff3fcb
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/OrientationTestUtils.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 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.app.Instrumentation;
+import android.content.pm.ActivityInfo;
+
+public class OrientationTestUtils {
+
+ /**
+ * Change the activity's orientation to something different and then switch back. This is used
+ * to trigger {@link Activity#onConfigurationChanged(android.content.res.Configuration)}.
+ *
+ * @param activity whose orientation will be changed and restored
+ */
+ public static void toggleOrientation(Activity activity) {
+ toggleOrientationSync(activity, null);
+ }
+
+ /**
+ * Same as {@link #toggleOrientation(Activity)} except {@link Instrumentation#waitForIdleSync()}
+ * is called after each orientation change.
+ *
+ * @param activity whose orientation will be changed and restored
+ * @param instrumentation use for idle syncing
+ */
+ public static void toggleOrientationSync(final Activity activity,
+ final Instrumentation instrumentation) {
+ final int originalOrientation = activity.getResources().getConfiguration().orientation;
+ final int newOrientation = originalOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+ : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+ changeOrientation(activity, instrumentation, newOrientation);
+ changeOrientation(activity, instrumentation, originalOrientation);
+ }
+
+ private static void changeOrientation(final Activity activity,
+ Instrumentation instrumentation, final int orientation) {
+ activity.setRequestedOrientation(orientation);
+ if (instrumentation != null) {
+ instrumentation.waitForIdleSync();
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/PendingIntentStubActivity.java b/tests/app/app/src/android/app/stubs/PendingIntentStubActivity.java
new file mode 100644
index 0000000..00b59d1
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/PendingIntentStubActivity.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+import android.os.Bundle;
+
+public class PendingIntentStubActivity extends Activity {
+
+ public static final int INVALIDATE = -1;
+ public static final int ON_CREATE = 0;
+ public static int status = INVALIDATE;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ status = ON_CREATE;
+ }
+
+}
diff --git a/tests/app/app/src/android/app/stubs/PipActivity.java b/tests/app/app/src/android/app/stubs/PipActivity.java
new file mode 100644
index 0000000..533f054
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/PipActivity.java
@@ -0,0 +1,23 @@
+/*
+ * 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
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+
+public class PipActivity extends Activity {
+
+}
diff --git a/tests/app/app/src/android/app/stubs/PipNotResizeableActivity.java b/tests/app/app/src/android/app/stubs/PipNotResizeableActivity.java
new file mode 100644
index 0000000..7ed1acc
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/PipNotResizeableActivity.java
@@ -0,0 +1,23 @@
+/*
+ * 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
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+
+public class PipNotResizeableActivity extends Activity {
+
+}
diff --git a/tests/app/app/src/android/app/stubs/PipNotSupportedActivity.java b/tests/app/app/src/android/app/stubs/PipNotSupportedActivity.java
new file mode 100644
index 0000000..e6656a0
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/PipNotSupportedActivity.java
@@ -0,0 +1,23 @@
+/*
+ * 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
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+
+public class PipNotSupportedActivity extends Activity {
+
+}
diff --git a/tests/app/app/src/android/app/stubs/SearchManagerStubActivity.java b/tests/app/app/src/android/app/stubs/SearchManagerStubActivity.java
new file mode 100644
index 0000000..d6eb968
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/SearchManagerStubActivity.java
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.app.SearchManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.cts.util.CTSResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+public class SearchManagerStubActivity extends Activity {
+
+ private static final String TAG = "SearchManagerStubActivity";
+
+ public static final String TEST_STOP_SEARCH = "stopSearch";
+ public static final String TEST_ON_DISMISSLISTENER = "setOnDismissListener";
+ public static final String TEST_ON_CANCELLISTENER = "setOnCancelListener";
+
+ private SearchManager mSearchManager;
+ private ComponentName mComponentName;
+
+ private static CTSResult sCTSResult;
+ private boolean mDismissCalled;
+ private boolean mCancelCalled;
+
+ public static void setCTSResult(CTSResult result) {
+ sCTSResult = result;
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mSearchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+ mComponentName = getComponentName();
+ String action = getIntent().getAction();
+ if (action.equals(TEST_STOP_SEARCH)) {
+ testStopSearch();
+ } else if (action.equals(TEST_ON_DISMISSLISTENER)) {
+ testOnDismissListener();
+ } else if (action.equals(TEST_ON_CANCELLISTENER)) {
+ testOnCancelListener();
+ }
+ }
+
+ private void testOnCancelListener() {
+ mCancelCalled = false;
+ mSearchManager.setOnCancelListener(new SearchManager.OnCancelListener() {
+ @Override
+ public void onCancel() {
+ mCancelCalled = true;
+ }
+ });
+
+ new TestStepHandler() {
+ @Override
+ public boolean doStep(int step) throws FailException {
+ switch (step) {
+ case 1:
+ startSearch("test", false, mComponentName, null, false);
+ return false;
+ case 2:
+ assertFalse("cancel called", mCancelCalled);
+ stopSearch();
+ return false;
+ case 3:
+ assertTrue("cancel not called", mCancelCalled);
+ pass();
+ return true;
+ default:
+ throw new IllegalArgumentException("Bad step " + step);
+ }
+ }
+ }.start();
+ }
+
+ private void testOnDismissListener() {
+ mDismissCalled = false;
+
+ mSearchManager.setOnDismissListener(new SearchManager.OnDismissListener() {
+ public void onDismiss() {
+ mDismissCalled = true;
+ }
+ });
+
+ new TestStepHandler() {
+ @Override
+ public boolean doStep(int step) throws FailException {
+ switch (step) {
+ case 1:
+ startSearch("test", false, mComponentName, null, false);
+ return false;
+ case 2:
+ if (mDismissCalled) {
+ throw new FailException("dismiss called");
+ } else {
+ stopSearch();
+ }
+ return false;
+ case 3:
+ if (mDismissCalled) {
+ pass();
+ } else {
+ throw new FailException("dismiss not called");
+ }
+ return true;
+ default:
+ throw new IllegalArgumentException("Bad step " + step);
+ }
+ }
+ }.start();
+ }
+
+ private void testStopSearch() {
+ new TestStepHandler() {
+ @Override
+ public boolean doStep(int step) throws FailException {
+ switch (step) {
+ case 1:
+ startSearch("test", false, mComponentName, null, false);
+ return false;
+ case 2:
+ assertVisible();
+ stopSearch();
+ return false;
+ case 3:
+ assertInVisible();
+ pass();
+ return true;
+ default:
+ throw new IllegalArgumentException("Bad step " + step);
+ }
+ }
+ }.start();
+ }
+
+ private void fail(Exception ex) {
+ Log.e(TAG, "test failed", ex);
+ sCTSResult.setResult(CTSResult.RESULT_FAIL);
+ finish();
+ }
+
+ private void pass() {
+ sCTSResult.setResult(CTSResult.RESULT_OK);
+ finish();
+ }
+
+ private void assertInVisible() throws FailException {
+ if (isVisible()) {
+ throw new FailException();
+ }
+ }
+
+ private void assertVisible() throws FailException {
+ if (!isVisible()) {
+ throw new FailException();
+ }
+ }
+
+ private void assertFalse(String message, boolean value) throws FailException {
+ assertTrue(message, !value);
+ }
+
+ private void assertTrue(String message, boolean value) throws FailException {
+ if (!value) {
+ throw new FailException(message);
+ }
+ }
+
+ private void startSearch(String initialQuery, boolean selectInitialQuery,
+ ComponentName launchActivity, Bundle appSearchData, boolean globalSearch) {
+ mSearchManager.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
+ globalSearch);
+ }
+
+ private void stopSearch() {
+ mSearchManager.stopSearch();
+ }
+
+ private boolean isVisible() {
+ return mSearchManager.isVisible();
+ }
+
+ private abstract class TestStepHandler extends Handler {
+
+ public void start() {
+ sendEmptyMessage(1);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ if (!doStep(msg.what)) {
+ sendEmptyMessage(msg.what + 1);
+ }
+ } catch (FailException ex) {
+ fail(ex);
+ }
+ }
+
+ /**
+ * Performs one step of the test.
+ *
+ * @param step The 1-based number of the step to perform.
+ * @return {@code true} if this was the last step.
+ * @throws FailException If the test failed.
+ */
+ protected abstract boolean doStep(int step) throws FailException;
+ }
+
+ private static class FailException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public FailException() {
+ super();
+ }
+
+ public FailException(String detailMessage) {
+ super(detailMessage);
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/StubRemoteService.java b/tests/app/app/src/android/app/stubs/StubRemoteService.java
new file mode 100644
index 0000000..4fde60b
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/StubRemoteService.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Process;
+
+public class StubRemoteService extends Service{
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ android.util.Log.d("Process test stub", "StubRemoteServiceProcessPid:" + Process.myPid());
+ }
+
+ private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() {
+ public int getPid() {
+ return Process.myPid();
+ }
+
+ public long getElapsedCpuTime() {
+ return Process.getElapsedCpuTime();
+ }
+
+ public String getTimeZoneID() {
+ return java.util.TimeZone.getDefault().getID();
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (ISecondary.class.getName().equals(intent.getAction())) {
+ return mSecondaryBinder;
+ }
+ return null;
+ }
+
+}
diff --git a/tests/app/app/src/android/app/stubs/TestDialog.java b/tests/app/app/src/android/app/stubs/TestDialog.java
new file mode 100644
index 0000000..e404e65
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/TestDialog.java
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ */
+package android.app.stubs;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.Window;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.WindowManager.LayoutParams;
+
+public class TestDialog extends Dialog {
+ private static final int OPTIONS_MENU_ITEM_0 = Menu.FIRST;
+ private static final int OPTIONS_MENU_ITEM_1 = Menu.FIRST + 1;
+ private static final int OPTIONS_MENU_ITEM_2 = Menu.FIRST + 2;
+ private static final int OPTIONS_MENU_ITEM_3 = Menu.FIRST + 3;
+ private static final int OPTIONS_MENU_ITEM_4 = Menu.FIRST + 4;
+ private static final int OPTIONS_MENU_ITEM_5 = Menu.FIRST + 5;
+ private static final int OPTIONS_MENU_ITEM_6 = Menu.FIRST + 6;
+ private static final int CONTEXT_MENU_ITEM_0 = Menu.FIRST + 7;
+ private static final int CONTEXT_MENU_ITEM_1 = Menu.FIRST + 8;
+ private static final int CONTEXT_MENU_ITEM_2 = Menu.FIRST + 9;
+ public boolean isOnStartCalled;
+ public boolean isOnStopCalled;
+ public boolean isOnCreateCalled;
+ public boolean isRequestWindowFeature;
+ public boolean isOnContentChangedCalled;
+ public boolean isOnWindowFocusChangedCalled;
+ public boolean isOnTouchEventCalled;
+ public boolean isOnTrackballEventCalled;
+ public boolean isOnKeyDownCalled;
+ public boolean isOnKeyUpCalled;
+ public boolean isOnKeyMultipleCalled;
+ public boolean isOnSaveInstanceStateCalled;
+ public static boolean isOnRestoreInstanceStateCalled;
+ public boolean isOnWindowAttributesChangedCalled;
+ public boolean isOnCreatePanelMenuCalled;
+ public boolean isOnCreatePanelViewCalled;
+ public boolean isOnPreparePanelCalled;
+ public boolean isOnMenuOpenedCalled;
+ public boolean isOnMenuItemSelectedCalled;
+ public boolean isOnPanelClosedCalled;
+ public boolean isOnCreateOptionsMenuCalled;
+ public boolean isOnPrepareOptionsMenuCalled;
+ public boolean isOnOptionsItemSelectedCalled;
+ public boolean isOnOptionsMenuClosedCalled;
+ public boolean isOnContextItemSelectedCalled;
+ public boolean isOnContextMenuClosedCalled;
+ public boolean isOnCreateContextMenuCalled;
+ public boolean isOnSearchRequestedCalled;
+ public boolean onKeyDownReturn;
+ public boolean onKeyMultipleReturn;
+ public boolean dispatchTouchEventResult;
+ public boolean dispatchKeyEventResult;
+ public int keyDownCode = -1;
+ public Window window;
+ public Bundle saveInstanceState;
+ public Bundle savedInstanceState;
+ public KeyEvent keyEvent;
+ public MotionEvent touchEvent;
+ public MotionEvent trackballEvent;
+ public MotionEvent onTrackballEvent;
+ public MotionEvent onTouchEvent;
+ public KeyEvent keyMultipleEvent;
+
+ public TestDialog(Context context) {
+ super(context);
+ }
+
+ public TestDialog(Context context, int theme) {
+ super(context, theme);
+ }
+
+ public TestDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
+ super(context, cancelable, cancelListener);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ isOnStartCalled = true;
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ isOnStopCalled = true;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ isRequestWindowFeature = requestWindowFeature(Window.FEATURE_LEFT_ICON);
+ super.onCreate(savedInstanceState);
+ isOnCreateCalled = true;
+ }
+
+ @Override
+ public void onContentChanged() {
+ super.onContentChanged();
+
+ isOnContentChangedCalled = true;
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+
+ isOnWindowFocusChangedCalled = true;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ isOnTouchEventCalled = true;
+ onTouchEvent = event;
+ return super.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ isOnTrackballEventCalled = true;
+ onTrackballEvent = event;
+ return super.onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ isOnKeyDownCalled = true;
+ keyDownCode = keyCode;
+ onKeyDownReturn = super.onKeyDown(keyCode, event);
+
+ return onKeyDownReturn;
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ isOnKeyUpCalled = true;
+
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
+ isOnKeyMultipleCalled = true;
+ onKeyMultipleReturn = super.onKeyMultiple(keyCode, repeatCount, event);
+ keyMultipleEvent = event;
+ return onKeyMultipleReturn;
+ }
+
+ @Override
+ public Bundle onSaveInstanceState() {
+ isOnSaveInstanceStateCalled = true;
+ saveInstanceState = super.onSaveInstanceState();
+ return saveInstanceState;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle savedInstanceState) {
+ isOnRestoreInstanceStateCalled = true;
+ this.savedInstanceState = savedInstanceState;
+
+ super.onRestoreInstanceState(savedInstanceState);
+ }
+
+ @Override
+ public void onWindowAttributesChanged(LayoutParams params) {
+ isOnWindowAttributesChangedCalled = true;
+ super.onWindowAttributesChanged(params);
+ }
+
+ @Override
+ public boolean onCreatePanelMenu(int featureId, Menu menu) {
+ isOnCreatePanelMenuCalled = true;
+ return super.onCreatePanelMenu(featureId, menu);
+ }
+
+ @Override
+ public View onCreatePanelView(int featureId) {
+ isOnCreatePanelViewCalled = true;
+ return super.onCreatePanelView(featureId);
+ }
+
+ @Override
+ public boolean onPreparePanel(int featureId, View view, Menu menu) {
+ isOnPreparePanelCalled = true;
+ return super.onPreparePanel(featureId, view, menu);
+ }
+
+ @Override
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {
+ isOnMenuItemSelectedCalled = true;
+ return super.onMenuItemSelected(featureId, item);
+ }
+
+ @Override
+ public boolean onMenuOpened(int featureId, Menu menu) {
+ isOnMenuOpenedCalled = true;
+ return super.onMenuOpened(featureId, menu);
+ }
+
+ @Override
+ public void onPanelClosed(int featureId, Menu menu) {
+ isOnPanelClosedCalled = true;
+ super.onPanelClosed(featureId, menu);
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ isOnPrepareOptionsMenuCalled = true;
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ menu.add(0, OPTIONS_MENU_ITEM_0, 0, "OptionsMenuItem0");
+ menu.add(0, OPTIONS_MENU_ITEM_1, 0, "OptionsMenuItem1");
+ menu.add(0, OPTIONS_MENU_ITEM_2, 0, "OptionsMenuItem2");
+ menu.add(0, OPTIONS_MENU_ITEM_3, 0, "OptionsMenuItem3");
+ menu.add(0, OPTIONS_MENU_ITEM_4, 0, "OptionsMenuItem4");
+ menu.add(0, OPTIONS_MENU_ITEM_5, 0, "OptionsMenuItem5");
+ menu.add(0, OPTIONS_MENU_ITEM_6, 0, "OptionsMenuItem6");
+ isOnCreateOptionsMenuCalled = true;
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ isOnOptionsItemSelectedCalled = true;
+ switch (item.getItemId()) {
+ case OPTIONS_MENU_ITEM_0:
+ case OPTIONS_MENU_ITEM_1:
+ case OPTIONS_MENU_ITEM_2:
+ case OPTIONS_MENU_ITEM_3:
+ case OPTIONS_MENU_ITEM_4:
+ case OPTIONS_MENU_ITEM_5:
+ case OPTIONS_MENU_ITEM_6:
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ public void onOptionsMenuClosed(Menu menu) {
+ isOnOptionsMenuClosedCalled = true;
+ super.onOptionsMenuClosed(menu);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ isOnContextItemSelectedCalled = true;
+ switch (item.getItemId()) {
+ case CONTEXT_MENU_ITEM_0:
+ case CONTEXT_MENU_ITEM_1:
+ case CONTEXT_MENU_ITEM_2:
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
+
+ @Override
+ public void onContextMenuClosed(Menu menu) {
+ isOnContextMenuClosedCalled = true;
+ super.onContextMenuClosed(menu);
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ menu.add(0, CONTEXT_MENU_ITEM_0, 0, "ContextMenuItem0");
+ menu.add(0, CONTEXT_MENU_ITEM_1, 0, "ContextMenuItem1");
+ menu.add(0, CONTEXT_MENU_ITEM_2, 0, "ContextMenuItem2");
+ isOnCreateContextMenuCalled = true;
+ }
+
+ @Override
+ public boolean onSearchRequested() {
+ isOnSearchRequestedCalled = true;
+ return super.onSearchRequested();
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ keyEvent = event;
+ dispatchKeyEventResult = super.dispatchKeyEvent(event);
+ return dispatchKeyEventResult;
+ }
+
+ @Override
+ public boolean dispatchTrackballEvent(MotionEvent ev) {
+ trackballEvent = ev;
+ return super.dispatchTrackballEvent(ev);
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ touchEvent = ev;
+ dispatchTouchEventResult = super.dispatchTouchEvent(ev);
+ return dispatchTouchEventResult;
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/TestedActivity.java b/tests/app/app/src/android/app/stubs/TestedActivity.java
new file mode 100644
index 0000000..fb90055
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/TestedActivity.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.MessageQueue;
+import android.util.Log;
+
+public class TestedActivity extends Activity {
+ private static final String TAG = "TestedActivity" ;
+ public TestedActivity() {
+ }
+
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ }
+
+ protected void onRestoreInstanceState(Bundle state) {
+ super.onRestoreInstanceState(state);
+ }
+
+ protected void onResume() {
+ super.onResume();
+ Looper.myLooper();
+ Looper.myQueue().addIdleHandler(new Idler());
+ }
+
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ }
+
+ protected void onStop() {
+ super.onStop();
+ }
+
+ private class Idler implements MessageQueue.IdleHandler {
+ public final boolean queueIdle() {
+ Log.i(TAG, "idle");
+ setResult(RESULT_OK);
+ finish();
+ return false;
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/TestedScreen.java b/tests/app/app/src/android/app/stubs/TestedScreen.java
new file mode 100644
index 0000000..1b707e7
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/TestedScreen.java
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.MessageQueue;
+import android.os.SystemClock;
+import android.util.Log;
+
+public class TestedScreen extends Activity {
+ public static final String WAIT_BEFORE_FINISH = "TestedScreen.WAIT_BEFORE_FINISH";
+ public static final String DELIVER_RESULT = "TestedScreen.DELIVER_RESULT";
+ public static final String CLEAR_TASK = "TestedScreen.CLEAR_TASK";
+ private static final String TAG = "TestedScreen" ;
+ public TestedScreen() {
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ if (LaunchpadActivity.FORWARD_RESULT.equals(getIntent().getAction())) {
+ final Intent intent = new Intent(getIntent());
+ intent.setAction(DELIVER_RESULT);
+ intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ startActivity(intent);
+ finish();
+ } else if (DELIVER_RESULT.equals(getIntent().getAction())) {
+ setResult(RESULT_OK, new Intent().setAction(LaunchpadActivity.RETURNED_RESULT));
+ finish();
+ } else if (CLEAR_TASK.equals(getIntent().getAction())) {
+ if (!getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) {
+ launchClearTask();
+ }
+ }
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle state) {
+ super.onRestoreInstanceState(state);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (CLEAR_TASK.equals(getIntent().getAction())) {
+ if (getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) {
+ Looper.myLooper();
+ Looper.myQueue().addIdleHandler(new Idler());
+ }
+ } else {
+ Looper.myLooper();
+ Looper.myQueue().addIdleHandler(new Idler());
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ }
+
+ private void launchClearTask() {
+ final Intent intent = new Intent(getIntent()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ .setClass(this, ClearTop.class);
+ startActivity(intent);
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (CLEAR_TASK.equals(getIntent().getAction())) {
+ launchClearTask();
+ } else {
+ setResult(RESULT_OK);
+ finish();
+ }
+ }
+ };
+
+ private class Idler implements MessageQueue.IdleHandler {
+ public final boolean queueIdle() {
+ Log.i(TAG, "idle");
+ if (WAIT_BEFORE_FINISH.equals(getIntent().getAction())) {
+ final Message m = Message.obtain();
+ mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
+ } else if (CLEAR_TASK.equals(getIntent().getAction())) {
+ final Message m = Message.obtain();
+ mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
+ } else {
+ setResult(RESULT_OK);
+ finish();
+ }
+ return false;
+ }
+ }
+}
diff --git a/tests/app/res/values/strings.xml b/tests/app/res/values/strings.xml
deleted file mode 100644
index c167278..0000000
--- a/tests/app/res/values/strings.xml
+++ /dev/null
@@ -1,179 +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.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="permlab_testGranted">Test Granted</string>
- <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
- where we have the permission.</string>
- <string name="permlab_testDynamic">Test Dynamic</string>
- <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
- dynamic permissions.</string>
- <string name="permlab_testDenied">Test Denied</string>
- <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
- where we do not have the permission.</string>
- <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
- else press failed button.</string>
- <string name="text_view_hello">Hello! Text view!</string>
- <string name="text_view_hello_two_lines">Hello! \nText view!</string>
- <string name="text_view_simple_hint">This is a hint.</string>
- <string name="text_view_hint">This is a string for testing hint of textview.</string>
- <string name="activity_forwarding">App/Forwarding</string>
- <string name="forwarding">$$$</string>
- <string name="go">Go</string>
- <string name="back">Back</string>
- <string name="forward_target">
- Press back button and notice we don\'t see the previous activity.
- </string>
- <string name="edit_text">testing</string>
- <string name="text">DialogTest</string>
- <string name="text_country">Country</string>
- <string name="text_name">Name</string>
- <string name="hello_world">Hello, World!</string>
- <string name="hello_android">Hello, Android!</string>
- <string name="alert_dialog_username">Name:</string>
- <string name="alert_dialog_password">Password:</string>
- <string name="alert_dialog_positive">Positive</string>
- <string name="alert_dialog_negative">Negative</string>
- <string name="alert_dialog_neutral">Neutral</string>
- <string name="notify">Notify </string>
- <string name="tabs_1">testing</string>
- <string name="table_layout_first">first</string>
- <string name="table_layout_second">second</string>
- <string name="table_layout_third">third</string>
- <string name="table_layout_long">Very long to make the string out of the screen</string>
- <string name="chronometer_text">Test Chronometer</string>
- <string name="am">AM</string>
- <string name="pm">PM</string>
- <string name="viewgroup_test">ViewGroup test</string>
- <string name="viewanimator_test">ViewAnimator test</string>
- <string name="id_ok">OK</string>
- <string name="id_cancel">Cancel</string>
- <string name="context_test_string1">This is %s string.</string>
- <string name="context_test_string2">This is test string.</string>
- <string name="animationutils_test_instructions">Choose different animations</string>
- <string name="animationutils_test_alpha">Alpha animation</string>
- <string name="animationutils_test_scale">Scale animation</string>
- <string name="animationutils_test_rotate">Rotate animation</string>
- <string name="animationutils_test_translate">Translate animation</string>
- <string name="animationutils_test_set">Animation set</string>
- <string name="animationutils_test_layout">Layout animation</string>
- <string name="animationutils_test_gridlayout">Grid layout animation</string>
- <string name="twolinelistitem_test_text1">text1</string>
- <string name="twolinelistitem_test_text2">text2</string>
- <string name="metadata_text">metadata text</string>
- <string name="horizontal_text_1">horizontal 1</string>
- <string name="horizontal_text_2">horizontal 2</string>
- <string name="horizontal_text_3">horizontal 3</string>
- <string name="vertical_text_1">vertical 1</string>
- <string name="vertical_text_2">vertical 2</string>
- <string name="vertical_text_3">vertical 3</string>
- <string name="reference">here</string>
- <string name="coerceIntegerToString">100</string>
- <string name="coerceBooleanToString">true</string>
- <string name="coerceColorToString">#fff</string>
- <string name="coerceFloatToString">100.0</string>
- <string name="coerceDimensionToString">100px</string>
- <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
- <string name="formattedStringNone">Format[]</string>
- <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
- <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
- <string name="checkboxpref_key">checkboxpref_key</string>
- <string name="checkboxpref_title">title of preference</string>
- <string name="checkboxpref_summary">summary of preference</string>
- <string name="checkboxpref_summary_on">summary on of preference</string>
- <string name="checkboxpref_summary_off">summary off of preference</string>
- <string name="checkboxpref_depend">checkboxpref_depend</string>
- <string name="checkboxpref_depend_title"> depend title of preference</string>
- <string name="checkboxpref_depend_summary"> depend summary of preference</string>
- <string name="edittextpref_key">edittextpref_key</string>
- <string name="edittextpref_default_value">default value of preference</string>
- <string name="edittextpref_title">title of edit text preference</string>
- <string name="edittextpref_summary">summary of edit text preference</string>
- <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
- <string name="edittextpref_text">text of edit text preference</string>
- <string name="listpref_key">listpref_key</string>
- <string name="listpref_title">title of list preference</string>
- <string name="listpref_summary">summary of list preference</string>
- <string name="listpref_dialogtitle">dialog title of list preference</string>
- <string name="easy">Easy</string>
- <string name="medium">Medium</string>
- <string name="hard">Hard</string>
- <string name="footer_view">Footer view</string>
- <string name="header_view">Header view</string>
- <string name="dialogpref_title">title of dialog preference </string>
- <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
- <string name="dialogpref_key">dialogpref_key</string>
- <string name="dialogpref_default_value">default value of dialog preference</string>
- <string name="dialogpref_summary">summary of dialog preference</string>
- <string name="dialogpref_message">message of dialog preference</string>
- <string name="dialogpref_sure">Sure</string>
- <string name="dialogpref_cancel">Cancel</string>
- <string name="pref_key">pref_key</string>
- <string name="pref_title">title of preference</string>
- <string name="pref_summary">summary of preference</string>
- <string name="pref_depend_key">pref_depend_key</string>
- <string name="pref_depend_title"> depend title of preference</string>
- <string name="pref_depend_summary"> depend summary of preference</string>
- <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
- <string name="def_pref_key">def_pref_key</string>
- <string name="def_pref_title">default preference</string>
- <string name="def_pref_summary">This is default preference of cts</string>
- <string name="relative_view1">view 1</string>
- <string name="relative_view2">view 2</string>
- <string name="relative_view3">view 3</string>
- <string name="relative_view4">view 4</string>
- <string name="relative_view5">view 5</string>
- <string name="relative_view6">view 6</string>
- <string name="relative_view7">view 7</string>
- <string name="relative_view8">view 8</string>
- <string name="relative_view9">view 9</string>
- <string name="relative_view10">view 10</string>
- <string name="relative_view11">view 11</string>
- <string name="relative_view12">view 12</string>
- <string name="relative_view13">view 13</string>
- <string name="country">Country:</string>
- <string name="symbol">Symbol:</string>
- <string name="country_warning">No such country registered</string>
- <string name="version_cur">base</string>
- <string name="version_old">base</string>
- <string name="version_v3">base</string>
- <string name="authenticator_label">Android CTS</string>
- <string name="search_label">Android CTS</string>
- <string name="tag1">tag 1</string>
- <string name="tag2">tag 2</string>
-
- <string name="button">Button</string>
- <string name="holo_test">Holo Test</string>
- <string name="holo_generator">Holo Generator</string>
- <string name="holo_light_test">Holo Light Test</string>
- <string name="holo_light_generator">Holo Light Generator</string>
- <string name="reference_image">Reference Image: </string>
- <string name="generated_image">Generated Image: </string>
- <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.
-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!
-I think so, so how about double this string, like copy and paste!
-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!
-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>
-</resources>
diff --git a/tests/app/res/xml/alias.xml b/tests/app/res/xml/alias.xml
deleted file mode 100644
index 321e536..0000000
--- a/tests/app/res/xml/alias.xml
+++ /dev/null
@@ -1,27 +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.
- */
--->
-
-<alias xmlns:android="http://schemas.android.com/apk/res/android">
- <intent android:action="android.intent.action.MAIN"
- android:targetPackage="com.android.cts.app.stub"
- android:targetClass="android.app.cts.ChildActivity"
- android:data="http://www.google.com/">
- </intent>
-</alias>
-
diff --git a/tests/tests/app/src/android/app/backup/cts/BackupAgentHelperTest.java b/tests/app/src/android/app/backup/cts/BackupAgentHelperTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/backup/cts/BackupAgentHelperTest.java
rename to tests/app/src/android/app/backup/cts/BackupAgentHelperTest.java
diff --git a/tests/tests/app/src/android/app/backup/cts/BackupAgentTest.java b/tests/app/src/android/app/backup/cts/BackupAgentTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/backup/cts/BackupAgentTest.java
rename to tests/app/src/android/app/backup/cts/BackupAgentTest.java
diff --git a/tests/app/src/android/app/backup/cts/BackupManagerTest.java b/tests/app/src/android/app/backup/cts/BackupManagerTest.java
new file mode 100644
index 0000000..510e8d1
--- /dev/null
+++ b/tests/app/src/android/app/backup/cts/BackupManagerTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 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.backup.cts;
+
+import android.app.backup.BackupManager;
+import android.app.backup.RestoreObserver;
+import android.test.AndroidTestCase;
+
+public class BackupManagerTest extends AndroidTestCase {
+
+ public void testBackupManager() throws Exception {
+ // Check that these don't crash as if they were called in an app...
+ BackupManager backupManager = new BackupManager(mContext);
+ backupManager.dataChanged();
+ BackupManager.dataChanged("android.app.stubs");
+
+ // Backup isn't expected to work in this test but check for obvious bugs...
+ int result = backupManager.requestRestore(new RestoreObserver() {});
+ assertTrue(result != 0);
+ }
+}
diff --git a/tests/tests/app/src/android/app/backup/cts/FileBackupHelperTest.java b/tests/app/src/android/app/backup/cts/FileBackupHelperTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/backup/cts/FileBackupHelperTest.java
rename to tests/app/src/android/app/backup/cts/FileBackupHelperTest.java
diff --git a/tests/tests/app/src/android/app/backup/cts/SharedPreferencesBackupHelperTest.java b/tests/app/src/android/app/backup/cts/SharedPreferencesBackupHelperTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/backup/cts/SharedPreferencesBackupHelperTest.java
rename to tests/app/src/android/app/backup/cts/SharedPreferencesBackupHelperTest.java
diff --git a/tests/app/src/android/app/cts/ActionBarActivity.java b/tests/app/src/android/app/cts/ActionBarActivity.java
deleted file mode 100644
index dc65cb2..0000000
--- a/tests/app/src/android/app/cts/ActionBarActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2012 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.ActionBar;
-import android.app.Activity;
-import android.os.Bundle;
-
-public class ActionBarActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- ActionBar bar = getActionBar();
- if (bar != null) {
- bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
- }
- }
-}
diff --git a/tests/app/src/android/app/cts/ActionBarTest.java b/tests/app/src/android/app/cts/ActionBarTest.java
new file mode 100644
index 0000000..3404b57
--- /dev/null
+++ b/tests/app/src/android/app/cts/ActionBarTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 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.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.FragmentTransaction;
+import android.app.stubs.ActionBarActivity;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+
+public class ActionBarTest extends ActivityInstrumentationTestCase2<ActionBarActivity> {
+
+ private ActionBarActivity mActivity;
+ private ActionBar mBar;
+
+ public ActionBarTest() {
+ super(ActionBarActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ mBar = mActivity.getActionBar();
+ }
+
+ @UiThreadTest
+ public void testAddTab() {
+ if (mBar == null) {
+ return;
+ }
+ assertEquals(0, mBar.getTabCount());
+
+ Tab t1 = createTab("Tab 1");
+ mBar.addTab(t1);
+ assertEquals(1, mBar.getTabCount());
+ assertEquals(t1, mBar.getSelectedTab());
+ assertEquals(t1, mBar.getTabAt(0));
+
+ Tab t2 = createTab("Tab 2");
+ mBar.addTab(t2);
+ assertEquals(2, mBar.getTabCount());
+ assertEquals(t1, mBar.getSelectedTab());
+ assertEquals(t2, mBar.getTabAt(1));
+
+ Tab t3 = createTab("Tab 3");
+ mBar.addTab(t3, true);
+ assertEquals(3, mBar.getTabCount());
+ assertEquals(t3, mBar.getSelectedTab());
+ assertEquals(t3, mBar.getTabAt(2));
+
+ Tab t4 = createTab("Tab 2.5");
+ mBar.addTab(t4, 2);
+ assertEquals(4, mBar.getTabCount());
+ assertEquals(t4, mBar.getTabAt(2));
+ assertEquals(t3, mBar.getTabAt(3));
+
+ Tab t5 = createTab("Tab 0.5");
+ mBar.addTab(t5, 0, true);
+ assertEquals(5, mBar.getTabCount());
+ assertEquals(t5, mBar.getSelectedTab());
+ assertEquals(t5, mBar.getTabAt(0));
+ assertEquals(t1, mBar.getTabAt(1));
+ assertEquals(t2, mBar.getTabAt(2));
+ assertEquals(t4, mBar.getTabAt(3));
+ assertEquals(t3, mBar.getTabAt(4));
+ }
+
+ private Tab createTab(String name) {
+ return mBar.newTab().setText("Tab 1").setTabListener(new TestTabListener());
+ }
+
+ static class TestTabListener implements TabListener {
+ @Override
+ public void onTabSelected(Tab tab, FragmentTransaction ft) {
+ }
+
+ @Override
+ public void onTabUnselected(Tab tab, FragmentTransaction ft) {
+ }
+
+ @Override
+ public void onTabReselected(Tab tab, FragmentTransaction ft) {
+ }
+ }
+}
diff --git a/tests/app/src/android/app/cts/ActivityGroupTest.java b/tests/app/src/android/app/cts/ActivityGroupTest.java
new file mode 100644
index 0000000..8b76cb6
--- /dev/null
+++ b/tests/app/src/android/app/cts/ActivityGroupTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.stubs.ActivityTestsBase;
+import android.app.stubs.LaunchpadActivity;
+import android.app.stubs.LaunchpadTabActivity;
+import android.content.ComponentName;
+import android.content.Intent;
+
+public class ActivityGroupTest extends ActivityTestsBase {
+ private Intent mTabIntent;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTabIntent = new Intent(mContext, LaunchpadTabActivity.class);
+ mTabIntent.putExtra("tab", new ComponentName(mContext, LaunchpadActivity.class));
+ }
+
+ public void testTabBasic() throws Exception {
+ mIntent = mTabIntent;
+ runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC);
+ }
+
+ public void testTabScreen() throws Exception {
+ mIntent = mTabIntent;
+ runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN);
+ }
+
+ public void testTabDialog() throws Exception {
+ mIntent = mTabIntent;
+ runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG);
+ }
+}
diff --git a/tests/app/src/android/app/cts/ActivityKeyboardShortcutsTest.java b/tests/app/src/android/app/cts/ActivityKeyboardShortcutsTest.java
new file mode 100644
index 0000000..3e48b1e
--- /dev/null
+++ b/tests/app/src/android/app/cts/ActivityKeyboardShortcutsTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.Activity;
+import android.app.stubs.KeyboardShortcutsActivity;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
+import android.view.Menu;
+import android.widget.PopupMenu;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests functionality in Activity related to Keyboard Shortcuts.
+ */
+public class ActivityKeyboardShortcutsTest
+ extends ActivityInstrumentationTestCase2<KeyboardShortcutsActivity> {
+
+ private Activity mActivity;
+ private Menu mMenu;
+
+ public ActivityKeyboardShortcutsTest() {
+ super(KeyboardShortcutsActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ mMenu = new PopupMenu(mActivity, null).getMenu();
+ }
+
+ public void testOnProvideKeyboardShortcuts() {
+ List<KeyboardShortcutGroup> data = new ArrayList<>();
+ mActivity.onCreateOptionsMenu(mMenu);
+ mActivity.onProvideKeyboardShortcuts(data, mMenu);
+
+ assertEquals(1, data.size());
+ assertEquals(1, data.get(0).getItems().size());
+ assertEquals(KeyboardShortcutsActivity.ITEM_1_NAME,
+ data.get(0).getItems().get(0).getLabel());
+ assertEquals(KeyboardShortcutsActivity.ITEM_1_SHORTCUT,
+ data.get(0).getItems().get(0).getBaseCharacter());
+ assertEquals(KeyEvent.META_CTRL_ON, data.get(0).getItems().get(0).getModifiers());
+ }
+}
diff --git a/tests/app/src/android/app/cts/ActivityManagerMemoryClassLaunchActivity.java b/tests/app/src/android/app/cts/ActivityManagerMemoryClassLaunchActivity.java
deleted file mode 100644
index f1f95b8..0000000
--- a/tests/app/src/android/app/cts/ActivityManagerMemoryClassLaunchActivity.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2011 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.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * {@link Activity} that just launches {@link ActivityManagerMemoryClassTestActivity} and
- * returns the result of that activity.
- */
-public class ActivityManagerMemoryClassLaunchActivity extends Activity {
-
- public static final String MEMORY_CLASS_EXTRA = "activityMemoryClass";
-
- private static final int TEST_ACTIVITY_REQUEST_CODE = 1337;
-
- private final CountDownLatch mLatch = new CountDownLatch(1);
-
- private int mChildResult = RESULT_CANCELED;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Start the activity that runs in a separate process to do the actual testing,
- // since the test itself cannot start an activity in a separate process. A separate
- // process is used to avoid including the overhead of the test instrumentation process.
-
- Intent intent = getIntent();
- int memoryClass = intent.getIntExtra(MEMORY_CLASS_EXTRA, -1);
-
- Intent testIntent = new Intent(this, ActivityManagerMemoryClassTestActivity.class);
- testIntent.putExtra(MEMORY_CLASS_EXTRA, memoryClass);
- startActivityForResult(testIntent, TEST_ACTIVITY_REQUEST_CODE);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == 1337) {
- synchronized (this) {
- mChildResult = resultCode;
- }
- } else {
- throw new IllegalStateException("Request code: " + requestCode);
- }
- }
-
- public int getResult() throws InterruptedException {
- mLatch.await(5, TimeUnit.SECONDS);
- synchronized (this) {
- return mChildResult;
- }
- }
-}
diff --git a/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
new file mode 100644
index 0000000..cb331d1
--- /dev/null
+++ b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2011 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.Activity;
+import android.app.ActivityManager;
+import android.app.stubs.ActivityManagerMemoryClassLaunchActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.WindowManager;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * {@link ActivityInstrumentationTestCase2} that tests {@link ActivityManager#getMemoryClass()}
+ * by checking that the memory class matches the proper screen density and by launching an
+ * application that attempts to allocate memory on the heap.
+ */
+public class ActivityManagerMemoryClassTest
+ extends ActivityInstrumentationTestCase2<ActivityManagerMemoryClassLaunchActivity> {
+
+ public ActivityManagerMemoryClassTest() {
+ super(ActivityManagerMemoryClassLaunchActivity.class);
+ }
+
+ public static class ExpectedMemorySizesClass {
+ private static final Map<Integer, Integer> expectedMemorySizeForWatch
+ = new HashMap<Integer, Integer>();
+ private static final Map<Integer, Integer> expectedMemorySizeForSmallNormalScreen
+ = new HashMap<Integer, Integer>();
+ private static final Map<Integer, Integer> expectedMemorySizeForLargeScreen
+ = new HashMap<Integer, Integer>();
+ private static final Map<Integer, Integer> expectedMemorySizeForXLargeScreen
+ = new HashMap<Integer, Integer>();
+
+ static {
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_LOW, 32);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_MEDIUM, 32);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_TV, 32);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_HIGH, 36);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_280, 36);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XHIGH, 48);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_360, 48);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_400, 56);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_420, 64);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XXHIGH, 88);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_560, 112);
+ expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XXXHIGH, 154);
+ }
+
+ static {
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_LOW, 32);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_MEDIUM, 32);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_TV, 48);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_HIGH, 48);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_280, 48);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XHIGH, 80);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_360, 80);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_400, 96);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_420, 112);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXHIGH, 128);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_560, 192);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 256);
+ }
+
+ static {
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_LOW, 32);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_MEDIUM, 64);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_TV, 80);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_HIGH, 80);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_280, 96);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XHIGH, 128);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_360, 160);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_400, 192);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_420, 228);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 256);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_560, 384);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 512);
+ }
+
+ static {
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_LOW, 48);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_MEDIUM, 80);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_TV, 96);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_HIGH, 96);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_280, 144);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XHIGH, 192);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_360, 240);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_400, 288);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_420, 336);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 384);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_560, 576);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 768);
+ }
+
+ public static Integer getExpectedMemorySize(
+ int screenSize,
+ int screenDensity,
+ boolean isWatch) {
+
+ if (isWatch) {
+ return expectedMemorySizeForWatch.get(screenDensity);
+ }
+
+ switch (screenSize) {
+ case Configuration.SCREENLAYOUT_SIZE_SMALL:
+ case Configuration.SCREENLAYOUT_SIZE_NORMAL:
+ return expectedMemorySizeForSmallNormalScreen.get(screenDensity);
+ case Configuration.SCREENLAYOUT_SIZE_LARGE:
+ return expectedMemorySizeForLargeScreen.get(screenDensity);
+ case Configuration.SCREENLAYOUT_SIZE_XLARGE:
+ return expectedMemorySizeForXLargeScreen.get(screenDensity);
+ default:
+ throw new IllegalArgumentException("No memory requirement specified "
+ + " for screen layout size " + screenSize);
+ }
+ }
+ }
+
+ public void testGetMemoryClass() throws Exception {
+ int memoryClass = getMemoryClass();
+ int screenDensity = getScreenDensity();
+ int screenSize = getScreenSize();
+ assertMemoryForScreenDensity(memoryClass, screenDensity, screenSize);
+
+ runHeapTestApp(memoryClass);
+ }
+
+ private int getMemoryClass() {
+ Context context = getInstrumentation().getTargetContext();
+ ActivityManager activityManager =
+ (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ return activityManager.getMemoryClass();
+ }
+
+ private int getScreenDensity() {
+ Context context = getInstrumentation().getTargetContext();
+ WindowManager windowManager =
+ (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = windowManager.getDefaultDisplay();
+ DisplayMetrics metrics = new DisplayMetrics();
+ display.getMetrics(metrics);
+ return metrics.densityDpi;
+ }
+
+ private int getScreenSize() {
+ Context context = getInstrumentation().getTargetContext();
+ Configuration config = context.getResources().getConfiguration();
+ return config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
+ }
+
+ private void assertMemoryForScreenDensity(int memoryClass, int screenDensity, int screenSize) {
+ Context context = getInstrumentation().getTargetContext();
+ boolean isWatch =
+ context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+ int expectedMinimumMemory =
+ ExpectedMemorySizesClass.getExpectedMemorySize(screenSize, screenDensity, isWatch);
+
+ assertTrue("Expected to have at least " + expectedMinimumMemory
+ + "mb of memory for screen density " + screenDensity,
+ memoryClass >= expectedMinimumMemory);
+ }
+
+ private void runHeapTestApp(int memoryClass) throws InterruptedException {
+ Intent intent = new Intent();
+ intent.putExtra(ActivityManagerMemoryClassLaunchActivity.MEMORY_CLASS_EXTRA,
+ memoryClass);
+ setActivityIntent(intent);
+ ActivityManagerMemoryClassLaunchActivity activity = getActivity();
+ assertEquals("The test application couldn't allocate memory close to the amount "
+ + " specified by the memory class.", Activity.RESULT_OK, activity.getResult());
+ }
+}
diff --git a/tests/app/src/android/app/cts/ActivityManagerMemoryClassTestActivity.java b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTestActivity.java
deleted file mode 100644
index e717b03..0000000
--- a/tests/app/src/android/app/cts/ActivityManagerMemoryClassTestActivity.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2011 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.Activity;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * {@link Activity} that allocates arrays of 256k until reaching 75% of the specified memory class.
- */
-public class ActivityManagerMemoryClassTestActivity extends Activity {
-
- private static final String TAG = "ActivityManagerMemoryClassTest";
-
- private static final double FREE_MEMORY_PERCENTAGE = 0.75;
-
- private static final int ARRAY_BYTES_SIZE = 256 * 1024;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Intent intent = getIntent();
- int memoryClass =
- intent.getIntExtra(ActivityManagerMemoryClassLaunchActivity.MEMORY_CLASS_EXTRA, -1);
- new AllocateMemoryTask(memoryClass).execute();
- }
-
- private class AllocateMemoryTask extends AsyncTask<Void, Void, Void> {
-
- private final int mMemoryClass;
-
- AllocateMemoryTask(int memoryClass) {
- this.mMemoryClass = memoryClass;
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- int targetMbs = (int) (mMemoryClass * FREE_MEMORY_PERCENTAGE);
- int numArrays = targetMbs * 1024 * 1024 / ARRAY_BYTES_SIZE;
- Log.i(TAG, "Memory class: " + mMemoryClass + "mb Target memory: "
- + targetMbs + "mb Number of arrays: " + numArrays);
-
- byte[][] arrays = new byte[numArrays][];
- for (int i = 0; i < arrays.length; i++) {
- Log.i(TAG, "Allocating array " + i + " of " + arrays.length
- + " (" + (i * ARRAY_BYTES_SIZE / 1024 / 1024) + "mb)");
- arrays[i] = new byte[ARRAY_BYTES_SIZE];
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- setResult(RESULT_OK);
- finish();
- }
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerMemoryInfoTest.java b/tests/app/src/android/app/cts/ActivityManagerMemoryInfoTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/ActivityManagerMemoryInfoTest.java
rename to tests/app/src/android/app/cts/ActivityManagerMemoryInfoTest.java
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerProcessErrorStateInfoTest.java b/tests/app/src/android/app/cts/ActivityManagerProcessErrorStateInfoTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/ActivityManagerProcessErrorStateInfoTest.java
rename to tests/app/src/android/app/cts/ActivityManagerProcessErrorStateInfoTest.java
diff --git a/tests/app/src/android/app/cts/ActivityManagerRecentOneActivity.java b/tests/app/src/android/app/cts/ActivityManagerRecentOneActivity.java
deleted file mode 100644
index b3edece..0000000
--- a/tests/app/src/android/app/cts/ActivityManagerRecentOneActivity.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.Activity;
-
-public class ActivityManagerRecentOneActivity extends Activity {
-}
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerRecentTaskInfoTest.java b/tests/app/src/android/app/cts/ActivityManagerRecentTaskInfoTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/ActivityManagerRecentTaskInfoTest.java
rename to tests/app/src/android/app/cts/ActivityManagerRecentTaskInfoTest.java
diff --git a/tests/app/src/android/app/cts/ActivityManagerRecentTwoActivity.java b/tests/app/src/android/app/cts/ActivityManagerRecentTwoActivity.java
deleted file mode 100644
index 97a91cc..0000000
--- a/tests/app/src/android/app/cts/ActivityManagerRecentTwoActivity.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.Activity;
-
-public class ActivityManagerRecentTwoActivity extends Activity {
-}
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerRunningTaskInfoTest.java b/tests/app/src/android/app/cts/ActivityManagerRunningTaskInfoTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/ActivityManagerRunningTaskInfoTest.java
rename to tests/app/src/android/app/cts/ActivityManagerRunningTaskInfoTest.java
diff --git a/tests/app/src/android/app/cts/ActivityManagerStubCrashActivity.java b/tests/app/src/android/app/cts/ActivityManagerStubCrashActivity.java
deleted file mode 100644
index b1c30a8..0000000
--- a/tests/app/src/android/app/cts/ActivityManagerStubCrashActivity.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.widget.TextView;
-
-public class ActivityManagerStubCrashActivity extends Activity {
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- final TextView tv = new TextView(this);
- tv.setText("Hello, Android but crash");
- setContentView(tv);
- die();
- }
-
- public void die() {
- throw new NullPointerException("Expected NPE.");
- }
-}
-
diff --git a/tests/app/src/android/app/cts/ActivityManagerStubFooActivity.java b/tests/app/src/android/app/cts/ActivityManagerStubFooActivity.java
deleted file mode 100644
index c002ec8..0000000
--- a/tests/app/src/android/app/cts/ActivityManagerStubFooActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.widget.TextView;
-
-public class ActivityManagerStubFooActivity extends Activity {
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- final TextView tv = new TextView(this);
- tv.setText("Hello, Android");
- setContentView(tv);
- }
-}
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
new file mode 100644
index 0000000..c03ad6d
--- /dev/null
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -0,0 +1,530 @@
+/*
+ * 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.
+ */
+package android.app.cts;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RecentTaskInfo;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityManager.RunningServiceInfo;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityOptions;
+import android.app.Instrumentation;
+import android.app.Instrumentation.ActivityMonitor;
+import android.app.Instrumentation.ActivityResult;
+import android.app.PendingIntent;
+import android.app.stubs.ActivityManagerRecentOneActivity;
+import android.app.stubs.ActivityManagerRecentTwoActivity;
+import android.app.stubs.MockApplicationActivity;
+import android.app.stubs.MockService;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ConfigurationInfo;
+import android.test.InstrumentationTestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ActivityManagerTest extends InstrumentationTestCase {
+ private static final String STUB_PACKAGE_NAME = "android.app.stubs";
+ private static final int WAITFOR_MSEC = 5000;
+ private static final String SERVICE_NAME = "android.app.stubs.MockService";
+ private static final int WAIT_TIME = 2000;
+ // A secondary test activity from another APK.
+ private static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp";
+ private static final String SIMPLE_ACTIVITY = ".SimpleActivity";
+ private static final String SIMPLE_ACTIVITY_IMMEDIATE_EXIT = ".SimpleActivityImmediateExit";
+ private static final String SIMPLE_ACTIVITY_CHAIN_EXIT = ".SimpleActivityChainExit";
+ // The action sent back by the SIMPLE_APP after a restart.
+ private static final String ACTIVITY_LAUNCHED_ACTION =
+ "com.android.cts.launchertests.LauncherAppsTests.LAUNCHED_ACTION";
+ // The action sent back by the SIMPLE_APP_IMMEDIATE_EXIT when it terminates.
+ private static final String ACTIVITY_EXIT_ACTION =
+ "com.android.cts.launchertests.LauncherAppsTests.EXIT_ACTION";
+ // The action sent back by the SIMPLE_APP_CHAIN_EXIT when the task chain ends.
+ private static final String ACTIVITY_CHAIN_EXIT_ACTION =
+ "com.android.cts.launchertests.LauncherAppsTests.CHAIN_EXIT_ACTION";
+ // The action sent to identify the time track info.
+ private static final String ACTIVITY_TIME_TRACK_INFO = "com.android.cts.TIME_TRACK_INFO";
+ // Return states of the ActivityReceiverFilter.
+ public static final int RESULT_PASS = 1;
+ public static final int RESULT_FAIL = 2;
+ public static final int RESULT_TIMEOUT = 3;
+
+ private Context mContext;
+ private ActivityManager mActivityManager;
+ private Intent mIntent;
+ private List<Activity> mStartedActivityList;
+ private int mErrorProcessID;
+ private Instrumentation mInstrumentation;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ mContext = mInstrumentation.getContext();
+ mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ mStartedActivityList = new ArrayList<Activity>();
+ mErrorProcessID = -1;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (mIntent != null) {
+ mInstrumentation.getContext().stopService(mIntent);
+ }
+ for (int i = 0; i < mStartedActivityList.size(); i++) {
+ mStartedActivityList.get(i).finish();
+ }
+ if (mErrorProcessID != -1) {
+ android.os.Process.killProcess(mErrorProcessID);
+ }
+ }
+
+ public void testGetRecentTasks() throws Exception {
+ int maxNum = 0;
+ int flags = 0;
+
+ List<RecentTaskInfo> recentTaskList;
+ // Test parameter: maxNum is set to 0
+ recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
+ assertNotNull(recentTaskList);
+ assertTrue(recentTaskList.size() == 0);
+ // Test parameter: maxNum is set to 50
+ maxNum = 50;
+ recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
+ assertNotNull(recentTaskList);
+ // start recent1_activity.
+ startSubActivity(ActivityManagerRecentOneActivity.class);
+ Thread.sleep(WAIT_TIME);
+ // start recent2_activity
+ startSubActivity(ActivityManagerRecentTwoActivity.class);
+ Thread.sleep(WAIT_TIME);
+ /*
+ * assert both recent1_activity and recent2_activity exist in the recent
+ * tasks list. Moreover,the index of the recent2_activity is smaller
+ * than the index of recent1_activity
+ */
+ recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
+ int indexRecentOne = -1;
+ int indexRecentTwo = -1;
+ int i = 0;
+ for (RecentTaskInfo rti : recentTaskList) {
+ if (rti.baseIntent.getComponent().getClassName().equals(
+ ActivityManagerRecentOneActivity.class.getName())) {
+ indexRecentOne = i;
+ } else if (rti.baseIntent.getComponent().getClassName().equals(
+ ActivityManagerRecentTwoActivity.class.getName())) {
+ indexRecentTwo = i;
+ }
+ i++;
+ }
+ assertTrue(indexRecentOne != -1 && indexRecentTwo != -1);
+ assertTrue(indexRecentTwo < indexRecentOne);
+
+ try {
+ mActivityManager.getRecentTasks(-1, 0);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected exception
+ }
+ }
+
+ public void testGetRecentTasksLimitedToCurrentAPK() throws Exception {
+ int maxNum = 0;
+ int flags = 0;
+
+ // Check the number of tasks at this time.
+ List<RecentTaskInfo> recentTaskList;
+ recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
+ int numberOfEntriesFirstRun = recentTaskList.size();
+
+ // Start another activity from another APK.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ ActivityReceiverFilter receiver = new ActivityReceiverFilter(ACTIVITY_LAUNCHED_ACTION);
+ mContext.startActivity(intent);
+
+ // Make sure the activity has really started.
+ assertEquals(RESULT_PASS, receiver.waitForActivity());
+ receiver.close();
+
+ // There shouldn't be any more tasks in this list at this time.
+ recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
+ int numberOfEntriesSecondRun = recentTaskList.size();
+ assertTrue(numberOfEntriesSecondRun == numberOfEntriesFirstRun);
+ }
+
+ // The receiver filter needs to be instantiated with the command to filter for before calling
+ // startActivity.
+ private class ActivityReceiverFilter extends BroadcastReceiver {
+ // The activity we want to filter for.
+ private String mActivityToFilter;
+ private int result = RESULT_TIMEOUT;
+ public long mTimeUsed = 0;
+ private static final int TIMEOUT_IN_MS = 1000;
+
+ // Create the filter with the intent to look for.
+ public ActivityReceiverFilter(String activityToFilter) {
+ mActivityToFilter = activityToFilter;
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(mActivityToFilter);
+ mInstrumentation.getTargetContext().registerReceiver(this, filter);
+ }
+
+ // Turn off the filter.
+ public void close() {
+ mInstrumentation.getTargetContext().unregisterReceiver(this);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(mActivityToFilter)) {
+ synchronized(this) {
+ result = RESULT_PASS;
+ if (mActivityToFilter.equals(ACTIVITY_TIME_TRACK_INFO)) {
+ mTimeUsed = intent.getExtras().getLong(
+ ActivityOptions.EXTRA_USAGE_TIME_REPORT);
+ }
+ notifyAll();
+ }
+ }
+ }
+
+ public int waitForActivity() {
+ synchronized(this) {
+ try {
+ wait(TIMEOUT_IN_MS);
+ } catch (InterruptedException e) {
+ }
+ }
+ return result;
+ }
+ }
+
+ private final <T extends Activity> void startSubActivity(Class<T> activityClass) {
+ final Instrumentation.ActivityResult result = new ActivityResult(0, new Intent());
+ final ActivityMonitor monitor = new ActivityMonitor(activityClass.getName(), result, false);
+ mInstrumentation.addMonitor(monitor);
+ launchActivity(STUB_PACKAGE_NAME, activityClass, null);
+ mStartedActivityList.add(monitor.waitForActivity());
+ }
+
+ public void testGetRunningTasks() {
+ // Test illegal parameter
+ List<RunningTaskInfo> runningTaskList;
+ runningTaskList = mActivityManager.getRunningTasks(-1);
+ assertTrue(runningTaskList.size() == 0);
+
+ runningTaskList = mActivityManager.getRunningTasks(0);
+ assertTrue(runningTaskList.size() == 0);
+
+ runningTaskList = mActivityManager.getRunningTasks(20);
+ int taskSize = runningTaskList.size();
+ assertTrue(taskSize >= 0 && taskSize <= 20);
+
+ // start recent1_activity.
+ startSubActivity(ActivityManagerRecentOneActivity.class);
+ // start recent2_activity
+ startSubActivity(ActivityManagerRecentTwoActivity.class);
+
+ /*
+ * assert both recent1_activity and recent2_activity exist in the
+ * running tasks list. Moreover,the index of the recent2_activity is
+ * smaller than the index of recent1_activity
+ */
+ runningTaskList = mActivityManager.getRunningTasks(20);
+ int indexRecentOne = -1;
+ int indexRecentTwo = -1;
+ int i = 0;
+ for (RunningTaskInfo rti : runningTaskList) {
+ if (rti.baseActivity.getClassName().equals(
+ ActivityManagerRecentOneActivity.class.getName())) {
+ indexRecentOne = i;
+ } else if (rti.baseActivity.getClassName().equals(
+ ActivityManagerRecentTwoActivity.class.getName())) {
+ indexRecentTwo = i;
+ }
+ i++;
+ }
+ assertTrue(indexRecentOne != -1 && indexRecentTwo != -1);
+ assertTrue(indexRecentTwo < indexRecentOne);
+ }
+
+ public void testGetRunningServices() throws Exception {
+ // Test illegal parameter
+ List<RunningServiceInfo> runningServiceInfo;
+ runningServiceInfo = mActivityManager.getRunningServices(-1);
+ assertTrue(runningServiceInfo.size() == 0);
+
+ runningServiceInfo = mActivityManager.getRunningServices(0);
+ assertTrue(runningServiceInfo.size() == 0);
+
+ runningServiceInfo = mActivityManager.getRunningServices(5);
+ assertTrue(runningServiceInfo.size() >= 0 && runningServiceInfo.size() <= 5);
+
+ Intent intent = new Intent();
+ intent.setClass(mInstrumentation.getTargetContext(), MockService.class);
+ mInstrumentation.getTargetContext().startService(intent);
+ Thread.sleep(WAIT_TIME);
+
+ runningServiceInfo = mActivityManager.getRunningServices(Integer.MAX_VALUE);
+ boolean foundService = false;
+ for (RunningServiceInfo rs : runningServiceInfo) {
+ if (rs.service.getClassName().equals(SERVICE_NAME)) {
+ foundService = true;
+ break;
+ }
+ }
+ assertTrue(foundService);
+ mContext.stopService(intent);
+ Thread.sleep(WAIT_TIME);
+ }
+
+ public void testGetMemoryInfo() {
+ ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
+ mActivityManager.getMemoryInfo(outInfo);
+ assertTrue(outInfo.lowMemory == (outInfo.availMem <= outInfo.threshold));
+ }
+
+ public void testGetRunningAppProcesses() throws Exception {
+ List<RunningAppProcessInfo> list = mActivityManager.getRunningAppProcesses();
+ assertNotNull(list);
+ final String SYSTEM_PROCESS = "system";
+ boolean hasSystemProcess = false;
+ // The package name is also the default name for the application process
+ final String TEST_PROCESS = STUB_PACKAGE_NAME;
+ boolean hasTestProcess = false;
+ for (RunningAppProcessInfo ra : list) {
+ if (ra.processName.equals(SYSTEM_PROCESS)) {
+ hasSystemProcess = true;
+ } else if (ra.processName.equals(TEST_PROCESS)) {
+ hasTestProcess = true;
+ }
+ }
+ // For security reasons the system process is not exposed.
+ assertTrue(!hasSystemProcess && hasTestProcess);
+
+ for (RunningAppProcessInfo ra : list) {
+ if (ra.processName.equals("android.app.stubs:remote")) {
+ fail("should be no process named android.app.stubs:remote");
+ }
+ }
+ // start a new process
+ mIntent = new Intent("android.app.REMOTESERVICE");
+ mIntent.setPackage("android.app.stubs");
+ mInstrumentation.getTargetContext().startService(mIntent);
+ Thread.sleep(WAITFOR_MSEC);
+
+ List<RunningAppProcessInfo> listNew = mActivityManager.getRunningAppProcesses();
+ assertTrue(list.size() <= listNew.size());
+
+ for (RunningAppProcessInfo ra : listNew) {
+ if (ra.processName.equals("android.app.stubs:remote")) {
+ return;
+ }
+ }
+ fail("android.app.stubs:remote process should be available");
+ }
+
+ public void testGetProcessInErrorState() throws Exception {
+ List<ActivityManager.ProcessErrorStateInfo> errList = null;
+ errList = mActivityManager.getProcessesInErrorState();
+ }
+
+ public void testRestartPackage() {
+ }
+
+ public void testGetDeviceConfigurationInfo() {
+ ConfigurationInfo conInf = mActivityManager.getDeviceConfigurationInfo();
+ assertNotNull(conInf);
+ }
+
+ /**
+ * Simple test for {@link ActivityManager.isUserAMonkey()} - verifies its false.
+ *
+ * TODO: test positive case
+ */
+ public void testIsUserAMonkey() {
+ assertFalse(ActivityManager.isUserAMonkey());
+ }
+
+ /**
+ * Verify that {@link ActivityManager.isRunningInTestHarness()} is false.
+ */
+ public void testIsRunningInTestHarness() {
+ assertFalse("isRunningInTestHarness must be false in production builds",
+ ActivityManager.isRunningInTestHarness());
+ }
+
+ /**
+ * Go back to the home screen since running applications can interfere with application
+ * lifetime tests.
+ */
+ private void launchHome() throws Exception {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ Thread.sleep(WAIT_TIME);
+ }
+
+ /**
+ * Verify that the TimeTrackingAPI works properly when starting and ending an activity.
+ */
+ public void testTimeTrackingAPI_SimpleStartExit() throws Exception {
+ launchHome();
+ // Prepare to start an activity from another APK.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(SIMPLE_PACKAGE_NAME,
+ SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_IMMEDIATE_EXIT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Prepare the time receiver action.
+ Context context = mInstrumentation.getTargetContext();
+ ActivityOptions options = ActivityOptions.makeBasic();
+ Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
+ options.requestUsageTimeReport(PendingIntent.getBroadcast(context,
+ 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
+
+ // The application finished tracker.
+ ActivityReceiverFilter appEndReceiver = new ActivityReceiverFilter(ACTIVITY_EXIT_ACTION);
+
+ // The filter for the time event.
+ ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
+
+ // Run the activity.
+ mContext.startActivity(intent, options.toBundle());
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
+ appEndReceiver.close();
+
+ // At this time the timerReceiver should not fire, even though the activity has shut down,
+ // because we are back to the home screen.
+ assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+ assertTrue(timeReceiver.mTimeUsed == 0);
+
+ // Issuing now another activity will trigger the timing information release.
+ final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
+ dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+ timeReceiver.close();
+ assertTrue(timeReceiver.mTimeUsed != 0);
+ }
+
+ /**
+ * Verify that the TimeTrackingAPI works properly when switching away from the monitored task.
+ */
+ public void testTimeTrackingAPI_SwitchAwayTriggers() throws Exception {
+ launchHome();
+
+ // Prepare to start an activity from another APK.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Prepare the time receiver action.
+ Context context = mInstrumentation.getTargetContext();
+ ActivityOptions options = ActivityOptions.makeBasic();
+ Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
+ options.requestUsageTimeReport(PendingIntent.getBroadcast(context,
+ 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
+
+ // The application started tracker.
+ ActivityReceiverFilter appStartedReceiver = new ActivityReceiverFilter(
+ ACTIVITY_LAUNCHED_ACTION);
+
+ // The filter for the time event.
+ ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
+
+ // Run the activity.
+ mContext.startActivity(intent, options.toBundle());
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, appStartedReceiver.waitForActivity());
+ appStartedReceiver.close();
+
+ // At this time the timerReceiver should not fire since our app is running.
+ assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+ assertTrue(timeReceiver.mTimeUsed == 0);
+
+ // Starting now another activity will put ours into the back hence releasing the timing.
+ final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
+ dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+ timeReceiver.close();
+ assertTrue(timeReceiver.mTimeUsed != 0);
+ }
+
+ /**
+ * Verify that the TimeTrackingAPI works properly when handling an activity chain gets started
+ * and ended.
+ */
+ public void testTimeTrackingAPI_ChainedActivityExit() throws Exception {
+ launchHome();
+ // Prepare to start an activity from another APK.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(SIMPLE_PACKAGE_NAME,
+ SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_CHAIN_EXIT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Prepare the time receiver action.
+ Context context = mInstrumentation.getTargetContext();
+ ActivityOptions options = ActivityOptions.makeBasic();
+ Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
+ options.requestUsageTimeReport(PendingIntent.getBroadcast(context,
+ 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
+
+ // The application finished tracker.
+ ActivityReceiverFilter appEndReceiver = new ActivityReceiverFilter(
+ ACTIVITY_CHAIN_EXIT_ACTION);
+
+ // The filter for the time event.
+ ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
+
+ // Run the activity.
+ mContext.startActivity(intent, options.toBundle());
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
+ appEndReceiver.close();
+
+ // At this time the timerReceiver should not fire, even though the activity has shut down.
+ assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+ assertTrue(timeReceiver.mTimeUsed == 0);
+
+ // Issue another activity so that the timing information gets released.
+ final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
+ dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+ timeReceiver.close();
+ assertTrue(timeReceiver.mTimeUsed != 0);
+ }
+}
diff --git a/tests/tests/app/src/android/app/cts/ActivityManager_RunningAppProcessInfoTest.java b/tests/app/src/android/app/cts/ActivityManager_RunningAppProcessInfoTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/ActivityManager_RunningAppProcessInfoTest.java
rename to tests/app/src/android/app/cts/ActivityManager_RunningAppProcessInfoTest.java
diff --git a/tests/app/src/android/app/cts/ActivityManager_RunningServiceInfoTest.java b/tests/app/src/android/app/cts/ActivityManager_RunningServiceInfoTest.java
new file mode 100644
index 0000000..fa34130
--- /dev/null
+++ b/tests/app/src/android/app/cts/ActivityManager_RunningServiceInfoTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+package android.app.cts;
+
+import android.app.ActivityManager;
+import android.app.stubs.MockActivity;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+public class ActivityManager_RunningServiceInfoTest extends AndroidTestCase {
+ private ActivityManager.RunningServiceInfo mRunningServiceInfo;
+ private ComponentName mService;
+ private static final String PROCESS = "process";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mRunningServiceInfo = new ActivityManager.RunningServiceInfo();
+ mService = new ComponentName(getContext(), MockActivity.class);
+
+ mRunningServiceInfo.service = mService;
+ mRunningServiceInfo.pid = 1;
+ mRunningServiceInfo.process = PROCESS;
+ mRunningServiceInfo.foreground = true;
+ mRunningServiceInfo.activeSince = 1l;
+ mRunningServiceInfo.started = true;
+ mRunningServiceInfo.clientCount = 2;
+ mRunningServiceInfo.crashCount = 1;
+ mRunningServiceInfo.lastActivityTime = 1l;
+ mRunningServiceInfo.restarting = 1l;
+ }
+
+ public void testConstructor() {
+ new ActivityManager.RunningServiceInfo();
+ }
+
+ public void testDescribeContents() {
+ assertEquals(0, mRunningServiceInfo.describeContents());
+ }
+
+ public void testWriteToParcel() throws Exception {
+
+ Parcel parcel = Parcel.obtain();
+ mRunningServiceInfo.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ ActivityManager.RunningServiceInfo values =
+ ActivityManager.RunningServiceInfo.CREATOR.createFromParcel(parcel);
+ assertEquals(mService, values.service);
+ assertEquals(1, values.pid);
+ assertEquals(PROCESS, values.process);
+ assertTrue(values.foreground);
+ assertEquals(1l, values.activeSince);
+ assertTrue(values.started);
+ assertEquals(2, values.clientCount);
+ assertEquals(1, values.crashCount);
+ assertEquals(1l, values.lastActivityTime);
+ assertEquals(1l, values.restarting);
+ }
+
+ public void testReadFromParcel() throws Exception {
+
+ Parcel parcel = Parcel.obtain();
+ mRunningServiceInfo.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ ActivityManager.RunningServiceInfo values =
+ new ActivityManager.RunningServiceInfo();
+ values.readFromParcel(parcel);
+ assertEquals(mService, values.service);
+ assertEquals(1, values.pid);
+ assertEquals(PROCESS, values.process);
+ assertTrue(values.foreground);
+ assertEquals(1l, values.activeSince);
+ assertTrue(values.started);
+ assertEquals(2, values.clientCount);
+ assertEquals(1, values.crashCount);
+ assertEquals(1l, values.lastActivityTime);
+ assertEquals(1l, values.restarting);
+ }
+
+}
diff --git a/tests/app/src/android/app/cts/ActivityTestsBase.java b/tests/app/src/android/app/cts/ActivityTestsBase.java
deleted file mode 100644
index 426a8b8..0000000
--- a/tests/app/src/android/app/cts/ActivityTestsBase.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.test.AndroidTestCase;
-import android.test.PerformanceTestCase;
-
-public class ActivityTestsBase extends AndroidTestCase implements PerformanceTestCase,
- LaunchpadActivity.CallingTest {
- public static final String PERMISSION_GRANTED = "android.app.cts.permission.TEST_GRANTED";
- public static final String PERMISSION_DENIED = "android.app.cts.permission.TEST_DENIED";
-
- private static final int TIMEOUT_MS = 60 * 1000;
-
- protected Intent mIntent;
-
- private PerformanceTestCase.Intermediates mIntermediates;
- private String mExpecting;
-
- // Synchronization of activity result.
- private boolean mFinished;
- private int mResultCode = 0;
- private Intent mData;
- private RuntimeException mResultStack = null;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mIntent = new Intent(mContext, LaunchpadActivity.class);
- mIntermediates = null;
- }
-
- @Override
- protected void tearDown() throws Exception {
- mIntermediates = null;
- super.tearDown();
- }
-
- public boolean isPerformanceOnly() {
- return false;
- }
-
- public void setInternalIterations(int count) {
- }
-
- public void startTiming(boolean realTime) {
- if (mIntermediates != null) {
- mIntermediates.startTiming(realTime);
- }
- }
-
- public void addIntermediate(String name) {
- if (mIntermediates != null) {
- mIntermediates.addIntermediate(name);
- }
- }
-
- public void addIntermediate(String name, long timeInNS) {
- if (mIntermediates != null) {
- mIntermediates.addIntermediate(name, timeInNS);
- }
- }
-
- public void finishTiming(boolean realTime) {
- if (mIntermediates != null) {
- mIntermediates.finishTiming(realTime);
- }
- }
-
- public void activityFinished(int resultCode, Intent data, RuntimeException where) {
- finishWithResult(resultCode, data, where);
- }
-
- public Intent editIntent() {
- return mIntent;
- }
-
- @Override
- public Context getContext() {
- return mContext;
- }
-
- public int startPerformance(Intermediates intermediates) {
- mIntermediates = intermediates;
- return 1;
- }
-
- public void finishGood() {
- finishWithResult(Activity.RESULT_OK, null);
- }
-
- public void finishBad(String error) {
- finishWithResult(Activity.RESULT_CANCELED, new Intent().setAction(error));
- }
-
- public void finishWithResult(int resultCode, Intent data) {
- final RuntimeException where = new RuntimeException("Original error was here");
- where.fillInStackTrace();
- finishWithResult(resultCode, data, where);
- }
-
- public void finishWithResult(int resultCode, Intent data, RuntimeException where) {
- synchronized (this) {
- mResultCode = resultCode;
- mData = data;
- mResultStack = where;
- mFinished = true;
- notifyAll();
- }
- }
-
- public int runLaunchpad(String action) {
- startLaunchpadActivity(action);
- return waitForResultOrThrow(TIMEOUT_MS);
- }
-
- private void startLaunchpadActivity(String action) {
- LaunchpadActivity.setCallingTest(this);
-
- synchronized (this) {
- mIntent.setAction(action);
- mFinished = false;
- mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(mIntent);
- }
- }
-
- public int waitForResultOrThrow(int timeoutMs) {
- return waitForResultOrThrow(timeoutMs, null);
- }
-
- public int waitForResultOrThrow(int timeoutMs, String expected) {
- final int res = waitForResult(timeoutMs, expected);
-
- if (res == Activity.RESULT_CANCELED) {
- if (mResultStack != null) {
- throw new RuntimeException(mData != null ? mData.toString() : "Unable to launch",
- mResultStack);
- } else {
- throw new RuntimeException(mData != null ? mData.toString() : "Unable to launch");
- }
- }
- return res;
- }
-
- public int waitForResult(int timeoutMs, String expected) {
- mExpecting = expected;
-
- final long endTime = System.currentTimeMillis() + timeoutMs;
-
- boolean timeout = false;
- synchronized (this) {
- while (!mFinished) {
- final long delay = endTime - System.currentTimeMillis();
- if (delay < 0) {
- timeout = true;
- break;
- }
-
- try {
- wait(delay);
- } catch (final java.lang.InterruptedException e) {
- // do nothing
- }
- }
- }
-
- mFinished = false;
-
- if (timeout) {
- mResultCode = Activity.RESULT_CANCELED;
- onTimeout();
- }
- return mResultCode;
- }
-
-
- public int getResultCode() {
- return mResultCode;
- }
-
- public Intent getResultData() {
- return mData;
- }
-
- public RuntimeException getResultStack() {
- return mResultStack;
- }
-
- public void onTimeout() {
- final String msg = mExpecting == null ? "Timeout" : "Timeout while expecting " + mExpecting;
- finishWithResult(Activity.RESULT_CANCELED, new Intent().setAction(msg));
- }
-}
diff --git a/tests/app/src/android/app/cts/AlarmManagerTest.java b/tests/app/src/android/app/cts/AlarmManagerTest.java
new file mode 100644
index 0000000..fabedd9
--- /dev/null
+++ b/tests/app/src/android/app/cts/AlarmManagerTest.java
@@ -0,0 +1,351 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+
+import android.app.AlarmManager;
+import android.app.AlarmManager.AlarmClockInfo;
+import android.app.PendingIntent;
+import android.app.stubs.MockAlarmReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.cts.util.PollingCheck;
+import android.os.Build;
+import android.os.SystemClock;
+import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
+import android.util.Log;
+
+public class AlarmManagerTest extends AndroidTestCase {
+ public static final String MOCKACTION = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER";
+ public static final String MOCKACTION2 = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER2";
+
+ private AlarmManager mAm;
+ private Intent mIntent;
+ private PendingIntent mSender;
+ private Intent mIntent2;
+ private PendingIntent mSender2;
+
+ /*
+ * The default snooze delay: 5 seconds
+ */
+ private static final long SNOOZE_DELAY = 5 * 1000L;
+ private long mWakeupTime;
+ private MockAlarmReceiver mMockAlarmReceiver;
+ private MockAlarmReceiver mMockAlarmReceiver2;
+
+ private static final int TIME_DELTA = 1000;
+ private static final int TIME_DELAY = 10000;
+ private static final int REPEAT_PERIOD = 60000;
+
+ // Receiver registration/unregistration between tests races with the system process, so
+ // we add a little buffer time here to allow the system to process before we proceed.
+ // This value is in milliseconds.
+ private static final long REGISTER_PAUSE = 250;
+
+ // Constants used for validating exact vs inexact alarm batching immunity. We run a few
+ // trials of an exact alarm that is placed within an inexact alarm's window of opportunity,
+ // and mandate that the average observed delivery skew between the two be statistically
+ // significant -- i.e. that the two alarms are not being coalesced. We also place an
+ // additional exact alarm only a short time after the inexact alarm's nominal trigger time.
+ // If exact alarms are allowed to batch with inexact ones this will tend to have no effect,
+ // but in the correct behavior -- inexact alarms not permitted to batch with exact ones --
+ // this additional exact alarm will have the effect of guaranteeing that the inexact alarm
+ // must fire no later than it -- i.e. a considerable time before the significant, later
+ // exact alarm.
+ //
+ // The test essentially amounts to requiring that the inexact MOCKACTION alarm and
+ // the much later exact MOCKACTION2 alarm fire far apart, always; with an implicit
+ // insistence that alarm batches are delivered at the head of their window.
+ private static final long TEST_WINDOW_LENGTH = 5 * 1000L;
+ private static final long TEST_ALARM_FUTURITY = 6 * 1000L;
+ private static final long FAIL_DELTA = 50;
+ private static final long NUM_TRIALS = 5;
+ private static final long MAX_NEAR_DELIVERIES = 2;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mAm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+
+ mIntent = new Intent(MOCKACTION)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mSender = PendingIntent.getBroadcast(mContext, 0, mIntent, 0);
+ mMockAlarmReceiver = new MockAlarmReceiver(mIntent.getAction());
+
+ mIntent2 = new Intent(MOCKACTION2)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mSender2 = PendingIntent.getBroadcast(mContext, 0, mIntent2, 0);
+ mMockAlarmReceiver2 = new MockAlarmReceiver(mIntent2.getAction());
+
+ IntentFilter filter = new IntentFilter(mIntent.getAction());
+ mContext.registerReceiver(mMockAlarmReceiver, filter);
+
+ IntentFilter filter2 = new IntentFilter(mIntent2.getAction());
+ mContext.registerReceiver(mMockAlarmReceiver2, filter2);
+
+ Thread.sleep(REGISTER_PAUSE);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mContext.unregisterReceiver(mMockAlarmReceiver);
+ mContext.unregisterReceiver(mMockAlarmReceiver2);
+
+ Thread.sleep(REGISTER_PAUSE);
+ }
+
+ public void testSetTypes() throws Exception {
+ // TODO: try to find a way to make device sleep then test whether
+ // AlarmManager perform the expected way
+
+ // test parameter type is RTC_WAKEUP
+ mMockAlarmReceiver.setAlarmedFalse();
+ mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
+ mAm.setExact(AlarmManager.RTC_WAKEUP, mWakeupTime, mSender);
+ new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+ assertEquals(mMockAlarmReceiver.rtcTime, mWakeupTime, TIME_DELTA);
+
+ // test parameter type is RTC
+ mMockAlarmReceiver.setAlarmedFalse();
+ mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
+ mAm.setExact(AlarmManager.RTC, mWakeupTime, mSender);
+ new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+ assertEquals(mMockAlarmReceiver.rtcTime, mWakeupTime, TIME_DELTA);
+
+ // test parameter type is ELAPSED_REALTIME
+ mMockAlarmReceiver.setAlarmedFalse();
+ mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
+ mAm.setExact(AlarmManager.ELAPSED_REALTIME, mWakeupTime, mSender);
+ new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+ assertEquals(mMockAlarmReceiver.elapsedTime, mWakeupTime, TIME_DELTA);
+
+ // test parameter type is ELAPSED_REALTIME_WAKEUP
+ mMockAlarmReceiver.setAlarmedFalse();
+ mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
+ mAm.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, mWakeupTime, mSender);
+ new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+ assertEquals(mMockAlarmReceiver.elapsedTime, mWakeupTime, TIME_DELTA);
+ }
+
+ public void testAlarmTriggersImmediatelyIfSetTimeIsNegative() throws Exception {
+ // An alarm with a negative wakeup time should be triggered immediately.
+ // This exercises a workaround for a limitation of the /dev/alarm driver
+ // that would instead cause such alarms to never be triggered.
+ mMockAlarmReceiver.setAlarmedFalse();
+ mWakeupTime = -1000;
+ mAm.set(AlarmManager.RTC, mWakeupTime, mSender);
+ new PollingCheck(TIME_DELAY) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+ }
+
+ public void testExactAlarmBatching() throws Exception {
+ int deliveriesTogether = 0;
+ for (int i = 0; i < NUM_TRIALS; i++) {
+ final long now = System.currentTimeMillis();
+ final long windowStart = now + TEST_ALARM_FUTURITY;
+ final long exactStart = windowStart + TEST_WINDOW_LENGTH - 1;
+
+ mMockAlarmReceiver.setAlarmedFalse();
+ mMockAlarmReceiver2.setAlarmedFalse();
+ mAm.setWindow(AlarmManager.RTC_WAKEUP, windowStart, TEST_WINDOW_LENGTH, mSender);
+ mAm.setExact(AlarmManager.RTC_WAKEUP, exactStart, mSender2);
+
+ // Wait until a half-second beyond its target window, just to provide a
+ // little safety slop.
+ new PollingCheck(TEST_WINDOW_LENGTH + (windowStart - now) + 500) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+
+ // Now wait until 1 sec beyond the expected exact alarm fire time, or for at
+ // least one second if we're already past the nominal exact alarm fire time
+ long timeToExact = Math.max(exactStart - System.currentTimeMillis() + 1000, 1000);
+ new PollingCheck(timeToExact) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver2.alarmed;
+ }
+ }.run();
+
+ // Success when we observe that the exact and windowed alarm are not being often
+ // delivered close together -- that is, when we can be confident that they are not
+ // being coalesced.
+ final long delta = Math.abs(mMockAlarmReceiver2.rtcTime - mMockAlarmReceiver.rtcTime);
+ Log.i("TEST", "[" + i + "] delta = " + delta);
+ if (delta < FAIL_DELTA) {
+ deliveriesTogether++;
+ assertTrue("Exact alarms appear to be coalescing with inexact alarms",
+ deliveriesTogether <= MAX_NEAR_DELIVERIES);
+ }
+ }
+ }
+
+ public void testSetRepeating() throws Exception {
+ mMockAlarmReceiver.setAlarmedFalse();
+ mWakeupTime = System.currentTimeMillis() + TEST_ALARM_FUTURITY;
+ mAm.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, REPEAT_PERIOD, mSender);
+
+ // wait beyond the initial alarm's possible delivery window to verify that it fires the first time
+ new PollingCheck(TEST_ALARM_FUTURITY + REPEAT_PERIOD) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+ assertTrue(mMockAlarmReceiver.alarmed);
+
+ // Now reset the receiver and wait for the intended repeat alarm to fire as expected
+ mMockAlarmReceiver.setAlarmedFalse();
+ new PollingCheck(REPEAT_PERIOD*2) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+ assertTrue(mMockAlarmReceiver.alarmed);
+
+ mAm.cancel(mSender);
+ }
+
+ public void testCancel() throws Exception {
+ mMockAlarmReceiver.setAlarmedFalse();
+ mMockAlarmReceiver2.setAlarmedFalse();
+
+ // set two alarms
+ final long when1 = System.currentTimeMillis() + TEST_ALARM_FUTURITY;
+ mAm.setExact(AlarmManager.RTC_WAKEUP, when1, mSender);
+ final long when2 = when1 + TIME_DELTA; // will fire after when1's target time
+ mAm.setExact(AlarmManager.RTC_WAKEUP, when2, mSender2);
+
+ // cancel the earlier one
+ mAm.cancel(mSender);
+
+ // and verify that only the later one fired
+ new PollingCheck(TIME_DELAY) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver2.alarmed;
+ }
+ }.run();
+
+ assertFalse(mMockAlarmReceiver.alarmed);
+ assertTrue(mMockAlarmReceiver2.alarmed);
+ }
+
+ public void testSetInexactRepeating() throws Exception {
+ mAm.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
+ AlarmManager.INTERVAL_FIFTEEN_MINUTES, mSender);
+ SystemClock.setCurrentTimeMillis(System.currentTimeMillis()
+ + AlarmManager.INTERVAL_FIFTEEN_MINUTES);
+ // currently there is no way to write Android system clock. When try to
+ // write the system time, there will be log as
+ // " Unable to open alarm driver: Permission denied". But still fail
+ // after tried many permission.
+ }
+
+ public void testSetAlarmClock() throws Exception {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ mMockAlarmReceiver.setAlarmedFalse();
+ mMockAlarmReceiver2.setAlarmedFalse();
+
+ // Set first alarm clock.
+ final long wakeupTimeFirst = System.currentTimeMillis()
+ + 2 * TEST_ALARM_FUTURITY;
+ mAm.setAlarmClock(new AlarmClockInfo(wakeupTimeFirst, null), mSender);
+
+ // Verify getNextAlarmClock returns first alarm clock.
+ AlarmClockInfo nextAlarmClock = mAm.getNextAlarmClock();
+ assertEquals(wakeupTimeFirst, nextAlarmClock.getTriggerTime());
+ assertNull(nextAlarmClock.getShowIntent());
+
+ // Set second alarm clock, earlier than first.
+ final long wakeupTimeSecond = System.currentTimeMillis()
+ + TEST_ALARM_FUTURITY;
+ PendingIntent showIntentSecond = PendingIntent.getBroadcast(getContext(), 0,
+ new Intent(getContext(), AlarmManagerTest.class).setAction("SHOW_INTENT"), 0);
+ mAm.setAlarmClock(new AlarmClockInfo(wakeupTimeSecond, showIntentSecond),
+ mSender2);
+
+ // Verify getNextAlarmClock returns second alarm clock now.
+ nextAlarmClock = mAm.getNextAlarmClock();
+ assertEquals(wakeupTimeSecond, nextAlarmClock.getTriggerTime());
+ assertEquals(showIntentSecond, nextAlarmClock.getShowIntent());
+
+ // Cancel second alarm.
+ mAm.cancel(mSender2);
+
+ // Verify getNextAlarmClock returns first alarm clock again.
+ nextAlarmClock = mAm.getNextAlarmClock();
+ assertEquals(wakeupTimeFirst, nextAlarmClock.getTriggerTime());
+ assertNull(nextAlarmClock.getShowIntent());
+
+ // Wait for first alarm to trigger.
+ assertFalse(mMockAlarmReceiver.alarmed);
+ new PollingCheck(2 * TEST_ALARM_FUTURITY + TIME_DELAY) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+
+ // Verify first alarm fired at the right time.
+ assertEquals(mMockAlarmReceiver.rtcTime, wakeupTimeFirst, TIME_DELTA);
+
+ // Verify second alarm didn't fire.
+ assertFalse(mMockAlarmReceiver2.alarmed);
+
+ // Verify the next alarm is not returning neither the first nor the second alarm.
+ nextAlarmClock = mAm.getNextAlarmClock();
+ MoreAsserts.assertNotEqual(wakeupTimeFirst, nextAlarmClock != null
+ ? nextAlarmClock.getTriggerTime()
+ : null);
+ MoreAsserts.assertNotEqual(wakeupTimeSecond, nextAlarmClock != null
+ ? nextAlarmClock.getTriggerTime()
+ : null);
+ }
+ }
+}
diff --git a/tests/app/src/android/app/cts/AlertDialogTest.java b/tests/app/src/android/app/cts/AlertDialogTest.java
new file mode 100644
index 0000000..1fe8de4
--- /dev/null
+++ b/tests/app/src/android/app/cts/AlertDialogTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.AlertDialog;
+import android.app.Instrumentation;
+import android.app.stubs.DialogStubActivity;
+import android.content.DialogInterface;
+import android.cts.util.PollingCheck;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyEvent;
+import android.widget.Button;
+
+import android.app.stubs.R;
+/*
+ * Test AlertDialog
+ */
+public class AlertDialogTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
+ private static final String ALERTDIALOG_CUSTOM_TITLE = "Hello, World!";
+
+ private Instrumentation mInstrumentation;
+ private DialogStubActivity mActivity;
+ private Button mPositiveButton;
+ private Button mNegativeButton;
+ private Button mNeutralButton;
+
+ public AlertDialogTest() {
+ super("android.app.stubs", DialogStubActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ }
+
+ protected void startDialogActivity(int dialogNumber) {
+ mActivity = DialogStubActivity.startDialogActivity(this, dialogNumber);
+ new PollingCheck() {
+ @Override
+ protected boolean check() {
+ return mActivity.getDialog().isShowing();
+ }
+ }.run();
+ }
+
+ public void testAlertDialog() throws Throwable {
+ doTestAlertDialog(DialogStubActivity.TEST_ALERTDIALOG);
+ }
+
+ private void doTestAlertDialog(int index) throws Throwable {
+ startDialogActivity(index);
+ assertTrue(mActivity.getDialog().isShowing());
+
+ mPositiveButton = ((AlertDialog) (mActivity.getDialog())).getButton(
+ DialogInterface.BUTTON_POSITIVE);
+ assertNotNull(mPositiveButton);
+ assertEquals(mActivity.getString(R.string.alert_dialog_positive),
+ mPositiveButton.getText());
+ mNeutralButton = ((AlertDialog) (mActivity.getDialog())).getButton(
+ DialogInterface.BUTTON_NEUTRAL);
+ assertNotNull(mNeutralButton);
+ assertEquals(mActivity.getString(R.string.alert_dialog_neutral),
+ mNeutralButton.getText());
+ mNegativeButton = ((AlertDialog) (mActivity.getDialog())).getButton(
+ DialogInterface.BUTTON_NEGATIVE);
+ assertNotNull(mNegativeButton);
+ assertEquals(mActivity.getString(R.string.alert_dialog_negative),
+ mNegativeButton.getText());
+
+ assertFalse(mActivity.isPositiveButtonClicked);
+ performClick(mPositiveButton);
+ assertTrue(mActivity.isPositiveButtonClicked);
+
+ assertFalse(mActivity.isNegativeButtonClicked);
+ performClick(mNegativeButton);
+ assertTrue(mActivity.isNegativeButtonClicked);
+
+ assertFalse(mActivity.isNeutralButtonClicked);
+ performClick(mNeutralButton);
+ assertTrue(mActivity.isNeutralButtonClicked);
+ }
+
+ public void testAlertDialogDeprecatedAPI() throws Throwable {
+ doTestAlertDialog(DialogStubActivity.TEST_ALERTDIALOG_DEPRECATED);
+ }
+
+ public void testAlertDialogDeprecatedAPIWithMessage() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE);
+ assertTrue(mActivity.getDialog().isShowing());
+
+ mPositiveButton = ((AlertDialog) (mActivity.getDialog())).getButton(
+ DialogInterface.BUTTON_POSITIVE);
+ assertNotNull(mPositiveButton);
+ assertEquals(mActivity.getString(R.string.alert_dialog_positive),
+ mPositiveButton.getText());
+ mNegativeButton = ((AlertDialog) (mActivity.getDialog())).getButton(
+ DialogInterface.BUTTON_NEGATIVE);
+ assertNotNull(mNegativeButton);
+ assertEquals(mActivity.getString(R.string.alert_dialog_negative),
+ mNegativeButton.getText());
+ mNeutralButton = ((AlertDialog) (mActivity.getDialog())).getButton(
+ DialogInterface.BUTTON_NEUTRAL);
+ assertNotNull(mNeutralButton);
+ assertEquals(mActivity.getString(R.string.alert_dialog_neutral),
+ mNeutralButton.getText());
+
+ DialogStubActivity.buttonIndex = 0;
+ performClick(mPositiveButton);
+ assertEquals(DialogInterface.BUTTON_POSITIVE, DialogStubActivity.buttonIndex);
+
+ DialogStubActivity.buttonIndex = 0;
+ performClick(mNeutralButton);
+ assertEquals(DialogInterface.BUTTON_NEUTRAL, DialogStubActivity.buttonIndex);
+
+ DialogStubActivity.buttonIndex = 0;
+ performClick(mNegativeButton);
+ assertEquals(DialogInterface.BUTTON_NEGATIVE, DialogStubActivity.buttonIndex);
+ }
+
+ private void performClick(final Button button) throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ button.performClick();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testCustomAlertDialog() {
+ startDialogActivity(DialogStubActivity.TEST_CUSTOM_ALERTDIALOG);
+ assertTrue(mActivity.getDialog().isShowing());
+ }
+
+ public void testCustomAlertDialogView() {
+ startDialogActivity(DialogStubActivity.TEST_CUSTOM_ALERTDIALOG_VIEW);
+ assertTrue(mActivity.getDialog().isShowing());
+ }
+
+
+ public void testCallback() {
+ startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_CALLBACK);
+ assertTrue(mActivity.onCreateCalled);
+
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
+ assertTrue(mActivity.onKeyDownCalled);
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
+ assertTrue(mActivity.onKeyUpCalled);
+ }
+
+ public void testAlertDialogTheme() throws Exception {
+ startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_THEME);
+ assertTrue(mActivity.getDialog().isShowing());
+ }
+
+ public void testAlertDialogCancelable() throws Exception {
+ startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_CANCELABLE);
+ assertTrue(mActivity.getDialog().isShowing());
+ assertFalse(mActivity.onCancelCalled);
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.onCancelCalled);
+ }
+
+ public void testAlertDialogNotCancelable() throws Exception {
+ startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_NOT_CANCELABLE);
+ assertTrue(mActivity.getDialog().isShowing());
+ assertFalse(mActivity.onCancelCalled);
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ assertFalse(mActivity.onCancelCalled);
+ }
+}
diff --git a/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java b/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
new file mode 100644
index 0000000..1a60225
--- /dev/null
+++ b/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
@@ -0,0 +1,669 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.Instrumentation;
+import android.app.stubs.DialogStubActivity;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnClickListener;
+import android.content.DialogInterface.OnKeyListener;
+import android.content.DialogInterface.OnMultiChoiceClickListener;
+import android.cts.util.PollingCheck;
+import android.database.Cursor;
+import android.database.CursorWrapper;
+import android.graphics.drawable.Drawable;
+import android.provider.Contacts.People;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+import android.app.stubs.R;
+
+import java.util.ArrayList;
+
+public class AlertDialog_BuilderTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
+ private Builder mBuilder;
+ private Context mContext;
+ private Instrumentation mInstrumentation;
+ private final CharSequence mTitle = "title";
+ private Drawable mDrawable;
+ private AlertDialog mDialog;
+ private Button mButton;
+ private boolean mResult;
+ private boolean mItemSelected;
+ private CharSequence mSelectedItem;
+ private final String[] mPROJECTION = new String[] {
+ People._ID, People.NAME
+ };
+
+ private View mView;
+ private ListView mListView;
+ private ArrayList<Integer> mSelectedItems;
+ private FrameLayout mFrameLayout;
+
+ private OnClickListener mOnClickListener = new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ mResult = true;
+ }
+ };
+
+ private OnCancelListener mOnCancelListener = new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ mResult = true;
+ }
+ };
+
+ private OnKeyListener mOnKeyListener = new OnKeyListener() {
+ public boolean onKey(DialogInterface dialog, int key, KeyEvent envnt) {
+ mResult = true;
+ return true;
+ }
+ };
+
+ private OnItemSelectedListener mOnItemSelectedListener = new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView parent, View v, int position, long id) {
+ mItemSelected = true;
+ }
+
+ public void onNothingSelected(AdapterView parent) {
+ }
+
+ };
+
+ private OnMultiChoiceClickListener mOnMultiChoiceClickListener =
+ new OnMultiChoiceClickListener() {
+ public void onClick(DialogInterface dialog, int which, boolean isChecked) {
+ mSelectedItems.add(which);
+ mResult = true;
+ }
+ };
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mBuilder = null;
+ mInstrumentation = getInstrumentation();
+ mContext = getActivity();
+ final Activity activity = getActivity();
+ new PollingCheck() {
+ @Override
+ protected boolean check() {
+ return activity.hasWindowFocus();
+ }
+ }.run();
+ mButton = null;
+ mView = null;
+ mListView = null;
+ mDialog = null;
+ mItemSelected = false;
+ mSelectedItem = null;
+ mSelectedItems = new ArrayList<Integer>();
+ }
+
+ public AlertDialog_BuilderTest() {
+ super("android.app.stubs", DialogStubActivity.class);
+ }
+
+ public void testConstructor() {
+ new AlertDialog.Builder(mContext);
+ }
+
+ public void testSetIconWithParamInt() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mDrawable = mContext.getResources().getDrawable(android.R.drawable.btn_default);
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setIcon(android.R.drawable.btn_default);
+ mDialog = mBuilder.show();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testSetIconWithParamDrawable() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mDrawable = mContext.getResources().getDrawable(android.R.drawable.btn_default);
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setIcon(mDrawable);
+ mDialog = mBuilder.show();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testSetPositiveButtonWithParamInt() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setPositiveButton(android.R.string.yes, mOnClickListener);
+ mDialog = mBuilder.show();
+ mButton = mDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+ mButton.performClick();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(mContext.getText(android.R.string.yes), mButton.getText());
+ assertTrue(mResult);
+ }
+
+ public void testSetPositiveButtonWithParamCharSequence() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setPositiveButton(android.R.string.yes, mOnClickListener);
+ mDialog = mBuilder.show();
+ mButton = mDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+ mButton.performClick();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(mContext.getText(android.R.string.yes), mButton.getText());
+ assertTrue(mResult);
+ }
+
+ public void testSetNegativeButtonWithParamCharSequence() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setNegativeButton(mTitle, mOnClickListener);
+ mDialog = mBuilder.show();
+ mButton = mDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
+ mButton.performClick();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(mTitle, mButton.getText());
+ assertTrue(mResult);
+ }
+
+ public void testSetNegativeButtonWithParamInt() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setNegativeButton(R.string.notify, mOnClickListener);
+ mDialog = mBuilder.show();
+ mButton = mDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
+ mButton.performClick();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(mContext.getText(R.string.notify), mButton.getText());
+ assertTrue(mResult);
+ }
+
+ public void testSetNeutralButtonWithParamInt() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setNeutralButton(R.string.notify, mOnClickListener);
+ mDialog = mBuilder.show();
+ mButton = mDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
+ mButton.performClick();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(mContext.getText(R.string.notify), mButton.getText());
+ assertTrue(mResult);
+ }
+
+ public void testSetNeutralButtonWithParamCharSequence() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setNeutralButton(mTitle, mOnClickListener);
+ mDialog = mBuilder.show();
+ mButton = mDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
+ mButton.performClick();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(mTitle, mButton.getText());
+ assertTrue(mResult);
+ }
+
+ private void testCancelable(final boolean cancelable) throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setCancelable(cancelable);
+ mDialog = mBuilder.show();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ new PollingCheck() {
+ @Override
+ protected boolean check() {
+ return mDialog.isShowing();
+ }
+ }.run();
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ mInstrumentation.waitForIdleSync();
+ new PollingCheck() {
+ @Override
+ protected boolean check() {
+ boolean showing = mDialog.isShowing();
+ if (cancelable) {
+ // if the dialog is cancelable, then pressing back
+ // should cancel it. Thus it should not be showing
+ return !showing;
+ } else {
+ // if the dialog is not cancelable, pressing back
+ // should so nothing and it should still be showing
+ return showing;
+ }
+ }
+ }.run();
+ }
+
+ public void testSetCancelable() throws Throwable {
+ testCancelable(true);
+ }
+
+ public void testDisableCancelable() throws Throwable {
+ testCancelable(false);
+ }
+
+ public void testSetOnCancelListener() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setOnCancelListener(mOnCancelListener);
+ mDialog = mBuilder.show();
+ mDialog.cancel();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mResult);
+ }
+
+ public void testSetOnKeyListener() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setOnKeyListener(mOnKeyListener);
+ mDialog = mBuilder.show();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ sendKeys(KeyEvent.ACTION_DOWN, KeyEvent.ACTION_DOWN);
+ assertTrue(mResult);
+ }
+
+ public void testSetItemsWithParamInt() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setItems(R.array.difficultyLevel, mOnClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ final CharSequence[] levels = mContext.getResources().getTextArray(
+ R.array.difficultyLevel);
+ assertEquals(levels[0], mListView.getItemAtPosition(0));
+ }
+
+ public void testSetItemsWithParamCharSequence() throws Throwable {
+ final CharSequence[] expect = mContext.getResources().getTextArray(
+ R.array.difficultyLevel);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setItems(expect, mOnClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(expect[0], mListView.getItemAtPosition(0));
+ }
+
+ public void testSetAdapter() throws Throwable {
+ final ListAdapter adapter = new AdapterTest();
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setAdapter(adapter, mOnClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(adapter, mListView.getAdapter());
+ }
+
+ public void testSetCursor() throws Throwable {
+ preparePeople();
+ final Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, mPROJECTION, null,
+ null, null);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setCursor(c, mOnClickListener, People.NAME);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ mListView.performItemClick(null, 0, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ final CursorWrapper selected = (CursorWrapper)mListView.getSelectedItem();
+ assertEquals(c.getString(1), selected.getString(1));
+ assertTrue(mResult);
+ }
+
+ public void testSetMultiChoiceItemsWithParamInt() throws Throwable {
+
+ final CharSequence[] items = mContext.getResources().getTextArray(
+ R.array.difficultyLevel);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setMultiChoiceItems(R.array.difficultyLevel, null,
+ mOnMultiChoiceClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ mSelectedItem = (CharSequence)mListView.getSelectedItem();
+ mListView.performItemClick(null, 0, 0);
+ mListView.performItemClick(null, 1, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(items[0], mSelectedItem);
+ assertEquals(2, mSelectedItems.size());
+ assertEquals(items[0], mListView.getItemAtPosition(0));
+ assertTrue(mResult);
+ }
+
+ public void testSetMultiChoiceItemsWithParamCharSequence() throws Throwable {
+ final CharSequence[] items = mContext.getResources().getTextArray(
+ R.array.difficultyLevel);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setMultiChoiceItems(items, null, mOnMultiChoiceClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ mSelectedItem = (CharSequence)mListView.getSelectedItem();
+ mListView.performItemClick(null, 0, 0);
+ mListView.performItemClick(null, 1, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(items[0], mSelectedItem);
+ assertEquals(2, mSelectedItems.size());
+ assertEquals(items[0], mListView.getItemAtPosition(0));
+ assertTrue(mResult);
+ }
+
+ public void testSetMultiChoiceItemsWithParamCursor() throws Throwable {
+ preparePeople();
+ final Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, mPROJECTION, null,
+ null, null);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setMultiChoiceItems(c, People.NAME, People.NAME,
+ mOnMultiChoiceClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ mListView.performItemClick(null, 0, 0);
+ mListView.performItemClick(null, 1, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ final CursorWrapper selected = (CursorWrapper)mListView.getSelectedItem();
+ assertEquals(c.getString(1), selected.getString(1));
+ assertEquals(2, mSelectedItems.size());
+ assertTrue(mResult);
+ }
+
+ public void testSetSingleChoiceItemsWithParamInt() throws Throwable {
+ final CharSequence[] items = mContext.getResources().getTextArray(
+ R.array.difficultyLevel);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setSingleChoiceItems(R.array.difficultyLevel, 0,
+ mOnClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ mSelectedItem = (CharSequence)mListView.getSelectedItem();
+ mListView.performItemClick(null, 0, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(items[0], mSelectedItem);
+ assertEquals(items[0], mListView.getItemAtPosition(0));
+ assertTrue(mResult);
+ }
+
+ private void preparePeople() {
+ final ContentResolver mResolver = mContext.getContentResolver();
+ mResolver.delete(People.CONTENT_URI, null, null);
+ final ContentValues valuse = new ContentValues();
+ valuse.put(People._ID, "1");
+ valuse.put(People.NAME, "name");
+ mResolver.insert(People.CONTENT_URI, valuse);
+ }
+
+ public void testSetSingleChoiceItemsWithParamCursor() throws Throwable {
+ final String[] PROJECTION = new String[] {
+ People._ID, People.NAME
+ };
+ preparePeople();
+ final Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, PROJECTION, null,
+ null, null);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setSingleChoiceItems(c, 0, People.NAME, mOnClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ mListView.performItemClick(null, 0, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ final CursorWrapper selected = (CursorWrapper)mListView.getSelectedItem();
+ assertEquals(c.getString(1), selected.getString(1));
+ assertTrue(mResult);
+ }
+
+ public void testSetSingleChoiceItemsWithParamCharSequence() throws Throwable {
+ final CharSequence[] items = mContext.getResources().getTextArray(
+ R.array.difficultyLevel);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setSingleChoiceItems(items, 0, mOnClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ mSelectedItem = (CharSequence)mListView.getSelectedItem();
+ mListView.performItemClick(null, 0, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(items[0], mSelectedItem);
+ assertEquals(items[0], mListView.getItemAtPosition(0));
+ assertTrue(mResult);
+ }
+
+ public void testSetSingleChoiceItems() throws Throwable {
+ final CharSequence[] items = mContext.getResources().getTextArray(
+ R.array.difficultyLevel);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setSingleChoiceItems(new ArrayAdapter<CharSequence>(mContext,
+ android.R.layout.select_dialog_singlechoice, android.R.id.text1, items), 0,
+ mOnClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ mSelectedItem = (CharSequence)mListView.getSelectedItem();
+ mListView.performItemClick(null, 0, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(items[0], mSelectedItem);
+ assertEquals(items[0], mListView.getItemAtPosition(0));
+ assertTrue(mResult);
+ }
+
+ public void testSetOnItemSelectedListener() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setOnItemSelectedListener(mOnItemSelectedListener);
+ mBuilder.setItems(R.array.difficultyLevel, mOnClickListener);
+ mDialog = mBuilder.show();
+ mListView = mDialog.getListView();
+ mListView.pointToPosition(0, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mItemSelected);
+ }
+
+ public void testSetView() throws Throwable {
+ final View view = new View(mContext);
+ view.setId(100);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setView(view);
+ mDialog = mBuilder.show();
+ mView = mDialog.getWindow().findViewById(100);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertEquals(view, mView);
+ }
+
+ public void testSetInverseBackgroundForced() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mBuilder.setInverseBackgroundForced(true);
+ mDialog = mBuilder.create();
+ mDialog.show();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testCreate() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mDialog = mBuilder.create();
+ mDialog.show();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertNotNull(mDialog);
+ assertTrue(mDialog.isShowing());
+ }
+
+ public void testShow() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mBuilder = new AlertDialog.Builder(mContext);
+ mDialog = mBuilder.show();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mDialog.isShowing());
+ }
+
+ private static class AdapterTest implements android.widget.ListAdapter {
+ public boolean areAllItemsEnabled() {
+ return true;
+ }
+
+ public boolean isEnabled(int position) {
+ return false;
+ }
+
+ public int getCount() {
+ return 0;
+ }
+
+ public Object getItem(int position) {
+ return null;
+ }
+
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ public int getItemViewType(int position) {
+ return 0;
+ }
+
+ public android.view.View getView( int position,
+ android.view.View convertView,
+ android.view.ViewGroup parent){
+ return null;
+ }
+
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ public boolean hasStableIds() {
+ return false;
+ }
+
+ public boolean isEmpty() {
+ return true;
+ }
+
+ public void registerDataSetObserver(
+ android.database.DataSetObserver observer) {
+ }
+
+ public void unregisterDataSetObserver(
+ android.database.DataSetObserver observer) {
+ }
+ }
+}
diff --git a/tests/app/src/android/app/cts/AliasActivityStub.java b/tests/app/src/android/app/cts/AliasActivityStub.java
deleted file mode 100644
index 977bdc3..0000000
--- a/tests/app/src/android/app/cts/AliasActivityStub.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.AliasActivity;
-import android.os.Bundle;
-
-public class AliasActivityStub extends AliasActivity {
-
- public static boolean isOnCreateCalled = false;
- public static boolean isFinished = false;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- isOnCreateCalled = true;
- }
-
- @Override
- public void finish() {
- super.finish();
- isFinished = true;
- }
-}
diff --git a/tests/app/src/android/app/cts/AliasActivityTest.java b/tests/app/src/android/app/cts/AliasActivityTest.java
new file mode 100644
index 0000000..d3fe06c
--- /dev/null
+++ b/tests/app/src/android/app/cts/AliasActivityTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.cts;
+
+import android.app.AliasActivity;
+import android.app.stubs.AliasActivityStub;
+import android.app.stubs.ChildActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.test.InstrumentationTestCase;
+
+public class AliasActivityTest extends InstrumentationTestCase {
+
+ private static final long SLEEP_TIME = 1000;
+
+ public void testAliasActivity() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ new AliasActivity();
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ Context context = getInstrumentation().getTargetContext();
+
+ Intent intent = new Intent();
+ intent.setClass(context, AliasActivityStub.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ assertFalse(ChildActivity.isStarted);
+ assertFalse(AliasActivityStub.isOnCreateCalled);
+ context.startActivity(intent);
+ Thread.sleep(SLEEP_TIME);
+ assertTrue(AliasActivityStub.isOnCreateCalled);
+ assertTrue(ChildActivity.isStarted);
+ assertTrue(AliasActivityStub.isFinished);
+ }
+
+}
diff --git a/tests/app/src/android/app/cts/AppStubActivity.java b/tests/app/src/android/app/cts/AppStubActivity.java
deleted file mode 100644
index da5e55a..0000000
--- a/tests/app/src/android/app/cts/AppStubActivity.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.view.ContextMenu;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
-
-import com.android.cts.app.stub.R;
-
-/**
- * A minimal "Hello, World!" application.
- */
-public class AppStubActivity extends Activity {
- private Dialog mDialog;
- public boolean mOnPrepareDialog;
- public boolean mOnOptionsMenuClosedCalled;
- public boolean mOnPrepareOptionsMenuCalled;
- public boolean mOnOptionsItemSelectedCalled;
- public boolean mOnCreateOptionsMenu;
- public boolean mIndterminate = false;
- public boolean mIndterminatevisibility = false;
- public boolean mSecPro = false;
- public boolean mOnContextItemSelectedCalled;
- public boolean mOnCreateContextMenu;
- public boolean mApplyResourceCalled;
- public boolean mCreateContextMenuCalled;
- public boolean mRequestWinFeatureRet = false;
-
- public AppStubActivity() {
-
- }
-
- public void finalize() {
- try {
- super.finalize();
- } catch (Throwable exception) {
- System.err.print("exception!");
- }
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- mRequestWinFeatureRet = requestWindowFeature(1);
- setContentView(R.layout.app_activity);
- }
-
- public Dialog getDialogById(int id) {
- return mDialog;
- }
-
- @Override
- public Dialog onCreateDialog(int id) {
- super.onCreateDialog(id);
- mDialog = new Dialog(this);
- return mDialog;
- }
-
- @Override
- protected void onPrepareDialog(int id, Dialog dialog) {
- super.onPrepareDialog(id, dialog);
- mOnPrepareDialog = true;
- }
-
- @Override
- public void onOptionsMenuClosed(Menu menu) {
- super.onOptionsMenuClosed(menu);
- mOnOptionsMenuClosedCalled = true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- mOnPrepareOptionsMenuCalled = true;
- return super.onPrepareOptionsMenu(menu);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- mOnCreateOptionsMenu = true;
- if(menu != null)
- menu.add(0, 0, 0, "Fake Item");
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- mOnOptionsItemSelectedCalled = true;
- return super.onOptionsItemSelected(item);
- }
-
- public boolean setProBarIndeterminate(boolean indeterminate){
- mIndterminate = indeterminate;
- super.setProgressBarIndeterminate(indeterminate);
- return mIndterminate;
- }
-
- public boolean setProBarIndeterminateVisibility(boolean visible){
- mIndterminatevisibility = visible;
- super.setProgressBarIndeterminateVisibility(visible);
- return mIndterminatevisibility;
- }
-
- public boolean setSecPro(int secPro){
- mSecPro = true;
- super.setSecondaryProgress(secPro);
- return mSecPro;
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item){
- mOnContextItemSelectedCalled = true;
- return super.onContextItemSelected(item);
- }
-
- @Override
- public void onApplyThemeResource( Resources.Theme theme,
- int resid,
- boolean first){
- super.onApplyThemeResource(theme,resid,first);
- mApplyResourceCalled = true;
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu,v,menuInfo);
- mCreateContextMenuCalled = true;
- }
-}
-
diff --git a/tests/app/src/android/app/cts/ApplicationTest.java b/tests/app/src/android/app/cts/ApplicationTest.java
new file mode 100644
index 0000000..aaed064
--- /dev/null
+++ b/tests/app/src/android/app/cts/ApplicationTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.Activity;
+import android.app.Application;
+import android.app.Instrumentation;
+import android.app.stubs.MockApplication;
+import android.app.stubs.MockApplicationActivity;
+import android.app.stubs.OrientationTestUtils;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.test.InstrumentationTestCase;
+
+/**
+ * Test {@link Application}.
+ */
+public class ApplicationTest extends InstrumentationTestCase {
+
+ public void testApplication() throws Throwable {
+ final Instrumentation instrumentation = getInstrumentation();
+ final Context targetContext = instrumentation.getTargetContext();
+
+ final Intent intent = new Intent(targetContext, MockApplicationActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ final Activity activity = instrumentation.startActivitySync(intent);
+ final MockApplication mockApp = (MockApplication) activity.getApplication();
+ assertTrue(mockApp.isConstructorCalled);
+ assertTrue(mockApp.isOnCreateCalled);
+
+ //skip if the device doesn't support both of portrait and landscape orientation screens.
+ final PackageManager pm = targetContext.getPackageManager();
+ if(!(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
+ && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT))){
+ return;
+ }
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ OrientationTestUtils.toggleOrientation(activity);
+ }
+ });
+ instrumentation.waitForIdleSync();
+ assertTrue(mockApp.isOnConfigurationChangedCalled);
+ }
+
+}
diff --git a/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java b/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java
deleted file mode 100644
index efe693a..0000000
--- a/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.cts.util.CTSResult;
-import android.test.InstrumentationTestCase;
-
-public class CTSActivityTestCaseBase extends InstrumentationTestCase implements CTSResult {
-
- private Sync mSync;
- static class Sync {
- public boolean mHasNotify;
- public int mResult;
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mSync = new Sync();
- }
-
- public void setResult(int resultCode) {
- synchronized (mSync) {
- mSync.mHasNotify = true;
- mSync.mResult = resultCode;
- mSync.notify();
- }
- }
-
- protected void waitForResult() throws InterruptedException {
- synchronized (mSync) {
- while (!mSync.mHasNotify) {
- mSync.wait();
- }
- assertEquals(CTSResult.RESULT_OK, mSync.mResult);
- }
- }
-}
diff --git a/tests/app/src/android/app/cts/ChildActivity.java b/tests/app/src/android/app/cts/ChildActivity.java
deleted file mode 100644
index 5f77655..0000000
--- a/tests/app/src/android/app/cts/ChildActivity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.Activity;
-
-public class ChildActivity extends Activity {
-
- public static boolean isStarted = false;
-
- @Override
- protected void onStart() {
- super.onStart();
- isStarted = true;
- }
-}
diff --git a/tests/app/src/android/app/cts/ChildTabActivity.java b/tests/app/src/android/app/cts/ChildTabActivity.java
deleted file mode 100644
index e3b2369..0000000
--- a/tests/app/src/android/app/cts/ChildTabActivity.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.Activity;
-
-/**
- * An empty activity for the TabActivity test
- */
-public class ChildTabActivity extends Activity {
-}
diff --git a/tests/app/src/android/app/cts/ClearTop.java b/tests/app/src/android/app/cts/ClearTop.java
deleted file mode 100644
index 5f608702..0000000
--- a/tests/app/src/android/app/cts/ClearTop.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-
-public class ClearTop extends Activity {
- public static final String WAIT_CLEAR_TASK = "waitClearTask";
- private static final String TAG = "ClearTop";
- public ClearTop() {
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- final Intent intent = new Intent(getIntent()).setAction(LocalScreen.CLEAR_TASK).setClass(
- this, LocalScreen.class);
- startActivity(intent);
- }
-
- @Override
- public void onNewIntent(Intent intent) {
- Log.i(TAG, "onNewIntent");
- if (LocalScreen.CLEAR_TASK.equals(intent.getAction())) {
- setResult(RESULT_OK);
- } else {
- setResult(RESULT_CANCELED, new Intent().setAction("New intent received " + intent
- + ", expecting action " + TestedScreen.CLEAR_TASK));
- }
- finish();
- }
-}
diff --git a/tests/app/src/android/app/cts/DialogStubActivity.java b/tests/app/src/android/app/cts/DialogStubActivity.java
deleted file mode 100644
index a773ae2..0000000
--- a/tests/app/src/android/app/cts/DialogStubActivity.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import com.android.cts.app.stub.R;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.DatePickerDialog;
-import android.app.Dialog;
-import android.app.TimePickerDialog;
-import android.app.DatePickerDialog.OnDateSetListener;
-import android.app.TimePickerDialog.OnTimeSetListener;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.DialogInterface.OnCancelListener;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.DatePicker;
-import android.widget.TimePicker;
-
-/*
- * Stub class for Dialog, AlertDialog, DatePickerDialog, TimePickerDialog etc.
- */
-public class DialogStubActivity extends Activity {
- public static final int TEST_DIALOG_WITHOUT_THEME = 0;
- public static final int TEST_DIALOG_WITH_THEME = 1;
- public static final int TEST_ALERTDIALOG = 2;
- public static final int TEST_CUSTOM_ALERTDIALOG = 3;
- public static final int TEST_DATEPICKERDIALOG = 4;
- public static final int TEST_DATEPICKERDIALOG_WITH_THEME = 5;
- public static final int TEST_TIMEPICKERDIALOG = 6;
- public static final int TEST_TIMEPICKERDIALOG_WITH_THEME = 7;
- public static final int TEST_ONSTART_AND_ONSTOP = 8;
- public static final int TEST_ALERTDIALOG_DEPRECATED = 9;
- public static final int TEST_ALERTDIALOG_CALLBACK = 10;
- public static final int TEST_CUSTOM_ALERTDIALOG_VIEW = 11;
- public static final int TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE = 12;
- public static final int TEST_ALERTDIALOG_THEME = 13;
- public static final int TEST_ALERTDIALOG_CANCELABLE = 14;
- public static final int TEST_ALERTDIALOG_NOT_CANCELABLE = 15;
- public static final int TEST_PROTECTED_CANCELABLE = 16;
- public static final int TEST_PROTECTED_NOT_CANCELABLE = 17;
-
- public static final int SPACING_LEFT = 10;
- public static final int SPACING_TOP = 20;
- public static final int SPACING_RIGHT = 30;
- public static final int SPACING_BOTTOM = 40;
- public static int buttonIndex;
-
- public static final String DEFAULT_ALERTDIALOG_TITLE = "AlertDialog";
- public static final String DEFAULT_ALERTDIALOG_MESSAGE = "AlertDialog message";
- private static final String LOG_TAG = "DialogStubActivity";
-
- public boolean isPositiveButtonClicked = false;
- public boolean isNegativeButtonClicked = false;
- public boolean isNeutralButtonClicked = false;
- public boolean isCallBackCalled;
- public boolean onCancelCalled;
- public boolean onKeyDownCalled;
- public boolean onKeyUpCalled;
- public boolean onCreateCalled;
- public boolean onCancelListenerCalled;
- public boolean onClickCalled;
- public static boolean onDateChangedCalled;
- public static boolean onRestoreInstanceStateCalled;
- public boolean onSaveInstanceStateCalled;
- public int updatedYear;
- public int updatedMonth;
- public int updatedDay;
-
- public final int INITIAL_YEAR = 2008;
- public final int INITIAL_MONTH = 7;
- public final int INITIAL_DAY_OF_MONTH = 27;
- private final int INITIAL_HOUR = 10;
- private final int INITIAL_MINUTE = 35;
- private Dialog mDialog;
- private AlertDialog mAlertDialog;
- private OnDateSetListener mOnDateSetListener = new OnDateSetListener() {
- public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
- updatedYear = year;
- updatedMonth = monthOfYear;
- updatedDay = dayOfMonth;
- }
- };
-
- @SuppressWarnings("deprecation")
- @Override
- protected Dialog onCreateDialog(int id) {
- switch (id) {
- case TEST_DIALOG_WITHOUT_THEME:
- mDialog = new Dialog(this);
- mDialog.setTitle("Hello, Dialog");
- break;
-
- case TEST_DIALOG_WITH_THEME:
- mDialog = new Dialog(this, 1);
- break;
-
- case TEST_ALERTDIALOG:
- mDialog = getAlertDialogInstance(false);
- break;
-
- case TEST_CUSTOM_ALERTDIALOG:
- mDialog = getCustomAlertDialogInstance(false);
- break;
-
- case TEST_CUSTOM_ALERTDIALOG_VIEW:
- mDialog = getCustomAlertDialogInstance(true);
- break;
-
- case TEST_DATEPICKERDIALOG:
- mDialog = new MockDatePickerDialog(this, mOnDateSetListener, INITIAL_YEAR,
- INITIAL_MONTH, INITIAL_DAY_OF_MONTH);
- break;
-
- case TEST_DATEPICKERDIALOG_WITH_THEME:
- mDialog = new MockDatePickerDialog(this,
- com.android.internal.R.style.Theme_Translucent, mOnDateSetListener,
- INITIAL_YEAR, INITIAL_MONTH, INITIAL_DAY_OF_MONTH);
- break;
-
- case TEST_TIMEPICKERDIALOG:
- mDialog = new TimePickerDialog(this, new OnTimeSetListener() {
- public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
- isCallBackCalled = true;
- }
- }, INITIAL_HOUR, INITIAL_MINUTE, true);
- break;
-
- case TEST_TIMEPICKERDIALOG_WITH_THEME:
- mDialog = new TimePickerDialog(this,
- com.android.internal.R.style.Theme_Translucent, null, INITIAL_HOUR,
- INITIAL_MINUTE, true);
- break;
-
- case TEST_ONSTART_AND_ONSTOP:
- mDialog = new TestDialog(this);
- Log.i(LOG_TAG, "mTestDialog:" + mDialog);
- return mDialog;
-
- case TEST_ALERTDIALOG_DEPRECATED:
- mDialog = getAlertDialogInstance(true);
- break;
-
- case TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE:
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- buttonIndex = msg.what;
- super.handleMessage(msg);
- }
- };
- final Message positiveMessage = Message.obtain();
- positiveMessage.setTarget(handler);
- positiveMessage.what = DialogInterface.BUTTON_POSITIVE;
-
- final Message negativeMessage = Message.obtain();
- negativeMessage.setTarget(handler);
- negativeMessage.what = DialogInterface.BUTTON_NEGATIVE;
-
- final Message neutralMessage = Message.obtain();
- neutralMessage.setTarget(handler);
- neutralMessage.what = DialogInterface.BUTTON_NEUTRAL;
- mAlertDialog = getAlertDialogInstance(false);
- mAlertDialog.setButton(getString(R.string.alert_dialog_positive), positiveMessage);
- mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), negativeMessage);
- mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), neutralMessage);
- mDialog = mAlertDialog;
- break;
-
- case TEST_ALERTDIALOG_CALLBACK:
- mDialog = new MockAlertDialog(this);
- break;
- case TEST_ALERTDIALOG_THEME:
- mDialog = new MockAlertDialog(this, R.style.Theme_AlertDialog);
- break;
- case TEST_ALERTDIALOG_CANCELABLE:
- mDialog = getAlertDialogCancelablInstance(true);
- break;
- case TEST_ALERTDIALOG_NOT_CANCELABLE:
- mDialog = getAlertDialogCancelablInstance(false);
- break;
- case TEST_PROTECTED_CANCELABLE:
- mDialog = new TestDialog(this, true, new OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- onCancelListenerCalled = true;
- }
- });
- break;
- case TEST_PROTECTED_NOT_CANCELABLE:
- mDialog = new TestDialog(this, false, new OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- onCancelListenerCalled = true;
- }
- });
- break;
- default:
- break;
- }
-
- Log.i(LOG_TAG, "mDialog:" + mDialog);
- return mDialog;
- }
-
- private AlertDialog getAlertDialogCancelablInstance(boolean cancelable) {
- OnCancelListener cancelListener = new OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- onCancelCalled = true;
- }
- };
- return new MockAlertDialog(this, cancelable, cancelListener);
- }
-
- @SuppressWarnings("deprecation")
- private AlertDialog getAlertDialogInstance(boolean deprecated) {
- mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create();
- mAlertDialog.setIcon(com.android.cts.app.stub.R.drawable.pass);
- mAlertDialog.setTitle(DEFAULT_ALERTDIALOG_TITLE);
- mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE);
- mAlertDialog.setInverseBackgroundForced(true);
- final DialogInterface.OnClickListener positiveListener = new MockOnClickListener(
- DialogInterface.BUTTON_POSITIVE);
- final DialogInterface.OnClickListener netativeListener = new MockOnClickListener(
- DialogInterface.BUTTON_NEGATIVE);
- final DialogInterface.OnClickListener neutralListener = new MockOnClickListener(
- DialogInterface.BUTTON_NEUTRAL);
-
- if (deprecated) {
- mAlertDialog.setButton(getString(R.string.alert_dialog_positive), positiveListener);
- mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), netativeListener);
- mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), neutralListener);
- } else {
- mAlertDialog.setButton(DialogInterface.BUTTON_POSITIVE,
- getString(R.string.alert_dialog_positive), positiveListener);
- mAlertDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
- getString(R.string.alert_dialog_negative), netativeListener);
- mAlertDialog.setButton(DialogInterface.BUTTON_NEUTRAL,
- getString(R.string.alert_dialog_neutral), neutralListener);
- }
- return mAlertDialog;
-
- }
-
- private AlertDialog getCustomAlertDialogInstance(boolean withSpacing) {
- final LayoutInflater inflate = getLayoutInflater();
- final View customTitleViewCustom = inflate.inflate(R.layout.alertdialog_custom_title, null);
- final View textEntryView = inflate.inflate(R.layout.alert_dialog_text_entry_2, null);
- mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create();
- mAlertDialog.setCustomTitle(customTitleViewCustom);
- mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE);
- if (withSpacing) {
- mAlertDialog.setView(textEntryView, SPACING_LEFT, SPACING_TOP, SPACING_RIGHT,
- SPACING_BOTTOM);
- } else {
- mAlertDialog.setView(textEntryView);
- }
-
- return mAlertDialog;
-
- }
-
- public Dialog getDialog() {
- return mDialog;
- }
-
- public String getDialogTitle() {
- return (String) mDialog.getWindow().getAttributes().getTitle();
- }
-
- private static final String TEST_DIALOG_NUMBER_EXTRA = "testDialogNumber";
-
- public static <T extends Activity> T startDialogActivity(
- ActivityInstrumentationTestCase2<T> testCase, int dialogNumber) {
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.putExtra(TEST_DIALOG_NUMBER_EXTRA, dialogNumber);
- testCase.setActivityIntent(intent);
- return testCase.getActivity();
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.dialog_stub_layout);
-
- Intent intent = getIntent();
- int dialogNum = intent.getIntExtra(TEST_DIALOG_NUMBER_EXTRA, -1);
- if (dialogNum != -1) {
- showDialog(dialogNum);
- }
- }
-
- public void setUpTitle(final String title) {
- runOnUiThread(new Runnable() {
- public void run() {
- getDialog().setTitle(title);
- }
- });
- }
-
- public void setUpTitle(final int id) {
- runOnUiThread(new Runnable() {
- public void run() {
- getDialog().setTitle(id);
- }
- });
- }
-
- class MockAlertDialog extends AlertDialog {
- public MockAlertDialog(Context context) {
- super(context);
- }
-
- public MockAlertDialog(Context context, int theme) {
- super(context, theme);
- }
-
- public MockAlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
- super(context, cancelable, cancelListener);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- onKeyDownCalled = true;
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- onKeyUpCalled = true;
- return super.onKeyUp(keyCode, event);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- onCreateCalled = true;
- super.onCreate(savedInstanceState);
- }
-
- }
-
- class MockOnClickListener implements DialogInterface.OnClickListener {
- private final int mId;
-
- public MockOnClickListener(final int buttonId) {
- mId = buttonId;
- }
-
- public void onClick(DialogInterface dialog, int which) {
- switch (mId) {
- case DialogInterface.BUTTON_POSITIVE:
- isPositiveButtonClicked = true;
- break;
- case DialogInterface.BUTTON_NEGATIVE:
- isNegativeButtonClicked = true;
- break;
- case DialogInterface.BUTTON_NEUTRAL:
- isNeutralButtonClicked = true;
- break;
- default:
- break;
- }
- }
- }
-
- class MockDatePickerDialog extends DatePickerDialog {
- public MockDatePickerDialog(Context context, OnDateSetListener callBack, int year,
- int monthOfYear, int dayOfMonth) {
- super(context, callBack, year, monthOfYear, dayOfMonth);
- }
-
- public MockDatePickerDialog(Context context, int theme, OnDateSetListener callBack,
- int year, int monthOfYear, int dayOfMonth) {
- super(context, theme, callBack, year, monthOfYear, dayOfMonth);
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- onClickCalled = true;
- super.onClick(dialog, which);
- }
-
- @Override
- public void onDateChanged(DatePicker view, int year, int month, int day) {
- onDateChangedCalled = true;
- super.onDateChanged(view, year, month, day);
- }
-
- @Override
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- onRestoreInstanceStateCalled = true;
- super.onRestoreInstanceState(savedInstanceState);
- }
-
- @Override
- public Bundle onSaveInstanceState() {
- onSaveInstanceStateCalled = true;
- return super.onSaveInstanceState();
- }
-
- }
-}
diff --git a/tests/app/src/android/app/cts/DialogTest.java b/tests/app/src/android/app/cts/DialogTest.java
new file mode 100755
index 0000000..8ae4c66
--- /dev/null
+++ b/tests/app/src/android/app/cts/DialogTest.java
@@ -0,0 +1,940 @@
+/*
+ * 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.
+ */
+package android.app.cts;
+
+import android.app.Dialog;
+import android.app.Instrumentation;
+import android.app.stubs.DialogStubActivity;
+import android.app.stubs.OrientationTestUtils;
+import android.app.stubs.TestDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.DialogInterface.OnKeyListener;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.cts.util.PollingCheck;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.LinearLayout;
+
+import android.app.stubs.R;
+
+import java.lang.ref.WeakReference;
+
+public class DialogTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
+
+ protected static final long SLEEP_TIME = 200;
+ private static final String STUB_ACTIVITY_PACKAGE = "android.app.stubs";
+ private static final long TEST_TIMEOUT = 1000L;
+
+ /**
+ * please refer to Dialog
+ */
+ private static final int DISMISS = 0x43;
+ private static final int CANCEL = 0x44;
+
+ private boolean mCalledCallback;
+ private boolean mIsKey0Listened;
+ private boolean mIsKey1Listened;
+ private boolean mOnCancelListenerCalled;
+
+ private Instrumentation mInstrumentation;
+ private Context mContext;
+ private DialogStubActivity mActivity;
+
+
+ public DialogTest() {
+ super(STUB_ACTIVITY_PACKAGE, DialogStubActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ mContext = mInstrumentation.getContext();
+ }
+
+ private void startDialogActivity(int dialogNumber) {
+ mActivity = DialogStubActivity.startDialogActivity(this, dialogNumber);
+ }
+
+ @UiThreadTest
+ public void testConstructor() {
+ new Dialog(mContext);
+ Dialog d = new Dialog(mContext, 0);
+ // According to javadoc of constructors, it will set theme to system default theme,
+ // when we set no theme id or set it theme id to 0.
+ // But CTS can no assert dialog theme equals system internal theme.
+
+ d = new Dialog(mContext, R.style.TextAppearance);
+ TypedArray ta =
+ d.getContext().getTheme().obtainStyledAttributes(R.styleable.TextAppearance);
+ assertTextAppearanceStyle(ta);
+
+ final Window w = d.getWindow();
+ ta = w.getContext().getTheme().obtainStyledAttributes(R.styleable.TextAppearance);
+ assertTextAppearanceStyle(ta);
+ }
+
+ public void testConstructor_protectedCancellable() {
+ startDialogActivity(DialogStubActivity.TEST_PROTECTED_CANCELABLE);
+ mActivity.onCancelListenerCalled = false;
+ sendKeys(KeyEvent.KEYCODE_BACK);
+ assertTrue(mActivity.onCancelListenerCalled);
+ }
+
+ public void testConstructor_protectedNotCancellable() {
+ startDialogActivity(DialogStubActivity.TEST_PROTECTED_NOT_CANCELABLE);
+ mActivity.onCancelListenerCalled = false;
+ sendKeys(KeyEvent.KEYCODE_BACK);
+ assertFalse(mActivity.onCancelListenerCalled);
+ }
+
+ private void assertTextAppearanceStyle(TypedArray ta) {
+ final int defValue = -1;
+ // get Theme and assert
+ final Resources.Theme expected = mContext.getResources().newTheme();
+ expected.setTo(mContext.getTheme());
+ expected.applyStyle(R.style.TextAppearance, true);
+ TypedArray expectedTa = expected.obtainStyledAttributes(R.styleable.TextAppearance);
+ assertEquals(expectedTa.getIndexCount(), ta.getIndexCount());
+ assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColor, defValue),
+ ta.getColor(R.styleable.TextAppearance_textColor, defValue));
+ assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColorHint, defValue),
+ ta.getColor(R.styleable.TextAppearance_textColorHint, defValue));
+ assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColorLink, defValue),
+ ta.getColor(R.styleable.TextAppearance_textColorLink, defValue));
+ assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColorHighlight, defValue),
+ ta.getColor(R.styleable.TextAppearance_textColorHighlight, defValue));
+ assertEquals(expectedTa.getDimension(R.styleable.TextAppearance_textSize, defValue),
+ ta.getDimension(R.styleable.TextAppearance_textSize, defValue));
+ assertEquals(expectedTa.getInt(R.styleable.TextAppearance_textStyle, defValue),
+ ta.getInt(R.styleable.TextAppearance_textStyle, defValue));
+ }
+
+ public void testOnStartCreateStop(){
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+
+ assertTrue(d.isOnStartCalled);
+ assertTrue(d.isOnCreateCalled);
+
+ assertFalse(d.isOnStopCalled);
+ sendKeys(KeyEvent.KEYCODE_BACK);
+ assertTrue(d.isOnStopCalled);
+ }
+
+ public void testAccessOwnerActivity() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ Dialog d = mActivity.getDialog();
+ assertNotNull(d);
+ assertSame(mActivity, d.getOwnerActivity());
+ d.setVolumeControlStream(d.getVolumeControlStream() + 1);
+ assertEquals(d.getOwnerActivity().getVolumeControlStream() + 1, d.getVolumeControlStream());
+
+ try {
+ d.setOwnerActivity(null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ Dialog dialog = new Dialog(mContext);
+ assertNull(dialog.getOwnerActivity());
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testShow() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+ final View decor = d.getWindow().getDecorView();
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.hide();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(View.GONE, decor.getVisibility());
+ assertTrue(d.isShowing());
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.show();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(View.VISIBLE, decor.getVisibility());
+ assertTrue(d.isShowing());
+ dialogDismiss(d);
+ assertFalse(d.isShowing());
+ }
+
+ public void testOnSaveInstanceState() {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+
+ assertFalse(d.isOnSaveInstanceStateCalled);
+ assertFalse(TestDialog.isOnRestoreInstanceStateCalled);
+
+ //skip if the device doesn't support both of portrait and landscape orientation screens.
+ final PackageManager pm = mContext.getPackageManager();
+ if(!(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
+ && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT))){
+ return;
+ }
+
+ OrientationTestUtils.toggleOrientationSync(mActivity, mInstrumentation);
+
+ assertTrue(d.isOnSaveInstanceStateCalled);
+ assertTrue(TestDialog.isOnRestoreInstanceStateCalled);
+ }
+
+ public void testGetCurrentFocus() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+ assertNull(d.getCurrentFocus());
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.takeKeyEvents(true);
+ d.setContentView(R.layout.alert_dialog_text_entry);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ sendKeys(KeyEvent.KEYCODE_0);
+ // When mWindow is not null getCUrrentFocus is the view in dialog
+ assertEquals(d.getWindow().getCurrentFocus(), d.getCurrentFocus());
+ }
+
+ public void testSetContentView() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+ assertNotNull(d);
+
+ // set content view to a four elements layout
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.setContentView(R.layout.alert_dialog_text_entry);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ // check if four elements are right there
+ assertNotNull(d.findViewById(R.id.username_view));
+ assertNotNull(d.findViewById(R.id.username_edit));
+ assertNotNull(d.findViewById(R.id.password_view));
+ assertNotNull(d.findViewById(R.id.password_edit));
+
+ final LayoutInflater inflate1 = d.getLayoutInflater();
+
+ // set content view to a two elements layout
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.setContentView(inflate1.inflate(R.layout.alert_dialog_text_entry_2, null));
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ // check if only two elements are right there
+ assertNotNull(d.findViewById(R.id.username_view));
+ assertNotNull(d.findViewById(R.id.username_edit));
+ assertNull(d.findViewById(R.id.password_view));
+ assertNull(d.findViewById(R.id.password_edit));
+
+ final WindowManager.LayoutParams lp = d.getWindow().getAttributes();
+ final LayoutInflater inflate2 = mActivity.getLayoutInflater();
+
+ // set content view to a four elements layout
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.setContentView(inflate2.inflate(R.layout.alert_dialog_text_entry, null), lp);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ // check if four elements are right there
+ assertNotNull(d.findViewById(R.id.username_view));
+ assertNotNull(d.findViewById(R.id.username_edit));
+ assertNotNull(d.findViewById(R.id.password_view));
+ assertNotNull(d.findViewById(R.id.password_edit));
+
+ final WindowManager.LayoutParams lp2 = d.getWindow().getAttributes();
+ final LayoutInflater inflate3 = mActivity.getLayoutInflater();
+ lp2.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ lp2.width = ViewGroup.LayoutParams.WRAP_CONTENT;
+
+ // add a check box view
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.addContentView(inflate3.inflate(R.layout.checkbox_layout, null), lp2);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ // check if four elements are right there, and new add view there.
+ assertNotNull(d.findViewById(R.id.check_box));
+ assertNotNull(d.findViewById(R.id.username_view));
+ assertNotNull(d.findViewById(R.id.username_edit));
+ assertNotNull(d.findViewById(R.id.password_view));
+ assertNotNull(d.findViewById(R.id.password_edit));
+ }
+
+ public void testSetTitle() {
+ final String expectedTitle = "Test Dialog Without theme";
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+
+ assertNotNull(mActivity.getDialog());
+ mActivity.setUpTitle(expectedTitle);
+ mInstrumentation.waitForIdleSync();
+
+ final Dialog d = mActivity.getDialog();
+ assertEquals(expectedTitle, (String) d.getWindow().getAttributes().getTitle());
+
+ mActivity.setUpTitle(R.string.hello_android);
+ mInstrumentation.waitForIdleSync();
+ assertEquals(mActivity.getResources().getString(R.string.hello_android),
+ (String) d.getWindow().getAttributes().getTitle());
+ }
+
+ public void testOnKeyDownKeyUp() {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+ assertFalse(d.isOnKeyDownCalled);
+ assertFalse(d.isOnKeyUpCalled);
+
+ // send key 0 down and up events, onKeyDown return false
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
+ assertTrue(d.isOnKeyDownCalled);
+ assertTrue(d.isOnKeyUpCalled);
+ assertEquals(KeyEvent.KEYCODE_0, d.keyDownCode);
+ assertFalse(d.onKeyDownReturn);
+
+ // send key back down and up events, onKeyDown return true
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ assertEquals(KeyEvent.KEYCODE_BACK, d.keyDownCode);
+ assertTrue(d.onKeyDownReturn);
+ }
+
+ public void testOnKeyMultiple() {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+
+ assertNull(d.keyMultipleEvent);
+ d.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_UNKNOWN));
+ assertTrue(d.isOnKeyMultipleCalled);
+ assertFalse(d.onKeyMultipleReturn);
+ assertEquals(KeyEvent.KEYCODE_UNKNOWN, d.keyMultipleEvent.getKeyCode());
+ assertEquals(KeyEvent.ACTION_MULTIPLE, d.keyMultipleEvent.getAction());
+ }
+
+ public void testTouchEvent() {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+
+ assertNull(d.onTouchEvent);
+ assertNull(d.touchEvent);
+ assertFalse(d.isOnTouchEventCalled);
+
+ // Send a touch event outside the activity. The event will be ignored
+ // because closeOnTouchOutside is false.
+ d.setCanceledOnTouchOutside(false);
+
+ long now = SystemClock.uptimeMillis();
+ MotionEvent touchMotionEvent = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
+ 1, getStatusBarHeight(), 0);
+ mInstrumentation.sendPointerSync(touchMotionEvent);
+
+ new PollingCheck(TEST_TIMEOUT) {
+ protected boolean check() {
+ return !d.dispatchTouchEventResult;
+ }
+ }.run();
+
+ assertMotionEventEquals(touchMotionEvent, d.touchEvent);
+
+ assertTrue(d.isOnTouchEventCalled);
+ assertMotionEventEquals(touchMotionEvent, d.onTouchEvent);
+ d.isOnTouchEventCalled = false;
+ assertTrue(d.isShowing());
+
+ // Watch activities cover the entire screen, so there is no way to touch outside.
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ // Send a touch event outside the activity. This time the dialog will be dismissed
+ // because closeOnTouchOutside is true.
+ d.setCanceledOnTouchOutside(true);
+
+ touchMotionEvent = MotionEvent.obtain(now, now + 1, MotionEvent.ACTION_DOWN,
+ 1, getStatusBarHeight(), 0);
+ mInstrumentation.sendPointerSync(touchMotionEvent);
+
+ new PollingCheck(TEST_TIMEOUT) {
+ protected boolean check() {
+ return d.dispatchTouchEventResult;
+ }
+ }.run();
+
+ assertMotionEventEquals(touchMotionEvent, d.touchEvent);
+
+ assertTrue(d.isOnTouchEventCalled);
+ assertMotionEventEquals(touchMotionEvent, d.onTouchEvent);
+ assertFalse(d.isShowing());
+ }
+ }
+
+ private int getStatusBarHeight() {
+ final Rect rect = new Rect();
+ Window window = mActivity.getWindow();
+ window.getDecorView().getWindowVisibleDisplayFrame(rect);
+ return rect.top;
+ }
+
+ public void testTrackballEvent() {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+ long eventTime = SystemClock.uptimeMillis();
+ final MotionEvent trackBallEvent = MotionEvent.obtain(eventTime, eventTime,
+ MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0);
+
+ assertNull(d.trackballEvent);
+ assertNull(d.onTrackballEvent);
+
+ assertFalse(d.isOnTrackballEventCalled);
+ mInstrumentation.sendTrackballEventSync(trackBallEvent);
+ assertTrue(d.isOnTrackballEventCalled);
+ assertMotionEventEquals(trackBallEvent, d.trackballEvent);
+ assertMotionEventEquals(trackBallEvent, d.onTrackballEvent);
+
+ }
+
+ private void assertMotionEventEquals(final MotionEvent expected, final MotionEvent actual) {
+ assertEquals(expected.getDownTime(), actual.getDownTime());
+ assertEquals(expected.getEventTime(), actual.getEventTime());
+ assertEquals(expected.getAction(), actual.getAction());
+ assertEquals(expected.getMetaState(), actual.getMetaState());
+ assertEquals(expected.getSize(), actual.getSize());
+ // As MotionEvent doc says the value of X and Y coordinate may have
+ // a fraction for input devices that are sub-pixel precise,
+ // so we won't assert them here.
+ }
+
+ public void testOnWindowAttributesChanged() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+
+ assertTrue(d.isOnWindowAttributesChangedCalled);
+ d.isOnWindowAttributesChangedCalled = false;
+
+ final WindowManager.LayoutParams lp = d.getWindow().getAttributes();
+ lp.setTitle("test OnWindowAttributesChanged");
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.getWindow().setAttributes(lp);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(d.isOnWindowAttributesChangedCalled);
+ assertSame(lp, d.getWindow().getAttributes());
+ }
+
+ public void testOnContentChanged() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+ assertNotNull(d);
+
+ assertFalse(d.isOnContentChangedCalled);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.setContentView(R.layout.alert_dialog_text_entry);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(d.isOnContentChangedCalled);
+ }
+
+ public void testOnWindowFocusChanged() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+ assertTrue(d.isOnWindowFocusChangedCalled);
+ d.isOnWindowFocusChangedCalled = false;
+
+ // show a new dialog, the new dialog get focus
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mActivity.showDialog(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ // Wait until TestDialog#OnWindowFocusChanged() is called
+ new PollingCheck(TEST_TIMEOUT) {
+ protected boolean check() {
+ return d.isOnWindowFocusChangedCalled;
+ }
+ }.run();
+ }
+
+ public void testDispatchKeyEvent() {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+
+ sendKeys(KeyEvent.KEYCODE_0);
+ assertFalse(d.dispatchKeyEventResult);
+ assertEquals(KeyEvent.KEYCODE_0, d.keyEvent.getKeyCode());
+
+ d.setOnKeyListener(new OnKeyListener() {
+ public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+ if (KeyEvent.ACTION_DOWN == event.getAction()) {
+ if (KeyEvent.KEYCODE_0 == keyCode) {
+ mIsKey0Listened = true;
+ return true;
+ }
+
+ if (KeyEvent.KEYCODE_1 == keyCode) {
+ mIsKey1Listened = true;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ });
+
+ mIsKey1Listened = false;
+ sendKeys(KeyEvent.KEYCODE_1);
+ assertTrue(mIsKey1Listened);
+
+ mIsKey0Listened = false;
+ sendKeys(KeyEvent.KEYCODE_0);
+ assertTrue(mIsKey0Listened);
+ }
+
+ /*
+ * Test point
+ * 1. registerForContextMenu() will OnCreateContextMenuListener on the view to this activity,
+ * so onCreateContextMenu() will be called when it is time to show the context menu.
+ * 2. Close context menu will make onPanelClosed to be called,
+ * and onPanelClosed will calls through to the new onPanelClosed method.
+ * 3. unregisterForContextMenu() will remove the OnCreateContextMenuListener on the view,
+ * so onCreateContextMenu() will not be called when try to open context menu.
+ * 4. Selected a item of context menu will make onMenuItemSelected() to be called,
+ * and onMenuItemSelected will calls through to the new onContextItemSelected method.
+ * 5. onContextMenuClosed is called whenever the context menu is being closed (either by
+ * the user canceling the menu with the back/menu button, or when an item is selected).
+ */
+ public void testContextMenu() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+ final LinearLayout parent = new LinearLayout(mContext);
+ final MockView v = new MockView(mContext);
+ parent.addView(v);
+ assertFalse(v.isShowContextMenuCalled);
+ // Register for context menu and open it
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.addContentView(parent, new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ d.registerForContextMenu(v);
+ d.openContextMenu(v);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(v.isShowContextMenuCalled);
+ assertTrue(d.isOnCreateContextMenuCalled);
+
+ assertFalse(d.isOnPanelClosedCalled);
+ assertFalse(d.isOnContextMenuClosedCalled);
+ // Closed context menu
+ sendKeys(KeyEvent.KEYCODE_BACK);
+ assertTrue(d.isOnPanelClosedCalled);
+ // Here isOnContextMenuClosedCalled should be true, see bug 1716918.
+ assertFalse(d.isOnContextMenuClosedCalled);
+
+ v.isShowContextMenuCalled = false;
+ d.isOnCreateContextMenuCalled = false;
+ // Unregister for context menu, and try to open it
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.unregisterForContextMenu(v);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.openContextMenu(v);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(v.isShowContextMenuCalled);
+ assertFalse(d.isOnCreateContextMenuCalled);
+
+ // Register for context menu and open it again
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.registerForContextMenu(v);
+ d.openContextMenu(v);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertFalse(d.isOnContextItemSelectedCalled);
+ assertFalse(d.isOnMenuItemSelectedCalled);
+ d.isOnPanelClosedCalled = false;
+ assertFalse(d.isOnContextMenuClosedCalled);
+ // select a context menu item
+ sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+ assertTrue(d.isOnMenuItemSelectedCalled);
+ // Here isOnContextItemSelectedCalled should be true, see bug 1716918.
+ assertFalse(d.isOnContextItemSelectedCalled);
+ assertTrue(d.isOnPanelClosedCalled);
+ // Here isOnContextMenuClosedCalled should be true, see bug 1716918.
+ assertFalse(d.isOnContextMenuClosedCalled);
+ }
+
+ public void testOnSearchRequested() {
+ }
+
+ public void testTakeKeyEvents() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+ final View v = d.getWindow().getDecorView();
+ assertNull(d.getCurrentFocus());
+ takeKeyEvents(d, true);
+ assertTrue(v.isFocusable());
+ sendKeys(KeyEvent.KEYCODE_0);
+ assertEquals(KeyEvent.KEYCODE_0, d.keyEvent.getKeyCode());
+ d.keyEvent = null;
+
+ takeKeyEvents(d, false);
+ assertNull(d.getCurrentFocus());
+ assertFalse(v.isFocusable());
+ sendKeys(KeyEvent.KEYCODE_0);
+ // d.keyEvent should be null
+ }
+
+ private void takeKeyEvents(final Dialog d, final boolean get) throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.takeKeyEvents(get);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testRequestWindowFeature() {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ // called requestWindowFeature at TestDialog onCreate method
+ assertTrue(((TestDialog) mActivity.getDialog()).isRequestWindowFeature);
+ }
+
+ public void testSetFeatureDrawableResource() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mActivity.getDialog().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
+ R.drawable.robot);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testSetFeatureDrawableUri() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mActivity.getDialog().setFeatureDrawableUri(Window.FEATURE_LEFT_ICON,
+ Uri.parse("http://www.google.com"));
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testSetFeatureDrawable() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mActivity.getDialog().setFeatureDrawable(Window.FEATURE_LEFT_ICON,
+ new MockDrawable());
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testSetFeatureDrawableAlpha() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mActivity.getDialog().setFeatureDrawableAlpha(Window.FEATURE_LEFT_ICON, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ public void testGetLayoutInflater() {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+ assertEquals(d.getWindow().getLayoutInflater(), d.getLayoutInflater());
+ }
+
+ public void testSetCancelable_true() {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+
+ d.setCancelable(true);
+ assertTrue(d.isShowing());
+ sendKeys(KeyEvent.KEYCODE_BACK);
+ assertFalse(d.isShowing());
+ }
+
+ public void testSetCancellable_false() {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+
+ d.setCancelable(false);
+ assertTrue(d.isShowing());
+ sendKeys(KeyEvent.KEYCODE_BACK);
+ assertTrue(d.isShowing());
+ }
+
+ /*
+ * Test point
+ * 1. Cancel the dialog.
+ * 2. Set a listener to be invoked when the dialog is canceled.
+ */
+ public void testCancel_listener() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+
+ assertTrue(d.isShowing());
+ mOnCancelListenerCalled = false;
+ d.setOnCancelListener(new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ mOnCancelListenerCalled = true;
+ }
+ });
+ dialogCancel(d);
+
+ assertFalse(d.isShowing());
+ assertTrue(mOnCancelListenerCalled);
+ }
+
+ public void testCancel_noListener() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+
+ assertTrue(d.isShowing());
+ mOnCancelListenerCalled = false;
+ d.setOnCancelListener(null);
+ dialogCancel(d);
+
+ assertFalse(d.isShowing());
+ assertFalse(mOnCancelListenerCalled);
+ }
+
+ public void testSetCancelMessage() throws Exception {
+ mCalledCallback = false;
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+ final HandlerThread ht = new HandlerThread("DialogTest");
+ ht.start();
+
+ d.setCancelMessage(new MockDismissCancelHandler(d, ht.getLooper()).obtainMessage(CANCEL,
+ new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ mCalledCallback = true;
+ }
+ }));
+ assertTrue(d.isShowing());
+ assertFalse(mCalledCallback);
+ sendKeys(KeyEvent.KEYCODE_BACK);
+ assertTrue(mCalledCallback);
+ assertFalse(d.isShowing());
+
+ ht.join(100);
+ }
+
+ /*
+ * Test point
+ * 1. Set a listener to be invoked when the dialog is dismissed.
+ * 2. set onDismissListener to null, it will not changed flag after dialog dismissed.
+ */
+ public void testSetOnDismissListener_listener() throws Throwable {
+ mCalledCallback = false;
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+
+ d.setOnDismissListener(new OnDismissListener() {
+ public void onDismiss(DialogInterface dialog) {
+ mCalledCallback = true;
+ }
+ });
+
+ assertTrue(d.isShowing());
+ assertFalse(mCalledCallback);
+ dialogDismiss(d);
+ assertTrue(mCalledCallback);
+ assertFalse(d.isShowing());
+ }
+
+ public void testSetOnDismissListener_noListener() throws Throwable {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+ assertTrue(d.isShowing());
+ mCalledCallback = false;
+ d.setOnDismissListener(null);
+ dialogDismiss(d);
+ assertFalse(mCalledCallback);
+ assertFalse(d.isShowing());
+ }
+
+ public void testSetDismissMessage() throws Throwable {
+ mCalledCallback = false;
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+
+ final HandlerThread ht = new HandlerThread("DialogTest");
+ ht.start();
+
+ d.setDismissMessage(new MockDismissCancelHandler(d, ht.getLooper()).obtainMessage(DISMISS,
+ new OnDismissListener() {
+ public void onDismiss(DialogInterface dialog) {
+ mCalledCallback = true;
+ }
+ }));
+ assertTrue(d.isShowing());
+ assertFalse(mCalledCallback);
+ dialogDismiss(d);
+ ht.join(100);
+ assertTrue(mCalledCallback);
+ assertFalse(d.isShowing());
+ }
+
+ private void dialogDismiss(final Dialog d) throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.dismiss();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ private void dialogCancel(final Dialog d) throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.cancel();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ private static class MockDismissCancelHandler extends Handler {
+ private WeakReference<DialogInterface> mDialog;
+
+ public MockDismissCancelHandler(Dialog dialog, Looper looper) {
+ super(looper);
+
+ mDialog = new WeakReference<DialogInterface>(dialog);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case DISMISS:
+ ((OnDismissListener) msg.obj).onDismiss(mDialog.get());
+ break;
+ case CANCEL:
+ ((OnCancelListener) msg.obj).onCancel(mDialog.get());
+ break;
+ }
+ }
+ }
+
+ private static class MockDrawable extends Drawable {
+ @Override
+ public void draw(Canvas canvas) {
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ }
+ }
+
+ private static class MockView extends View {
+ public boolean isShowContextMenuCalled;
+ protected OnCreateContextMenuListener mOnCreateContextMenuListener;
+
+ public MockView(Context context) {
+ super(context);
+ }
+
+ public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
+ super.setOnCreateContextMenuListener(l);
+ mOnCreateContextMenuListener = l;
+ }
+
+ public OnCreateContextMenuListener getOnCreateContextMenuListener() {
+ return mOnCreateContextMenuListener;
+ }
+
+ @Override
+ public boolean showContextMenu() {
+ isShowContextMenuCalled = true;
+ return super.showContextMenu();
+ }
+ }
+}
diff --git a/tests/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/DownloadManagerTest.java
rename to tests/app/src/android/app/cts/DownloadManagerTest.java
diff --git a/tests/app/src/android/app/cts/ExpandableListActivityTest.java b/tests/app/src/android/app/cts/ExpandableListActivityTest.java
new file mode 100644
index 0000000..a457cf7
--- /dev/null
+++ b/tests/app/src/android/app/cts/ExpandableListActivityTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.stubs.ActivityTestsBase;
+import android.app.stubs.ExpandableListTestActivity;
+import android.app.stubs.LaunchpadActivity;
+import android.content.ComponentName;
+
+public class ExpandableListActivityTest extends ActivityTestsBase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mIntent.putExtra("component", new ComponentName(getContext(),
+ ExpandableListTestActivity.class));
+ }
+
+ public void testSelect() {
+ runLaunchpad(LaunchpadActivity.EXPANDLIST_SELECT);
+ }
+
+ public void testView() {
+ runLaunchpad(LaunchpadActivity.EXPANDLIST_VIEW);
+ }
+
+ public void testCallback() {
+ runLaunchpad(LaunchpadActivity.EXPANDLIST_CALLBACK);
+ }
+}
\ No newline at end of file
diff --git a/tests/app/src/android/app/cts/ExpandableListTestActivity.java b/tests/app/src/android/app/cts/ExpandableListTestActivity.java
deleted file mode 100644
index 8c8b65b..0000000
--- a/tests/app/src/android/app/cts/ExpandableListTestActivity.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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.
- */
-package android.app.cts;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import android.app.ExpandableListActivity;
-import android.os.Bundle;
-import android.os.Looper;
-import android.os.MessageQueue;
-import android.view.ContextMenu;
-import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.widget.ExpandableListAdapter;
-import android.widget.ExpandableListView;
-import android.widget.SimpleExpandableListAdapter;
-
-import com.android.internal.R;
-import com.android.internal.view.menu.ContextMenuBuilder;
-import com.google.android.collect.Lists;
-
-public class ExpandableListTestActivity extends ExpandableListActivity {
- private static final String NAME = "NAME";
- private static final String IS_EVEN = "IS_EVEN";
- private boolean mOnContentChangedCalled = false;
- private boolean mOnCreateContextMenuCalled = false;
- private boolean mOnGroupCollapseCalled = false;
- private boolean mOnGroupExpandCalled = false;
- private ExpandableListAdapter mAdapter;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- final List<Map<String, String>> groupData = Lists.newArrayList();
- final List<List<Map<String, String>>> childData = Lists.newArrayList();
- for (int i = 0; i < 20; i++) {
- final Map<String, String> curGroupMap = new HashMap<String, String>();
- groupData.add(curGroupMap);
- curGroupMap.put(NAME, "Group " + i);
- curGroupMap.put(IS_EVEN, (i % 2 == 0) ? "This group is even" : "This group is odd");
-
- final List<Map<String, String>> children = Lists.newArrayList();
- for (int j = 0; j < 15; j++) {
- Map<String, String> curChildMap = new HashMap<String, String>();
- children.add(curChildMap);
- curChildMap.put(NAME, "Child " + j);
- curChildMap.put(IS_EVEN, (j % 2 == 0) ? "This child is even" : "This child is odd");
- }
- childData.add(children);
- }
-
- // Set up our adapter
- mAdapter = new SimpleExpandableListAdapter(this, groupData,
- R.layout.simple_expandable_list_item_1,
- new String[] { NAME, IS_EVEN }, new int[] { R.id.text1, R.id.text2 }, childData,
- R.layout.simple_expandable_list_item_2,
- new String[] { NAME, IS_EVEN }, new int[] { R.id.text1, R.id.text2 });
- setListAdapter(mAdapter);
-
- }
-
- private int testCallback() {
- final ExpandableListView v = getExpandableListView();
- final ExpandableListAdapter a = getExpandableListAdapter();
- final View convertView = new View(this);
- final View gv = a.getGroupView(0, true, convertView, v);
- v.setOnCreateContextMenuListener(this);
- v.createContextMenu(new ContextMenuBuilder(this));
- for (int i = 0; i < 20; i++) {
- v.expandGroup(i);
- v.performClick();
- v.performLongClick();
- for (int k = 0; k < 15; k++) {
- v.performItemClick(gv, i, k);
- }
- v.collapseGroup(i);
- }
- if (mOnContentChangedCalled && mOnCreateContextMenuCalled
- && mOnGroupCollapseCalled && mOnGroupExpandCalled)
- return RESULT_OK;
-
- return RESULT_CANCELED;
- }
-
- private int testView() {
- final ExpandableListView currentView = getExpandableListView();
- for (int i = 0; i < 20; i++) {
- if (!currentView.expandGroup(i))
- return RESULT_CANCELED;
- if (!currentView.collapseGroup(i))
- return RESULT_CANCELED;
- }
- final View otherView = findViewById(android.R.id.list);
- setContentView(otherView);
- if (!otherView.equals(getExpandableListView()))
- return RESULT_CANCELED;
- setContentView(currentView);
- return RESULT_OK;
- }
-
- private int testSelecte() {
- final ExpandableListView v = getExpandableListView();
- for (int i = 0; i < 20; i++) {
- v.expandGroup(i);
- setSelectedGroup(i);
- for (int k = 0; k < 15; k++) {
- setSelectedChild(i, k, false);
- if (ExpandableListView.getPackedPositionForChild(i, k) != getSelectedPosition())
- return RESULT_CANCELED;
- }
-
- for (int k = 0; k < 15; k++) {
- setSelectedChild(i, k, true);
- if (ExpandableListView.getPackedPositionForChild(i, k) != getSelectedPosition())
- return RESULT_CANCELED;
- }
- v.collapseGroup(i);
- }
- return RESULT_OK;
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- final String action = getIntent().getAction();
- if (LaunchpadActivity.EXPANDLIST_SELECT.equals(action)) {
- setResult(testSelecte());
- } else if (LaunchpadActivity.EXPANDLIST_VIEW.equals(action)) {
- setResult(testView());
- } else if (LaunchpadActivity.EXPANDLIST_CALLBACK.equals(action)) {
- setResult(testCallback());
- }
- Looper.myQueue().addIdleHandler(new Idler());
- }
-
- protected void onRestoreInstanceState(Bundle state) {
- super.onRestoreInstanceState(state);
- }
-
- @Override
- public void onContentChanged() {
- mOnContentChangedCalled = true;
- super.onContentChanged();
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
- mOnCreateContextMenuCalled = true;
- super.onCreateContextMenu(menu, v, menuInfo);
- }
-
- @Override
- public void onGroupCollapse(int groupPosition) {
- mOnGroupCollapseCalled = true;
- super.onGroupCollapse(groupPosition);
- }
-
- @Override
- public void onGroupExpand(int groupPosition) {
- mOnGroupExpandCalled = true;
- super.onGroupExpand(groupPosition);
- }
-
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- }
-
- protected void onStop() {
- super.onStop();
- }
-
- private class Idler implements MessageQueue.IdleHandler {
- public final boolean queueIdle() {
- finish();
- return false;
- }
- }
-
-}
diff --git a/tests/app/src/android/app/cts/FragmentReplaceTest.java b/tests/app/src/android/app/cts/FragmentReplaceTest.java
new file mode 100644
index 0000000..ad9e3af
--- /dev/null
+++ b/tests/app/src/android/app/cts/FragmentReplaceTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.stubs.FragmentTestActivity;
+import android.app.stubs.FragmentTestActivity.TestFragment;
+import android.app.stubs.R;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+
+/**
+ * Test to prevent regressions in FragmentManager fragment replace method. See b/24693644
+ */
+public class FragmentReplaceTest extends
+ ActivityInstrumentationTestCase2<FragmentTestActivity> {
+ private FragmentTestActivity mActivity;
+
+
+ public FragmentReplaceTest() {
+ super(FragmentTestActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ }
+
+ @UiThreadTest
+ public void testReplaceFragment() throws Throwable {
+ mActivity.getFragmentManager().beginTransaction()
+ .add(R.id.content, new TestFragment(R.layout.fragment_a))
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ assertNotNull(mActivity.findViewById(R.id.textA));
+ assertNull(mActivity.findViewById(R.id.textB));
+ assertNull(mActivity.findViewById(R.id.textC));
+
+ mActivity.getFragmentManager().beginTransaction()
+ .add(R.id.content, new TestFragment(R.layout.fragment_b))
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ assertNotNull(mActivity.findViewById(R.id.textA));
+ assertNotNull(mActivity.findViewById(R.id.textB));
+ assertNull(mActivity.findViewById(R.id.textC));
+
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, new TestFragment(R.layout.fragment_c))
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ assertNull(mActivity.findViewById(R.id.textA));
+ assertNull(mActivity.findViewById(R.id.textB));
+ assertNotNull(mActivity.findViewById(R.id.textC));
+ }
+}
diff --git a/tests/tests/app/src/android/app/cts/FragmentTest.java b/tests/app/src/android/app/cts/FragmentTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/FragmentTest.java
rename to tests/app/src/android/app/cts/FragmentTest.java
diff --git a/tests/app/src/android/app/cts/FragmentTransitionTest.java b/tests/app/src/android/app/cts/FragmentTransitionTest.java
new file mode 100644
index 0000000..7270672
--- /dev/null
+++ b/tests/app/src/android/app/cts/FragmentTransitionTest.java
@@ -0,0 +1,466 @@
+/*
+ * 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.
+ */
+package android.app.cts;
+
+import android.app.FragmentManager;
+import android.app.stubs.FragmentTestActivity;
+import android.app.stubs.FragmentTestActivity.OnTransitionListener;
+import android.app.stubs.FragmentTestActivity.TestFragment;
+import android.app.stubs.R;
+import android.os.Debug;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.View;
+
+public class FragmentTransitionTest extends
+ ActivityInstrumentationTestCase2<FragmentTestActivity> {
+ private TestFragment mStartFragment;
+ private TestFragment mMidFragment;
+ private TestFragment mEndFragment;
+ private FragmentTestActivity mActivity;
+
+ public FragmentTransitionTest() {
+ super(FragmentTestActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mStartFragment = null;
+ mMidFragment = null;
+ mEndFragment = null;
+ mActivity = getActivity();
+ }
+
+ public void testFragmentTransition() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mStartFragment = new TestFragment(R.layout.fragment_start);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mStartFragment)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mStartFragment, TestFragment.ENTER);
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
+ mStartFragment.clearNotifications();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ final View sharedElement = mActivity.findViewById(R.id.hello);
+ assertEquals("source", sharedElement.getTransitionName());
+
+ mEndFragment = new TestFragment(R.layout.fragment_end);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mEndFragment)
+ .addSharedElement(sharedElement, "destination")
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mEndFragment, TestFragment.ENTER);
+ assertTrue(mEndFragment.wasEndCalled(TestFragment.ENTER));
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.EXIT));
+ assertTrue(mEndFragment.wasEndCalled(TestFragment.SHARED_ELEMENT_ENTER));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ final View textView = mActivity.findViewById(R.id.hello);
+ assertEquals("destination", textView.getTransitionName());
+ mActivity.getFragmentManager().popBackStack();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mStartFragment, TestFragment.REENTER);
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.REENTER));
+ assertTrue(mEndFragment.wasEndCalled(TestFragment.RETURN));
+ }
+
+ public void testFirstOutLastInTransition() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mStartFragment = new TestFragment(R.layout.fragment_start);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mStartFragment)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mStartFragment, TestFragment.ENTER);
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
+ mStartFragment.clearNotifications();
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mMidFragment = new TestFragment(R.layout.checkbox_layout);
+ mEndFragment = new TestFragment(R.layout.fragment_end);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mMidFragment)
+ .replace(R.id.content, mEndFragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mEndFragment, TestFragment.ENTER);
+ assertTrue(mEndFragment.wasEndCalled(TestFragment.ENTER));
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.EXIT));
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.RETURN));
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.REENTER));
+
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.EXIT));
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.ENTER));
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.RETURN));
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.REENTER));
+
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
+
+ mStartFragment.clearNotifications();
+ mEndFragment.clearNotifications();
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.getFragmentManager().popBackStack();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mEndFragment, TestFragment.RETURN);
+ assertTrue(mEndFragment.wasEndCalled(TestFragment.RETURN));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
+
+ assertTrue(mStartFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.RETURN));
+ }
+
+ public void testPopTwo() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mStartFragment = new TestFragment(R.layout.fragment_start);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mStartFragment)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mStartFragment, TestFragment.ENTER);
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
+ mStartFragment.clearNotifications();
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mMidFragment = new TestFragment(R.layout.checkbox_layout);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mMidFragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mMidFragment, TestFragment.ENTER);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mEndFragment = new TestFragment(R.layout.fragment_end);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mEndFragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mEndFragment, TestFragment.ENTER);
+ assertTrue(mEndFragment.wasEndCalled(TestFragment.ENTER));
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.EXIT));
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.RETURN));
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.REENTER));
+
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.EXIT));
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.ENTER));
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.RETURN));
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.REENTER));
+
+ assertTrue(mMidFragment.wasStartCalled(TestFragment.ENTER));
+ assertTrue(mMidFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
+
+ mStartFragment.clearNotifications();
+ mMidFragment.clearNotifications();
+ mEndFragment.clearNotifications();
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ FragmentManager fm = mActivity.getFragmentManager();
+ int id = fm.getBackStackEntryAt(0).getId();
+ fm.popBackStack(id, FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ fm.executePendingTransactions();
+ }
+ });
+ waitForEnd(mEndFragment, TestFragment.RETURN);
+ assertTrue(mEndFragment.wasEndCalled(TestFragment.RETURN));
+
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
+
+ assertTrue(mStartFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.RETURN));
+ }
+
+ public void testNullTransition() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mStartFragment = new TestFragment(R.layout.fragment_start);
+ mStartFragment.clearTransitions();
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mStartFragment)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForStart(mStartFragment, TestFragment.ENTER);
+ // No transitions
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mMidFragment = new TestFragment(R.layout.checkbox_layout);
+ mEndFragment = new TestFragment(R.layout.fragment_end);
+ mEndFragment.clearTransitions();
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mMidFragment)
+ .replace(R.id.content, mEndFragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForStart(mEndFragment, TestFragment.ENTER);
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.ENTER));
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.EXIT));
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.RETURN));
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.REENTER));
+
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.EXIT));
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.ENTER));
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.RETURN));
+ assertFalse(mStartFragment.wasEndCalled(TestFragment.REENTER));
+
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.getFragmentManager().popBackStack();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForStart(mEndFragment, TestFragment.RETURN);
+ assertFalse(mEndFragment.wasEndCalled(TestFragment.RETURN));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mMidFragment.wasStartCalled(TestFragment.RETURN));
+
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.RETURN));
+ }
+
+ public void testRemoveAdded() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mStartFragment = new TestFragment(R.layout.fragment_start);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mStartFragment)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mStartFragment, TestFragment.ENTER);
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
+ mStartFragment.clearNotifications();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mEndFragment = new TestFragment(R.layout.fragment_end);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mEndFragment)
+ .replace(R.id.content, mStartFragment)
+ .replace(R.id.content, mEndFragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mEndFragment, TestFragment.ENTER);
+ assertTrue(mEndFragment.wasEndCalled(TestFragment.ENTER));
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.EXIT));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.getFragmentManager().popBackStack();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mStartFragment, TestFragment.REENTER);
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.REENTER));
+ assertTrue(mEndFragment.wasEndCalled(TestFragment.RETURN));
+ }
+
+ public void testAddRemoved() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mStartFragment = new TestFragment(R.layout.fragment_start);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mStartFragment)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForEnd(mStartFragment, TestFragment.ENTER);
+ assertTrue(mStartFragment.wasEndCalled(TestFragment.ENTER));
+ mStartFragment.clearNotifications();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mEndFragment = new TestFragment(R.layout.fragment_end);
+ mActivity.getFragmentManager().beginTransaction()
+ .replace(R.id.content, mEndFragment)
+ .replace(R.id.content, mStartFragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForStart(mStartFragment, TestFragment.ENTER);
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.EXIT));
+ assertFalse(mEndFragment.wasStartCalled(TestFragment.ENTER));
+ assertFalse(mEndFragment.wasStartCalled(TestFragment.EXIT));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.getFragmentManager().popBackStack();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ waitForStart(mStartFragment, TestFragment.REENTER);
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mStartFragment.wasStartCalled(TestFragment.RETURN));
+ assertFalse(mEndFragment.wasStartCalled(TestFragment.REENTER));
+ assertFalse(mEndFragment.wasStartCalled(TestFragment.RETURN));
+ }
+
+ private boolean waitForStart(TestFragment fragment, int key) throws InterruptedException {
+ final boolean started;
+ WaitForTransition listener = new WaitForTransition(key, true);
+ fragment.setOnTransitionListener(listener);
+ final long endTime = SystemClock.uptimeMillis() + 100;
+ synchronized (listener) {
+ long waitTime;
+ while ((waitTime = endTime - SystemClock.uptimeMillis()) > 0 &&
+ !listener.isDone()) {
+ listener.wait(waitTime);
+ }
+ started = listener.isDone();
+ }
+ fragment.setOnTransitionListener(null);
+ getInstrumentation().waitForIdleSync();
+ return started;
+ }
+
+ private boolean waitForEnd(TestFragment fragment, int key) throws InterruptedException {
+ if (!waitForStart(fragment, key)) {
+ return false;
+ }
+ final boolean ended;
+ WaitForTransition listener = new WaitForTransition(key, false);
+ fragment.setOnTransitionListener(listener);
+ final long endTime = SystemClock.uptimeMillis() + 400;
+ synchronized (listener) {
+ long waitTime;
+ while ((waitTime = endTime - SystemClock.uptimeMillis()) > 0 &&
+ !listener.isDone()) {
+ listener.wait(waitTime);
+ }
+ ended = listener.isDone();
+ }
+ fragment.setOnTransitionListener(null);
+ getInstrumentation().waitForIdleSync();
+ return ended;
+ }
+
+ private static class WaitForTransition implements OnTransitionListener {
+ final int key;
+ final boolean isStart;
+ boolean isDone;
+
+ public WaitForTransition(int key, boolean isStart) {
+ this.key = key;
+ this.isStart = isStart;
+ }
+
+ protected boolean isComplete(TestFragment fragment) {
+ if (isStart) {
+ return fragment.wasStartCalled(key);
+ } else {
+ return fragment.wasEndCalled(key);
+ }
+ }
+
+ public synchronized boolean isDone() {
+ return isDone;
+ }
+
+ @Override
+ public synchronized void onTransition(TestFragment fragment) {
+ isDone = isComplete(fragment);
+ if (isDone) {
+ notifyAll();
+ }
+ }
+ }
+
+}
diff --git a/tests/app/src/android/app/cts/ISecondary.aidl b/tests/app/src/android/app/cts/ISecondary.aidl
deleted file mode 100644
index c3280d3..0000000
--- a/tests/app/src/android/app/cts/ISecondary.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-interface ISecondary {
-
- int getPid();
-
- long getElapsedCpuTime();
-
- String getTimeZoneID();
-}
diff --git a/tests/app/src/android/app/cts/InstrumentationTest.java b/tests/app/src/android/app/cts/InstrumentationTest.java
new file mode 100644
index 0000000..5019586
--- /dev/null
+++ b/tests/app/src/android/app/cts/InstrumentationTest.java
@@ -0,0 +1,717 @@
+/*
+ * 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.cts;
+
+import android.app.Activity;
+import android.app.Application;
+import android.app.Instrumentation;
+import android.app.Instrumentation.ActivityMonitor;
+import android.app.Instrumentation.ActivityResult;
+import android.app.stubs.InstrumentationTestActivity;
+import android.app.stubs.MockApplication;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.graphics.Point;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
+import android.view.InputQueue;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.view.Window;
+
+import java.util.List;
+
+import android.app.stubs.R;
+
+public class InstrumentationTest extends InstrumentationTestCase {
+
+ private static final int WAIT_TIME = 1000;
+ private Instrumentation mInstrumentation;
+ private InstrumentationTestActivity mActivity;
+ private Intent mIntent;
+ private boolean mRunOnMainSyncResult;
+ private Context mContext;
+ private MockActivity mMockActivity;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ mContext = mInstrumentation.getTargetContext();
+ mIntent = new Intent(mContext, InstrumentationTestActivity.class);
+ mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mActivity = (InstrumentationTestActivity) mInstrumentation.startActivitySync(mIntent);
+ }
+
+ protected void tearDown() throws Exception {
+ mInstrumentation = null;
+ mIntent = null;
+ if (mActivity != null) {
+ mActivity.finish();
+ mActivity = null;
+ }
+ super.tearDown();
+ }
+
+ public void testConstructor() throws Exception {
+ new Instrumentation();
+ }
+
+ public void testMonitor() throws Exception {
+ if (mActivity != null)
+ mActivity.finish();
+ ActivityResult result = new ActivityResult(Activity.RESULT_OK, new Intent());
+ ActivityMonitor monitor = new ActivityMonitor(
+ InstrumentationTestActivity.class.getName(), result, false);
+ mInstrumentation.addMonitor(monitor);
+ Intent intent = new Intent(mContext, InstrumentationTestActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ Activity activity = mInstrumentation.waitForMonitorWithTimeout(monitor, WAIT_TIME);
+ assertTrue(activity instanceof InstrumentationTestActivity);
+ assertTrue(mInstrumentation.checkMonitorHit(monitor, 1));
+ activity.finish();
+
+ mInstrumentation.addMonitor(monitor);
+ mInstrumentation.removeMonitor(monitor);
+ Activity a = mInstrumentation.startActivitySync(intent);
+ assertTrue(a instanceof InstrumentationTestActivity);
+ activity = mInstrumentation.waitForMonitorWithTimeout(monitor, WAIT_TIME);
+ assertNull(activity);
+ a.finish();
+
+ IntentFilter filter = new IntentFilter();
+ ActivityMonitor am = mInstrumentation.addMonitor(filter, result, false);
+ mContext.startActivity(intent);
+ mInstrumentation.waitForIdleSync();
+ activity = am.waitForActivity();
+ assertTrue(activity instanceof InstrumentationTestActivity);
+ activity.finish();
+ mInstrumentation.removeMonitor(am);
+ am = mInstrumentation
+ .addMonitor(InstrumentationTestActivity.class.getName(), result, false);
+ mContext.startActivity(intent);
+ activity = am.waitForActivity();
+ assertTrue(activity instanceof InstrumentationTestActivity);
+ activity.finish();
+ mInstrumentation.removeMonitor(am);
+ }
+
+ public void testCallActivityOnCreate() throws Throwable {
+ mActivity.setOnCreateCalled(false);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mInstrumentation.callActivityOnCreate(mActivity, new Bundle());
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnCreateCalled());
+ }
+
+ public void testAllocCounting() throws Exception {
+ mInstrumentation.startAllocCounting();
+
+ Bundle b = mInstrumentation.getAllocCounts();
+ assertTrue(b.size() > 0);
+ b = mInstrumentation.getBinderCounts();
+ assertTrue(b.size() > 0);
+
+ int globeAllocCount = Debug.getGlobalAllocCount();
+ int globeAllocSize = Debug.getGlobalAllocSize();
+ int globeExternalAllCount = Debug.getGlobalExternalAllocCount();
+ int globeExternalAllSize = Debug.getGlobalExternalAllocSize();
+ int threadAllocCount = Debug.getThreadAllocCount();
+
+ assertTrue(Debug.getGlobalAllocCount() >= globeAllocCount);
+ assertTrue(Debug.getGlobalAllocSize() >= globeAllocSize);
+ assertTrue(Debug.getGlobalExternalAllocCount() >= globeExternalAllCount);
+ assertTrue(Debug.getGlobalExternalAllocSize() >= globeExternalAllSize);
+ assertTrue(Debug.getThreadAllocCount() >= threadAllocCount);
+
+ mInstrumentation.stopAllocCounting();
+
+ globeAllocCount = Debug.getGlobalAllocCount();
+ globeAllocSize = Debug.getGlobalAllocSize();
+ globeExternalAllCount = Debug.getGlobalExternalAllocCount();
+ globeExternalAllSize = Debug.getGlobalExternalAllocSize();
+ threadAllocCount = Debug.getThreadAllocCount();
+ assertEquals(globeAllocCount, Debug.getGlobalAllocCount());
+ assertEquals(globeAllocSize, Debug.getGlobalAllocSize());
+ assertEquals(globeExternalAllCount, Debug.getGlobalExternalAllocCount());
+ assertEquals(globeExternalAllSize, Debug.getGlobalExternalAllocSize());
+ assertEquals(threadAllocCount, Debug.getThreadAllocCount());
+ }
+
+ public void testSendTrackballEventSync() throws Exception {
+ long now = SystemClock.uptimeMillis();
+ MotionEvent orig = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
+ 100, 100, 0);
+ mInstrumentation.sendTrackballEventSync(orig);
+ mInstrumentation.waitForIdleSync();
+
+ MotionEvent motionEvent = mActivity.getMotionEvent();
+ assertEquals(orig.getMetaState(), motionEvent.getMetaState());
+ assertEquals(orig.getEventTime(), motionEvent.getEventTime());
+ assertEquals(orig.getDownTime(), motionEvent.getDownTime());
+ }
+
+ public void testCallApplicationOnCreate() throws Exception {
+ InstrumentationTestStub ca = new InstrumentationTestStub();
+ mInstrumentation.callApplicationOnCreate(ca);
+ assertTrue(ca.mIsOnCreateCalled);
+ }
+
+ public void testContext() throws Exception {
+ Context c1 = mInstrumentation.getContext();
+ Context c2 = mInstrumentation.getTargetContext();
+ assertNotSame(c1.getPackageName(), c2.getPackageName());
+ }
+
+ public void testInvokeMenuActionSync() throws Exception {
+ final int resId = R.id.goto_menu_id;
+ if (mActivity.getWindow().hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+ mInstrumentation.invokeMenuActionSync(mActivity, resId, 0);
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(resId, mActivity.getMenuID());
+ }
+ }
+
+ public void testCallActivityOnPostCreate() throws Throwable {
+ mActivity.setOnPostCreate(false);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mInstrumentation.callActivityOnPostCreate(mActivity, new Bundle());
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnPostCreate());
+ }
+
+ public void testCallActivityOnNewIntent() throws Throwable {
+ mActivity.setOnNewIntentCalled(false);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mInstrumentation.callActivityOnNewIntent(mActivity, null);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(mActivity.isOnNewIntentCalled());
+ }
+
+ public void testCallActivityOnResume() throws Throwable {
+ mActivity.setOnResume(false);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mInstrumentation.callActivityOnResume(mActivity);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnResume());
+ }
+
+ public void testMisc() throws Exception {
+ }
+
+ public void testPerformanceSnapshot() throws Exception {
+ mInstrumentation.setAutomaticPerformanceSnapshots();
+ mInstrumentation.startPerformanceSnapshot();
+ mInstrumentation.endPerformanceSnapshot();
+ }
+
+ public void testProfiling() throws Exception {
+ // by default, profiling was disabled. but after set the handleProfiling attribute in the
+ // manifest file for this Instrumentation to true, the profiling was also disabled.
+ assertFalse(mInstrumentation.isProfiling());
+
+ mInstrumentation.startProfiling();
+ mInstrumentation.stopProfiling();
+ }
+
+ public void testInvokeContextMenuAction() throws Exception {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mMockActivity = new MockActivity();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ final int id = 1;
+ final int flag = 2;
+ mInstrumentation.invokeContextMenuAction(mMockActivity, id, flag);
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(id, mMockActivity.mWindow.mId);
+ assertEquals(flag, mMockActivity.mWindow.mFlags);
+ }
+
+ public void testSendStringSync() {
+ final String text = "abcd";
+ mInstrumentation.sendStringSync(text);
+ mInstrumentation.waitForIdleSync();
+
+ List<KeyEvent> keyUpList = mActivity.getKeyUpList();
+ List<KeyEvent> keyDownList = mActivity.getKeyDownList();
+ assertEquals(text.length(), keyDownList.size());
+ assertEquals(text.length(), keyUpList.size());
+
+ KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
+ KeyEvent[] keyEvents = kcm.getEvents(text.toCharArray());
+
+ int i = 0;
+ for (int j = 0; j < keyDownList.size(); j++) {
+ assertEquals(keyEvents[i++].getKeyCode(), keyDownList.get(j).getKeyCode());
+ assertEquals(keyEvents[i++].getKeyCode(), keyUpList.get(j).getKeyCode());
+ }
+ }
+
+ public void testCallActivityOnSaveInstanceState() throws Throwable {
+ final Bundle bundle = new Bundle();
+ mActivity.setOnSaveInstanceState(false);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mInstrumentation.callActivityOnSaveInstanceState(mActivity, bundle);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(mActivity.isOnSaveInstanceState());
+ assertSame(bundle, mActivity.getBundle());
+ }
+
+ public void testSendPointerSync() throws Exception {
+ mInstrumentation.waitForIdleSync();
+ mInstrumentation.setInTouchMode(true);
+
+ // Send a touch event to the middle of the activity.
+ // We assume that the Activity is empty so there won't be anything in the middle
+ // to handle the touch. Consequently the Activity should receive onTouchEvent
+ // because nothing else handled it.
+ Point size = new Point();
+ mActivity.getWindowManager().getDefaultDisplay().getSize(size);
+ final int x = size.x / 2;
+ final int y = size.y / 2;
+ long now = SystemClock.uptimeMillis();
+ MotionEvent orig = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
+ x, y, 0);
+ mInstrumentation.sendPointerSync(orig);
+
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnTouchEventCalled());
+ mActivity.setOnTouchEventCalled(false);
+ }
+
+ public void testGetComponentName() throws Exception {
+ ComponentName com = getInstrumentation().getComponentName();
+ assertNotNull(com.getPackageName());
+ assertNotNull(com.getClassName());
+ assertNotNull(com.getShortClassName());
+ }
+
+ public void testNewApplication() throws Exception {
+ final String className = "android.app.stubs.MockApplication";
+ ClassLoader cl = getClass().getClassLoader();
+
+ Application app = mInstrumentation.newApplication(cl, className, mContext);
+ assertEquals(className, app.getClass().getName());
+
+ app = Instrumentation.newApplication(MockApplication.class, mContext);
+ assertEquals(className, app.getClass().getName());
+ }
+
+ public void testRunOnMainSync() throws Exception {
+ mRunOnMainSyncResult = false;
+ mInstrumentation.runOnMainSync(new Runnable() {
+ public void run() {
+ mRunOnMainSyncResult = true;
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mRunOnMainSyncResult);
+ }
+
+ public void testCallActivityOnPause() throws Exception {
+ mActivity.setOnPauseCalled(false);
+ mInstrumentation.callActivityOnPause(mActivity);
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnPauseCalled());
+ }
+
+ public void testSendKeyDownUpSync() throws Exception {
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
+ mInstrumentation.waitForIdleSync();
+ assertEquals(1, mActivity.getKeyUpList().size());
+ assertEquals(1, mActivity.getKeyDownList().size());
+ assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyUpList().get(0).getKeyCode());
+ assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyDownList().get(0).getKeyCode());
+ }
+
+ @UiThreadTest
+ public void testNewActivity() throws Exception {
+ Intent intent = new Intent();
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ ClassLoader cl = getClass().getClassLoader();
+ Activity activity = mInstrumentation.newActivity(cl, InstrumentationTestActivity.class
+ .getName(), intent);
+ assertEquals(InstrumentationTestActivity.class.getName(), activity.getClass().getName());
+ activity.finish();
+ activity = null;
+
+ intent = new Intent(mContext, InstrumentationTestActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ Activity father = new Activity();
+ ActivityInfo info = new ActivityInfo();
+
+ activity = mInstrumentation
+ .newActivity(InstrumentationTestActivity.class, mContext, null, null, intent, info,
+ InstrumentationTestActivity.class.getName(), father, null, null);
+
+ assertEquals(father, activity.getParent());
+ assertEquals(InstrumentationTestActivity.class.getName(), activity.getClass().getName());
+ activity.finish();
+ }
+
+ public void testCallActivityOnStart() throws Exception {
+ mActivity.setOnStart(false);
+ mInstrumentation.callActivityOnStart(mActivity);
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnStart());
+ }
+
+ public void testWaitForIdle() throws Exception {
+ MockRunnable mr = new MockRunnable();
+ assertFalse(mr.isRunCalled());
+ mInstrumentation.waitForIdle(mr);
+ Thread.sleep(WAIT_TIME);
+ assertTrue(mr.isRunCalled());
+ }
+
+ public void testSendCharacterSync() throws Exception {
+ mInstrumentation.sendCharacterSync(KeyEvent.KEYCODE_0);
+ mInstrumentation.waitForIdleSync();
+ assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyDownCode());
+ assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyUpCode());
+ }
+
+ public void testCallActivityOnRestart() throws Exception {
+ mActivity.setOnRestart(false);
+ mInstrumentation.callActivityOnRestart(mActivity);
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnRestart());
+ }
+
+ public void testCallActivityOnStop() throws Exception {
+ mActivity.setOnStop(false);
+ mInstrumentation.callActivityOnStop(mActivity);
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnStop());
+ }
+
+ public void testCallActivityOnUserLeaving() throws Exception {
+ assertFalse(mActivity.isOnLeave());
+ mInstrumentation.callActivityOnUserLeaving(mActivity);
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnLeave());
+ }
+
+ public void testCallActivityOnRestoreInstanceState() throws Exception {
+ mActivity.setOnRestoreInstanceState(false);
+ mInstrumentation.callActivityOnRestoreInstanceState(mActivity, new Bundle());
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActivity.isOnRestoreInstanceState());
+ }
+
+ public void testSendKeySync() throws Exception {
+ KeyEvent key = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
+ mInstrumentation.sendKeySync(key);
+ mInstrumentation.waitForIdleSync();
+ assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyDownCode());
+ }
+
+ private static class MockRunnable implements Runnable {
+ private boolean mIsRunCalled ;
+
+ public void run() {
+ mIsRunCalled = true;
+ }
+
+ public boolean isRunCalled() {
+ return mIsRunCalled;
+ }
+ }
+
+ private class MockActivity extends Activity {
+ MockWindow mWindow = new MockWindow(mContext);
+
+ @Override
+ public Window getWindow() {
+ return mWindow;
+ }
+
+ private class MockWindow extends Window {
+
+ public int mId;
+ public int mFlags;
+
+ public MockWindow(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void addContentView(View view, LayoutParams params) {
+ }
+
+ @Override
+ public void closeAllPanels() {
+ }
+
+ @Override
+ public void closePanel(int featureId) {
+ }
+
+ @Override
+ public View getCurrentFocus() {
+ return null;
+ }
+
+ @Override
+ public View getDecorView() {
+ return null;
+ }
+
+ @Override
+ public LayoutInflater getLayoutInflater() {
+ return null;
+ }
+
+ @Override
+ public int getVolumeControlStream() {
+ return 0;
+ }
+
+ @Override
+ public boolean isFloating() {
+ return false;
+ }
+
+ @Override
+ public boolean isShortcutKey(int keyCode, KeyEvent event) {
+ return false;
+ }
+
+ @Override
+ protected void onActive() {
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ }
+
+ @Override
+ public void openPanel(int featureId, KeyEvent event) {
+ }
+
+ public void alwaysReadCloseOnTouchAttr() {
+ }
+
+ @Override
+ public View peekDecorView() {
+ return null;
+ }
+
+ @Override
+ public boolean performContextMenuIdentifierAction(int id, int flags) {
+ mId = id;
+ mFlags = flags;
+ return false;
+ }
+
+ @Override
+ public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
+ return false;
+ }
+
+ @Override
+ public boolean performPanelShortcut(int featureId, int keyCode,
+ KeyEvent event, int flags) {
+ return false;
+ }
+
+ @Override
+ public void restoreHierarchyState(Bundle savedInstanceState) {
+ }
+
+ @Override
+ public Bundle saveHierarchyState() {
+ return null;
+ }
+
+ @Override
+ public void setBackgroundDrawable(Drawable drawable) {
+ }
+
+ @Override
+ public void setChildDrawable(int featureId, Drawable drawable) {
+ }
+
+ @Override
+ public void setChildInt(int featureId, int value) {
+ }
+
+ @Override
+ public void setContentView(int layoutResID) {
+ }
+
+ @Override
+ public void setContentView(View view) {
+ }
+
+ @Override
+ public void setContentView(View view, LayoutParams params) {
+ }
+
+ @Override
+ public void setFeatureDrawable(int featureId, Drawable drawable) {
+ }
+
+ @Override
+ public void setFeatureDrawableAlpha(int featureId, int alpha) {
+ }
+
+ @Override
+ public void setFeatureDrawableResource(int featureId, int resId) {
+ }
+
+ @Override
+ public void setFeatureDrawableUri(int featureId, Uri uri) {
+ }
+
+ @Override
+ public void setFeatureInt(int featureId, int value) {
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ }
+
+ @Override
+ public void setTitleColor(int textColor) {
+ }
+
+ @Override
+ public void setVolumeControlStream(int streamType) {
+ }
+
+ @Override
+ public boolean superDispatchKeyEvent(KeyEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean superDispatchTouchEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean superDispatchTrackballEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean superDispatchGenericMotionEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public void takeKeyEvents(boolean get) {
+ }
+
+ @Override
+ public void togglePanel(int featureId, KeyEvent event) {
+ }
+
+ @Override
+ public void invalidatePanelMenu(int featureId) {
+ }
+
+ @Override
+ public void takeSurface(SurfaceHolder.Callback2 callback) {
+ }
+
+ @Override
+ public void takeInputQueue(InputQueue.Callback queue) {
+ }
+
+ @Override
+ public void setStatusBarColor(int color) {
+ }
+
+ @Override
+ public int getStatusBarColor() {
+ return 0;
+ }
+
+ @Override
+ public void setNavigationBarColor(int color) {
+ }
+
+ @Override
+ public void setDecorCaptionShade(int decorCaptionShade) {
+ }
+
+ @Override
+ public void setResizingCaptionDrawable(Drawable drawable) {
+ }
+
+ @Override
+ public int getNavigationBarColor() {
+ return 0;
+ }
+ }
+ }
+
+ private static class InstrumentationTestStub extends Application {
+ boolean mIsOnCreateCalled = false;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mIsOnCreateCalled = true;
+ }
+ }
+}
diff --git a/tests/app/src/android/app/cts/InstrumentationTestActivity.java b/tests/app/src/android/app/cts/InstrumentationTestActivity.java
deleted file mode 100644
index bec721e..0000000
--- a/tests/app/src/android/app/cts/InstrumentationTestActivity.java
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * 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.cts;
-
-import java.util.ArrayList;
-import java.util.List;
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.TextView;
-import com.android.cts.app.stub.R;
-
-public class InstrumentationTestActivity extends Activity {
-
- private boolean mOnCreateCalled;
- private boolean mOnDestroyCalled ;
- private boolean mOnNewIntentCalled;
- private boolean mOnPauseCalled;
- private boolean mOnPostCreate;
- private boolean mOnRestart;
- private boolean mOnRestoreInstanceState;
- private boolean mOnResume;
- private boolean mOnSaveInstanceState;
- private boolean mOnStart;
- private boolean mOnStop;
- private boolean mOnMenuOpened;
- private boolean mOnLeave;
- private int mMenuID;
- private boolean mOnTouchEventCalled;
- private int mKeyDownCode;
- private int mKeyUpCode;
- private MotionEvent mMotionEvent;
- private Bundle mBundle;
- private MockTextView mTextView;
- private List<KeyEvent> mKeyDownList = new ArrayList<KeyEvent>();
- private List<KeyEvent> mKeyUpList = new ArrayList<KeyEvent>();
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mTextView = new MockTextView(this);
- setContentView(mTextView);
- mOnCreateCalled = true;
- }
-
- class MockTextView extends TextView {
-
- public MockTextView(Context context) {
- super(context);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- return super.onTouchEvent(event);
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- return super.onTrackballEvent(event);
- }
-
- @Override
- public void getLocationOnScreen(int[] location) {
- super.getLocationOnScreen(location);
- location[0] = location[1] = 10;
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mOnDestroyCalled = true;
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- mOnNewIntentCalled = true;
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mOnPauseCalled = true;
- }
-
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- mOnPostCreate = true;
- }
-
- @Override
- protected void onRestart() {
- super.onRestart();
- mOnRestart = true;
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- mOnRestoreInstanceState = true;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- mOnTouchEventCalled = true;
- mMotionEvent = event;
- return super.onTouchEvent(event);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mOnResume = true;
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mOnSaveInstanceState = true;
- mBundle = outState;
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- mOnStart = true;
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- mOnStop = true;
- }
-
- @Override
- protected void onUserLeaveHint() {
- super.onUserLeaveHint();
- mOnLeave = true;
- }
-
- @Override
- public boolean onMenuOpened(int featureId, Menu menu) {
- mOnMenuOpened = true;
- return super.onMenuOpened(featureId, menu);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.browser, menu);
-
- menu.add("title");
- mOnMenuOpened = true;
- return true;
- }
-
- @Override
- public boolean onCreatePanelMenu(int featureId, Menu menu) {
- return super.onCreatePanelMenu(featureId, menu);
- }
-
- @Override
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- mMenuID = item.getItemId();
- return super.onMenuItemSelected(featureId, item);
- }
-
- @Override
- public void openContextMenu(View view) {
- super.openContextMenu(view);
- }
-
- @Override
- public void openOptionsMenu() {
- super.openOptionsMenu();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- mKeyDownList.add(event);
- mKeyDownCode = keyCode;
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- mMotionEvent = event;
- return super.onTrackballEvent(event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- mKeyUpList.add(event);
- mKeyUpCode = keyCode;
- return super.onKeyUp(keyCode, event);
- }
-
- public boolean isOnCreateCalled() {
- return mOnCreateCalled;
- }
-
- public void setOnCreateCalled(boolean onCreateCalled) {
- mOnCreateCalled = onCreateCalled;
- }
-
- public boolean isOnDestroyCalled() {
- return mOnDestroyCalled;
- }
-
- public void setOnDestroyCalled(boolean onDestroyCalled) {
- mOnDestroyCalled = onDestroyCalled;
- }
-
- public boolean isOnNewIntentCalled() {
- return mOnNewIntentCalled;
- }
-
- public void setOnNewIntentCalled(boolean onNewIntentCalled) {
- mOnNewIntentCalled = onNewIntentCalled;
- }
-
- public boolean isOnPauseCalled() {
- return mOnPauseCalled;
- }
-
- public void setOnPauseCalled(boolean onPauseCalled) {
- mOnPauseCalled = onPauseCalled;
- }
-
- public boolean isOnPostCreate() {
- return mOnPostCreate;
- }
-
- public void setOnPostCreate(boolean onPostCreate) {
- mOnPostCreate = onPostCreate;
- }
-
- public boolean isOnRestart() {
- return mOnRestart;
- }
-
- public void setOnRestart(boolean onRestart) {
- mOnRestart = onRestart;
- }
-
- public boolean isOnRestoreInstanceState() {
- return mOnRestoreInstanceState;
- }
-
- public void setOnRestoreInstanceState(boolean onRestoreInstanceState) {
- mOnRestoreInstanceState = onRestoreInstanceState;
- }
-
- public boolean isOnResume() {
- return mOnResume;
- }
-
- public void setOnResume(boolean onResume) {
- mOnResume = onResume;
- }
-
- public boolean isOnSaveInstanceState() {
- return mOnSaveInstanceState;
- }
-
- public void setOnSaveInstanceState(boolean onSaveInstanceState) {
- mOnSaveInstanceState = onSaveInstanceState;
- }
-
- public boolean isOnStart() {
- return mOnStart;
- }
-
- public void setOnStart(boolean onStart) {
- mOnStart = onStart;
- }
-
- public boolean isOnStop() {
- return mOnStop;
- }
-
- public boolean isOnLeave() {
- return mOnLeave;
- }
-
- public void setOnStop(boolean onStop) {
- mOnStop = onStop;
- }
-
- public boolean isMOnMenuOpened() {
- return mOnMenuOpened;
- }
-
- public void setOnMenuOpened(boolean onMenuOpened) {
- mOnMenuOpened = onMenuOpened;
- }
-
- public int getMenuID() {
- return mMenuID;
- }
-
- public void setMenuID(int menuID) {
- mMenuID = menuID;
- }
-
- public MotionEvent getMotionEvent() {
- return mMotionEvent;
- }
-
- public Bundle getBundle() {
- return mBundle;
- }
-
- public boolean isOnTouchEventCalled() {
- return mOnTouchEventCalled;
- }
-
- public void setOnTouchEventCalled(boolean onTouchEventCalled) {
- mOnTouchEventCalled = onTouchEventCalled;
- }
-
- public int getKeyUpCode() {
- return mKeyUpCode;
- }
-
- public int getKeyDownCode() {
- return mKeyDownCode;
- }
-
- public List<KeyEvent> getKeyUpList() {
- return mKeyUpList;
- }
-
- public List<KeyEvent> getKeyDownList() {
- return mKeyDownList;
- }
-}
diff --git a/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java b/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java
new file mode 100644
index 0000000..719f74b
--- /dev/null
+++ b/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.Instrumentation.ActivityMonitor;
+import android.app.Instrumentation.ActivityResult;
+import android.app.stubs.InstrumentationTestActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.test.InstrumentationTestCase;
+
+public class Instrumentation_ActivityMonitorTest extends InstrumentationTestCase {
+
+ private static final long WAIT_TIMEOUT = 100;
+
+ /**
+ * check points:
+ * 1 Constructor with blocking true and false
+ * 2 waitForActivity with timeout and no timeout
+ * 3 get info about ActivityMonitor
+ */
+ public void testActivityMonitor() throws Exception {
+ ActivityResult result = new ActivityResult(Activity.RESULT_OK, new Intent());
+ Instrumentation instrumentation = getInstrumentation();
+ ActivityMonitor am = instrumentation.addMonitor(
+ InstrumentationTestActivity.class.getName(), result, false);
+ Context context = instrumentation.getTargetContext();
+ Intent intent = new Intent(context, InstrumentationTestActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ Activity lastActivity = am.getLastActivity();
+ final long TIMEOUT_MSEC = 5000;
+ long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
+ while (lastActivity == null && System.currentTimeMillis() < timeout) {
+ Thread.sleep(WAIT_TIMEOUT);
+ lastActivity = am.getLastActivity();
+ }
+ Activity activity = am.waitForActivity();
+ assertSame(activity, lastActivity);
+ assertEquals(1, am.getHits());
+ assertTrue(activity instanceof InstrumentationTestActivity);
+ activity.finish();
+ instrumentation.waitForIdleSync();
+ context.startActivity(intent);
+ timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
+ activity = null;
+ while (activity == null && System.currentTimeMillis() < timeout) {
+ Thread.sleep(WAIT_TIMEOUT);
+ activity = am.waitForActivityWithTimeout(WAIT_TIMEOUT);
+ }
+ assertNotNull(activity);
+ activity.finish();
+ instrumentation.removeMonitor(am);
+
+ am = new ActivityMonitor(InstrumentationTestActivity.class.getName(), result, true);
+ assertSame(result, am.getResult());
+ assertTrue(am.isBlocking());
+ IntentFilter which = new IntentFilter();
+ am = new ActivityMonitor(which, result, false);
+ assertSame(which, am.getFilter());
+ assertFalse(am.isBlocking());
+ }
+}
diff --git a/tests/tests/app/src/android/app/cts/Instrumentation_ActivityResultTest.java b/tests/app/src/android/app/cts/Instrumentation_ActivityResultTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/Instrumentation_ActivityResultTest.java
rename to tests/app/src/android/app/cts/Instrumentation_ActivityResultTest.java
diff --git a/tests/app/src/android/app/cts/IntentServiceStub.java b/tests/app/src/android/app/cts/IntentServiceStub.java
deleted file mode 100644
index 8f23a4f..0000000
--- a/tests/app/src/android/app/cts/IntentServiceStub.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.IntentService;
-import android.content.Intent;
-import android.cts.util.PollingCheck;
-import android.os.Binder;
-import android.os.IBinder;
-
-public class IntentServiceStub extends IntentService {
- public IntentServiceStub() {
- super("IntentServiceStub");
- }
-
- public static final String ISS_ADD = "add";
- public static final String ISS_VALUE = "value";
-
- private static int onHandleIntentCalled;
- private static boolean onBindCalled;
- private static boolean onCreateCalled;
- private static boolean onDestroyCalled;
- private static boolean onStartCalled;
- private static int accumulator;
-
- private static Throwable throwable;
-
- public synchronized static void reset() {
- onHandleIntentCalled = 0;
- onBindCalled = false;
- onCreateCalled = false;
- onDestroyCalled = false;
- onStartCalled = false;
- accumulator = 0;
- throwable = null;
- }
-
- public static void waitToFinish(long timeout) throws Throwable {
- new PollingCheck(timeout) {
- @Override
- protected boolean check() {
- synchronized (IntentServiceStub.class) {
- return IntentServiceStub.onDestroyCalled;
- }
- }
- }.run();
- if (throwable != null) {
- throw throwable;
- }
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- synchronized (IntentServiceStub.class) {
- onHandleIntentCalled += 1;
- try {
- String action = intent.getAction();
- if (action != null && action.equals(ISS_ADD)) {
- accumulator += intent.getIntExtra(ISS_VALUE, 0);
- }
- } catch (Throwable t) {
- throwable = t;
- }
- }
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- synchronized (IntentServiceStub.class) {
- onBindCalled = true;
- }
- return new Binder();
- }
-
- @Override
- public void onCreate() {
- synchronized (IntentServiceStub.class) {
- onCreateCalled = true;
- }
- super.onCreate();
- }
-
- @Override
- public void onDestroy() {
- synchronized (IntentServiceStub.class) {
- onDestroyCalled = true;
- }
- super.onDestroy();
- }
-
- @Override
- public void onStart(Intent intent, int startId) {
- synchronized (IntentService.class) {
- onStartCalled = true;
- }
- super.onStart(intent, startId);
- }
-
- public synchronized static int getOnHandleIntentCalledCount() {
- return onHandleIntentCalled;
- }
-
- public synchronized static boolean isOnBindCalled() {
- return onBindCalled;
- }
-
- public synchronized static boolean isOnCreateCalled() {
- return onCreateCalled;
- }
-
- public synchronized static boolean isOnDestroyCalled() {
- return onDestroyCalled;
- }
-
- public synchronized static boolean isOnStartCalled() {
- return onStartCalled;
- }
-
- public synchronized static int getAccumulator() {
- return accumulator;
- }
-}
diff --git a/tests/app/src/android/app/cts/IntentServiceTest.java b/tests/app/src/android/app/cts/IntentServiceTest.java
new file mode 100644
index 0000000..9d721fe
--- /dev/null
+++ b/tests/app/src/android/app/cts/IntentServiceTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.cts;
+
+import android.app.stubs.ActivityTestsBase;
+import android.app.stubs.IntentServiceStub;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.cts.util.PollingCheck;
+import android.os.IBinder;
+
+import java.util.concurrent.Callable;
+
+public class IntentServiceTest extends ActivityTestsBase {
+
+ private Intent mIntent;
+ private static final int TIMEOUT_MSEC = 30000;
+ private boolean mConnected;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ IntentServiceStub.reset();
+ mIntent = new Intent(mContext, IntentServiceStub.class);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mContext.stopService(mIntent);
+ }
+
+ public void testIntents() throws Throwable {
+ final int value = 42;
+ final int adds = 3;
+
+ Intent addIntent = new Intent(mContext, IntentServiceStub.class);
+
+ addIntent.setAction(IntentServiceStub.ISS_ADD);
+ addIntent.putExtra(IntentServiceStub.ISS_VALUE, 42);
+
+ for (int i = 0; i < adds; i++) {
+ mContext.startService(addIntent);
+ }
+
+ PollingCheck.check("onHandleIntentCalled not called enough", TIMEOUT_MSEC,
+ new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return IntentServiceStub.getOnHandleIntentCalledCount() == adds;
+ }
+ });
+
+ PollingCheck.check("accumulator not correct", TIMEOUT_MSEC, new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return IntentServiceStub.getAccumulator() == adds * value;
+ }
+ });
+
+ PollingCheck.check("onDestroyCalled not called", TIMEOUT_MSEC, new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return IntentServiceStub.isOnDestroyCalled();
+ }
+ });
+ }
+
+ public void testIntentServiceLifeCycle() throws Throwable {
+ // start service
+ mContext.startService(mIntent);
+ new PollingCheck(TIMEOUT_MSEC) {
+ protected boolean check() {
+ return IntentServiceStub.getOnHandleIntentCalledCount() > 0;
+ }
+ }.run();
+ assertTrue(IntentServiceStub.isOnCreateCalled());
+ assertTrue(IntentServiceStub.isOnStartCalled());
+
+ // bind service
+ ServiceConnection conn = new TestConnection();
+ mContext.bindService(mIntent, conn, Context.BIND_AUTO_CREATE);
+ new PollingCheck(TIMEOUT_MSEC) {
+ protected boolean check() {
+ return mConnected;
+ }
+ }.run();
+ assertTrue(IntentServiceStub.isOnBindCalled());
+
+ // unbind service
+ mContext.unbindService(conn);
+ // stop service
+ mContext.stopService(mIntent);
+ IntentServiceStub.waitToFinish(TIMEOUT_MSEC);
+ }
+
+ private class TestConnection implements ServiceConnection {
+
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mConnected = true;
+ }
+
+ public void onServiceDisconnected(ComponentName name) {
+ }
+ }
+}
diff --git a/tests/app/src/android/app/cts/KeyguardManagerActivity.java b/tests/app/src/android/app/cts/KeyguardManagerActivity.java
deleted file mode 100644
index a1f5289..0000000
--- a/tests/app/src/android/app/cts/KeyguardManagerActivity.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.
- */
-package android.app.cts;
-
-import android.app.Activity;
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.KeyEvent;
-
-public class KeyguardManagerActivity extends Activity {
- private static final String TAG = "KeyguardManagerActivity";
- public static final boolean DEBUG = false;
- private KeyguardManager mKeyguardManager;
- private KeyguardManager.KeyguardLock mKeyLock;
- public int keyCode;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
- mKeyLock = null;
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (DEBUG) {
- Log.d(TAG, "onResume");
- }
- if (mKeyLock == null) {
- mKeyLock = mKeyguardManager.newKeyguardLock(TAG);
- mKeyLock.disableKeyguard();
- if (DEBUG) {
- Log.d(TAG, "disableKeyguard");
- }
- }
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- this.keyCode = keyCode;
- if (keyCode == KeyEvent.KEYCODE_0 && mKeyLock != null) {
- mKeyLock.reenableKeyguard();
- mKeyLock = null;
- if (DEBUG) {
- Log.d(TAG, "reenableKeyguard");
- }
- }
- if (DEBUG) {
- Log.d(TAG, "onKeyDown");
- }
- return super.onKeyDown(keyCode, event);
- }
-}
diff --git a/tests/app/src/android/app/cts/KeyguardManagerKeyguardLockTest.java b/tests/app/src/android/app/cts/KeyguardManagerKeyguardLockTest.java
new file mode 100644
index 0000000..33d42ce
--- /dev/null
+++ b/tests/app/src/android/app/cts/KeyguardManagerKeyguardLockTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.test.InstrumentationTestCase;
+
+public class KeyguardManagerKeyguardLockTest extends InstrumentationTestCase {
+
+ public void testDisableKeyguard() {
+ }
+
+ public void testReenableKeyguard() {
+ }
+}
diff --git a/tests/app/src/android/app/cts/KeyguardManagerTest.java b/tests/app/src/android/app/cts/KeyguardManagerTest.java
new file mode 100644
index 0000000..23410ed5
--- /dev/null
+++ b/tests/app/src/android/app/cts/KeyguardManagerTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.KeyguardManager;
+import android.app.stubs.KeyguardManagerActivity;
+import android.content.Context;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class KeyguardManagerTest
+ extends ActivityInstrumentationTestCase2<KeyguardManagerActivity> {
+
+ private static final String TAG = "KeyguardManagerTest";
+
+ public KeyguardManagerTest() {
+ super("android.app.stubs", KeyguardManagerActivity.class);
+ }
+
+ public void testNewKeyguardLock() {
+ final Context c = getInstrumentation().getContext();
+ final KeyguardManager keyguardManager = (KeyguardManager) c.getSystemService(
+ Context.KEYGUARD_SERVICE);
+ final KeyguardManager.KeyguardLock keyLock = keyguardManager.newKeyguardLock(TAG);
+ assertNotNull(keyLock);
+ }
+
+ public void testInKeyguardRestrictedInputMode() {
+ }
+
+ public void testExitKeyguardSecurely() {
+ }
+}
diff --git a/tests/app/src/android/app/cts/LaunchTest.java b/tests/app/src/android/app/cts/LaunchTest.java
new file mode 100644
index 0000000..eaa4b2f
--- /dev/null
+++ b/tests/app/src/android/app/cts/LaunchTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.stubs.ActivityTestsBase;
+import android.app.stubs.ClearTop;
+import android.app.stubs.LaunchpadActivity;
+import android.app.stubs.LocalActivity;
+import android.app.stubs.LocalScreen;
+import android.app.stubs.TestedActivity;
+import android.app.stubs.TestedScreen;
+import android.content.ComponentName;
+
+public class LaunchTest extends ActivityTestsBase {
+
+ public void testClearTopWhilResumed() {
+ mIntent.putExtra("component", new ComponentName(getContext(), ClearTop.class));
+ mIntent.putExtra(ClearTop.WAIT_CLEAR_TASK, true);
+ runLaunchpad(LaunchpadActivity.LAUNCH);
+ }
+
+ public void testClearTopInCreate() throws Exception {
+ mIntent.putExtra("component", new ComponentName(getContext(), ClearTop.class));
+ runLaunchpad(LaunchpadActivity.LAUNCH);
+ }
+
+ public void testForwardResult() {
+ runLaunchpad(LaunchpadActivity.FORWARD_RESULT);
+ }
+
+ public void testLocalScreen() {
+ mIntent.putExtra("component", new ComponentName(getContext(), LocalScreen.class));
+ runLaunchpad(LaunchpadActivity.LAUNCH);
+ }
+
+ public void testColdScreen() {
+ mIntent.putExtra("component", new ComponentName(getContext(), TestedScreen.class));
+ runLaunchpad(LaunchpadActivity.LAUNCH);
+ }
+
+ public void testLocalActivity() {
+ mIntent.putExtra("component", new ComponentName(getContext(), LocalActivity.class));
+ runLaunchpad(LaunchpadActivity.LAUNCH);
+ }
+
+ public void testColdActivity() {
+ mIntent.putExtra("component", new ComponentName(getContext(), TestedActivity.class));
+ runLaunchpad(LaunchpadActivity.LAUNCH);
+ }
+}
diff --git a/tests/app/src/android/app/cts/LauncherActivityStub.java b/tests/app/src/android/app/cts/LauncherActivityStub.java
deleted file mode 100644
index 4be63d6..0000000
--- a/tests/app/src/android/app/cts/LauncherActivityStub.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.LauncherActivity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.ListView;
-
-public class LauncherActivityStub extends LauncherActivity {
- public boolean isOnCreateCalled = false;
- public boolean isOnListItemClick = false;
- // For testing LauncherActivity#getTargetIntent()
- private Intent mSuperIntent;
-
- public Intent getSuperIntent() {
- return mSuperIntent;
- }
-
- @Override
- protected Intent getTargetIntent() {
- mSuperIntent = super.getTargetIntent();
- Intent targetIntent = new Intent(Intent.ACTION_MAIN, null);
- targetIntent.addCategory(Intent.CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST);
- targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- return targetIntent;
- }
-
- @Override
- protected Intent intentForPosition(int position) {
- return super.intentForPosition(position);
- }
-
- public LauncherActivityStub() {
- super();
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- isOnCreateCalled = true;
- }
-
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- super.onListItemClick(l, v, position, id);
- isOnListItemClick = true;
- }
-}
diff --git a/tests/app/src/android/app/cts/LauncherActivityTest.java b/tests/app/src/android/app/cts/LauncherActivityTest.java
new file mode 100644
index 0000000..6ab4608
--- /dev/null
+++ b/tests/app/src/android/app/cts/LauncherActivityTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.Instrumentation;
+import android.app.LauncherActivity.ListItem;
+import android.app.stubs.LauncherActivityStub;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyEvent;
+
+import java.util.List;
+
+public class LauncherActivityTest
+ extends ActivityInstrumentationTestCase2<LauncherActivityStub> {
+
+ private Instrumentation mInstrumentation;
+ private LauncherActivityStub mActivity;
+
+ public LauncherActivityTest() {
+ super("android.app.stubs", LauncherActivityStub.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ }
+
+ public void testLaunchActivity() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ // Test getTargetIntent. LaunchActivity#getTargetIntent() just returns a Intent() instance
+ // with no content, so we use LaunchActivityStub#getSuperIntent() to get the default Intent,
+ // and create a new intent for other tests.
+ assertNotNull(mActivity.getSuperIntent());
+
+ // Test makeListItems. Make sure the size > 0. The sorted order is related to the sort
+ // way, so it's mutable.
+ final List<ListItem> list = mActivity.makeListItems();
+ assertTrue(list.size() > 0);
+
+ // There should be an activity(but with uncertain content) in position 0.
+ assertNotNull(mActivity.intentForPosition(0));
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ // Test onListItemClick
+ sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+ sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+ sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+ sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+ assertTrue(mActivity.isOnListItemClick);
+ }
+}
diff --git a/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java b/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java
new file mode 100644
index 0000000..b6ba9c6
--- /dev/null
+++ b/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.cts;
+
+import android.app.LauncherActivity.IconResizer;
+import android.app.stubs.LauncherActivityStub;
+import android.graphics.drawable.Drawable;
+import android.test.ActivityInstrumentationTestCase2;
+
+import android.app.stubs.R;
+
+public class LauncherActivity_IconResizerTest extends
+ ActivityInstrumentationTestCase2<LauncherActivityStub> {
+
+ private static final String PACKAGE = "android.app.stubs";
+ private LauncherActivityStub mActivity;
+
+ public LauncherActivity_IconResizerTest() {
+ super(PACKAGE, LauncherActivityStub.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ }
+
+ public void testIconResizer() throws Throwable {
+ final IconResizer ir = mActivity.new IconResizer();
+ final Drawable d = mActivity.getResources().getDrawable(R.drawable.pass);
+ assertNotNull(d);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ Drawable thumbNail = ir.createIconThumbnail(d);
+ assertNotNull(thumbNail);
+ // The size of the thumbnail is defined by inner R resource file
+ // whose details are not open.
+ assertTrue(thumbNail.getIntrinsicHeight() > 0);
+ assertTrue(thumbNail.getIntrinsicWidth() > 0);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ }
+}
diff --git a/tests/app/src/android/app/cts/LauncherActivity_ListItemTest.java b/tests/app/src/android/app/cts/LauncherActivity_ListItemTest.java
new file mode 100644
index 0000000..6c22905
--- /dev/null
+++ b/tests/app/src/android/app/cts/LauncherActivity_ListItemTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.cts;
+
+import android.app.LauncherActivity;
+import android.test.AndroidTestCase;
+
+public class LauncherActivity_ListItemTest extends AndroidTestCase {
+ public void testConstructor() {
+ // Test public constructor
+ new LauncherActivity.ListItem();
+ }
+}
diff --git a/tests/app/src/android/app/cts/LaunchpadActivity.java b/tests/app/src/android/app/cts/LaunchpadActivity.java
deleted file mode 100644
index 2a90055..0000000
--- a/tests/app/src/android/app/cts/LaunchpadActivity.java
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.test.PerformanceTestCase;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-class MyBadParcelable implements Parcelable {
- public MyBadParcelable() {
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeString("I am bad");
- }
-
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<MyBadParcelable> CREATOR =
- new Parcelable.Creator<MyBadParcelable>() {
- public MyBadParcelable createFromParcel(Parcel in) {
- return new MyBadParcelable(in);
- }
-
- public MyBadParcelable[] newArray(int size) {
- return new MyBadParcelable[size];
- }
- };
-
- public MyBadParcelable(Parcel in) {
- in.readString();
- }
-}
-
-public class LaunchpadActivity extends Activity {
- public interface CallingTest extends PerformanceTestCase.Intermediates {
- public void startTiming(boolean realTime);
-
- public void addIntermediate(String name);
-
- public void addIntermediate(String name, long timeInNS);
-
- public void finishTiming(boolean realTime);
-
- public void activityFinished(int resultCode, Intent data, RuntimeException where);
- }
-
- // Also used as the Binder interface descriptor string in these tests
- public static final String LAUNCH = "android.app.cts.activity.LAUNCH";
-
- public static final String FORWARD_RESULT = "android.app.cts.activity.FORWARD_RESULT";
- public static final String RETURNED_RESULT = "android.app.cts.activity.RETURNED_RESULT";
-
- public static final String BAD_PARCELABLE = "android.app.cts.activity.BAD_PARCELABLE";
-
- public static final int LAUNCHED_RESULT = 1;
- public static final int FORWARDED_RESULT = 2;
-
- public static final String LIFECYCLE_BASIC = "android.app.cts.activity.LIFECYCLE_BASIC";
- public static final String LIFECYCLE_SCREEN = "android.app.cts.activity.LIFECYCLE_SCREEN";
- public static final String LIFECYCLE_DIALOG = "android.app.cts.activity.LIFECYCLE_DIALOG";
-
- public static final String BROADCAST_REGISTERED = "android.app.cts.activity.BROADCAST_REGISTERED";
- public static final String BROADCAST_LOCAL = "android.app.cts.activity.BROADCAST_LOCAL";
- public static final String BROADCAST_REMOTE = "android.app.cts.activity.BROADCAST_REMOTE";
- public static final String BROADCAST_ALL = "android.app.cts.activity.BROADCAST_ALL";
- public static final String BROADCAST_REPEAT = "android.app.cts.activity.BROADCAST_REPEAT";
- public static final String BROADCAST_MULTI = "android.app.cts.activity.BROADCAST_MULTI";
- public static final String BROADCAST_ABORT = "android.app.cts.activity.BROADCAST_ABORT";
-
- public static final String EXPANDLIST_SELECT = "EXPANDLIST_SELECT";
- public static final String EXPANDLIST_VIEW = "EXPANDLIST_VIEW";
- public static final String EXPANDLIST_CALLBACK = "EXPANDLIST_CALLBACK";
-
- public static final String BROADCAST_STICKY1 = "android.app.cts.activity.BROADCAST_STICKY1";
- public static final String BROADCAST_STICKY2 = "android.app.cts.activity.BROADCAST_STICKY2";
-
- public static final String ALIAS_ACTIVITY = "android.app.cts.activity.ALIAS_ACTIVITY";
-
- public static final String RECEIVER_REG = "receiver-reg";
- public static final String RECEIVER_LOCAL = "receiver-local";
- public static final String RECEIVER_REMOTE = "receiver-remote";
- public static final String RECEIVER_ABORT = "receiver-abort";
-
- public static final String DATA_1 = "one";
- public static final String DATA_2 = "two";
-
- public static final String ON_START = "onStart";
- public static final String ON_RESTART = "onRestart";
- public static final String ON_RESUME = "onResume";
- public static final String ON_FREEZE = "onSaveInstanceState";
- public static final String ON_PAUSE = "onPause";
-
- // ON_STOP and ON_DESTROY are not tested because they may not be called.
-
- public static final String DO_FINISH = "finish";
- public static final String DO_LOCAL_SCREEN = "local-screen";
- public static final String DO_LOCAL_DIALOG = "local-dialog";
-
- private static final String TAG = "LaunchpadActivity";
-
- private boolean mBadParcelable = false;
-
- private boolean mStarted = false;
-
- private int mResultCode = RESULT_CANCELED;
- private Intent mData = new Intent().setAction("No result received");
- private RuntimeException mResultStack = null;
-
- /** Index into the {@link #mNextLifecycle} array. */
- private int mNextLifecycle;
-
- /** Current lifecycle expected to be followed. */
- private String[] mExpectedLifecycle;
-
- /** Other possible lifecycles. Never includes the current {@link #mExpectedLifecycle}. */
- private List<String[]> mOtherPossibleLifecycles = new ArrayList<String[]>(2);
-
- /** Map from lifecycle arrays to debugging log names. */
- private Map<String[], String> mLifecycleNames = new HashMap<String[], String>(2);
-
- private String[] mExpectedReceivers = null;
- private int mNextReceiver;
-
- private String[] mExpectedData = null;
- private boolean[] mReceivedData = null;
-
- boolean mReceiverRegistered = false;
-
- private static CallingTest sCallingTest = null;
-
- public static void setCallingTest(CallingTest ct) {
- sCallingTest = ct;
- }
-
- public LaunchpadActivity() {
- }
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- resetLifecycles();
-
- // ON_STOP and ON_DESTROY are not tested because they may not be called.
-
- final String action = getIntent().getAction();
- if (LIFECYCLE_BASIC.equals(action)) {
- addPossibleLifecycle(LIFECYCLE_BASIC, new String[] {
- ON_START, ON_RESUME, DO_FINISH, ON_PAUSE
- });
- } else if (LIFECYCLE_SCREEN.equals(action)) {
- addPossibleLifecycle(LIFECYCLE_SCREEN + "_RESTART", new String[] {
- ON_START, ON_RESUME, DO_LOCAL_SCREEN, ON_PAUSE,
- ON_RESTART, ON_START, ON_RESUME, DO_FINISH, ON_PAUSE
- });
- addPossibleLifecycle(LIFECYCLE_SCREEN + "_RESUME", new String[] {
- ON_START, ON_RESUME, DO_LOCAL_SCREEN, ON_PAUSE,
- ON_RESUME, DO_FINISH, ON_PAUSE
- });
- } else if (LIFECYCLE_DIALOG.equals(action)) {
- addPossibleLifecycle(LIFECYCLE_DIALOG + "_RESTART", new String[] {
- ON_START, ON_RESUME, DO_LOCAL_DIALOG, ON_PAUSE,
- ON_RESTART, ON_START, ON_RESUME, DO_FINISH, ON_PAUSE
- });
- addPossibleLifecycle(LIFECYCLE_DIALOG + "_RESUME", new String[] {
- ON_START, ON_RESUME, DO_LOCAL_DIALOG, ON_PAUSE,
- ON_RESUME, DO_FINISH, ON_PAUSE
- });
- }
- }
-
- private void resetLifecycles() {
- mNextLifecycle = 0;
- mExpectedLifecycle = null;
- mOtherPossibleLifecycles.clear();
- mLifecycleNames.clear();
- }
-
- /**
- * Add a potential lifecycle that this activity may follow, since there
- * are usually multiple valid lifecycles. For instance, sometimes onPause
- * will lead to onResume rather than onStop when another activity is
- * raised over the current one.
- *
- * @param debugName for the lifecycle shown in the logs
- * @param lifecycle array containing tokens indicating the expected lifecycle
- */
- private void addPossibleLifecycle(String debugName, String[] lifecycle) {
- mLifecycleNames.put(lifecycle, debugName);
- if (mExpectedLifecycle == null) {
- mExpectedLifecycle = lifecycle;
- } else {
- mOtherPossibleLifecycles.add(lifecycle);
- }
- }
-
- /**
- * Switch to the next possible lifecycle and return if switching was
- * successful. Call this method when mExpectedLifecycle doesn't match
- * the current lifecycle and you need to check another possible lifecycle.
- *
- * @return whether on not there was a lifecycle to switch to
- */
- private boolean switchToNextPossibleLifecycle() {
- if (!mOtherPossibleLifecycles.isEmpty()) {
- String[] newLifecycle = mOtherPossibleLifecycles.remove(0);
- Log.w(TAG, "Switching expected lifecycles from "
- + mLifecycleNames.get(mExpectedLifecycle) + " to "
- + mLifecycleNames.get(newLifecycle));
- mExpectedLifecycle = newLifecycle;
- return true;
- } else {
- Log.w(TAG, "No more lifecycles after "
- + mLifecycleNames.get(mExpectedLifecycle));
- mExpectedLifecycle = null;
- return false;
- }
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- checkLifecycle(ON_START);
- }
-
- @Override
- protected void onRestart() {
- super.onStart();
- checkLifecycle(ON_RESTART);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- checkLifecycle(ON_RESUME);
-
- if (!mStarted) {
- mStarted = true;
-
- mHandler.postDelayed(mTimeout, 10 * 1000);
-
- final String action = getIntent().getAction();
-
- sCallingTest.startTiming(true);
-
- if (LAUNCH.equals(action)) {
- final Intent intent = getIntent();
- intent.setFlags(0);
- intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
- startActivityForResult(intent, LAUNCHED_RESULT);
-
- } else if (FORWARD_RESULT.equals(action)) {
- final Intent intent = getIntent();
- intent.setFlags(0);
- intent.setClass(this, LocalScreen.class);
- startActivityForResult(intent, FORWARDED_RESULT);
- } else if (BAD_PARCELABLE.equals(action)) {
- mBadParcelable = true;
- final Intent intent = getIntent();
- intent.setFlags(0);
- intent.setClass(this, LocalScreen.class);
- startActivityForResult(intent, LAUNCHED_RESULT);
- } else if (BROADCAST_REGISTERED.equals(action)) {
- setExpectedReceivers(new String[] {
- RECEIVER_REG
- });
- registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED));
- sCallingTest.addIntermediate("after-register");
- sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED));
- } else if (BROADCAST_LOCAL.equals(action)) {
- setExpectedReceivers(new String[] {
- RECEIVER_LOCAL
- });
- sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL));
- } else if (BROADCAST_REMOTE.equals(action)) {
- setExpectedReceivers(new String[] {
- RECEIVER_REMOTE
- });
- sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE));
- } else if (BROADCAST_ALL.equals(action)) {
- setExpectedReceivers(new String[] {
- RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL
- });
- registerMyReceiver(new IntentFilter(BROADCAST_ALL));
- sCallingTest.addIntermediate("after-register");
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
- } else if (BROADCAST_MULTI.equals(action)) {
- setExpectedReceivers(new String[] {
- RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE,
- RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE, RECEIVER_REG,
- RECEIVER_LOCAL, RECEIVER_LOCAL, RECEIVER_REMOTE, RECEIVER_LOCAL,
- RECEIVER_REMOTE, RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL,
- RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE,
- RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE, RECEIVER_LOCAL,
- RECEIVER_REMOTE, RECEIVER_LOCAL
- });
- registerMyReceiver(new IntentFilter(BROADCAST_ALL));
- sCallingTest.addIntermediate("after-register");
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REPEAT), null);
- } else if (BROADCAST_ABORT.equals(action)) {
- setExpectedReceivers(new String[] {
- RECEIVER_REMOTE, RECEIVER_ABORT
- });
- registerMyReceiver(new IntentFilter(BROADCAST_ABORT));
- sCallingTest.addIntermediate("after-register");
- sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ABORT), null);
- } else if (BROADCAST_STICKY1.equals(action)) {
- setExpectedReceivers(new String[] {
- RECEIVER_REG
- });
- setExpectedData(new String[] {
- DATA_1
- });
- registerMyReceiver(new IntentFilter(BROADCAST_STICKY1));
- sCallingTest.addIntermediate("after-register");
- } else if (BROADCAST_STICKY2.equals(action)) {
- setExpectedReceivers(new String[] {
- RECEIVER_REG, RECEIVER_REG
- });
- setExpectedData(new String[] {
- DATA_1, DATA_2
- });
- final IntentFilter filter = new IntentFilter(BROADCAST_STICKY1);
- filter.addAction(BROADCAST_STICKY2);
- registerMyReceiver(filter);
- sCallingTest.addIntermediate("after-register");
- } else if (ALIAS_ACTIVITY.equals(action)) {
- final Intent intent = getIntent();
- intent.setFlags(0);
- intent.setClass(this, AliasActivityStub.class);
- startActivityForResult(intent, LAUNCHED_RESULT);
- } else if (EXPANDLIST_SELECT.equals(action)) {
- final Intent intent = getIntent();
- intent.setFlags(0);
- intent.setAction(action);
- intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
- startActivityForResult(intent, LAUNCHED_RESULT);
- } else if (EXPANDLIST_VIEW.equals(action)) {
- final Intent intent = getIntent();
- intent.setFlags(0);
- intent.setAction(action);
- intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
- startActivityForResult(intent, LAUNCHED_RESULT);
- } else if (EXPANDLIST_CALLBACK.equals(action)) {
- final Intent intent = getIntent();
- intent.setFlags(0);
- intent.setAction(action);
- intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
- startActivityForResult(intent, LAUNCHED_RESULT);
- }
- }
- }
-
- @Override
- protected void onSaveInstanceState(Bundle icicle) {
- super.onSaveInstanceState(icicle);
- if (mBadParcelable) {
- icicle.putParcelable("baddy", new MyBadParcelable());
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- checkLifecycle(ON_PAUSE);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case LAUNCHED_RESULT:
- sCallingTest.finishTiming(true);
- finishWithResult(resultCode, data);
- break;
- case FORWARDED_RESULT:
- sCallingTest.finishTiming(true);
- if (RETURNED_RESULT.equals(data.getAction())) {
- finishWithResult(resultCode, data);
- } else {
- finishWithResult(RESULT_CANCELED, new Intent().setAction("Bad data returned: "
- + data));
- }
- break;
- default:
- sCallingTest.finishTiming(true);
- finishWithResult(RESULT_CANCELED, new Intent()
- .setAction("Unexpected request code: " + requestCode));
- break;
- }
- }
-
- private void checkLifecycle(String where) {
- String action = getIntent().getAction();
-
- if (mExpectedLifecycle == null) {
- return;
- }
-
- if (mNextLifecycle >= mExpectedLifecycle.length) {
- finishBad("Activity lifecycle for " + action + " incorrect: received " + where
- + " but don't expect any more calls");
- mExpectedLifecycle = null;
- return;
- }
-
- do {
- if (mExpectedLifecycle[mNextLifecycle].equals(where)) {
- Log.w(TAG, "Matched: " + where);
- break;
- } else {
- Log.w(TAG, "Expected " + mExpectedLifecycle[mNextLifecycle] + " but got " + where);
- }
- } while (switchToNextPossibleLifecycle());
-
- if (mExpectedLifecycle == null) {
- finishBad("Activity lifecycle for " + action + " incorrect: received " + where
- + " at " + mNextLifecycle);
- return;
- }
-
- mNextLifecycle++;
-
- if (mNextLifecycle >= mExpectedLifecycle.length) {
- finishGood();
- return;
- }
-
- final String next = mExpectedLifecycle[mNextLifecycle];
- if (next.equals(DO_FINISH)) {
- mNextLifecycle++;
- if (mNextLifecycle >= mExpectedLifecycle.length) {
- setTestResult(RESULT_OK, null);
- }
- if (!isFinishing()) {
- finish();
- }
- } else if (next.equals(DO_LOCAL_SCREEN)) {
- mNextLifecycle++;
- final Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH);
- intent.setClass(this, LocalScreen.class);
- startActivity(intent);
- } else if (next.equals(DO_LOCAL_DIALOG)) {
- mNextLifecycle++;
- final Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH);
- intent.setClass(this, LocalDialog.class);
- startActivity(intent);
- }
- }
-
- private void setExpectedReceivers(String[] receivers) {
- mExpectedReceivers = receivers;
- mNextReceiver = 0;
- }
-
- private void setExpectedData(String[] data) {
- mExpectedData = data;
- mReceivedData = new boolean[data.length];
- }
-
- @SuppressWarnings("deprecation")
- private Intent makeBroadcastIntent(String action) {
- final Intent intent = new Intent(action, null);
- intent.putExtra("caller", mCallTarget);
- return intent;
- }
-
- private void finishGood() {
- finishWithResult(RESULT_OK, null);
- }
-
- private void finishBad(String error) {
- finishWithResult(RESULT_CANCELED, new Intent().setAction(error));
- }
-
- private void finishWithResult(int resultCode, Intent data) {
- setTestResult(resultCode, data);
- finish();
-
- // Member fields set by calling setTestResult above...
- sCallingTest.activityFinished(mResultCode, mData, mResultStack);
- }
-
- private void setTestResult(int resultCode, Intent data) {
- mHandler.removeCallbacks(mTimeout);
- unregisterMyReceiver();
- mResultCode = resultCode;
- mData = data;
- mResultStack = new RuntimeException("Original error was here");
- mResultStack.fillInStackTrace();
- }
-
- private void registerMyReceiver(IntentFilter filter) {
- mReceiverRegistered = true;
- registerReceiver(mReceiver, filter);
- }
-
- private void unregisterMyReceiver() {
- if (mReceiverRegistered) {
- mReceiverRegistered = false;
- unregisterReceiver(mReceiver);
- }
- }
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- }
- };
-
- static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
- static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
-
- private final Binder mCallTarget = new Binder() {
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
- data.setDataPosition(0);
- data.enforceInterface(LaunchpadActivity.LAUNCH);
- if (code == GOT_RECEIVE_TRANSACTION) {
- final String name = data.readString();
- gotReceive(name, null);
- return true;
- } else if (code == ERROR_TRANSACTION) {
- finishBad(data.readString());
- return true;
- }
- return false;
- }
- };
-
- private final void gotReceive(String name, Intent intent) {
- synchronized (this) {
-
- sCallingTest.addIntermediate(mNextReceiver + "-" + name);
-
- if (mExpectedData != null) {
- final int n = mExpectedData.length;
- int i;
- boolean prev = false;
- for (i = 0; i < n; i++) {
- if (mExpectedData[i].equals(intent.getStringExtra("test"))) {
- if (mReceivedData[i]) {
- prev = true;
- continue;
- }
- mReceivedData[i] = true;
- break;
- }
- }
- if (i >= n) {
- if (prev) {
- finishBad("Receive got data too many times: "
- + intent.getStringExtra("test"));
- } else {
- finishBad("Receive got unexpected data: " + intent.getStringExtra("test"));
- }
- return;
- }
- }
-
- if (mNextReceiver >= mExpectedReceivers.length) {
- finishBad("Got too many onReceiveIntent() calls!");
- } else if (!mExpectedReceivers[mNextReceiver].equals(name)) {
- finishBad("Receive out of order: got " + name + " but expected "
- + mExpectedReceivers[mNextReceiver] + " at " + mNextReceiver);
- } else {
- mNextReceiver++;
- if (mNextReceiver == mExpectedReceivers.length) {
- mHandler.post(mUnregister);
- }
- }
-
- }
- }
-
- private final Runnable mUnregister = new Runnable() {
- public void run() {
- if (mReceiverRegistered) {
- sCallingTest.addIntermediate("before-unregister");
- unregisterMyReceiver();
- }
- sCallingTest.finishTiming(true);
- finishGood();
- }
- };
-
- private final Runnable mTimeout = new Runnable() {
- public void run() {
- Log.i(TAG, "timeout");
- String msg = "Timeout";
- if (mExpectedReceivers != null && mNextReceiver < mExpectedReceivers.length) {
- msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver];
- }
- finishBad(msg);
- }
- };
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- gotReceive(RECEIVER_REG, intent);
- }
- };
-}
diff --git a/tests/app/src/android/app/cts/LaunchpadTabActivity.java b/tests/app/src/android/app/cts/LaunchpadTabActivity.java
deleted file mode 100644
index 3dfd2c3..0000000
--- a/tests/app/src/android/app/cts/LaunchpadTabActivity.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.TabActivity;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.Bundle;
-import android.widget.TabHost;
-
-public class LaunchpadTabActivity extends TabActivity {
- public LaunchpadTabActivity() {
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- final Intent tabIntent = new Intent(getIntent());
- tabIntent.setComponent((ComponentName) tabIntent.getParcelableExtra("tab"));
-
- final TabHost th = getTabHost();
- final TabHost.TabSpec ts = th.newTabSpec("1");
- ts.setIndicator("One");
- ts.setContent(tabIntent);
- th.addTab(ts);
- }
-}
diff --git a/tests/app/src/android/app/cts/LifecycleTest.java b/tests/app/src/android/app/cts/LifecycleTest.java
new file mode 100644
index 0000000..8b08dcb
--- /dev/null
+++ b/tests/app/src/android/app/cts/LifecycleTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.stubs.ActivityTestsBase;
+import android.app.stubs.LaunchpadActivity;
+import android.app.stubs.LaunchpadTabActivity;
+import android.content.ComponentName;
+import android.content.Intent;
+
+public class LifecycleTest extends ActivityTestsBase {
+ private Intent mTopIntent;
+ private Intent mTabIntent;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTopIntent = mIntent;
+ mTabIntent = new Intent(mContext, LaunchpadTabActivity.class);
+ mTabIntent.putExtra("tab", new ComponentName(mContext, LaunchpadActivity.class));
+ }
+
+ public void testTabDialog() {
+ mIntent = mTabIntent;
+ runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG);
+ }
+
+ public void testDialog() {
+ mIntent = mTopIntent;
+ runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG);
+ }
+
+ public void testTabScreen() {
+ mIntent = mTabIntent;
+ runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN);
+ }
+
+ public void testScreen() {
+ mIntent = mTopIntent;
+ runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN);
+ }
+
+ public void testTabBasic() {
+ mIntent = mTabIntent;
+ runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC);
+ }
+
+ public void testBasic() {
+ mIntent = mTopIntent;
+ runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC);
+ }
+}
diff --git a/tests/app/src/android/app/cts/LocalActivity.java b/tests/app/src/android/app/cts/LocalActivity.java
deleted file mode 100644
index 67fad8c..0000000
--- a/tests/app/src/android/app/cts/LocalActivity.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-public class LocalActivity extends TestedActivity {
- public LocalActivity() {
- }
-}
diff --git a/tests/app/src/android/app/cts/LocalActivityManagerStubActivity.java b/tests/app/src/android/app/cts/LocalActivityManagerStubActivity.java
deleted file mode 100644
index e64c75a..0000000
--- a/tests/app/src/android/app/cts/LocalActivityManagerStubActivity.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class LocalActivityManagerStubActivity extends Activity{
-
- public static boolean sIsOnResumeCalled;
- public static boolean sIsOnStopCalled;
- public static boolean sIsOnPauseCalled;
- public static boolean sIsOnDestroyCalled;
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- sIsOnResumeCalled = true;
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- sIsOnStopCalled = true;
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- sIsOnPauseCalled = true;
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- sIsOnDestroyCalled = true;
- }
-}
diff --git a/tests/app/src/android/app/cts/LocalActivityManagerTest.java b/tests/app/src/android/app/cts/LocalActivityManagerTest.java
new file mode 100644
index 0000000..7f6fd2f
--- /dev/null
+++ b/tests/app/src/android/app/cts/LocalActivityManagerTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.LocalActivityManager;
+import android.app.stubs.LocalActivityManagerTestHelper;
+import android.content.Intent;
+import android.cts.util.CTSResult;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
+
+public class LocalActivityManagerTest extends InstrumentationTestCase implements CTSResult {
+
+ private Instrumentation mInstrumentation;
+
+ private Sync mSync = new Sync();
+ private static class Sync {
+ public boolean mHasNotify;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ mSync = new Sync();
+ }
+
+ private void setupActivity(final String action) {
+ final Intent intent = new Intent(mInstrumentation.getTargetContext(),
+ LocalActivityManagerTestHelper.class);
+ intent.setAction(action);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mInstrumentation.getTargetContext().startActivity(intent);
+ }
+
+ @UiThreadTest
+ public void testConstructor() {
+ new LocalActivityManager(new Activity(), true);
+ new LocalActivityManager(new Activity(), false);
+ new LocalActivityManager(null, false);
+ new LocalActivityManager(null, true);
+ }
+
+ public void testDispatchResume() throws InterruptedException {
+ LocalActivityManagerTestHelper.setResult(this);
+ setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_RESUME);
+ waitForResult();
+ }
+
+ private void waitForResult() throws InterruptedException {
+ synchronized (mSync) {
+ if (!mSync.mHasNotify) {
+ mSync.wait();
+ }
+ }
+ }
+
+ public void testStartActivity() throws InterruptedException {
+ LocalActivityManagerTestHelper.setResult(this);
+ setupActivity(LocalActivityManagerTestHelper.ACTION_START_ACTIVITY);
+ waitForResult();
+ }
+
+ public void testDispatchCreate() throws InterruptedException {
+ LocalActivityManagerTestHelper.setResult(this);
+ setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_CREATE);
+ waitForResult();
+ }
+
+ public void testDispatchStop() throws InterruptedException {
+ LocalActivityManagerTestHelper.setResult(this);
+ setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_STOP);
+ waitForResult();
+ }
+
+ public void testDispatchPauseTrue() throws InterruptedException {
+ LocalActivityManagerTestHelper.setResult(this);
+ setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_PAUSE_TRUE);
+ waitForResult();
+ }
+
+ public void testDispatchPauseFalse() throws InterruptedException {
+ LocalActivityManagerTestHelper.setResult(this);
+ setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_PAUSE_FALSE);
+ waitForResult();
+ }
+
+ public void testSaveInstanceState() throws InterruptedException {
+ LocalActivityManagerTestHelper.setResult(this);
+ setupActivity(LocalActivityManagerTestHelper.ACTION_SAVE_INSTANCE_STATE);
+ waitForResult();
+ }
+
+ public void testDispatchDestroy() throws InterruptedException {
+ LocalActivityManagerTestHelper.setResult(this);
+ setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_DESTROY);
+ waitForResult();
+ }
+
+ public void testRemoveAllActivities() throws InterruptedException {
+ LocalActivityManagerTestHelper.setResult(this);
+ setupActivity(LocalActivityManagerTestHelper.ACTION_REMOVE_ALL_ACTIVITY);
+ waitForResult();
+ }
+
+ public void setResult(final int resultCode) {
+ synchronized (mSync) {
+ mSync.mHasNotify = true;
+ mSync.notify();
+ assertEquals(CTSResult.RESULT_OK, resultCode);
+ }
+ }
+
+ public void setResult(Exception e) {
+ setResult(CTSResult.RESULT_FAIL);
+ }
+
+}
diff --git a/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java b/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java
deleted file mode 100644
index 70764e4..0000000
--- a/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.Activity;
-import android.app.ActivityGroup;
-import android.app.LocalActivityManager;
-import android.content.Intent;
-import android.cts.util.CTSResult;
-import android.os.Bundle;
-import android.view.Window;
-
-public class LocalActivityManagerTestHelper extends ActivityGroup {
-
- public static final String ACTION_DISPATCH_RESUME = "dispatchResume";
- public static final String ACTION_START_ACTIVITY = "startActivity";
- public static final String ACTION_DISPATCH_CREATE = "dispatchCreate";
- public static final String ACTION_DISPATCH_STOP = "dispatchStop";
- public static final String ACTION_DISPATCH_PAUSE_TRUE = "dispatchPauseTrue";
- public static final String ACTION_DISPATCH_PAUSE_FALSE = "dispatchPauseFalse";
- public static final String ACTION_SAVE_INSTANCE_STATE = "saveInstanceState";
- public static final String ACTION_DISPATCH_DESTROY = "dispatchDestroy";
- public static final String ACTION_REMOVE_ALL_ACTIVITY = "removeAllActivities";
-
- private String mCurrentAction;
- private LocalActivityManager mLocalActivityManager;
-
- private static CTSResult sResult;
-
- public static void setResult(CTSResult cr) {
- sResult = cr;
- }
-
- public LocalActivityManagerTestHelper() {
- super();
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mCurrentAction = getIntent().getAction();
- mLocalActivityManager = getLocalActivityManager();
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- }
-
- protected void onResume() {
- super.onResume();
- if (mCurrentAction.equals(ACTION_DISPATCH_RESUME)) {
- testDispatchResume();
- } else if (mCurrentAction.equals(ACTION_START_ACTIVITY)) {
- testStartActivity();
- } else if (mCurrentAction.equals(ACTION_DISPATCH_CREATE)) {
- testDispatchCreate();
- } else if (mCurrentAction.equals(ACTION_DISPATCH_STOP)) {
- testDispatchStop();
- } else if (mCurrentAction.equals(ACTION_DISPATCH_PAUSE_TRUE)) {
- testDispatchPauseTrue();
- } else if (mCurrentAction.equals(ACTION_DISPATCH_PAUSE_FALSE)) {
- testDispatchPauseFalse();
- } else if (mCurrentAction.equals(ACTION_SAVE_INSTANCE_STATE)) {
- testSaveInstanceState();
- } else if (mCurrentAction.equals(ACTION_DISPATCH_DESTROY)) {
- testDispatchDestroy();
- } else if (mCurrentAction.equals(ACTION_REMOVE_ALL_ACTIVITY)) {
- testRemoveAllActivity();
- }
- }
-
- private void testRemoveAllActivity() {
- final String id = "id_remove_activity";
- final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mLocalActivityManager.startActivity(id, intent);
-
- Activity activity = mLocalActivityManager.getActivity(id);
- if (activity == null) {
- fail();
- return;
- }
-
- if (!activity.getClass().getName().equals("android.app.cts."
- + "LocalActivityManagerStubActivity")) {
- fail();
- return;
- }
-
- mLocalActivityManager.removeAllActivities();
- activity = mLocalActivityManager.getActivity(id);
- if (activity != null) {
- fail();
- return;
- }
- pass();
- }
-
- private void testDispatchDestroy() {
- final String id1 = "id_dispatch_destroy1";
- final String id2 = "id_dispatch_destroy2";
- final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mLocalActivityManager.startActivity(id1, intent);
-
- LocalActivityManagerStubActivity.sIsOnDestroyCalled = false;
- mLocalActivityManager.dispatchDestroy(false);
- if (mLocalActivityManager.getCurrentActivity().isFinishing()){
- fail();
- return;
- }
-
- if (!LocalActivityManagerStubActivity.sIsOnDestroyCalled) {
- fail();
- return;
- }
-
- mLocalActivityManager.startActivity(id2, intent);
- LocalActivityManagerStubActivity.sIsOnDestroyCalled = false;
- mLocalActivityManager.dispatchDestroy(true);
-
- if (!LocalActivityManagerStubActivity.sIsOnDestroyCalled) {
- fail();
- return;
- }
-
- if (!mLocalActivityManager.getCurrentActivity().isFinishing()){
- fail();
- return;
- }
- pass();
- }
-
- private void testSaveInstanceState() {
- final String key = "_id1";
- mLocalActivityManager.dispatchCreate(null);
- final Bundle bundle = mLocalActivityManager.saveInstanceState();
- if (bundle != null) {
- fail();
- return;
- }
-
- final String id = "id_dispatch_pause";
- final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mLocalActivityManager.startActivity(id, intent);
-
- final Bundle savedBundle = new Bundle();
- final Bundle bb = new Bundle();
- savedBundle.putBundle(key, bb);
-
- mLocalActivityManager.dispatchCreate(savedBundle);
- final Bundle returnedBundle = mLocalActivityManager.saveInstanceState();
- if (returnedBundle.getBundle(key) == null ) {
- fail();
- return;
- }
- pass();
- }
-
- private void testDispatchPauseFalse() {
- final String id = "id_dispatch_pause";
- final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mLocalActivityManager.startActivity(id, intent);
- LocalActivityManagerStubActivity.sIsOnPauseCalled = false;
- mLocalActivityManager.dispatchPause(false);
- if (!LocalActivityManagerStubActivity.sIsOnPauseCalled) {
- fail();
- return;
- }
- pass();
- }
-
- private void testDispatchPauseTrue() {
- final String id = "id_dispatch_pause";
- final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mLocalActivityManager.startActivity(id, intent);
- LocalActivityManagerStubActivity.sIsOnPauseCalled = false;
- mLocalActivityManager.dispatchPause(true);
- if (!LocalActivityManagerStubActivity.sIsOnPauseCalled) {
- fail();
- return;
- }
- pass();
- }
-
- private void testDispatchStop() {
- final String id = "id_dispatch_stop";
- final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mLocalActivityManager.startActivity(id, intent);
- if (mLocalActivityManager.getCurrentActivity() == null) {
- fail();
- return;
- }
-
- LocalActivityManagerStubActivity.sIsOnStopCalled = false;
- mLocalActivityManager.dispatchStop();
-
- if (!LocalActivityManagerStubActivity.sIsOnStopCalled) {
- fail();
- return;
- }
- pass();
- }
-
- private void testDispatchCreate() {
- final Bundle EXPECTED = new Bundle();
- final String id = "id";
-
- final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mLocalActivityManager.startActivity("_id" + System.currentTimeMillis(), intent);
- final Bundle bundle = mLocalActivityManager.saveInstanceState();
- if (bundle == null) {
- fail();
- return;
- }
-
- if (bundle.keySet().size() != 1) {
- fail();
- return;
- }
-
- bundle.putBundle(id, EXPECTED);
- // test null parameter
- mLocalActivityManager.dispatchCreate(null);
-
- if (mLocalActivityManager.saveInstanceState().keySet().size() != 1) {
- fail();
- return;
- }
-
- mLocalActivityManager.dispatchCreate(bundle);
-
- final Bundle b = mLocalActivityManager.saveInstanceState();
- final Bundle bb = b.getBundle(id);
- if (bb != EXPECTED) {
- fail();
- return;
- }
- pass();
- }
-
- private void testStartActivity() {
- final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final String id = "_id_resume_test";
- final Window w = mLocalActivityManager.startActivity(id, intent);
- if (w == null) {
- fail();
- return;
- }
-
- Activity activity = mLocalActivityManager.getActivity(id);
- if (activity == null) {
- fail();
- return;
- }
-
- // testing null id
- activity = mLocalActivityManager.getActivity("null id");
- if (activity != null) {
- fail();
- return;
- }
-
- if (!mLocalActivityManager.getCurrentId().equals(id)) {
- fail();
- return;
- }
-
- if (mLocalActivityManager.getActivity(id) != mLocalActivityManager
- .getCurrentActivity()) {
- fail();
- return;
- }
-
- if (mLocalActivityManager.destroyActivity(id, true) == null) {
- fail();
- return;
- }
-
- if (mLocalActivityManager.startActivity(null, intent) == null) {
- fail();
- return;
- }
-
- try {
- // test when calling startActivity with both null parameter.
- mLocalActivityManager.startActivity(null, null);
- fail();
- return;
- } catch (NullPointerException e) {
- }
- pass();
- }
-
- private void testDispatchResume() {
- final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mLocalActivityManager.startActivity("_id_resume_test", intent);
- mLocalActivityManager.dispatchStop();
- LocalActivityManagerStubActivity.sIsOnResumeCalled = false;
- mLocalActivityManager.dispatchResume();
- if (LocalActivityManagerStubActivity.sIsOnResumeCalled) {
- pass();
- } else {
- fail();
- }
- }
-
- private void fail() {
- sResult.setResult(CTSResult.RESULT_FAIL);
- finish();
- }
-
- private void pass() {
- sResult.setResult(CTSResult.RESULT_OK);
- finish();
- }
-}
diff --git a/tests/app/src/android/app/cts/LocalDeniedService.java b/tests/app/src/android/app/cts/LocalDeniedService.java
deleted file mode 100644
index d3c9153..0000000
--- a/tests/app/src/android/app/cts/LocalDeniedService.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-public class LocalDeniedService extends LocalService
-{
-}
-
diff --git a/tests/app/src/android/app/cts/LocalDialog.java b/tests/app/src/android/app/cts/LocalDialog.java
deleted file mode 100644
index ec670fc..0000000
--- a/tests/app/src/android/app/cts/LocalDialog.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-public class LocalDialog extends TestedScreen {
- public LocalDialog() {
- }
-}
diff --git a/tests/app/src/android/app/cts/LocalGrantedService.java b/tests/app/src/android/app/cts/LocalGrantedService.java
deleted file mode 100644
index c073f12..0000000
--- a/tests/app/src/android/app/cts/LocalGrantedService.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-public class LocalGrantedService extends LocalService
-{
-}
-
diff --git a/tests/app/src/android/app/cts/LocalScreen.java b/tests/app/src/android/app/cts/LocalScreen.java
deleted file mode 100644
index 87f5530..0000000
--- a/tests/app/src/android/app/cts/LocalScreen.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-public class LocalScreen extends TestedScreen {
- public LocalScreen() {
- }
-}
diff --git a/tests/app/src/android/app/cts/LocalService.java b/tests/app/src/android/app/cts/LocalService.java
deleted file mode 100644
index 6c4ae99..0000000
--- a/tests/app/src/android/app/cts/LocalService.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Service;
-import android.content.Intent;
-import android.cts.util.IBinderParcelable;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.RemoteException;
-
-public class LocalService extends Service {
- public static final String SERVICE_LOCAL =
- "android.app.cts.activity.SERVICE_LOCAL";
- public static final String SERVICE_LOCAL_GRANTED =
- "android.app.cts.activity.SERVICE_LOCAL_GRANTED";
- public static final String SERVICE_LOCAL_DENIED =
- "android.app.cts.activity.SERVICE_LOCAL_DENIED";
-
- public static final String REPORT_OBJ_NAME = "report";
-
- public static final int STARTED_CODE = 1;
- public static final int DESTROYED_CODE = 2;
- public static final int SET_REPORTER_CODE = 3;
- public static final int UNBIND_CODE = 4;
- public static final int REBIND_CODE = 5;
-
- private IBinder mReportObject;
- private int mStartCount = 1;
-
- private final IBinder mBinder = new Binder() {
- @Override
- protected boolean onTransact(int code, Parcel data, Parcel reply,
- int flags) throws RemoteException {
- if (code == SET_REPORTER_CODE) {
- data.enforceInterface(SERVICE_LOCAL);
- mReportObject = data.readStrongBinder();
- return true;
- } else {
- return super.onTransact(code, data, reply, flags);
- }
- }
- };
-
-
- public LocalService() {
- }
-
- @Override
- public void onStart(Intent intent, int startId) {
- if (intent.getExtras() != null) {
- IBinderParcelable parcelable
- = (IBinderParcelable) intent.getExtras().getParcelable(REPORT_OBJ_NAME);
- mReportObject = parcelable.binder;
- if (mReportObject != null) {
- bindAction(STARTED_CODE);
- }
- }
- }
-
- @Override
- public void onDestroy() {
- if (mReportObject != null) {
- bindAction(DESTROYED_CODE);
- }
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- @Override
- public boolean onUnbind(Intent intent) {
- if (mReportObject != null) {
- bindAction(UNBIND_CODE);
- }
- return true;
- }
-
- @Override
- public void onRebind(Intent intent) {
- if (mReportObject != null) {
- bindAction(REBIND_CODE);
- }
- }
-
- private void bindAction(final int bindCode) {
- try {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(SERVICE_LOCAL);
- if (bindCode == STARTED_CODE) {
- data.writeInt(mStartCount);
- mStartCount++;
- }
- mReportObject.transact(
- bindCode, data, null, 0);
- data.recycle();
- } catch (RemoteException e) {
- // fail
- }
- }
-}
diff --git a/tests/app/src/android/app/cts/MockActivity.java b/tests/app/src/android/app/cts/MockActivity.java
deleted file mode 100644
index 8d10c71..0000000
--- a/tests/app/src/android/app/cts/MockActivity.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-
-public class MockActivity extends Activity {
-
-}
diff --git a/tests/app/src/android/app/cts/MockAlarmReceiver.java b/tests/app/src/android/app/cts/MockAlarmReceiver.java
deleted file mode 100644
index 8745db6..0000000
--- a/tests/app/src/android/app/cts/MockAlarmReceiver.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.SystemClock;
-
-/**
- * this class receive alarm from AlarmManagerTest
- */
-public class MockAlarmReceiver extends BroadcastReceiver {
- private final Object mSync = new Object();
- public final String mTargetAction;
-
- public volatile boolean alarmed = false;
- public volatile long elapsedTime;
- public volatile long rtcTime;
-
- public MockAlarmReceiver(String targetAction) {
- mTargetAction = targetAction;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (action.equals(mTargetAction)) {
- synchronized (mSync) {
- alarmed = true;
- elapsedTime = SystemClock.elapsedRealtime();
- rtcTime = System.currentTimeMillis();
- }
- }
- }
-
- public void setAlarmedFalse() {
- synchronized (mSync) {
- alarmed = false;
- }
- }
-}
diff --git a/tests/app/src/android/app/cts/MockApplication.java b/tests/app/src/android/app/cts/MockApplication.java
deleted file mode 100644
index 0d0cb43..0000000
--- a/tests/app/src/android/app/cts/MockApplication.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Application;
-import android.content.res.Configuration;
-
-
-public class MockApplication extends Application {
-
- public boolean isOnCreateCalled;
- public boolean isConstructorCalled;
- public boolean isOnConfigurationChangedCalled;
- public boolean isOnLowMemoryCalled;
-
- public MockApplication() {
- super();
- isConstructorCalled = true;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- isOnCreateCalled = true;
- }
-
- @Override
- public void onTerminate() {
- super.onTerminate();
- // The documentation states that one cannot rely on this method being called. No need to
- // test it here.
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- isOnConfigurationChangedCalled = true;
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- isOnLowMemoryCalled = true;
- }
-}
diff --git a/tests/app/src/android/app/cts/MockApplicationActivity.java b/tests/app/src/android/app/cts/MockApplicationActivity.java
deleted file mode 100644
index 40299ee..0000000
--- a/tests/app/src/android/app/cts/MockApplicationActivity.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.widget.TextView;
-
-public class MockApplicationActivity extends Activity {
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- TextView textView = new TextView(this);
- textView.setText("Test");
- setContentView(textView);
- }
-
-}
diff --git a/tests/app/src/android/app/cts/MockReceiver.java b/tests/app/src/android/app/cts/MockReceiver.java
deleted file mode 100644
index d102cbe..0000000
--- a/tests/app/src/android/app/cts/MockReceiver.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-public class MockReceiver extends BroadcastReceiver {
-
- // PendingIntent may return same instance or new instance, so static variable is needed.
- public static int sResultCode = 0;
- public static final String MOCKACTION = "android.app.PendingIntentTest.TEST_RECEIVER";
- public static String sAction;
-
- /**
- * set the result as true when received alarm
- */
- @Override
- public void onReceive(Context context, Intent intent) {
- sAction = intent.getAction();
- if (sAction.equals(MOCKACTION)) {
- sResultCode = getResultCode();
- }
- }
-}
-
diff --git a/tests/app/src/android/app/cts/MockService.java b/tests/app/src/android/app/cts/MockService.java
deleted file mode 100644
index 510e731..0000000
--- a/tests/app/src/android/app/cts/MockService.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-
-public class MockService extends Service {
- public static boolean result = false;
- private final IBinder mBinder = new MockBinder();
-
- public class MockBinder extends Binder {
- MockService getService() {
- return MockService.this;
- }
- }
-
- /**
- * set the result as true when service bind
- */
- @Override
- public IBinder onBind(Intent intent) {
- result = true;
- return mBinder;
- }
-
- /**
- * set the result as true when service start
- */
- @Override
- public void onStart(Intent intent, int startId) {
- super.onStart(intent, startId);
- result = true;
- }
-}
-
diff --git a/tests/app/src/android/app/cts/MockTabActivity.java b/tests/app/src/android/app/cts/MockTabActivity.java
deleted file mode 100644
index aca19f5..0000000
--- a/tests/app/src/android/app/cts/MockTabActivity.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.app.TabActivity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.widget.TabHost;
-
-public class MockTabActivity extends TabActivity {
-
- private static final String TAB1 = "tab1";
- private static final String TAB2 = "tab2";
- private static final String TAB3 = "tab3";
-
- public boolean isOnChildTitleChangedCalled;
- public boolean isOnPostCreateCalled;
- public boolean isOnSaveInstanceStateCalled;
- public boolean isOnContentChangedCalled;
- public static boolean isOnRestoreInstanceStateCalled;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- final TabHost tabHost = getTabHost();
-
- tabHost.addTab(tabHost.newTabSpec(TAB1).setIndicator(TAB1)
- .setContent(new Intent(this, ChildTabActivity.class)));
-
- tabHost.addTab(tabHost.newTabSpec(TAB2).setIndicator(TAB2)
- .setContent(new Intent(this, MockActivity.class)));
-
- tabHost.addTab(tabHost.newTabSpec(TAB3).setIndicator(TAB3).setContent(
- new Intent(this, AppStubActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)));
-
- }
-
- @Override
- protected void onChildTitleChanged(Activity childActivity, CharSequence title) {
- super.onChildTitleChanged(childActivity, title);
- isOnChildTitleChangedCalled = true;
- }
-
- @Override
- protected void onPostCreate(Bundle icicle) {
- super.onPostCreate(icicle);
- isOnPostCreateCalled = true;
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle state) {
- super.onRestoreInstanceState(state);
- isOnRestoreInstanceStateCalled = true;
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- isOnSaveInstanceStateCalled = true;
- }
-
- @Override
- public void onContentChanged() {
- super.onContentChanged();
- isOnContentChangedCalled = true;
- }
-}
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
new file mode 100644
index 0000000..04aeecd
--- /dev/null
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Telephony.Threads;
+import android.service.notification.StatusBarNotification;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import android.app.stubs.R;
+
+public class NotificationManagerTest extends AndroidTestCase {
+ final String TAG = NotificationManagerTest.class.getSimpleName();
+ final boolean DEBUG = false;
+
+ private NotificationManager mNotificationManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mNotificationManager = (NotificationManager) mContext.getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ // clear the deck so that our getActiveNotifications results are predictable
+ mNotificationManager.cancelAll();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mNotificationManager.cancelAll();
+ }
+
+ public void testNotify() {
+ mNotificationManager.cancelAll();
+
+ final int id = 1;
+ sendNotification(id, R.drawable.black);
+ // test updating the same notification
+ sendNotification(id, R.drawable.blue);
+ sendNotification(id, R.drawable.yellow);
+
+ // assume that sendNotification tested to make sure individual notifications were present
+ StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
+ for (StatusBarNotification sbn : sbns) {
+ if (sbn.getId() != id) {
+ fail("we got back other notifications besides the one we posted: "
+ + sbn.getKey());
+ }
+ }
+ }
+
+ public void testCancel() {
+ final int id = 9;
+ sendNotification(id, R.drawable.black);
+ mNotificationManager.cancel(id);
+
+ if (!checkNotificationExistence(id, /*shouldExist=*/ false)) {
+ fail("canceled notification was still alive, id=" + id);
+ }
+ }
+
+ public void testCancelAll() {
+ sendNotification(1, R.drawable.black);
+ sendNotification(2, R.drawable.blue);
+ sendNotification(3, R.drawable.yellow);
+
+ if (DEBUG) {
+ Log.d(TAG, "posted 3 notifications, here they are: ");
+ StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
+ for (StatusBarNotification sbn : sbns) {
+ Log.d(TAG, " " + sbn);
+ }
+ Log.d(TAG, "about to cancel...");
+ }
+ mNotificationManager.cancelAll();
+
+ StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
+ assertTrue("notification list was not empty after cancelAll", sbns.length == 0);
+ }
+
+ private void sendNotification(final int id, final int icon) {
+ final Intent intent = new Intent(Intent.ACTION_MAIN, Threads.CONTENT_URI);
+
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.setAction(Intent.ACTION_MAIN);
+
+ final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+ final Notification notification = new Notification.Builder(mContext)
+ .setSmallIcon(icon)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("notify#" + id)
+ .setContentText("This is #" + id + "notification ")
+ .setContentIntent(pendingIntent)
+ .build();
+ mNotificationManager.notify(id, notification);
+
+
+ if (!checkNotificationExistence(id, /*shouldExist=*/ true)) {
+ fail("couldn't find posted notification id=" + id);
+ }
+ }
+
+ private boolean checkNotificationExistence(int id, boolean shouldExist) {
+ // notification is a bit asynchronous so it may take a few ms to appear in getActiveNotifications()
+ // we will check for it for up to 200ms before giving up
+ boolean found = false;
+ for (int tries=3; tries-->0;) {
+ final StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
+ for (StatusBarNotification sbn : sbns) {
+ if (sbn.getId() == id) {
+ found = true;
+ break;
+ }
+ }
+ if (found == shouldExist) break;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ }
+ return found == shouldExist;
+ }
+}
diff --git a/tests/app/src/android/app/cts/NotificationTest.java b/tests/app/src/android/app/cts/NotificationTest.java
new file mode 100644
index 0000000..9da1b25
--- /dev/null
+++ b/tests/app/src/android/app/cts/NotificationTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.Notification;
+import android.app.Notification.Topic;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.widget.RemoteViews;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class NotificationTest extends AndroidTestCase {
+
+ private Notification mNotification;
+ private Context mContext;
+
+ private static final String TICKER_TEXT = "tickerText";
+ private static final String CONTENT_TITLE = "contentTitle";
+ private static final String CONTENT_TEXT = "contentText";
+ private static final String URI_STRING = "uriString";
+ private static final int TOLERANCE = 200;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getContext();
+ mNotification = new Notification();
+ }
+
+ public void testConstructor() {
+ mNotification = null;
+ mNotification = new Notification();
+ assertNotNull(mNotification);
+ assertTrue(System.currentTimeMillis() - mNotification.when < TOLERANCE);
+
+ mNotification = null;
+ final int notificationTime = 200;
+ mNotification = new Notification(0, TICKER_TEXT, notificationTime);
+ assertEquals(notificationTime, mNotification.when);
+ assertEquals(0, mNotification.icon);
+ assertEquals(TICKER_TEXT, mNotification.tickerText);
+ }
+
+ public void testDescribeContents() {
+ final int expected = 0;
+ mNotification = new Notification();
+ assertEquals(expected, mNotification.describeContents());
+ }
+
+ public void testWriteToParcel() {
+ mNotification = new Notification();
+ mNotification.icon = 0;
+ mNotification.number = 1;
+ final Intent intent = new Intent();
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ mNotification.contentIntent = pendingIntent;
+ final Intent deleteIntent = new Intent();
+ final PendingIntent delPendingIntent = PendingIntent.getBroadcast(
+ mContext, 0, deleteIntent, 0);
+ mNotification.deleteIntent = delPendingIntent;
+ mNotification.tickerText = TICKER_TEXT;
+
+ final RemoteViews contentView = new RemoteViews(mContext.getPackageName(),
+ android.R.layout.simple_list_item_1);
+ mNotification.contentView = contentView;
+ mNotification.defaults = 0;
+ mNotification.flags = 0;
+ final Uri uri = Uri.parse(URI_STRING);
+ mNotification.sound = uri;
+ mNotification.audioStreamType = 0;
+ final long[] longArray = { 1l, 2l, 3l };
+ mNotification.vibrate = longArray;
+ mNotification.ledARGB = 0;
+ mNotification.ledOnMS = 0;
+ mNotification.ledOffMS = 0;
+ mNotification.iconLevel = 0;
+ Parcel parcel = Parcel.obtain();
+ mNotification.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ // Test Notification(Parcel)
+ Notification result = new Notification(parcel);
+ assertEquals(mNotification.icon, result.icon);
+ assertEquals(mNotification.when, result.when);
+ assertEquals(mNotification.number, result.number);
+ assertNotNull(result.contentIntent);
+ assertNotNull(result.deleteIntent);
+ assertEquals(mNotification.tickerText, result.tickerText);
+ assertNotNull(result.contentView);
+ assertEquals(mNotification.defaults, result.defaults);
+ assertEquals(mNotification.flags, result.flags);
+ assertNotNull(result.sound);
+ assertEquals(mNotification.audioStreamType, result.audioStreamType);
+ assertEquals(mNotification.vibrate[0], result.vibrate[0]);
+ assertEquals(mNotification.vibrate[1], result.vibrate[1]);
+ assertEquals(mNotification.vibrate[2], result.vibrate[2]);
+ assertEquals(mNotification.ledARGB, result.ledARGB);
+ assertEquals(mNotification.ledOnMS, result.ledOnMS);
+ assertEquals(mNotification.ledOffMS, result.ledOffMS);
+ assertEquals(mNotification.iconLevel, result.iconLevel);
+
+ mNotification.contentIntent = null;
+ parcel = Parcel.obtain();
+ mNotification.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ result = new Notification(parcel);
+ assertNull(result.contentIntent);
+
+ mNotification.deleteIntent = null;
+ parcel = Parcel.obtain();
+ mNotification.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ result = new Notification(parcel);
+ assertNull(result.deleteIntent);
+
+ mNotification.tickerText = null;
+ parcel = Parcel.obtain();
+ mNotification.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ result = new Notification(parcel);
+ assertNull(result.tickerText);
+
+ mNotification.contentView = null;
+ parcel = Parcel.obtain();
+ mNotification.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ result = new Notification(parcel);
+ assertNull(result.contentView);
+
+ mNotification.sound = null;
+ parcel = Parcel.obtain();
+ mNotification.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ result = new Notification(parcel);
+ assertNull(result.sound);
+ }
+
+ public void testBuilder() {
+ final Intent intent = new Intent();
+ final PendingIntent contentIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ mNotification = new Notification.Builder(mContext)
+ .setSmallIcon(1)
+ .setContentTitle(CONTENT_TITLE)
+ .setContentText(CONTENT_TEXT)
+ .setContentIntent(contentIntent)
+ .setTopic(new Topic("id1", "label1"))
+ .build();
+ assertEquals(CONTENT_TEXT, mNotification.extras.getString(Notification.EXTRA_TEXT));
+ assertEquals(CONTENT_TITLE, mNotification.extras.getString(Notification.EXTRA_TITLE));
+ assertEquals(1, mNotification.icon);
+ assertEquals(contentIntent, mNotification.contentIntent);
+ assertEquals(new Topic("id1", "label1"), mNotification.getTopic());
+ }
+
+ public void testWriteTopicToParcel() {
+ mNotification = new Notification.Builder(mContext)
+ .setTopic(new Topic("id2", "label2"))
+ .build();
+ Parcel parcel = Parcel.obtain();
+ mNotification.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ // Test Notification(Parcel)
+ Notification result = new Notification(parcel);
+ assertEquals(new Topic("id2", "label2"), result.getTopic());
+
+ mNotification = new Notification();
+ parcel = Parcel.obtain();
+ mNotification.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ // Test Notification(Parcel)
+ result = new Notification(parcel);
+ assertNull(result.getTopic());
+ }
+
+ public void testToString() {
+ mNotification = new Notification();
+ assertNotNull(mNotification.toString());
+ }
+}
diff --git a/tests/app/src/android/app/cts/OrientationTestUtils.java b/tests/app/src/android/app/cts/OrientationTestUtils.java
deleted file mode 100644
index 7b2b568..0000000
--- a/tests/app/src/android/app/cts/OrientationTestUtils.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2010 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.Activity;
-import android.app.Instrumentation;
-import android.content.pm.ActivityInfo;
-
-public class OrientationTestUtils {
-
- /**
- * Change the activity's orientation to something different and then switch back. This is used
- * to trigger {@link Activity#onConfigurationChanged(android.content.res.Configuration)}.
- *
- * @param activity whose orientation will be changed and restored
- */
- public static void toggleOrientation(Activity activity) {
- toggleOrientationSync(activity, null);
- }
-
- /**
- * Same as {@link #toggleOrientation(Activity)} except {@link Instrumentation#waitForIdleSync()}
- * is called after each orientation change.
- *
- * @param activity whose orientation will be changed and restored
- * @param instrumentation use for idle syncing
- */
- public static void toggleOrientationSync(final Activity activity,
- final Instrumentation instrumentation) {
- final int originalOrientation = activity.getResources().getConfiguration().orientation;
- final int newOrientation = originalOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
- ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
- : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
- changeOrientation(activity, instrumentation, newOrientation);
- changeOrientation(activity, instrumentation, originalOrientation);
- }
-
- private static void changeOrientation(final Activity activity,
- Instrumentation instrumentation, final int orientation) {
- activity.setRequestedOrientation(orientation);
- if (instrumentation != null) {
- instrumentation.waitForIdleSync();
- }
- }
-}
diff --git a/tests/app/src/android/app/cts/PendingIntentStubActivity.java b/tests/app/src/android/app/cts/PendingIntentStubActivity.java
deleted file mode 100644
index a2a3bd8..0000000
--- a/tests/app/src/android/app/cts/PendingIntentStubActivity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class PendingIntentStubActivity extends Activity {
-
- public static final int INVALIDATE = -1;
- public static final int ON_CREATE = 0;
- public static int status = INVALIDATE;
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- status = ON_CREATE;
- }
-
-}
diff --git a/tests/app/src/android/app/cts/PendingIntentTest.java b/tests/app/src/android/app/cts/PendingIntentTest.java
new file mode 100644
index 0000000..697de72
--- /dev/null
+++ b/tests/app/src/android/app/cts/PendingIntentTest.java
@@ -0,0 +1,456 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.app.stubs.MockReceiver;
+import android.app.stubs.MockService;
+import android.app.stubs.PendingIntentStubActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+public class PendingIntentTest extends AndroidTestCase {
+
+ private static final int WAIT_TIME = 5000;
+ private PendingIntent mPendingIntent;
+ private Intent mIntent;
+ private Context mContext;
+ private boolean mFinishResult;
+ private boolean mHandleResult;
+ private String mResultAction;
+ private PendingIntent.OnFinished mFinish;
+ private boolean mLooperStart;
+ private Looper mLooper;
+ private Handler mHandler;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getContext();
+ mFinish = new PendingIntent.OnFinished() {
+ public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
+ String resultData, Bundle resultExtras) {
+ mFinishResult = true;
+ if (intent != null) {
+ mResultAction = intent.getAction();
+ }
+ }
+ };
+
+ new Thread() {
+ @Override
+ public void run() {
+ Looper.prepare();
+ mLooper = Looper.myLooper();
+ mLooperStart = true;
+ Looper.loop();
+ }
+ }.start();
+ while (!mLooperStart) {
+ Thread.sleep(50);
+ }
+ mHandler = new Handler(mLooper) {
+ @Override
+ public void dispatchMessage(Message msg) {
+ mHandleResult = true;
+ super.dispatchMessage(msg);
+ }
+
+ @Override
+ public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
+ mHandleResult = true;
+ return super.sendMessageAtTime(msg, uptimeMillis);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ mHandleResult = true;
+ }
+ };
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mLooper.quit();
+ }
+
+ public void testGetActivity() throws InterruptedException, CanceledException {
+ PendingIntentStubActivity.status = PendingIntentStubActivity.INVALIDATE;
+ mPendingIntent = null;
+ mIntent = new Intent();
+
+ mIntent.setClass(mContext, PendingIntentStubActivity.class);
+ mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ assertEquals(mContext.getPackageName(), mPendingIntent.getTargetPackage());
+
+ mPendingIntent.send();
+
+ Thread.sleep(WAIT_TIME);
+ assertNotNull(mPendingIntent);
+ assertEquals(PendingIntentStubActivity.status, PendingIntentStubActivity.ON_CREATE);
+
+ // test getActivity return null
+ mPendingIntent.cancel();
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
+ PendingIntent.FLAG_NO_CREATE);
+ assertNull(mPendingIntent);
+
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
+ PendingIntent.FLAG_ONE_SHOT);
+
+ pendingIntentSendError(mPendingIntent);
+ }
+
+ private void pendingIntentSendError(PendingIntent pendingIntent) {
+ try {
+ // From the doc send function will throw CanceledException if the PendingIntent
+ // is no longer allowing more intents to be sent through it. So here call it twice then
+ // a CanceledException should be caught.
+ mPendingIntent.send();
+ mPendingIntent.send();
+ fail("CanceledException expected, but not thrown");
+ } catch (PendingIntent.CanceledException e) {
+ // expected
+ }
+ }
+
+ public void testGetBroadcast() throws InterruptedException, CanceledException {
+ MockReceiver.sAction = null;
+ mIntent = new Intent(MockReceiver.MOCKACTION);
+ mIntent.setClass(mContext, MockReceiver.class);
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+
+ mPendingIntent.send();
+
+ Thread.sleep(WAIT_TIME);
+ assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
+
+ // test getBroadcast return null
+ mPendingIntent.cancel();
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
+ PendingIntent.FLAG_NO_CREATE);
+ assertNull(mPendingIntent);
+
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
+ PendingIntent.FLAG_ONE_SHOT);
+
+ pendingIntentSendError(mPendingIntent);
+ }
+
+ public void testGetService() throws InterruptedException, CanceledException {
+ MockService.result = false;
+ mIntent = new Intent();
+ mIntent.setClass(mContext, MockService.class);
+ mPendingIntent = PendingIntent.getService(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+
+ mPendingIntent.send();
+
+ Thread.sleep(WAIT_TIME);
+ assertTrue(MockService.result);
+
+ // test getService return null
+ mPendingIntent.cancel();
+ mPendingIntent = PendingIntent.getService(mContext, 1, mIntent,
+ PendingIntent.FLAG_NO_CREATE);
+ assertNull(mPendingIntent);
+
+ mPendingIntent = PendingIntent.getService(mContext, 1, mIntent,
+ PendingIntent.FLAG_ONE_SHOT);
+
+ pendingIntentSendError(mPendingIntent);
+ }
+
+ public void testCancel() throws CanceledException {
+ mIntent = new Intent();
+ mIntent.setClass(mContext, MockService.class);
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+
+ mPendingIntent.send();
+
+ mPendingIntent.cancel();
+ pendingIntentSendShouldFail(mPendingIntent);
+ }
+
+ private void pendingIntentSendShouldFail(PendingIntent pendingIntent) {
+ try {
+ pendingIntent.send();
+ fail("CanceledException expected, but not thrown");
+ } catch (CanceledException e) {
+ // expected
+ }
+ }
+
+ public void testSend() throws InterruptedException, CanceledException {
+ MockReceiver.sAction = null;
+ MockReceiver.sResultCode = -1;
+ mIntent = new Intent();
+ mIntent.setAction(MockReceiver.MOCKACTION);
+ mIntent.setClass(mContext, MockReceiver.class);
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+
+ mPendingIntent.send();
+
+ Thread.sleep(WAIT_TIME);
+
+ // send function to send default code 0
+ assertEquals(0, MockReceiver.sResultCode);
+ assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
+ mPendingIntent.cancel();
+
+ pendingIntentSendShouldFail(mPendingIntent);
+ }
+
+ public void testSendWithParamInt() throws InterruptedException, CanceledException {
+ mIntent = new Intent(MockReceiver.MOCKACTION);
+ mIntent.setClass(mContext, MockReceiver.class);
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ MockReceiver.sResultCode = 0;
+ MockReceiver.sAction = null;
+ // send result code 1.
+ mPendingIntent.send(1);
+ Thread.sleep(WAIT_TIME);
+ assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
+
+ // assert the result code
+ assertEquals(1, MockReceiver.sResultCode);
+ assertEquals(mResultAction, null);
+
+ mResultAction = null;
+ MockReceiver.sResultCode = 0;
+ // send result code 2
+ mPendingIntent.send(2);
+ Thread.sleep(WAIT_TIME);
+
+ assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
+
+ // assert the result code
+ assertEquals(2, MockReceiver.sResultCode);
+ assertEquals(MockReceiver.sAction, MockReceiver.MOCKACTION);
+ assertNull(mResultAction);
+ mPendingIntent.cancel();
+ pendingIntentSendShouldFail(mPendingIntent);
+ }
+
+ public void testSendWithParamContextIntIntent() throws InterruptedException, CanceledException {
+ mIntent = new Intent(MockReceiver.MOCKACTION);
+ mIntent.setClass(mContext, MockReceiver.class);
+
+ MockReceiver.sAction = null;
+ MockReceiver.sResultCode = 0;
+
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
+
+ mPendingIntent.send(mContext, 1, null);
+ Thread.sleep(WAIT_TIME);
+
+ assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
+ assertEquals(1, MockReceiver.sResultCode);
+ mPendingIntent.cancel();
+
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
+ MockReceiver.sAction = null;
+ MockReceiver.sResultCode = 0;
+
+ mPendingIntent.send(mContext, 2, mIntent);
+ Thread.sleep(WAIT_TIME);
+ assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
+ assertEquals(2, MockReceiver.sResultCode);
+ mPendingIntent.cancel();
+ }
+
+ public void testSendWithParamIntOnFinishedHandler() throws InterruptedException,
+ CanceledException {
+ mIntent = new Intent(MockReceiver.MOCKACTION);
+ mIntent.setClass(mContext, MockReceiver.class);
+
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
+ mFinishResult = false;
+ mHandleResult = false;
+ MockReceiver.sAction = null;
+ MockReceiver.sResultCode = 0;
+
+ mPendingIntent.send(1, null, null);
+ Thread.sleep(WAIT_TIME);
+ assertFalse(mFinishResult);
+ assertFalse(mHandleResult);
+ assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
+
+ // assert result code
+ assertEquals(1, MockReceiver.sResultCode);
+ mPendingIntent.cancel();
+
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
+ mFinishResult = false;
+ MockReceiver.sAction = null;
+ MockReceiver.sResultCode = 0;
+ mHandleResult = false;
+
+ mPendingIntent.send(2, mFinish, null);
+ Thread.sleep(WAIT_TIME);
+ assertTrue(mFinishResult);
+ assertFalse(mHandleResult);
+ assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
+
+ // assert result code
+ assertEquals(2, MockReceiver.sResultCode);
+ mPendingIntent.cancel();
+
+ mHandleResult = false;
+ mFinishResult = false;
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
+ MockReceiver.sAction = null;
+ mPendingIntent.send(3, mFinish, mHandler);
+ Thread.sleep(WAIT_TIME);
+ assertTrue(mHandleResult);
+ assertTrue(mFinishResult);
+ assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
+
+ // assert result code
+ assertEquals(3, MockReceiver.sResultCode);
+ mPendingIntent.cancel();
+ }
+
+ public void testSendWithParamContextIntIntentOnFinishedHandler() throws InterruptedException,
+ CanceledException {
+ mIntent = new Intent(MockReceiver.MOCKACTION);
+ mIntent.setAction(MockReceiver.MOCKACTION);
+
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
+ mFinishResult = false;
+ mResultAction = null;
+ mHandleResult = false;
+ mPendingIntent.send(mContext, 1, mIntent, null, null);
+ Thread.sleep(WAIT_TIME);
+ assertFalse(mFinishResult);
+ assertFalse(mHandleResult);
+ assertNull(mResultAction);
+ mPendingIntent.cancel();
+
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
+ mFinishResult = false;
+ mResultAction = null;
+ mHandleResult = false;
+ mPendingIntent.send(mContext, 1, mIntent, mFinish, null);
+ Thread.sleep(WAIT_TIME);
+ assertTrue(mFinishResult);
+ assertEquals(mResultAction, MockReceiver.MOCKACTION);
+ assertFalse(mHandleResult);
+ mPendingIntent.cancel();
+
+ mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
+ mFinishResult = false;
+ mResultAction = null;
+ mHandleResult = false;
+ mPendingIntent.send(mContext, 1, mIntent, mFinish, mHandler);
+ Thread.sleep(WAIT_TIME);
+ assertTrue(mHandleResult);
+ assertEquals(mResultAction, MockReceiver.MOCKACTION);
+ assertTrue(mFinishResult);
+ mPendingIntent.cancel();
+ }
+
+ public void testGetTargetPackage() {
+ mIntent = new Intent();
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ assertEquals(mContext.getPackageName(), mPendingIntent.getTargetPackage());
+ }
+
+ public void testEquals() {
+ mIntent = new Intent();
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+
+ PendingIntent target = PendingIntent.getActivity(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+
+ assertFalse(mPendingIntent.equals(target));
+ assertFalse(mPendingIntent.hashCode() == target.hashCode());
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent, 1);
+
+ target = PendingIntent.getActivity(mContext, 1, mIntent, 1);
+ assertTrue(mPendingIntent.equals(target));
+
+ mIntent = new Intent(MockReceiver.MOCKACTION);
+ target = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
+ assertFalse(mPendingIntent.equals(target));
+ assertFalse(mPendingIntent.hashCode() == target.hashCode());
+
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent, 1);
+ target = PendingIntent.getActivity(mContext, 1, mIntent, 1);
+
+ assertTrue(mPendingIntent.equals(target));
+ assertEquals(mPendingIntent.hashCode(), target.hashCode());
+ }
+
+ public void testDescribeContents() {
+ mIntent = new Intent();
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ final int expected = 0;
+ assertEquals(expected, mPendingIntent.describeContents());
+ }
+
+ public void testWriteToParcel() {
+ mIntent = new Intent();
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ Parcel parcel = Parcel.obtain();
+
+ mPendingIntent.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ PendingIntent pendingIntent = PendingIntent.CREATOR.createFromParcel(parcel);
+ assertTrue(mPendingIntent.equals(pendingIntent));
+ }
+
+ public void testReadAndWritePendingIntentOrNullToParcel() {
+ mIntent = new Intent();
+ mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ assertNotNull(mPendingIntent.toString());
+
+ Parcel parcel = Parcel.obtain();
+ PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, parcel);
+ parcel.setDataPosition(0);
+ PendingIntent target = PendingIntent.readPendingIntentOrNullFromParcel(parcel);
+ assertEquals(mPendingIntent, target);
+ assertEquals(mPendingIntent.getTargetPackage(), target.getTargetPackage());
+
+ mPendingIntent = null;
+ parcel = Parcel.obtain();
+ PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, parcel);
+ target = PendingIntent.readPendingIntentOrNullFromParcel(parcel);
+ assertNull(target);
+ }
+
+}
diff --git a/tests/tests/app/src/android/app/cts/PendingIntent_CanceledExceptionTest.java b/tests/app/src/android/app/cts/PendingIntent_CanceledExceptionTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/PendingIntent_CanceledExceptionTest.java
rename to tests/app/src/android/app/cts/PendingIntent_CanceledExceptionTest.java
diff --git a/tests/app/src/android/app/cts/PipActivityTest.java b/tests/app/src/android/app/cts/PipActivityTest.java
new file mode 100644
index 0000000..a553169
--- /dev/null
+++ b/tests/app/src/android/app/cts/PipActivityTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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
+ */
+
+package android.app.cts;
+
+import android.app.Instrumentation;
+import android.app.stubs.PipActivity;
+import android.test.ActivityInstrumentationTestCase2;
+
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+
+public class PipActivityTest extends ActivityInstrumentationTestCase2<PipActivity> {
+
+ private Instrumentation mInstrumentation;
+ private PipActivity mActivity;
+
+ public PipActivityTest() {
+ super("android.app.stubs", PipActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ }
+
+ public void testLaunchPipActivity() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ final boolean supportsPip =
+ mActivity.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
+ if (supportsPip) {
+ mActivity.enterPictureInPictureMode();
+ assertTrue(mActivity.inMultiWindowMode());
+ assertTrue(mActivity.inPictureInPictureMode());
+ } else {
+ boolean pipSupportDisabled = false;
+ try {
+ mActivity.enterPictureInPictureMode();
+ } catch (IllegalStateException e) {
+ // Pip not supported
+ pipSupportDisabled = true;
+ }
+ assertTrue(pipSupportDisabled);
+ assertFalse(mActivity.inMultiWindowMode());
+ assertFalse(mActivity.inPictureInPictureMode());
+ }
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+}
diff --git a/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java b/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java
new file mode 100644
index 0000000..4f7f63e
--- /dev/null
+++ b/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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
+ */
+
+package android.app.cts;
+
+import android.app.Instrumentation;
+import android.app.stubs.PipNotResizeableActivity;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class PipNotResizeableActivityTest
+ extends ActivityInstrumentationTestCase2<PipNotResizeableActivity> {
+
+ private Instrumentation mInstrumentation;
+ private PipNotResizeableActivity mActivity;
+
+ public PipNotResizeableActivityTest() {
+ super("android.app.stubs", PipNotResizeableActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ }
+
+ public void testLaunchPipNotResizeableActivity() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ boolean pipSupportDisabled = false;
+ try {
+ mActivity.enterPictureInPictureMode();
+ } catch (IllegalStateException e) {
+ // Pip not supported
+ pipSupportDisabled = true;
+ } catch (IllegalArgumentException e) {
+ // Pip not supported
+ pipSupportDisabled = true;
+ }
+ assertTrue(pipSupportDisabled);
+ assertFalse(mActivity.inMultiWindowMode());
+ assertFalse(mActivity.inPictureInPictureMode());
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+ }
diff --git a/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java b/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java
new file mode 100644
index 0000000..245421a
--- /dev/null
+++ b/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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
+ */
+
+package android.app.cts;
+
+import android.app.Instrumentation;
+import android.app.stubs.PipNotSupportedActivity;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class PipNotSupportedActivityTest
+ extends ActivityInstrumentationTestCase2<PipNotSupportedActivity> {
+
+ private Instrumentation mInstrumentation;
+ private PipNotSupportedActivity mActivity;
+
+ public PipNotSupportedActivityTest() {
+ super("android.app.stubs", PipNotSupportedActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ }
+
+ public void testLaunchPipNotSupportedActivity() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ boolean pipSupportDisabled = false;
+ try {
+ mActivity.enterPictureInPictureMode();
+ } catch (IllegalStateException e) {
+ // Pip not supported
+ pipSupportDisabled = true;
+ } catch (IllegalArgumentException e) {
+ // Pip not supported
+ pipSupportDisabled = true;
+ }
+ assertTrue(pipSupportDisabled);
+ assertFalse(mActivity.inMultiWindowMode());
+ assertFalse(mActivity.inPictureInPictureMode());
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+}
diff --git a/tests/app/src/android/app/cts/ProgressDialogTest.java b/tests/app/src/android/app/cts/ProgressDialogTest.java
new file mode 100644
index 0000000..4f4007e
--- /dev/null
+++ b/tests/app/src/android/app/cts/ProgressDialogTest.java
@@ -0,0 +1,365 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.Instrumentation;
+import android.app.ProgressDialog;
+import android.app.stubs.MockActivity;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.view.Window;
+import android.widget.ProgressBar;
+
+import android.app.stubs.R;
+
+/**
+ * Test {@link ProgressDialog}.
+ */
+public class ProgressDialogTest extends ActivityInstrumentationTestCase2<MockActivity> {
+ private final CharSequence TITLE = "title";
+ private final CharSequence MESSAGE = "message";
+
+ private boolean mCanceled;
+ private Drawable mDrawable;
+ private Drawable mActualDrawableNull;
+ private Drawable mActualDrawable;
+ private ProgressBar mProgressBar;
+ private int mProgress1;
+ private int mProgress2;
+
+ private Context mContext;
+ private Instrumentation mInstrumentation;
+ private MockActivity mActivity;
+
+ public ProgressDialogTest() {
+ super("android.app.stubs", MockActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mCanceled = false;
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ mContext = mActivity;
+ mDrawable = getActivity().getResources().getDrawable(
+ R.drawable.yellow);
+ }
+
+ @UiThreadTest
+ public void testProgressDialog1(){
+ new ProgressDialog(mContext);
+ }
+
+ @UiThreadTest
+ public void testProgressDialog2(){
+ new ProgressDialog(mContext, R.style.Theme_AlertDialog);
+ }
+
+ @UiThreadTest
+ public void testOnStartCreateStop() {
+ MockProgressDialog pd = new MockProgressDialog(mContext);
+
+ assertFalse(pd.mIsOnCreateCalled);
+ assertFalse(pd.mIsOnStartCalled);
+ pd.show();
+ assertTrue(pd.mIsOnCreateCalled);
+ assertTrue(pd.mIsOnStartCalled);
+
+ assertFalse(pd.mIsOnStopCalled);
+ pd.dismiss();
+ assertTrue(pd.mIsOnStopCalled);
+ }
+
+ @UiThreadTest
+ public void testShow1() {
+ ProgressDialog.show(mContext, TITLE, MESSAGE);
+ }
+
+ @UiThreadTest
+ public void testShow2() {
+ ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, false);
+
+ /*
+ * note: the progress bar's style only supports indeterminate mode,
+ * so can't change indeterminate
+ */
+ assertTrue(dialog.isIndeterminate());
+
+ dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true);
+ assertTrue(dialog.isIndeterminate());
+ }
+
+ public void testShow3() throws Throwable {
+ final OnCancelListener cL = new OnCancelListener(){
+ public void onCancel(DialogInterface dialog) {
+ mCanceled = true;
+ }
+ };
+
+ // cancelable is false
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, false);
+
+ dialog.setOnCancelListener(cL);
+ dialog.onBackPressed();
+ dialog.dismiss();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertFalse(mCanceled);
+
+ // cancelable is true
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, true);
+ assertFalse(mCanceled);
+ dialog.setOnCancelListener(cL);
+ dialog.onBackPressed();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(mCanceled);
+ }
+
+ public void testShow4() throws Throwable {
+ final OnCancelListener cL = new OnCancelListener(){
+ public void onCancel(DialogInterface dialog) {
+ mCanceled = true;
+ }
+ };
+
+ // cancelable is false
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ ProgressDialog dialog = ProgressDialog.show(
+ mContext, TITLE, MESSAGE, true, false, cL);
+
+ dialog.onBackPressed();
+ dialog.dismiss();;
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertFalse(mCanceled);
+
+ // cancelable is true
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ ProgressDialog dialog = ProgressDialog.show(
+ mContext, TITLE, MESSAGE, true, true, cL);
+
+ assertFalse(mCanceled);
+ dialog.onBackPressed();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(mCanceled);
+ }
+
+ @UiThreadTest
+ public void testAccessMax() {
+ // progressDialog is null
+ ProgressDialog progressDialog = buildDialog();
+ progressDialog.setMax(2008);
+ assertEquals(2008, progressDialog.getMax());
+
+ // progressDialog is not null
+ progressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+ progressDialog.setMax(2009);
+ assertEquals(2009, progressDialog.getMax());
+ }
+
+ @UiThreadTest
+ public void testAccessProgress() {
+ // progressDialog is null
+ ProgressDialog progressDialog = buildDialog();
+ progressDialog.setProgress(11);
+ assertEquals(11, progressDialog.getProgress());
+
+ /* progressDialog is not null
+ * note: the progress bar's style only supports indeterminate mode,
+ * so can't change progress
+ */
+ progressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+ progressDialog.setProgress(12);
+ assertEquals(0, progressDialog.getProgress());
+ }
+
+ @UiThreadTest
+ public void testAccessSecondaryProgress() {
+ // dialog is null
+ ProgressDialog dialog = buildDialog();
+ dialog.setSecondaryProgress(17);
+ assertEquals(17, dialog.getSecondaryProgress());
+
+ /* mProgress is not null
+ * note: the progress bar's style only supports indeterminate mode,
+ * so can't change secondary progress
+ */
+ dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+ dialog.setSecondaryProgress(18);
+ assertEquals(0, dialog.getSecondaryProgress());
+ }
+
+ @UiThreadTest
+ public void testSetIndeterminate() {
+ // progress is null
+ ProgressDialog dialog = buildDialog();
+ dialog.setIndeterminate(true);
+ assertTrue(dialog.isIndeterminate());
+ dialog.setIndeterminate(false);
+ assertFalse(dialog.isIndeterminate());
+
+ /* mProgress is not null
+ * note: the progress bar's style only supports indeterminate mode,
+ * so can't change indeterminate
+ */
+ dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+ dialog.setIndeterminate(true);
+ assertTrue(dialog.isIndeterminate());
+ dialog.setIndeterminate(false);
+ assertTrue(dialog.isIndeterminate());
+ }
+
+ @UiThreadTest
+ public void testIncrementProgressBy() throws Throwable {
+ ProgressDialog dialog = new ProgressDialog(mContext);
+ dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ dialog.show();
+ dialog.setProgress(10);
+ mProgress1 = dialog.getProgress();
+ dialog.incrementProgressBy(60);
+ mProgress2 = dialog.getProgress();
+ dialog.cancel();
+
+ assertEquals(10, mProgress1);
+ assertEquals(70, mProgress2);
+ }
+
+ @UiThreadTest
+ public void testIncrementSecondaryProgressBy() throws Throwable {
+ ProgressDialog dialog = new ProgressDialog(mContext);
+ dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ dialog.show();
+ dialog.setSecondaryProgress(10);
+ mProgress1 = dialog.getSecondaryProgress();
+ dialog.incrementSecondaryProgressBy(60);
+ mProgress2 = dialog.getSecondaryProgress();
+
+ assertEquals(10, mProgress1);
+ assertEquals(70, mProgress2);
+ }
+
+ @UiThreadTest
+ public void testSetProgressDrawable() throws Throwable {
+ ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+ Window w = dialog.getWindow();
+ ProgressBar progressBar = (ProgressBar) w.findViewById(android.R.id.progress);
+
+ dialog.setProgressDrawable(mDrawable);
+ mActualDrawable = progressBar.getProgressDrawable();
+
+ dialog.setProgressDrawable(null);
+ mActualDrawableNull = progressBar.getProgressDrawable();
+ assertEquals(mDrawable, mActualDrawable);
+ assertEquals(null, mActualDrawableNull);
+ }
+
+ @UiThreadTest
+ public void testSetIndeterminateDrawable() throws Throwable {
+ ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+ Window w = dialog.getWindow();
+ mProgressBar = (ProgressBar) w.findViewById(android.R.id.progress);
+
+ dialog.setIndeterminateDrawable(mDrawable);
+ mActualDrawable = mProgressBar.getIndeterminateDrawable();
+ assertEquals(mDrawable, mActualDrawable);
+
+ dialog.setIndeterminateDrawable(null);
+ mActualDrawableNull = mProgressBar.getIndeterminateDrawable();
+ assertEquals(null, mActualDrawableNull);
+ }
+
+ @UiThreadTest
+ public void testSetMessage() throws Throwable {
+ ProgressDialog dialog = new ProgressDialog(mContext);
+ dialog = new ProgressDialog(mContext);
+ dialog.setMessage(MESSAGE);
+ dialog.show();
+ // dialog is not null
+ dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+ dialog.setMessage("Chuck Norris");
+ }
+
+ @UiThreadTest
+ public void testSetProgressStyle() throws Throwable {
+ ProgressDialog dialog = new ProgressDialog(mContext);
+ setProgressStyle(dialog, ProgressDialog.STYLE_HORIZONTAL);
+ setProgressStyle(dialog, ProgressDialog.STYLE_SPINNER);
+ setProgressStyle(dialog, 100);
+ }
+
+ private void setProgressStyle(ProgressDialog dialog, int style) {
+ dialog.setProgressStyle(style);
+ dialog.show();
+ dialog.setProgress(10);
+ dialog.setMax(100);
+ }
+
+ private static class MockProgressDialog extends ProgressDialog {
+ public boolean mIsOnStopCalled;
+ public boolean mIsOnStartCalled;
+ public boolean mIsOnCreateCalled;
+
+ public MockProgressDialog(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mIsOnCreateCalled = true;
+ }
+
+ @Override
+ public void onStart(){
+ super.onStart();
+ mIsOnStartCalled = true;
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ mIsOnStopCalled = true;
+ }
+ }
+
+ private ProgressDialog buildDialog() {
+ return new ProgressDialog(mContext);
+ }
+}
diff --git a/tests/app/src/android/app/cts/SearchManagerStubActivity.java b/tests/app/src/android/app/cts/SearchManagerStubActivity.java
deleted file mode 100644
index 0dbd832..0000000
--- a/tests/app/src/android/app/cts/SearchManagerStubActivity.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.app.SearchManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.cts.util.CTSResult;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-public class SearchManagerStubActivity extends Activity {
-
- private static final String TAG = "SearchManagerStubActivity";
-
- public static final String TEST_STOP_SEARCH = "stopSearch";
- public static final String TEST_ON_DISMISSLISTENER = "setOnDismissListener";
- public static final String TEST_ON_CANCELLISTENER = "setOnCancelListener";
-
- private SearchManager mSearchManager;
- private ComponentName mComponentName;
-
- private static CTSResult sCTSResult;
- private boolean mDismissCalled;
- private boolean mCancelCalled;
-
- public static void setCTSResult(CTSResult result) {
- sCTSResult = result;
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- mSearchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
- mComponentName = getComponentName();
- String action = getIntent().getAction();
- if (action.equals(TEST_STOP_SEARCH)) {
- testStopSearch();
- } else if (action.equals(TEST_ON_DISMISSLISTENER)) {
- testOnDismissListener();
- } else if (action.equals(TEST_ON_CANCELLISTENER)) {
- testOnCancelListener();
- }
- }
-
- private void testOnCancelListener() {
- mCancelCalled = false;
- mSearchManager.setOnCancelListener(new SearchManager.OnCancelListener() {
- @Override
- public void onCancel() {
- mCancelCalled = true;
- }
- });
-
- new TestStepHandler() {
- @Override
- public boolean doStep(int step) throws FailException {
- switch (step) {
- case 1:
- startSearch("test", false, mComponentName, null, false);
- return false;
- case 2:
- assertFalse("cancel called", mCancelCalled);
- stopSearch();
- return false;
- case 3:
- assertTrue("cancel not called", mCancelCalled);
- pass();
- return true;
- default:
- throw new IllegalArgumentException("Bad step " + step);
- }
- }
- }.start();
- }
-
- private void testOnDismissListener() {
- mDismissCalled = false;
-
- mSearchManager.setOnDismissListener(new SearchManager.OnDismissListener() {
- public void onDismiss() {
- mDismissCalled = true;
- }
- });
-
- new TestStepHandler() {
- @Override
- public boolean doStep(int step) throws FailException {
- switch (step) {
- case 1:
- startSearch("test", false, mComponentName, null, false);
- return false;
- case 2:
- if (mDismissCalled) {
- throw new FailException("dismiss called");
- } else {
- stopSearch();
- }
- return false;
- case 3:
- if (mDismissCalled) {
- pass();
- } else {
- throw new FailException("dismiss not called");
- }
- return true;
- default:
- throw new IllegalArgumentException("Bad step " + step);
- }
- }
- }.start();
- }
-
- private void testStopSearch() {
- new TestStepHandler() {
- @Override
- public boolean doStep(int step) throws FailException {
- switch (step) {
- case 1:
- startSearch("test", false, mComponentName, null, false);
- return false;
- case 2:
- assertVisible();
- stopSearch();
- return false;
- case 3:
- assertInVisible();
- pass();
- return true;
- default:
- throw new IllegalArgumentException("Bad step " + step);
- }
- }
- }.start();
- }
-
- private void fail(Exception ex) {
- Log.e(TAG, "test failed", ex);
- sCTSResult.setResult(CTSResult.RESULT_FAIL);
- finish();
- }
-
- private void pass() {
- sCTSResult.setResult(CTSResult.RESULT_OK);
- finish();
- }
-
- private void assertInVisible() throws FailException {
- if (isVisible()) {
- throw new FailException();
- }
- }
-
- private void assertVisible() throws FailException {
- if (!isVisible()) {
- throw new FailException();
- }
- }
-
- private void assertFalse(String message, boolean value) throws FailException {
- assertTrue(message, !value);
- }
-
- private void assertTrue(String message, boolean value) throws FailException {
- if (!value) {
- throw new FailException(message);
- }
- }
-
- private void startSearch(String initialQuery, boolean selectInitialQuery,
- ComponentName launchActivity, Bundle appSearchData, boolean globalSearch) {
- mSearchManager.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
- globalSearch);
- }
-
- private void stopSearch() {
- mSearchManager.stopSearch();
- }
-
- private boolean isVisible() {
- return mSearchManager.isVisible();
- }
-
- private abstract class TestStepHandler extends Handler {
-
- public void start() {
- sendEmptyMessage(1);
- }
-
- @Override
- public void handleMessage(Message msg) {
- try {
- if (!doStep(msg.what)) {
- sendEmptyMessage(msg.what + 1);
- }
- } catch (FailException ex) {
- fail(ex);
- }
- }
-
- /**
- * Performs one step of the test.
- *
- * @param step The 1-based number of the step to perform.
- * @return {@code true} if this was the last step.
- * @throws FailException If the test failed.
- */
- protected abstract boolean doStep(int step) throws FailException;
- }
-
- private static class FailException extends Exception {
- private static final long serialVersionUID = 1L;
-
- public FailException() {
- super();
- }
-
- public FailException(String detailMessage) {
- super(detailMessage);
- }
- }
-}
diff --git a/tests/app/src/android/app/cts/SearchManagerTest.java b/tests/app/src/android/app/cts/SearchManagerTest.java
new file mode 100644
index 0000000..00ba5e7
--- /dev/null
+++ b/tests/app/src/android/app/cts/SearchManagerTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.stubs.CTSActivityTestCaseBase;
+import android.app.stubs.SearchManagerStubActivity;
+import android.content.Intent;
+
+public class SearchManagerTest extends CTSActivityTestCaseBase {
+
+ private void setupActivity(String action) {
+ Intent intent = new Intent();
+ intent.setAction(action);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setClass(getInstrumentation().getTargetContext(), SearchManagerStubActivity.class);
+ getInstrumentation().getTargetContext().startActivity(intent);
+ }
+
+ public void testStopSearch() throws InterruptedException {
+ SearchManagerStubActivity.setCTSResult(this);
+ setupActivity(SearchManagerStubActivity.TEST_STOP_SEARCH);
+ waitForResult();
+ }
+
+ public void testSetOnDismissListener() throws InterruptedException {
+ SearchManagerStubActivity.setCTSResult(this);
+ setupActivity(SearchManagerStubActivity.TEST_ON_DISMISSLISTENER);
+ waitForResult();
+ }
+
+ public void testSetOnCancelListener() throws InterruptedException {
+ SearchManagerStubActivity.setCTSResult(this);
+ setupActivity(SearchManagerStubActivity.TEST_ON_CANCELLISTENER);
+ waitForResult();
+ }
+}
diff --git a/tests/app/src/android/app/cts/ServiceTest.java b/tests/app/src/android/app/cts/ServiceTest.java
new file mode 100644
index 0000000..4842bb1
--- /dev/null
+++ b/tests/app/src/android/app/cts/ServiceTest.java
@@ -0,0 +1,468 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.stubs.ActivityTestsBase;
+import android.app.stubs.LocalDeniedService;
+import android.app.stubs.LocalGrantedService;
+import android.app.stubs.LocalService;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.cts.util.IBinderParcelable;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.test.suitebuilder.annotation.MediumTest;
+
+public class ServiceTest extends ActivityTestsBase {
+ private static final int STATE_START_1 = 0;
+ private static final int STATE_START_2 = 1;
+ private static final int STATE_UNBIND = 2;
+ private static final int STATE_DESTROY = 3;
+ private static final int STATE_REBIND = 4;
+ private static final int STATE_UNBIND_ONLY = 5;
+ private static final int DELAY = 5000;
+ private static final
+ String EXIST_CONN_TO_RECEIVE_SERVICE = "existing connection to receive service";
+ private static final String EXIST_CONN_TO_LOSE_SERVICE = "existing connection to lose service";
+ private int mExpectedServiceState;
+ private Context mContext;
+ private Intent mLocalService;
+ private Intent mLocalDeniedService;
+ private Intent mLocalGrantedService;
+ private Intent mLocalService_ApplicationHasPermission;
+ private Intent mLocalService_ApplicationDoesNotHavePermission;
+
+ private IBinder mStateReceiver;
+
+ private static class EmptyConnection implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ }
+ }
+
+ private class TestConnection implements ServiceConnection {
+ private final boolean mExpectDisconnect;
+ private final boolean mSetReporter;
+ private boolean mMonitor;
+ private int mCount;
+
+ public TestConnection(boolean expectDisconnect, boolean setReporter) {
+ mExpectDisconnect = expectDisconnect;
+ mSetReporter = setReporter;
+ mMonitor = !setReporter;
+ }
+
+ void setMonitor(boolean v) {
+ mMonitor = v;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (mSetReporter) {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(LocalService.SERVICE_LOCAL);
+ data.writeStrongBinder(mStateReceiver);
+ try {
+ service.transact(LocalService.SET_REPORTER_CODE, data, null, 0);
+ } catch (RemoteException e) {
+ finishBad("DeadObjectException when sending reporting object");
+ }
+ data.recycle();
+ }
+
+ if (mMonitor) {
+ mCount++;
+ if (mExpectedServiceState == STATE_START_1) {
+ if (mCount == 1) {
+ finishGood();
+ } else {
+ finishBad("onServiceConnected() again on an object when it "
+ + "should have been the first time");
+ }
+ } else if (mExpectedServiceState == STATE_START_2) {
+ if (mCount == 2) {
+ finishGood();
+ } else {
+ finishBad("onServiceConnected() the first time on an object "
+ + "when it should have been the second time");
+ }
+ } else {
+ finishBad("onServiceConnected() called unexpectedly");
+ }
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (mMonitor) {
+ if (mExpectedServiceState == STATE_DESTROY) {
+ if (mExpectDisconnect) {
+ finishGood();
+ } else {
+ finishBad("onServiceDisconnected() when it shouldn't have been");
+ }
+ } else {
+ finishBad("onServiceDisconnected() called unexpectedly");
+ }
+ }
+ }
+ }
+
+ private void startExpectResult(Intent service) {
+ startExpectResult(service, new Bundle());
+ }
+
+ private void startExpectResult(Intent service, Bundle bundle) {
+ bundle.putParcelable(LocalService.REPORT_OBJ_NAME, new IBinderParcelable(mStateReceiver));
+
+ boolean success = false;
+ try {
+ mExpectedServiceState = STATE_START_1;
+ mContext.startService(new Intent(service).putExtras(bundle));
+ waitForResultOrThrow(DELAY, "service to start first time");
+ mExpectedServiceState = STATE_START_2;
+ mContext.startService(new Intent(service).putExtras(bundle));
+ waitForResultOrThrow(DELAY, "service to start second time");
+ success = true;
+ } finally {
+ if (!success) {
+ mContext.stopService(service);
+ }
+ }
+ mExpectedServiceState = STATE_DESTROY;
+ mContext.stopService(service);
+ waitForResultOrThrow(DELAY, "service to be destroyed");
+ }
+
+ /**
+ * test the service lifecycle, a service can be used in two ways:
+ * 1 It can be started and allowed to run until someone stops it or it stops itself.
+ * In this mode, it's started by calling Context.startService()
+ * and stopped by calling Context.stopService().
+ * It can stop itself by calling Service.stopSelf() or Service.stopSelfResult().
+ * Only one stopService() call is needed to stop the service,
+ * no matter how many times startService() was called.
+ * 2 It can be operated programmatically using an interface that it defines and exports.
+ * Clients establish a connection to the Service object
+ * and use that connection to call into the service.
+ * The connection is established by calling Context.bindService(),
+ * and is closed by calling Context.unbindService().
+ * Multiple clients can bind to the same service.
+ * If the service has not already been launched, bindService() can optionally launch it.
+ */
+ private void bindExpectResult(Intent service) {
+ TestConnection conn = new TestConnection(true, false);
+ TestConnection conn2 = new TestConnection(false, false);
+ boolean success = false;
+ try {
+ // Expect to see the TestConnection connected.
+ mExpectedServiceState = STATE_START_1;
+ mContext.bindService(service, conn, 0);
+ mContext.startService(service);
+ waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE);
+
+ // Expect to see the second TestConnection connected.
+ mContext.bindService(service, conn2, 0);
+ waitForResultOrThrow(DELAY, "new connection to receive service");
+
+ mContext.unbindService(conn2);
+ success = true;
+ } finally {
+ if (!success) {
+ mContext.unbindService(conn);
+ mContext.unbindService(conn2);
+ mContext.stopService(service);
+ }
+ }
+
+ // Expect to see the TestConnection disconnected.
+ mExpectedServiceState = STATE_DESTROY;
+ mContext.stopService(service);
+ waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE);
+
+ mContext.unbindService(conn);
+
+ conn = new TestConnection(true, true);
+ success = false;
+ try {
+ // Expect to see the TestConnection connected.
+ conn.setMonitor(true);
+ mExpectedServiceState = STATE_START_1;
+ mContext.bindService(service, conn, 0);
+ mContext.startService(service);
+ waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE);
+
+ success = true;
+ } finally {
+ if (!success) {
+ mContext.unbindService(conn);
+ mContext.stopService(service);
+ }
+ }
+
+ // Expect to see the service unbind and then destroyed.
+ conn.setMonitor(false);
+ mExpectedServiceState = STATE_UNBIND;
+ mContext.stopService(service);
+ waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE);
+
+ mContext.unbindService(conn);
+
+ conn = new TestConnection(true, true);
+ success = false;
+ try {
+ // Expect to see the TestConnection connected.
+ conn.setMonitor(true);
+ mExpectedServiceState = STATE_START_1;
+ mContext.bindService(service, conn, 0);
+ mContext.startService(service);
+ waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE);
+
+ success = true;
+ } finally {
+ if (!success) {
+ mContext.unbindService(conn);
+ mContext.stopService(service);
+ }
+ }
+
+ // Expect to see the service unbind but not destroyed.
+ conn.setMonitor(false);
+ mExpectedServiceState = STATE_UNBIND_ONLY;
+ mContext.unbindService(conn);
+ waitForResultOrThrow(DELAY, "existing connection to unbind service");
+
+ // Expect to see the service rebound.
+ mExpectedServiceState = STATE_REBIND;
+ mContext.bindService(service, conn, 0);
+ waitForResultOrThrow(DELAY, "existing connection to rebind service");
+
+ // Expect to see the service unbind and then destroyed.
+ mExpectedServiceState = STATE_UNBIND;
+ mContext.stopService(service);
+ waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE);
+
+ mContext.unbindService(conn);
+ }
+
+ /**
+ * test automatically create the service as long as the binding exists
+ * and disconnect from an application service
+ */
+ private void bindAutoExpectResult(Intent service) {
+ TestConnection conn = new TestConnection(false, true);
+ boolean success = false;
+ try {
+ conn.setMonitor(true);
+ mExpectedServiceState = STATE_START_1;
+ mContext.bindService(
+ service, conn, Context.BIND_AUTO_CREATE);
+ waitForResultOrThrow(DELAY, "connection to start and receive service");
+ success = true;
+ } finally {
+ if (!success) {
+ mContext.unbindService(conn);
+ }
+ }
+ mExpectedServiceState = STATE_UNBIND;
+ mContext.unbindService(conn);
+ waitForResultOrThrow(DELAY, "disconnecting from service");
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getContext();
+ mLocalService = new Intent(mContext, LocalService.class);
+ mLocalDeniedService = new Intent(mContext, LocalDeniedService.class);
+ mLocalGrantedService = new Intent(mContext, LocalGrantedService.class);
+ mLocalService_ApplicationHasPermission = new Intent(
+ LocalService.SERVICE_LOCAL_GRANTED, null /*uri*/, mContext, LocalService.class);
+ mLocalService_ApplicationDoesNotHavePermission = new Intent(
+ LocalService.SERVICE_LOCAL_DENIED, null /*uri*/, mContext, LocalService.class);
+ mStateReceiver = new MockBinder();
+ }
+
+ private class MockBinder extends Binder {
+ @Override
+ protected boolean onTransact(int code, Parcel data, Parcel reply,
+ int flags) throws RemoteException {
+ if (code == LocalService.STARTED_CODE) {
+ data.enforceInterface(LocalService.SERVICE_LOCAL);
+ int count = data.readInt();
+ if (mExpectedServiceState == STATE_START_1) {
+ if (count == 1) {
+ finishGood();
+ } else {
+ finishBad("onStart() again on an object when it "
+ + "should have been the first time");
+ }
+ } else if (mExpectedServiceState == STATE_START_2) {
+ if (count == 2) {
+ finishGood();
+ } else {
+ finishBad("onStart() the first time on an object when it "
+ + "should have been the second time");
+ }
+ } else {
+ finishBad("onStart() was called when not expected (state="
+ + mExpectedServiceState + ")");
+ }
+ return true;
+ } else if (code == LocalService.DESTROYED_CODE) {
+ data.enforceInterface(LocalService.SERVICE_LOCAL);
+ if (mExpectedServiceState == STATE_DESTROY) {
+ finishGood();
+ } else {
+ finishBad("onDestroy() was called when not expected (state="
+ + mExpectedServiceState + ")");
+ }
+ return true;
+ } else if (code == LocalService.UNBIND_CODE) {
+ data.enforceInterface(LocalService.SERVICE_LOCAL);
+ if (mExpectedServiceState == STATE_UNBIND) {
+ mExpectedServiceState = STATE_DESTROY;
+ } else if (mExpectedServiceState == STATE_UNBIND_ONLY) {
+ finishGood();
+ } else {
+ finishBad("onUnbind() was called when not expected (state="
+ + mExpectedServiceState + ")");
+ }
+ return true;
+ } else if (code == LocalService.REBIND_CODE) {
+ data.enforceInterface(LocalService.SERVICE_LOCAL);
+ if (mExpectedServiceState == STATE_REBIND) {
+ finishGood();
+ } else {
+ finishBad("onRebind() was called when not expected (state="
+ + mExpectedServiceState + ")");
+ }
+ return true;
+ } else {
+ return super.onTransact(code, data, reply, flags);
+ }
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mContext.stopService(mLocalService);
+ mContext.stopService(mLocalGrantedService);
+ mContext.stopService(mLocalService_ApplicationHasPermission);
+ }
+
+ public void testLocalStartClass() throws Exception {
+ startExpectResult(mLocalService);
+ }
+
+ public void testLocalStartAction() throws Exception {
+ startExpectResult(new Intent(
+ LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class));
+ }
+
+ public void testLocalBindClass() throws Exception {
+ bindExpectResult(mLocalService);
+ }
+
+ @MediumTest
+ public void testLocalBindAction() throws Exception {
+ bindExpectResult(new Intent(
+ LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class));
+ }
+
+ @MediumTest
+ public void testLocalBindAutoClass() throws Exception {
+ bindAutoExpectResult(mLocalService);
+ }
+
+ @MediumTest
+ public void testLocalBindAutoAction() throws Exception {
+ bindAutoExpectResult(new Intent(
+ LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class));
+ }
+
+ @MediumTest
+ public void testLocalStartClassPermissions() throws Exception {
+ startExpectResult(mLocalGrantedService);
+ startExpectResult(mLocalDeniedService);
+ }
+
+ @MediumTest
+ public void testLocalStartActionPermissions() throws Exception {
+ startExpectResult(mLocalService_ApplicationHasPermission);
+ startExpectResult(mLocalService_ApplicationDoesNotHavePermission);
+ }
+
+ @MediumTest
+ public void testLocalBindClassPermissions() throws Exception {
+ bindExpectResult(mLocalGrantedService);
+ bindExpectResult(mLocalDeniedService);
+ }
+
+ @MediumTest
+ public void testLocalBindActionPermissions() throws Exception {
+ bindExpectResult(mLocalService_ApplicationHasPermission);
+ bindExpectResult(mLocalService_ApplicationDoesNotHavePermission);
+ }
+
+ @MediumTest
+ public void testLocalBindAutoClassPermissionGranted() throws Exception {
+ bindAutoExpectResult(mLocalGrantedService);
+ }
+
+ @MediumTest
+ public void testLocalBindAutoActionPermissionGranted() throws Exception {
+ bindAutoExpectResult(mLocalService_ApplicationHasPermission);
+ }
+
+ @MediumTest
+ public void testLocalUnbindTwice() throws Exception {
+ EmptyConnection conn = new EmptyConnection();
+ mContext.bindService(
+ mLocalService_ApplicationHasPermission, conn, 0);
+ mContext.unbindService(conn);
+ try {
+ mContext.unbindService(conn);
+ fail("No exception thrown on the second unbind");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ @MediumTest
+ public void testImplicitIntentFailsOnApiLevel21() throws Exception {
+ Intent intent = new Intent(LocalService.SERVICE_LOCAL);
+ EmptyConnection conn = new EmptyConnection();
+ try {
+ mContext.bindService(intent, conn, 0);
+ mContext.unbindService(conn);
+ fail("Implicit intents should be disallowed for apps targeting API 21+");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/app/src/android/app/cts/StubRemoteService.java b/tests/app/src/android/app/cts/StubRemoteService.java
deleted file mode 100644
index 1239734..0000000
--- a/tests/app/src/android/app/cts/StubRemoteService.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.Process;
-
-public class StubRemoteService extends Service{
-
- @Override
- public void onCreate() {
- super.onCreate();
- android.util.Log.d("Process test stub", "StubRemoteServiceProcessPid:" + Process.myPid());
- }
-
- private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() {
- public int getPid() {
- return Process.myPid();
- }
-
- public long getElapsedCpuTime() {
- return Process.getElapsedCpuTime();
- }
-
- public String getTimeZoneID() {
- return java.util.TimeZone.getDefault().getID();
- }
- };
-
- @Override
- public IBinder onBind(Intent intent) {
- if (ISecondary.class.getName().equals(intent.getAction())) {
- return mSecondaryBinder;
- }
- return null;
- }
-
-}
diff --git a/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/app/src/android/app/cts/SystemFeaturesTest.java
new file mode 100644
index 0000000..028ca89
--- /dev/null
+++ b/tests/app/src/android/app/cts/SystemFeaturesTest.java
@@ -0,0 +1,503 @@
+/*
+ * Copyright (C) 2010 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.ActivityManager;
+import android.app.Instrumentation;
+import android.app.WallpaperManager;
+import android.bluetooth.BluetoothAdapter;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
+import android.hardware.Camera.Parameters;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
+import android.location.LocationManager;
+import android.net.sip.SipManager;
+import android.net.wifi.WifiManager;
+import android.nfc.NfcAdapter;
+import android.telephony.TelephonyManager;
+import android.test.InstrumentationTestCase;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Test for checking that the {@link PackageManager} is reporting the correct features.
+ */
+public class SystemFeaturesTest extends InstrumentationTestCase {
+
+ private Context mContext;
+ private PackageManager mPackageManager;
+ private HashSet<String> mAvailableFeatures;
+
+ private ActivityManager mActivityManager;
+ private LocationManager mLocationManager;
+ private SensorManager mSensorManager;
+ private TelephonyManager mTelephonyManager;
+ private WifiManager mWifiManager;
+ private CameraManager mCameraManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ Instrumentation instrumentation = getInstrumentation();
+ mContext = instrumentation.getTargetContext();
+ mPackageManager = mContext.getPackageManager();
+ mAvailableFeatures = new HashSet<String>();
+ if (mPackageManager.getSystemAvailableFeatures() != null) {
+ for (FeatureInfo feature : mPackageManager.getSystemAvailableFeatures()) {
+ mAvailableFeatures.add(feature.name);
+ }
+ }
+ mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+ mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+ mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
+ }
+
+ /**
+ * Check for features improperly prefixed with "android." that are not defined in
+ * {@link PackageManager}.
+ */
+ public void testFeatureNamespaces() throws IllegalArgumentException, IllegalAccessException {
+ Set<String> officialFeatures = getFeatureConstantsNames("FEATURE_");
+ assertFalse(officialFeatures.isEmpty());
+
+ Set<String> notOfficialFeatures = new HashSet<String>(mAvailableFeatures);
+ notOfficialFeatures.removeAll(officialFeatures);
+
+ for (String featureName : notOfficialFeatures) {
+ if (featureName != null) {
+ assertFalse("Use a different namespace than 'android' for " + featureName,
+ featureName.startsWith("android"));
+ }
+ }
+ }
+
+ public void testBluetoothFeature() {
+ if (BluetoothAdapter.getDefaultAdapter() != null) {
+ assertAvailable(PackageManager.FEATURE_BLUETOOTH);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_BLUETOOTH);
+ }
+ }
+
+ public void testCameraFeatures() throws Exception {
+ int numCameras = Camera.getNumberOfCameras();
+ if (numCameras == 0) {
+ assertNotAvailable(PackageManager.FEATURE_CAMERA);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_FRONT);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_ANY);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_LEVEL_FULL);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_CAPABILITY_RAW);
+
+ assertFalse("Devices supporting external cameras must have a representative camera " +
+ "connected for testing",
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
+ } else {
+ assertAvailable(PackageManager.FEATURE_CAMERA_ANY);
+ checkFrontCamera();
+ checkRearCamera();
+ checkCamera2Features();
+ }
+ }
+
+ private void checkCamera2Features() throws Exception {
+ String[] cameraIds = mCameraManager.getCameraIdList();
+ boolean fullCamera = false;
+ boolean manualSensor = false;
+ boolean manualPostProcessing = false;
+ boolean raw = false;
+ CameraCharacteristics[] cameraChars = new CameraCharacteristics[cameraIds.length];
+ for (String cameraId : cameraIds) {
+ CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId);
+ Integer hwLevel = chars.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+ int[] capabilities = chars.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+ if (hwLevel == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) {
+ fullCamera = true;
+ }
+ for (int capability : capabilities) {
+ switch (capability) {
+ case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR:
+ manualSensor = true;
+ break;
+ case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING:
+ manualPostProcessing = true;
+ break;
+ case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW:
+ raw = true;
+ break;
+ default:
+ // Capabilities don't have a matching system feature
+ break;
+ }
+ }
+ }
+ assertFeature(fullCamera, PackageManager.FEATURE_CAMERA_LEVEL_FULL);
+ assertFeature(manualSensor, PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR);
+ assertFeature(manualPostProcessing,
+ PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING);
+ assertFeature(raw, PackageManager.FEATURE_CAMERA_CAPABILITY_RAW);
+ }
+
+ private void checkFrontCamera() {
+ CameraInfo info = new CameraInfo();
+ int numCameras = Camera.getNumberOfCameras();
+ int frontCameraId = -1;
+ for (int i = 0; i < numCameras; i++) {
+ Camera.getCameraInfo(i, info);
+ if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
+ frontCameraId = i;
+ }
+ }
+
+ if (frontCameraId > -1) {
+ assertTrue("Device has front-facing camera but does not report either " +
+ "the FEATURE_CAMERA_FRONT or FEATURE_CAMERA_EXTERNAL feature",
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
+ } else {
+ assertFalse("Device does not have front-facing camera but reports either " +
+ "the FEATURE_CAMERA_FRONT or FEATURE_CAMERA_EXTERNAL feature",
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
+ }
+ }
+
+ private void checkRearCamera() {
+ Camera camera = null;
+ try {
+ camera = Camera.open();
+ if (camera != null) {
+ assertAvailable(PackageManager.FEATURE_CAMERA);
+
+ Camera.Parameters params = camera.getParameters();
+ if (params.getSupportedFocusModes().contains(Parameters.FOCUS_MODE_AUTO)) {
+ assertAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
+ }
+
+ if (params.getFlashMode() != null) {
+ assertAvailable(PackageManager.FEATURE_CAMERA_FLASH);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
+ }
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_CAMERA);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
+ assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
+ }
+ } finally {
+ if (camera != null) {
+ camera.release();
+ }
+ }
+ }
+
+ public void testLiveWallpaperFeature() {
+ try {
+ Intent intent = new Intent(WallpaperManager.ACTION_LIVE_WALLPAPER_CHOOSER);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ assertAvailable(PackageManager.FEATURE_LIVE_WALLPAPER);
+ } catch (ActivityNotFoundException e) {
+ assertNotAvailable(PackageManager.FEATURE_LIVE_WALLPAPER);
+ }
+ }
+
+ public void testLocationFeatures() {
+ if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
+ assertAvailable(PackageManager.FEATURE_LOCATION);
+ assertAvailable(PackageManager.FEATURE_LOCATION_GPS);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_LOCATION_GPS);
+ }
+
+ if (mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
+ assertAvailable(PackageManager.FEATURE_LOCATION);
+ assertAvailable(PackageManager.FEATURE_LOCATION_NETWORK);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_LOCATION_NETWORK);
+ }
+ }
+
+ public void testNfcFeatures() {
+ if (NfcAdapter.getDefaultAdapter(mContext) != null) {
+ assertAvailable(PackageManager.FEATURE_NFC);
+ assertAvailable(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_NFC);
+ }
+ }
+
+ public void testScreenFeatures() {
+ assertTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
+ || mPackageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT));
+ }
+
+ /**
+ * Check that the sensor features reported by the PackageManager correspond to the sensors
+ * returned by {@link SensorManager#getSensorList(int)}.
+ */
+ public void testSensorFeatures() throws Exception {
+ Set<String> featuresLeft = getFeatureConstantsNames("FEATURE_SENSOR_");
+
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_ACCELEROMETER,
+ Sensor.TYPE_ACCELEROMETER);
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_BAROMETER,
+ Sensor.TYPE_PRESSURE);
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_COMPASS,
+ Sensor.TYPE_MAGNETIC_FIELD);
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_GYROSCOPE,
+ Sensor.TYPE_GYROSCOPE);
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_LIGHT,
+ Sensor.TYPE_LIGHT);
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_PROXIMITY,
+ Sensor.TYPE_PROXIMITY);
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_STEP_COUNTER,
+ Sensor.TYPE_STEP_COUNTER);
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_STEP_DETECTOR,
+ Sensor.TYPE_STEP_DETECTOR);
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_AMBIENT_TEMPERATURE,
+ Sensor.TYPE_AMBIENT_TEMPERATURE);
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_RELATIVE_HUMIDITY,
+ Sensor.TYPE_RELATIVE_HUMIDITY);
+
+
+ /*
+ * We have three cases to test for :
+ * Case 1: Device does not have an HRM
+ * FEATURE_SENSOR_HEART_RATE false
+ * FEATURE_SENSOR_HEART_RATE_ECG false
+ * assertFeatureForSensor(TYPE_HEART_RATE) false
+ *
+ * Case 2: Device has a PPG HRM
+ * FEATURE_SENSOR_HEART_RATE true
+ * FEATURE_SENSOR_HEART_RATE_ECG false
+ * assertFeatureForSensor(TYPE_HEART_RATE) true
+ *
+ * Case 3: Device has an ECG HRM
+ * FEATURE_SENSOR_HEART_RATE false
+ * FEATURE_SENSOR_HEART_RATE_ECG true
+ * assertFeatureForSensor(TYPE_HEART_RATE) true
+ */
+
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG)) {
+ /* Case 3 for FEATURE_SENSOR_HEART_RATE_ECG true case */
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
+ Sensor.TYPE_HEART_RATE);
+
+ /* Remove HEART_RATE from featuresLeft, no way to test that one */
+ assertTrue("Features left " + featuresLeft + " to check did not include "
+ + PackageManager.FEATURE_SENSOR_HEART_RATE,
+ featuresLeft.remove(PackageManager.FEATURE_SENSOR_HEART_RATE));
+ } else if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE)) {
+ /* Case 1 & 2 for FEATURE_SENSOR_HEART_RATE_ECG false case */
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
+ Sensor.TYPE_HEART_RATE);
+
+ /* Case 1 & 3 for FEATURE_SENSOR_HEART_RATE false case */
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE,
+ Sensor.TYPE_HEART_RATE);
+ } else {
+ /* Case 2 for FEATURE_SENSOR_HEART_RATE true case */
+ assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE,
+ Sensor.TYPE_HEART_RATE);
+
+ /* Remove HEART_RATE_ECG from featuresLeft, no way to test that one */
+ assertTrue("Features left " + featuresLeft + " to check did not include "
+ + PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
+ featuresLeft.remove(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG));
+ }
+
+ assertTrue("Assertions need to be added to this test for " + featuresLeft,
+ featuresLeft.isEmpty());
+ }
+
+ /** Get a list of feature constants in PackageManager matching a prefix. */
+ private static Set<String> getFeatureConstantsNames(String prefix)
+ throws IllegalArgumentException, IllegalAccessException {
+ Set<String> features = new HashSet<String>();
+ Field[] fields = PackageManager.class.getFields();
+ for (Field field : fields) {
+ if (field.getName().startsWith(prefix)) {
+ String feature = (String) field.get(null);
+ features.add(feature);
+ }
+ }
+ return features;
+ }
+
+ public void testSipFeatures() {
+ if (SipManager.newInstance(mContext) != null) {
+ assertAvailable(PackageManager.FEATURE_SIP);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_SIP);
+ assertNotAvailable(PackageManager.FEATURE_SIP_VOIP);
+ }
+
+ if (SipManager.isApiSupported(mContext)) {
+ assertAvailable(PackageManager.FEATURE_SIP);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_SIP);
+ assertNotAvailable(PackageManager.FEATURE_SIP_VOIP);
+ }
+
+ if (SipManager.isVoipSupported(mContext)) {
+ assertAvailable(PackageManager.FEATURE_SIP);
+ assertAvailable(PackageManager.FEATURE_SIP_VOIP);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_SIP_VOIP);
+ }
+ }
+
+ /**
+ * Check that if the PackageManager declares a sensor feature that the device has at least
+ * one sensor that matches that feature. Also check that if a PackageManager does not declare
+ * a sensor that the device also does not have such a sensor.
+ *
+ * @param featuresLeft to check in order to make sure the test covers all sensor features
+ * @param expectedFeature that the PackageManager may report
+ * @param expectedSensorType that that {@link SensorManager#getSensorList(int)} may have
+ */
+ private void assertFeatureForSensor(Set<String> featuresLeft, String expectedFeature,
+ int expectedSensorType) {
+ assertTrue("Features left " + featuresLeft + " to check did not include "
+ + expectedFeature, featuresLeft.remove(expectedFeature));
+
+ boolean hasSensorFeature = mPackageManager.hasSystemFeature(expectedFeature);
+
+ List<Sensor> sensors = mSensorManager.getSensorList(expectedSensorType);
+ List<String> sensorNames = new ArrayList<String>(sensors.size());
+ for (Sensor sensor : sensors) {
+ sensorNames.add(sensor.getName());
+ }
+ boolean hasSensorType = !sensors.isEmpty();
+
+ String message = "PackageManager#hasSystemFeature(" + expectedFeature + ") returns "
+ + hasSensorFeature
+ + " but SensorManager#getSensorList(" + expectedSensorType + ") shows sensors "
+ + sensorNames;
+
+ assertEquals(message, hasSensorFeature, hasSensorType);
+ }
+
+ /**
+ * Check that the {@link TelephonyManager#getPhoneType()} matches the reported features.
+ */
+ public void testTelephonyFeatures() {
+ int phoneType = mTelephonyManager.getPhoneType();
+ switch (phoneType) {
+ case TelephonyManager.PHONE_TYPE_GSM:
+ assertAvailable(PackageManager.FEATURE_TELEPHONY);
+ assertAvailable(PackageManager.FEATURE_TELEPHONY_GSM);
+ break;
+
+ case TelephonyManager.PHONE_TYPE_CDMA:
+ assertAvailable(PackageManager.FEATURE_TELEPHONY);
+ assertAvailable(PackageManager.FEATURE_TELEPHONY_CDMA);
+ break;
+
+ case TelephonyManager.PHONE_TYPE_NONE:
+ assertNotAvailable(PackageManager.FEATURE_TELEPHONY);
+ assertNotAvailable(PackageManager.FEATURE_TELEPHONY_CDMA);
+ assertNotAvailable(PackageManager.FEATURE_TELEPHONY_GSM);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Did you add a new phone type? " + phoneType);
+ }
+ }
+
+ public void testTouchScreenFeatures() {
+ ConfigurationInfo configInfo = mActivityManager.getDeviceConfigurationInfo();
+ if (configInfo.reqTouchScreen != Configuration.TOUCHSCREEN_NOTOUCH) {
+ assertAvailable(PackageManager.FEATURE_TOUCHSCREEN);
+ assertAvailable(PackageManager.FEATURE_FAKETOUCH);
+ } else {
+ assertNotAvailable(PackageManager.FEATURE_TOUCHSCREEN);
+ }
+
+ // TODO: Add tests for the other touchscreen features.
+ }
+
+ public void testUsbAccessory() {
+ assertAvailable(PackageManager.FEATURE_USB_ACCESSORY);
+ }
+
+ public void testWifiFeature() throws Exception {
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
+ // no WiFi, skip the test
+ return;
+ }
+ boolean enabled = mWifiManager.isWifiEnabled();
+ try {
+ // WifiManager is hard-coded to return true,
+ // the case without WiFi is already handled,
+ // so this case MUST have WiFi.
+ if (mWifiManager.setWifiEnabled(true)) {
+ assertAvailable(PackageManager.FEATURE_WIFI);
+ }
+ } finally {
+ if (!enabled) {
+ mWifiManager.setWifiEnabled(false);
+ }
+ }
+ }
+
+ private void assertAvailable(String feature) {
+ assertTrue("PackageManager#hasSystemFeature should return true for " + feature,
+ mPackageManager.hasSystemFeature(feature));
+ assertTrue("PackageManager#getSystemAvailableFeatures should have " + feature,
+ mAvailableFeatures.contains(feature));
+ }
+
+ private void assertNotAvailable(String feature) {
+ assertFalse("PackageManager#hasSystemFeature should NOT return true for " + feature,
+ mPackageManager.hasSystemFeature(feature));
+ assertFalse("PackageManager#getSystemAvailableFeatures should NOT have " + feature,
+ mAvailableFeatures.contains(feature));
+ }
+
+ private void assertFeature(boolean exist, String feature) {
+ if (exist) {
+ assertAvailable(feature);
+ } else {
+ assertNotAvailable(feature);
+ }
+ }
+}
diff --git a/tests/app/src/android/app/cts/TabActivityTest.java b/tests/app/src/android/app/cts/TabActivityTest.java
new file mode 100644
index 0000000..77a17e8
--- /dev/null
+++ b/tests/app/src/android/app/cts/TabActivityTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.TabActivity;
+import android.app.stubs.MockTabActivity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
+import android.widget.TabHost;
+
+public class TabActivityTest extends InstrumentationTestCase {
+ private Instrumentation mInstrumentation;
+ private MockTabActivity mActivity;
+ private Activity mChildActivity;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = super.getInstrumentation();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (mActivity != null) {
+ if (!mActivity.isFinishing()) {
+ mActivity.finish();
+ } else if (mChildActivity != null) {
+ if (!mChildActivity.isFinishing()) {
+ mChildActivity.finish();
+ }
+ }
+ }
+ super.tearDown();
+ }
+
+ public void testTabActivity() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ // Test constructor
+ new TabActivity();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ final String packageName = "android.app.stubs";
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setClassName(packageName, MockTabActivity.class.getName());
+ mActivity = (MockTabActivity) mInstrumentation.startActivitySync(intent);
+ // Test onPostCreate, onContentChanged. These two methods are invoked in starting
+ // activity. Default values of isOnContentChangedCalled, isOnPostCreateCalled are false.
+ assertTrue(mActivity.isOnContentChangedCalled);
+ assertTrue(mActivity.isOnPostCreateCalled);
+
+ // Can't get default value.
+ final int defaultIndex = 1;
+ mActivity.setDefaultTab(defaultIndex);
+ final String defaultTab = "DefaultTab";
+ mActivity.setDefaultTab(defaultTab);
+ // Test getTabHost, getTabWidget
+ final TabHost tabHost = mActivity.getTabHost();
+ assertNotNull(tabHost);
+ assertNotNull(tabHost.getTabWidget());
+ }
+
+ @UiThreadTest
+ public void testChildTitleCallback() throws Exception {
+ final Context context = mInstrumentation.getTargetContext();
+ final Intent intent = new Intent(context, MockTabActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ final MockTabActivity father = new MockTabActivity();
+ final ComponentName componentName = new ComponentName(context, MockTabActivity.class);
+ final ActivityInfo info = context.getPackageManager().getActivityInfo(componentName, 0);
+ mChildActivity = mInstrumentation.newActivity(MockTabActivity.class, mInstrumentation
+ .getTargetContext(), null, null, intent, info, MockTabActivity.class.getName(),
+ father, null, null);
+
+ assertNotNull(mChildActivity);
+ final String newTitle = "New Title";
+ mChildActivity.setTitle(newTitle);
+ assertTrue(father.isOnChildTitleChangedCalled);
+ }
+}
diff --git a/tests/app/src/android/app/cts/TestDialog.java b/tests/app/src/android/app/cts/TestDialog.java
deleted file mode 100644
index 7effc79..0000000
--- a/tests/app/src/android/app/cts/TestDialog.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * 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.
- */
-package android.app.cts;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.view.ContextMenu;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.Window;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.WindowManager.LayoutParams;
-
-public class TestDialog extends Dialog {
- private static final int OPTIONS_MENU_ITEM_0 = Menu.FIRST;
- private static final int OPTIONS_MENU_ITEM_1 = Menu.FIRST + 1;
- private static final int OPTIONS_MENU_ITEM_2 = Menu.FIRST + 2;
- private static final int OPTIONS_MENU_ITEM_3 = Menu.FIRST + 3;
- private static final int OPTIONS_MENU_ITEM_4 = Menu.FIRST + 4;
- private static final int OPTIONS_MENU_ITEM_5 = Menu.FIRST + 5;
- private static final int OPTIONS_MENU_ITEM_6 = Menu.FIRST + 6;
- private static final int CONTEXT_MENU_ITEM_0 = Menu.FIRST + 7;
- private static final int CONTEXT_MENU_ITEM_1 = Menu.FIRST + 8;
- private static final int CONTEXT_MENU_ITEM_2 = Menu.FIRST + 9;
- public boolean isOnStartCalled;
- public boolean isOnStopCalled;
- public boolean isOnCreateCalled;
- public boolean isRequestWindowFeature;
- public boolean isOnContentChangedCalled;
- public boolean isOnWindowFocusChangedCalled;
- public boolean isOnTouchEventCalled;
- public boolean isOnTrackballEventCalled;
- public boolean isOnKeyDownCalled;
- public boolean isOnKeyUpCalled;
- public boolean isOnKeyMultipleCalled;
- public boolean isOnSaveInstanceStateCalled;
- public static boolean isOnRestoreInstanceStateCalled;
- public boolean isOnWindowAttributesChangedCalled;
- public boolean isOnCreatePanelMenuCalled;
- public boolean isOnCreatePanelViewCalled;
- public boolean isOnPreparePanelCalled;
- public boolean isOnMenuOpenedCalled;
- public boolean isOnMenuItemSelectedCalled;
- public boolean isOnPanelClosedCalled;
- public boolean isOnCreateOptionsMenuCalled;
- public boolean isOnPrepareOptionsMenuCalled;
- public boolean isOnOptionsItemSelectedCalled;
- public boolean isOnOptionsMenuClosedCalled;
- public boolean isOnContextItemSelectedCalled;
- public boolean isOnContextMenuClosedCalled;
- public boolean isOnCreateContextMenuCalled;
- public boolean isOnSearchRequestedCalled;
- public boolean onKeyDownReturn;
- public boolean onKeyMultipleReturn;
- public boolean dispatchTouchEventResult;
- public boolean dispatchKeyEventResult;
- public int keyDownCode = -1;
- public Window window;
- public Bundle saveInstanceState;
- public Bundle savedInstanceState;
- public KeyEvent keyEvent;
- public MotionEvent touchEvent;
- public MotionEvent trackballEvent;
- public MotionEvent onTrackballEvent;
- public MotionEvent onTouchEvent;
- public KeyEvent keyMultipleEvent;
-
- public TestDialog(Context context) {
- super(context);
- }
-
- public TestDialog(Context context, int theme) {
- super(context, theme);
- }
-
- public TestDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
- super(context, cancelable, cancelListener);
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- isOnStartCalled = true;
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- isOnStopCalled = true;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- isRequestWindowFeature = requestWindowFeature(Window.FEATURE_LEFT_ICON);
- super.onCreate(savedInstanceState);
- isOnCreateCalled = true;
- }
-
- @Override
- public void onContentChanged() {
- super.onContentChanged();
-
- isOnContentChangedCalled = true;
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
-
- isOnWindowFocusChangedCalled = true;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- isOnTouchEventCalled = true;
- onTouchEvent = event;
- return super.onTouchEvent(event);
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- isOnTrackballEventCalled = true;
- onTrackballEvent = event;
- return super.onTrackballEvent(event);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- isOnKeyDownCalled = true;
- keyDownCode = keyCode;
- onKeyDownReturn = super.onKeyDown(keyCode, event);
-
- return onKeyDownReturn;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- isOnKeyUpCalled = true;
-
- return super.onKeyUp(keyCode, event);
- }
-
- @Override
- public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
- isOnKeyMultipleCalled = true;
- onKeyMultipleReturn = super.onKeyMultiple(keyCode, repeatCount, event);
- keyMultipleEvent = event;
- return onKeyMultipleReturn;
- }
-
- @Override
- public Bundle onSaveInstanceState() {
- isOnSaveInstanceStateCalled = true;
- saveInstanceState = super.onSaveInstanceState();
- return saveInstanceState;
- }
-
- @Override
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- isOnRestoreInstanceStateCalled = true;
- this.savedInstanceState = savedInstanceState;
-
- super.onRestoreInstanceState(savedInstanceState);
- }
-
- @Override
- public void onWindowAttributesChanged(LayoutParams params) {
- isOnWindowAttributesChangedCalled = true;
- super.onWindowAttributesChanged(params);
- }
-
- @Override
- public boolean onCreatePanelMenu(int featureId, Menu menu) {
- isOnCreatePanelMenuCalled = true;
- return super.onCreatePanelMenu(featureId, menu);
- }
-
- @Override
- public View onCreatePanelView(int featureId) {
- isOnCreatePanelViewCalled = true;
- return super.onCreatePanelView(featureId);
- }
-
- @Override
- public boolean onPreparePanel(int featureId, View view, Menu menu) {
- isOnPreparePanelCalled = true;
- return super.onPreparePanel(featureId, view, menu);
- }
-
- @Override
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- isOnMenuItemSelectedCalled = true;
- return super.onMenuItemSelected(featureId, item);
- }
-
- @Override
- public boolean onMenuOpened(int featureId, Menu menu) {
- isOnMenuOpenedCalled = true;
- return super.onMenuOpened(featureId, menu);
- }
-
- @Override
- public void onPanelClosed(int featureId, Menu menu) {
- isOnPanelClosedCalled = true;
- super.onPanelClosed(featureId, menu);
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- isOnPrepareOptionsMenuCalled = true;
- return super.onPrepareOptionsMenu(menu);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- menu.add(0, OPTIONS_MENU_ITEM_0, 0, "OptionsMenuItem0");
- menu.add(0, OPTIONS_MENU_ITEM_1, 0, "OptionsMenuItem1");
- menu.add(0, OPTIONS_MENU_ITEM_2, 0, "OptionsMenuItem2");
- menu.add(0, OPTIONS_MENU_ITEM_3, 0, "OptionsMenuItem3");
- menu.add(0, OPTIONS_MENU_ITEM_4, 0, "OptionsMenuItem4");
- menu.add(0, OPTIONS_MENU_ITEM_5, 0, "OptionsMenuItem5");
- menu.add(0, OPTIONS_MENU_ITEM_6, 0, "OptionsMenuItem6");
- isOnCreateOptionsMenuCalled = true;
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- isOnOptionsItemSelectedCalled = true;
- switch (item.getItemId()) {
- case OPTIONS_MENU_ITEM_0:
- case OPTIONS_MENU_ITEM_1:
- case OPTIONS_MENU_ITEM_2:
- case OPTIONS_MENU_ITEM_3:
- case OPTIONS_MENU_ITEM_4:
- case OPTIONS_MENU_ITEM_5:
- case OPTIONS_MENU_ITEM_6:
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- public void onOptionsMenuClosed(Menu menu) {
- isOnOptionsMenuClosedCalled = true;
- super.onOptionsMenuClosed(menu);
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- isOnContextItemSelectedCalled = true;
- switch (item.getItemId()) {
- case CONTEXT_MENU_ITEM_0:
- case CONTEXT_MENU_ITEM_1:
- case CONTEXT_MENU_ITEM_2:
- return true;
- default:
- return super.onContextItemSelected(item);
- }
- }
-
- @Override
- public void onContextMenuClosed(Menu menu) {
- isOnContextMenuClosedCalled = true;
- super.onContextMenuClosed(menu);
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- menu.add(0, CONTEXT_MENU_ITEM_0, 0, "ContextMenuItem0");
- menu.add(0, CONTEXT_MENU_ITEM_1, 0, "ContextMenuItem1");
- menu.add(0, CONTEXT_MENU_ITEM_2, 0, "ContextMenuItem2");
- isOnCreateContextMenuCalled = true;
- }
-
- @Override
- public boolean onSearchRequested() {
- isOnSearchRequestedCalled = true;
- return super.onSearchRequested();
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- keyEvent = event;
- dispatchKeyEventResult = super.dispatchKeyEvent(event);
- return dispatchKeyEventResult;
- }
-
- @Override
- public boolean dispatchTrackballEvent(MotionEvent ev) {
- trackballEvent = ev;
- return super.dispatchTrackballEvent(ev);
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- touchEvent = ev;
- dispatchTouchEventResult = super.dispatchTouchEvent(ev);
- return dispatchTouchEventResult;
- }
-}
diff --git a/tests/app/src/android/app/cts/TestedActivity.java b/tests/app/src/android/app/cts/TestedActivity.java
deleted file mode 100644
index b6565bf..0000000
--- a/tests/app/src/android/app/cts/TestedActivity.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.os.Looper;
-import android.os.MessageQueue;
-import android.util.Log;
-
-public class TestedActivity extends Activity {
- private static final String TAG = "TestedActivity" ;
- public TestedActivity() {
- }
-
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- }
-
- protected void onRestoreInstanceState(Bundle state) {
- super.onRestoreInstanceState(state);
- }
-
- protected void onResume() {
- super.onResume();
- Looper.myLooper();
- Looper.myQueue().addIdleHandler(new Idler());
- }
-
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- }
-
- protected void onStop() {
- super.onStop();
- }
-
- private class Idler implements MessageQueue.IdleHandler {
- public final boolean queueIdle() {
- Log.i(TAG, "idle");
- setResult(RESULT_OK);
- finish();
- return false;
- }
- }
-}
diff --git a/tests/app/src/android/app/cts/TestedScreen.java b/tests/app/src/android/app/cts/TestedScreen.java
deleted file mode 100644
index 052fb34..0000000
--- a/tests/app/src/android/app/cts/TestedScreen.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.MessageQueue;
-import android.os.SystemClock;
-import android.util.Log;
-
-public class TestedScreen extends Activity {
- public static final String WAIT_BEFORE_FINISH = "TestedScreen.WAIT_BEFORE_FINISH";
- public static final String DELIVER_RESULT = "TestedScreen.DELIVER_RESULT";
- public static final String CLEAR_TASK = "TestedScreen.CLEAR_TASK";
- private static final String TAG = "TestedScreen" ;
- public TestedScreen() {
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- if (LaunchpadActivity.FORWARD_RESULT.equals(getIntent().getAction())) {
- final Intent intent = new Intent(getIntent());
- intent.setAction(DELIVER_RESULT);
- intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- startActivity(intent);
- finish();
- } else if (DELIVER_RESULT.equals(getIntent().getAction())) {
- setResult(RESULT_OK, new Intent().setAction(LaunchpadActivity.RETURNED_RESULT));
- finish();
- } else if (CLEAR_TASK.equals(getIntent().getAction())) {
- if (!getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) {
- launchClearTask();
- }
- }
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle state) {
- super.onRestoreInstanceState(state);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (CLEAR_TASK.equals(getIntent().getAction())) {
- if (getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) {
- Looper.myLooper();
- Looper.myQueue().addIdleHandler(new Idler());
- }
- } else {
- Looper.myLooper();
- Looper.myQueue().addIdleHandler(new Idler());
- }
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- }
-
- private void launchClearTask() {
- final Intent intent = new Intent(getIntent()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
- .setClass(this, ClearTop.class);
- startActivity(intent);
- }
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (CLEAR_TASK.equals(getIntent().getAction())) {
- launchClearTask();
- } else {
- setResult(RESULT_OK);
- finish();
- }
- }
- };
-
- private class Idler implements MessageQueue.IdleHandler {
- public final boolean queueIdle() {
- Log.i(TAG, "idle");
- if (WAIT_BEFORE_FINISH.equals(getIntent().getAction())) {
- final Message m = Message.obtain();
- mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
- } else if (CLEAR_TASK.equals(getIntent().getAction())) {
- final Message m = Message.obtain();
- mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
- } else {
- setResult(RESULT_OK);
- finish();
- }
- return false;
- }
- }
-}
diff --git a/tests/app/src/android/app/cts/TimePickerDialogTest.java b/tests/app/src/android/app/cts/TimePickerDialogTest.java
new file mode 100644
index 0000000..3da25ab
--- /dev/null
+++ b/tests/app/src/android/app/cts/TimePickerDialogTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+package android.app.cts;
+
+import android.app.TimePickerDialog;
+import android.app.TimePickerDialog.OnTimeSetListener;
+import android.app.stubs.DialogStubActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.widget.TimePicker;
+
+import android.app.stubs.R;
+
+/**
+ * Test {@link TimePickerDialog}.
+ */
+public class TimePickerDialogTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
+ private static final String HOUR = "hour";
+ private static final String MINUTE = "minute";
+ private static final String IS_24_HOUR = "is24hour";
+
+ private static final int TARGET_HOUR = 15;
+ private static final int TARGET_MINUTE = 9;
+
+ private int mCallbackHour;
+ private int mCallbackMinute;
+
+ private OnTimeSetListener mOnTimeSetListener;
+
+ private Context mContext;
+ private DialogStubActivity mActivity;
+
+ public TimePickerDialogTest() {
+ super("android.app.stubs", DialogStubActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mContext = getInstrumentation().getContext();
+ mOnTimeSetListener = new OnTimeSetListener(){
+ public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+ mCallbackHour = hourOfDay;
+ mCallbackMinute = minute;
+ }
+ };
+ }
+
+ @UiThreadTest
+ public void testSaveInstanceState() {
+ TimePickerDialog tD = new TimePickerDialog(
+ mContext, mOnTimeSetListener, TARGET_HOUR, TARGET_MINUTE, true);
+
+ Bundle b = tD.onSaveInstanceState();
+
+ assertEquals(TARGET_HOUR, b.getInt(HOUR));
+ assertEquals(TARGET_MINUTE, b.getInt(MINUTE));
+ assertTrue(b.getBoolean(IS_24_HOUR));
+
+ int minute = 13;
+ tD = new TimePickerDialog(
+ mContext, R.style.Theme_AlertDialog,
+ mOnTimeSetListener, TARGET_HOUR, minute, false);
+
+ b = tD.onSaveInstanceState();
+
+ assertEquals(TARGET_HOUR, b.getInt(HOUR));
+ assertEquals(minute, b.getInt(MINUTE));
+ assertFalse(b.getBoolean(IS_24_HOUR));
+ }
+
+ @UiThreadTest
+ public void testOnClick() {
+ TimePickerDialog timePickerDialog = buildDialog();
+ timePickerDialog.onClick(null, TimePickerDialog.BUTTON_POSITIVE);
+
+ assertEquals(TARGET_HOUR, mCallbackHour);
+ assertEquals(TARGET_MINUTE, mCallbackMinute);
+ }
+
+ public void testOnTimeChanged() throws Throwable {
+ final int minute = 34;
+ startDialogActivity(DialogStubActivity.TEST_TIMEPICKERDIALOG);
+ final TimePickerDialog d = (TimePickerDialog) mActivity.getDialog();
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ d.onTimeChanged(null, TARGET_HOUR, minute);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ }
+
+ @UiThreadTest
+ public void testUpdateTime() {
+ TimePickerDialog timePickerDialog = buildDialog();
+ int minute = 18;
+ timePickerDialog.updateTime(TARGET_HOUR, minute);
+
+ // here call onSaveInstanceState is to check the data put by updateTime
+ Bundle b = timePickerDialog.onSaveInstanceState();
+
+ assertEquals(TARGET_HOUR, b.getInt(HOUR));
+ assertEquals(minute, b.getInt(MINUTE));
+ }
+
+ @UiThreadTest
+ public void testOnRestoreInstanceState() {
+ int minute = 27;
+ Bundle b1 = new Bundle();
+ b1.putInt(HOUR, TARGET_HOUR);
+ b1.putInt(MINUTE, minute);
+ b1.putBoolean(IS_24_HOUR, false);
+
+ TimePickerDialog timePickerDialog = buildDialog();
+ timePickerDialog.onRestoreInstanceState(b1);
+
+ //here call onSaveInstanceState is to check the data put by onRestoreInstanceState
+ Bundle b2 = timePickerDialog.onSaveInstanceState();
+
+ assertEquals(TARGET_HOUR, b2.getInt(HOUR));
+ assertEquals(minute, b2.getInt(MINUTE));
+ assertFalse(b2.getBoolean(IS_24_HOUR));
+ }
+
+ private void startDialogActivity(int dialogNumber) {
+ mActivity = DialogStubActivity.startDialogActivity(this, dialogNumber);
+ }
+
+ private TimePickerDialog buildDialog() {
+ return new TimePickerDialog(
+ mContext, mOnTimeSetListener, TARGET_HOUR, TARGET_MINUTE, true);
+ }
+}
diff --git a/tests/app/src/android/app/cts/UiModeManagerTest.java b/tests/app/src/android/app/cts/UiModeManagerTest.java
new file mode 100644
index 0000000..40fe0f5
--- /dev/null
+++ b/tests/app/src/android/app/cts/UiModeManagerTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+package android.app.cts;
+
+import android.app.UiModeManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+public class UiModeManagerTest extends AndroidTestCase {
+ private static final String TAG = "UiModeManagerTest";
+
+ private UiModeManager mUiModeManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mUiModeManager = (UiModeManager) getContext().getSystemService(Context.UI_MODE_SERVICE);
+ assertNotNull(mUiModeManager);
+ }
+
+ public void testUiMode() throws Exception {
+ if (isAutomotive()) {
+ Log.i(TAG, "testUiMode automotive");
+ doTestUiModeForAutomotive();
+ } else if (isTelevision()) {
+ assertEquals(Configuration.UI_MODE_TYPE_TELEVISION,
+ mUiModeManager.getCurrentModeType());
+ doTestLockedUiMode();
+ } else if (isWatch()) {
+ assertEquals(Configuration.UI_MODE_TYPE_WATCH,
+ mUiModeManager.getCurrentModeType());
+ doTestLockedUiMode();
+ } else {
+ Log.i(TAG, "testUiMode generic");
+ doTestUiModeGeneric();
+ }
+ }
+
+ public void testNightMode() throws Exception {
+ if (isAutomotive()) {
+ assertTrue(mUiModeManager.isNightModeLocked());
+ doTestLockedNightMode();
+ } else {
+ if (mUiModeManager.isNightModeLocked()) {
+ doTestLockedNightMode();
+ } else {
+ doTestUnlockedNightMode();
+ }
+ }
+ }
+
+ private boolean isAutomotive() {
+ return getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
+ private boolean isTelevision() {
+ PackageManager pm = getContext().getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
+ || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
+ private boolean isWatch() {
+ return getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_WATCH);
+ }
+
+ private void doTestUiModeForAutomotive() throws Exception {
+ assertEquals(Configuration.UI_MODE_TYPE_CAR, mUiModeManager.getCurrentModeType());
+ assertTrue(mUiModeManager.isUiModeLocked());
+ doTestLockedUiMode();
+ }
+
+ private void doTestUiModeGeneric() throws Exception {
+ if (mUiModeManager.isUiModeLocked()) {
+ doTestLockedUiMode();
+ } else {
+ doTestUnlockedUiMode();
+ }
+ }
+
+ private void doTestLockedUiMode() throws Exception {
+ int originalMode = mUiModeManager.getCurrentModeType();
+ mUiModeManager.enableCarMode(0);
+ assertEquals(originalMode, mUiModeManager.getCurrentModeType());
+ mUiModeManager.disableCarMode(0);
+ assertEquals(originalMode, mUiModeManager.getCurrentModeType());
+ }
+
+ private void doTestUnlockedUiMode() throws Exception {
+ mUiModeManager.enableCarMode(0);
+ assertEquals(Configuration.UI_MODE_TYPE_CAR, mUiModeManager.getCurrentModeType());
+ mUiModeManager.disableCarMode(0);
+ assertNotSame(Configuration.UI_MODE_TYPE_CAR, mUiModeManager.getCurrentModeType());
+ }
+
+ private void doTestLockedNightMode() throws Exception {
+ int currentMode = mUiModeManager.getNightMode();
+ if (currentMode == UiModeManager.MODE_NIGHT_YES) {
+ mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
+ assertEquals(currentMode, mUiModeManager.getNightMode());
+ } else {
+ mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_YES);
+ assertEquals(currentMode, mUiModeManager.getNightMode());
+ }
+ }
+
+ private void doTestUnlockedNightMode() throws Exception {
+ // day night mode should be settable regardless of car mode.
+ mUiModeManager.enableCarMode(0);
+ doTestAllNightModes();
+ mUiModeManager.disableCarMode(0);
+ doTestAllNightModes();
+ }
+
+ private void doTestAllNightModes() {
+ assertNightModeChange(UiModeManager.MODE_NIGHT_AUTO);
+ assertNightModeChange(UiModeManager.MODE_NIGHT_YES);
+ assertNightModeChange(UiModeManager.MODE_NIGHT_NO);
+ }
+
+ private void assertNightModeChange(int mode) {
+ mUiModeManager.setNightMode(mode);
+ assertEquals(mode, mUiModeManager.getNightMode());
+ }
+}
diff --git a/tests/tests/app/src/android/app/cts/WallpaperManagerTest.java b/tests/app/src/android/app/cts/WallpaperManagerTest.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/WallpaperManagerTest.java
rename to tests/app/src/android/app/cts/WallpaperManagerTest.java
diff --git a/tests/browser/Android.mk b/tests/browser/Android.mk
new file mode 100644
index 0000000..a85c960
--- /dev/null
+++ b/tests/browser/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner ctstestserver
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsBrowserTestCases
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/browser/AndroidManifest.xml b/tests/browser/AndroidManifest.xml
new file mode 100644
index 0000000..f850e28
--- /dev/null
+++ b/tests/browser/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.browser.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.browser.cts" />
+</manifest>
diff --git a/tests/browser/AndroidTest.xml b/tests/browser/AndroidTest.xml
new file mode 100644
index 0000000..49c93fc
--- /dev/null
+++ b/tests/browser/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Browser test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsBrowserTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.browser.cts" />
+ <option name="runtime-hint" value="4m14s" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/base.js b/tests/browser/assets/octane/base.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/base.js
rename to tests/browser/assets/octane/base.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/box2d.js b/tests/browser/assets/octane/box2d.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/box2d.js
rename to tests/browser/assets/octane/box2d.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/code-load.js b/tests/browser/assets/octane/code-load.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/code-load.js
rename to tests/browser/assets/octane/code-load.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/crypto.js b/tests/browser/assets/octane/crypto.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/crypto.js
rename to tests/browser/assets/octane/crypto.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/css/bootstrap-responsive.css b/tests/browser/assets/octane/css/bootstrap-responsive.css
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/css/bootstrap-responsive.css
rename to tests/browser/assets/octane/css/bootstrap-responsive.css
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/css/bootstrap.css b/tests/browser/assets/octane/css/bootstrap.css
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/css/bootstrap.css
rename to tests/browser/assets/octane/css/bootstrap.css
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/css/docs.css b/tests/browser/assets/octane/css/docs.css
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/css/docs.css
rename to tests/browser/assets/octane/css/docs.css
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/cts_report.html b/tests/browser/assets/octane/cts_report.html
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/cts_report.html
rename to tests/browser/assets/octane/cts_report.html
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/cts_report.js b/tests/browser/assets/octane/cts_report.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/cts_report.js
rename to tests/browser/assets/octane/cts_report.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/deltablue.js b/tests/browser/assets/octane/deltablue.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/deltablue.js
rename to tests/browser/assets/octane/deltablue.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/earley-boyer.js b/tests/browser/assets/octane/earley-boyer.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/earley-boyer.js
rename to tests/browser/assets/octane/earley-boyer.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/gbemu.js b/tests/browser/assets/octane/gbemu.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/gbemu.js
rename to tests/browser/assets/octane/gbemu.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/ico/apple-touch-icon-114-precomposed.png b/tests/browser/assets/octane/ico/apple-touch-icon-114-precomposed.png
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/ico/apple-touch-icon-114-precomposed.png
rename to tests/browser/assets/octane/ico/apple-touch-icon-114-precomposed.png
Binary files differ
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/ico/apple-touch-icon-144-precomposed.png b/tests/browser/assets/octane/ico/apple-touch-icon-144-precomposed.png
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/ico/apple-touch-icon-144-precomposed.png
rename to tests/browser/assets/octane/ico/apple-touch-icon-144-precomposed.png
Binary files differ
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/ico/apple-touch-icon-57-precomposed.png b/tests/browser/assets/octane/ico/apple-touch-icon-57-precomposed.png
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/ico/apple-touch-icon-57-precomposed.png
rename to tests/browser/assets/octane/ico/apple-touch-icon-57-precomposed.png
Binary files differ
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/ico/apple-touch-icon-72-precomposed.png b/tests/browser/assets/octane/ico/apple-touch-icon-72-precomposed.png
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/ico/apple-touch-icon-72-precomposed.png
rename to tests/browser/assets/octane/ico/apple-touch-icon-72-precomposed.png
Binary files differ
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/ico/favicon.ico b/tests/browser/assets/octane/ico/favicon.ico
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/ico/favicon.ico
rename to tests/browser/assets/octane/ico/favicon.ico
Binary files differ
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/index.html b/tests/browser/assets/octane/index.html
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/index.html
rename to tests/browser/assets/octane/index.html
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/js/bootstrap-collapse.js b/tests/browser/assets/octane/js/bootstrap-collapse.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/js/bootstrap-collapse.js
rename to tests/browser/assets/octane/js/bootstrap-collapse.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/js/bootstrap-transition.js b/tests/browser/assets/octane/js/bootstrap-transition.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/js/bootstrap-transition.js
rename to tests/browser/assets/octane/js/bootstrap-transition.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/js/jquery.js b/tests/browser/assets/octane/js/jquery.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/js/jquery.js
rename to tests/browser/assets/octane/js/jquery.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/mandreel.js b/tests/browser/assets/octane/mandreel.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/mandreel.js
rename to tests/browser/assets/octane/mandreel.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/navier-stokes.js b/tests/browser/assets/octane/navier-stokes.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/navier-stokes.js
rename to tests/browser/assets/octane/navier-stokes.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/pdfjs.js b/tests/browser/assets/octane/pdfjs.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/pdfjs.js
rename to tests/browser/assets/octane/pdfjs.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/raytrace.js b/tests/browser/assets/octane/raytrace.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/raytrace.js
rename to tests/browser/assets/octane/raytrace.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/regexp.js b/tests/browser/assets/octane/regexp.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/regexp.js
rename to tests/browser/assets/octane/regexp.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/richards.js b/tests/browser/assets/octane/richards.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/richards.js
rename to tests/browser/assets/octane/richards.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/run.js b/tests/browser/assets/octane/run.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/run.js
rename to tests/browser/assets/octane/run.js
diff --git a/suite/cts/deviceTests/browserbench/assets/octane/splay.js b/tests/browser/assets/octane/splay.js
similarity index 100%
rename from suite/cts/deviceTests/browserbench/assets/octane/splay.js
rename to tests/browser/assets/octane/splay.js
diff --git a/tests/browser/src/android/browser/cts/BrowserBenchTest.java b/tests/browser/src/android/browser/cts/BrowserBenchTest.java
new file mode 100644
index 0000000..ff1a2ab
--- /dev/null
+++ b/tests/browser/src/android/browser/cts/BrowserBenchTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2012 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.browser.cts;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.cts.util.CtsAndroidTestCase;
+import android.cts.util.WatchDog;
+import android.net.Uri;
+import android.provider.Browser;
+import android.util.Log;
+import android.webkit.cts.CtsTestServer;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+import com.android.cts.util.TimeoutReq;
+
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.RequestLine;
+
+import java.net.URLDecoder;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+/**
+ * Browser benchmarking.
+ * It launches an activity with URL and wait for POST from the client.
+ */
+public class BrowserBenchTest extends CtsAndroidTestCase {
+ private static final String TAG = BrowserBenchTest.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final String OCTANE_START_FILE = "octane/index.html";
+ private static final String ROBOHORNET_START_FILE = "robohornet/robohornet.html";
+ private static final String HOST_COMPLETION_BROADCAST = "android.browser.cts.completion";
+ // time-out for watch-dog. POST should happen within this time.
+ private static long BROWSER_POST_TIMEOUT_IN_MS = 10 * 60 * 1000L;
+ // watch-dog will time-out first. So make it long enough.
+ private static long BROWSER_COMPLETION_TIMEOUT_IN_MS = 60 * 60 * 1000L;
+ private static final String HTTP_USER_AGENT = "User-Agent";
+ private CtsTestServer mWebServer;
+ // used for final score
+ private ResultType mTypeNonFinal = ResultType.NEUTRAL;
+ private ResultUnit mUnitNonFinal = ResultUnit.NONE;
+ // used for all other scores
+ private ResultType mTypeFinal = ResultType.NEUTRAL;
+ private ResultUnit mUnitFinal = ResultUnit.SCORE;
+ private WatchDog mWatchDog;
+ private CountDownLatch mLatch;
+ // can be changed by each test before starting
+ private volatile int mNumberRepeat;
+ /** tells how many tests have run up to now */
+ private volatile int mRunIndex;
+ /** stores results for each runs. last entry will be the final score. */
+ private LinkedHashMap<String, double[]> mResultsMap;
+ private PackageManager mPackageManager;
+ private DeviceReportLog mReport;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mReport = new DeviceReportLog();
+ mPackageManager = getInstrumentation().getContext().getPackageManager();
+ mWebServer = new CtsTestServer(getContext()) {
+ @Override
+ protected HttpResponse onPost(HttpRequest request) throws Exception {
+ // post uri will look like "cts_report.html?final=1&score=10.1&message=hello"
+ RequestLine requestLine = request.getRequestLine();
+ String uriString = URLDecoder.decode(requestLine.getUri(), "UTF-8");
+ if (DEBUG) {
+ Log.i(TAG, "uri:" + uriString);
+ }
+ String resultRe =
+ ".*cts_report.html\\?final=([\\d])&score=([\\d]+\\.?[\\d]*)&message=([\\w][\\w ]*)";
+ Pattern resultPattern = Pattern.compile(resultRe);
+ Matcher matchResult = resultPattern.matcher(uriString);
+ if (matchResult.find()) {
+ int isFinal = Integer.parseInt(matchResult.group(1));
+ double score = Double.parseDouble(matchResult.group(2));
+ String message = matchResult.group(3);
+ Log.i(TAG, message + ":" + score);
+ if (!mResultsMap.containsKey(message)) {
+ mResultsMap.put(message, new double[mNumberRepeat]);
+ }
+ double[] scores = mResultsMap.get(message);
+ scores[mRunIndex] = score;
+ if (isFinal == 1) {
+ String userAgent = request.getFirstHeader(HTTP_USER_AGENT).getValue();
+ mReport.addValue(HTTP_USER_AGENT + "=" + userAgent, 0,
+ ResultType.NEUTRAL, ResultUnit.NONE);
+ mLatch.countDown();
+ }
+ mWatchDog.reset();
+ }
+ return null; // default response is OK as it will be ignored by client anyway.
+ }
+ };
+ mResultsMap = new LinkedHashMap<String, double[]>();
+ mWatchDog = new WatchDog(BROWSER_POST_TIMEOUT_IN_MS);
+ mWatchDog.start();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mWatchDog.stop();
+ mWebServer.shutdown();
+ mWebServer = null;
+ mResultsMap = null;
+ mReport.submit(getInstrumentation());
+ super.tearDown();
+ }
+
+ @TimeoutReq(minutes = 60)
+ public void testOctane() throws InterruptedException {
+ if (!isBrowserSupported()) {
+ Log.i(TAG, "Skipping test for device with no supported browser");
+ return;
+ }
+ String url = mWebServer.getAssetUrl(OCTANE_START_FILE) + "?auto=1";
+ final int kRepeat = 5;
+ doTest(url, ResultType.LOWER_BETTER, ResultUnit.MS,
+ ResultType.HIGHER_BETTER, ResultUnit.SCORE, kRepeat);
+ }
+
+ private void doTest(String url, ResultType typeNonFinal, ResultUnit unitNonFinal,
+ ResultType typeFinal, ResultUnit unitFinal, int numberRepeat)
+ throws InterruptedException {
+ mTypeNonFinal = typeNonFinal;
+ mUnitNonFinal = unitNonFinal;
+ mTypeFinal = typeFinal;
+ mUnitFinal = unitFinal;
+ mNumberRepeat = numberRepeat;
+ Uri uri = Uri.parse(url);
+ for (mRunIndex = 0; mRunIndex < numberRepeat; mRunIndex++) {
+ Log.i(TAG, mRunIndex + "-th round");
+ mLatch = new CountDownLatch(1);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ // force using only one window or tab
+ intent.putExtra(Browser.EXTRA_APPLICATION_ID, getContext().getPackageName());
+ getContext().startActivity(intent);
+ boolean ok = mLatch.await(BROWSER_COMPLETION_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS);
+ assertTrue("timed-out", ok);
+ }
+ // it is somewhat awkward to handle the last one specially with Map
+ int numberEntries = mResultsMap.size();
+ int numberToProcess = 1;
+ for (Map.Entry<String, double[]> entry : mResultsMap.entrySet()) {
+ String message = entry.getKey();
+ double[] scores = entry.getValue();
+ if (numberToProcess == numberEntries) { // final score
+ // store the whole results first
+ mReport.addValues(message, scores, mTypeFinal, mUnitFinal);
+ mReport.setSummary(message, Stat.getAverage(scores), mTypeFinal, mUnitFinal);
+ } else { // interim results
+ mReport.addValues(message, scores, mTypeNonFinal, mUnitNonFinal);
+ }
+ numberToProcess++;
+ }
+ }
+
+ /**
+ * @return true iff this device is has a working browser.
+ */
+ private boolean isBrowserSupported() {
+ return !(mPackageManager.hasSystemFeature("android.hardware.type.television")
+ || mPackageManager.hasSystemFeature("android.software.leanback")
+ || mPackageManager.hasSystemFeature("android.hardware.type.watch"));
+ }
+}
diff --git a/tests/camera/Android.mk b/tests/camera/Android.mk
index 4cae7c4..d072975 100644
--- a/tests/camera/Android.mk
+++ b/tests/camera/Android.mk
@@ -27,6 +27,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsCameraTestCases
LOCAL_SDK_VERSION := current
diff --git a/tests/camera/AndroidTest.xml b/tests/camera/AndroidTest.xml
new file mode 100644
index 0000000..df15689
--- /dev/null
+++ b/tests/camera/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Camera test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsCameraTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.camera.cts" />
+ <option name="runtime-hint" value="12m7s" />
+ </test>
+</configuration>
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 44fda14..3778b95 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -425,6 +425,7 @@
// method on the camera device or session.
class ChainedCaptureCallback extends CameraCaptureSession.CaptureCallback {
+ @Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
TotalCaptureResult result) {
try {
@@ -450,6 +451,7 @@
}
}
+ @Override
public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
CaptureFailure failure) {
try {
@@ -466,6 +468,7 @@
class ChainedSessionListener extends CameraCaptureSession.StateCallback {
private final ChainedCaptureCallback mCaptureCallback = new ChainedCaptureCallback();
+ @Override
public void onConfigured(CameraCaptureSession session) {
try {
CaptureRequest.Builder request =
@@ -486,6 +489,7 @@
}
}
+ @Override
public void onConfigureFailed(CameraCaptureSession session) {
try {
CameraDevice camera = session.getDevice();
@@ -503,6 +507,7 @@
public CameraDevice cameraDevice;
+ @Override
public void onOpened(CameraDevice camera) {
cameraDevice = camera;
@@ -525,6 +530,7 @@
}
}
+ @Override
public void onDisconnected(CameraDevice camera) {
try {
camera.close();
@@ -534,6 +540,7 @@
}
}
+ @Override
public void onError(CameraDevice camera, int error) {
try {
camera.close();
@@ -1508,7 +1515,6 @@
}
}
- // Edge enhancement and noise reduction modes
boolean supportReprocessing =
availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING) ||
availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);
@@ -1522,6 +1528,7 @@
CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
}
+ // Edge enhancement, noise reduction and aberration correction modes.
mCollector.expectEquals("Edge mode must be present in request if " +
"available edge modes are present in metadata, and vice-versa.",
mStaticInfo.areKeysAvailable(CameraCharacteristics.
@@ -1530,12 +1537,10 @@
if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
List<Integer> availableEdgeModes =
Arrays.asList(toObject(mStaticInfo.getAvailableEdgeModesChecked()));
+ // Don't need check fast as fast or high quality must be both present or both not.
if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_HIGH_QUALITY)) {
mCollector.expectKeyValueEquals(request, EDGE_MODE,
CaptureRequest.EDGE_MODE_HIGH_QUALITY);
- } else if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_FAST)) {
- mCollector.expectKeyValueEquals(request, EDGE_MODE,
- CaptureRequest.EDGE_MODE_FAST);
} else {
mCollector.expectKeyValueEquals(request, EDGE_MODE,
CaptureRequest.EDGE_MODE_OFF);
@@ -1551,25 +1556,86 @@
CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES)) {
List<Integer> availableNoiseReductionModes =
Arrays.asList(toObject(mStaticInfo.getAvailableNoiseReductionModesChecked()));
+ // Don't need check fast as fast or high quality must be both present or both not.
if (availableNoiseReductionModes
.contains(CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY)) {
mCollector.expectKeyValueEquals(
request, NOISE_REDUCTION_MODE,
CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
- } else if (availableNoiseReductionModes
- .contains(CaptureRequest.NOISE_REDUCTION_MODE_FAST)) {
- mCollector.expectKeyValueEquals(
- request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_FAST);
} else {
mCollector.expectKeyValueEquals(
request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
}
}
+
+ boolean supportAvailableAberrationModes = mStaticInfo.areKeysAvailable(
+ CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES);
+ boolean supportAberrationRequestKey = mStaticInfo.areKeysAvailable(
+ CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE);
+ mCollector.expectEquals("Aberration correction mode must be present in request if " +
+ "available aberration correction reductions are present in metadata, and "
+ + "vice-versa.", supportAvailableAberrationModes, supportAberrationRequestKey);
+ if (supportAberrationRequestKey) {
+ List<Integer> availableAberrationModes = Arrays.asList(
+ toObject(mStaticInfo.getAvailableColorAberrationModesChecked()));
+ // Don't need check fast as fast or high quality must be both present or both not.
+ if (availableAberrationModes
+ .contains(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY)) {
+ mCollector.expectKeyValueEquals(
+ request, COLOR_CORRECTION_ABERRATION_MODE,
+ CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);
+ } else {
+ mCollector.expectKeyValueEquals(
+ request, COLOR_CORRECTION_ABERRATION_MODE,
+ CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_OFF);
+ }
+ }
} else if (template == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG && supportReprocessing) {
mCollector.expectKeyValueEquals(request, EDGE_MODE,
CaptureRequest.EDGE_MODE_ZERO_SHUTTER_LAG);
mCollector.expectKeyValueEquals(request, NOISE_REDUCTION_MODE,
CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG);
+ } else if (template == CameraDevice.TEMPLATE_PREVIEW ||
+ template == CameraDevice.TEMPLATE_RECORD){
+ List<Integer> availableEdgeModes =
+ Arrays.asList(toObject(mStaticInfo.getAvailableEdgeModesChecked()));
+ if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_FAST)) {
+ mCollector.expectKeyValueEquals(request, EDGE_MODE,
+ CaptureRequest.EDGE_MODE_FAST);
+ } else {
+ mCollector.expectKeyValueEquals(request, EDGE_MODE,
+ CaptureRequest.EDGE_MODE_OFF);
+ }
+
+ if (mStaticInfo.areKeysAvailable(NOISE_REDUCTION_MODE)) {
+ List<Integer> availableNoiseReductionModes =
+ Arrays.asList(toObject(
+ mStaticInfo.getAvailableNoiseReductionModesChecked()));
+ if (availableNoiseReductionModes
+ .contains(CaptureRequest.NOISE_REDUCTION_MODE_FAST)) {
+ mCollector.expectKeyValueEquals(
+ request, NOISE_REDUCTION_MODE,
+ CaptureRequest.NOISE_REDUCTION_MODE_FAST);
+ } else {
+ mCollector.expectKeyValueEquals(
+ request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
+ }
+ }
+
+ if (mStaticInfo.areKeysAvailable(COLOR_CORRECTION_ABERRATION_MODE)) {
+ List<Integer> availableAberrationModes = Arrays.asList(
+ toObject(mStaticInfo.getAvailableColorAberrationModesChecked()));
+ if (availableAberrationModes
+ .contains(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_FAST)) {
+ mCollector.expectKeyValueEquals(
+ request, COLOR_CORRECTION_ABERRATION_MODE,
+ CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_FAST);
+ } else {
+ mCollector.expectKeyValueEquals(
+ request, COLOR_CORRECTION_ABERRATION_MODE,
+ CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_OFF);
+ }
+ }
} else {
if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
mCollector.expectKeyValueNotNull(request, EDGE_MODE);
@@ -1578,6 +1644,10 @@
if (mStaticInfo.areKeysAvailable(NOISE_REDUCTION_MODE)) {
mCollector.expectKeyValueNotNull(request, NOISE_REDUCTION_MODE);
}
+
+ if (mStaticInfo.areKeysAvailable(COLOR_CORRECTION_ABERRATION_MODE)) {
+ mCollector.expectKeyValueNotNull(request, COLOR_CORRECTION_ABERRATION_MODE);
+ }
}
// Tone map and lens shading modes.
@@ -1681,6 +1751,7 @@
* @param listener The {@link #CaptureCallback} camera device used to notify callbacks.
* @param handler The handler camera device used to post callbacks.
*/
+ @Override
protected void startCapture(CaptureRequest request, boolean repeating,
CameraCaptureSession.CaptureCallback listener, Handler handler)
throws CameraAccessException {
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java
index d78b3b5..85eeb0b 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -818,7 +818,8 @@
ByteBuffer buffer = null;
// JPEG doesn't have pixelstride and rowstride, treat it as 1D buffer.
// Same goes for DEPTH_POINT_CLOUD
- if (format == ImageFormat.JPEG || format == ImageFormat.DEPTH_POINT_CLOUD) {
+ if (format == ImageFormat.JPEG || format == ImageFormat.DEPTH_POINT_CLOUD ||
+ format == ImageFormat.RAW_PRIVATE) {
buffer = planes[0].getBuffer();
assertNotNull("Fail to get jpeg or depth ByteBuffer", buffer);
data = new byte[buffer.remaining()];
@@ -898,6 +899,7 @@
break;
case ImageFormat.JPEG:
case ImageFormat.RAW_SENSOR:
+ case ImageFormat.RAW_PRIVATE:
case ImageFormat.DEPTH16:
case ImageFormat.DEPTH_POINT_CLOUD:
assertEquals("JPEG/RAW/depth Images should have one plane", 1, planes.length);
@@ -1320,6 +1322,9 @@
case ImageFormat.DEPTH_POINT_CLOUD:
validateDepthPointCloudData(data, width, height, format, image.getTimestamp(), filePath);
break;
+ case ImageFormat.RAW_PRIVATE:
+ validateRawPrivateData(data, width, height, image.getTimestamp(), filePath);
+ break;
default:
throw new UnsupportedOperationException("Unsupported format for validation: "
+ format);
@@ -1416,6 +1421,26 @@
return;
}
+ private static void validateRawPrivateData(byte[] rawData, int width, int height,
+ long ts, String filePath) {
+ if (VERBOSE) Log.v(TAG, "Validating private raw data");
+ // Expect each RAW pixel should occupy at least one byte and no more than 2.5 bytes
+ int expectedSizeMin = width * height;
+ int expectedSizeMax = width * height * 5 / 2;
+
+ assertTrue("Opaque RAW size " + rawData.length + "out of normal bound [" +
+ expectedSizeMin + "," + expectedSizeMax + "]",
+ expectedSizeMin <= rawData.length && rawData.length <= expectedSizeMax);
+
+ if (DEBUG && filePath != null) {
+ String fileName =
+ filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".rawPriv";
+ dumpFile(fileName, rawData);
+ }
+
+ return;
+ }
+
private static void validateDepth16Data(byte[] depthData, int width, int height, int format,
long ts, String filePath) {
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index dd4e3e3..a4e1917 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -29,18 +29,20 @@
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.hardware.camera2.params.BlackLevelPattern;
import android.hardware.camera2.params.ColorSpaceTransform;
import android.hardware.camera2.params.Face;
import android.hardware.camera2.params.LensShadingMap;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.RggbChannelVector;
import android.hardware.camera2.params.TonemapCurve;
-
+import android.media.Image;
import android.util.Log;
import android.util.Range;
import android.util.Rational;
import android.util.Size;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -85,11 +87,12 @@
private static final float FOCUS_DISTANCE_ERROR_PERCENT_APPROXIMATE = 0.10f;
private static final int ANTI_FLICKERING_50HZ = 1;
private static final int ANTI_FLICKERING_60HZ = 2;
-
// 5 percent error margin for resulting crop regions
private static final float CROP_REGION_ERROR_PERCENT_DELTA = 0.05f;
// 1 percent error margin for centering the crop region
private static final float CROP_REGION_ERROR_PERCENT_CENTERED = 0.01f;
+ private static final float DYNAMIC_VS_FIXED_BLK_WH_LVL_ERROR_MARGIN = 0.25f;
+ private static final float DYNAMIC_VS_OPTICAL_BLK_LVL_ERROR_MARGIN = 0.1f;
// Linear tone mapping curve example.
private static final float[] TONEMAP_CURVE_LINEAR = {0, 0, 1.0f, 1.0f};
@@ -178,6 +181,32 @@
}
/**
+ * Test dynamic black/white levels if they are supported.
+ *
+ * <p>
+ * If the dynamic black and white levels are reported, test below:
+ * 1. the dynamic black and white levels shouldn't deviate from the global value too much
+ * for different sensitivities.
+ * 2. If the RAW_SENSOR and optical black regions are supported, capture RAW images and
+ * calculate the optical black level values. The reported dynamic black level should be
+ * close enough to the optical black level values.
+ * </p>
+ */
+ public void testDynamicBlackWhiteLevel() throws Exception {
+ for (String id : mCameraIds) {
+ try {
+ openDevice(id);
+ if (!mStaticInfo.isDynamicBlackLevelSupported()) {
+ continue;
+ }
+ dynamicBlackWhiteLevelTestByCamera();
+ } finally {
+ closeDevice();
+ }
+ }
+ }
+
+ /**
* Basic lens shading map request test.
* <p>
* When {@link CaptureRequest#SHADING_MODE} is set to OFF, no lens shading correction will
@@ -630,6 +659,170 @@
// TODO: add 3A state machine test.
+ /**
+ * Per camera dynamic black and white level test.
+ */
+ private void dynamicBlackWhiteLevelTestByCamera() throws Exception {
+ SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+ SimpleImageReaderListener imageListener = null;
+ CaptureRequest.Builder previewBuilder =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ CaptureRequest.Builder rawBuilder = null;
+ Size previewSize =
+ getMaxPreviewSize(mCamera.getId(), mCameraManager,
+ getPreviewSizeBound(mWindowManager, PREVIEW_SIZE_BOUND));
+ Size rawSize = null;
+ boolean canCaptureBlackRaw =
+ mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW) &&
+ mStaticInfo.isOpticalBlackRegionSupported();
+ if (canCaptureBlackRaw) {
+ // Capture Raw16, then calculate the optical black, and use it to check with the dynamic
+ // black level.
+ rawBuilder =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ rawSize = mStaticInfo.getRawDimensChecked();
+ imageListener = new SimpleImageReaderListener();
+ prepareRawCaptureAndStartPreview(previewBuilder, rawBuilder, previewSize, rawSize,
+ resultListener, imageListener);
+ } else {
+ startPreview(previewBuilder, previewSize, resultListener);
+ }
+
+ // Capture a sequence of frames with different sensitivities and validate the black/white
+ // level values
+ int[] sensitivities = getSensitivityTestValues();
+ float[][] dynamicBlackLevels = new float[sensitivities.length][];
+ int[] dynamicWhiteLevels = new int[sensitivities.length];
+ float[][] opticalBlackLevels = new float[sensitivities.length][];
+ for (int i = 0; i < sensitivities.length; i++) {
+ CaptureResult result = null;
+ if (canCaptureBlackRaw) {
+ changeExposure(rawBuilder, DEFAULT_EXP_TIME_NS, sensitivities[i]);
+ CaptureRequest rawRequest = rawBuilder.build();
+ mSession.capture(rawRequest, resultListener, mHandler);
+ result = resultListener.getCaptureResultForRequest(rawRequest,
+ NUM_RESULTS_WAIT_TIMEOUT);
+ Image rawImage = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+
+ // Get max (area-wise) optical black region
+ Rect[] opticalBlackRegions = mStaticInfo.getCharacteristics().get(
+ CameraCharacteristics.SENSOR_OPTICAL_BLACK_REGIONS);
+ Rect maxRegion = opticalBlackRegions[0];
+ for (Rect region : opticalBlackRegions) {
+ if (region.width() * region.height() > maxRegion.width() * maxRegion.height()) {
+ maxRegion = region;
+ }
+ }
+
+ // Get average black pixel values in the region (region is multiple of 2x2)
+ Image.Plane rawPlane = rawImage.getPlanes()[0];
+ ByteBuffer rawBuffer = rawPlane.getBuffer();
+ float[] avgBlackLevels = {0, 0, 0, 0};
+ int rowSize = rawPlane.getRowStride() * rawPlane.getPixelStride();
+ int bytePerPixel = rawPlane.getPixelStride();
+ if (VERBOSE) {
+ Log.v(TAG, "maxRegion: " + maxRegion + ", Row stride: " +
+ rawPlane.getRowStride());
+ }
+ for (int row = maxRegion.left; row < maxRegion.right; row += 2) {
+ for (int col = maxRegion.top; col < maxRegion.bottom; col += 2) {
+ int startOffset = col * rawPlane.getRowStride() + row * bytePerPixel;
+ avgBlackLevels[0] += rawBuffer.getShort(startOffset);
+ avgBlackLevels[1] += rawBuffer.getShort(startOffset + bytePerPixel);
+ startOffset += rowSize;
+ avgBlackLevels[2] += rawBuffer.getShort(startOffset);
+ avgBlackLevels[3] += rawBuffer.getShort(startOffset + bytePerPixel);
+ }
+ }
+ int numBlackBlocks = maxRegion.width() * maxRegion.height() / (2 * 2);
+ for (int m = 0; m < avgBlackLevels.length; m++) {
+ avgBlackLevels[m] /= numBlackBlocks;
+ }
+ opticalBlackLevels[i] = avgBlackLevels;
+
+ if (VERBOSE) {
+ Log.v(TAG, String.format("Optical black level results for sensitivity (%d): %s",
+ sensitivities[i], Arrays.toString(avgBlackLevels)));
+ }
+
+ rawImage.close();
+ } else {
+ changeExposure(previewBuilder, DEFAULT_EXP_TIME_NS, sensitivities[i]);
+ CaptureRequest previewRequest = previewBuilder.build();
+ mSession.capture(previewRequest, resultListener, mHandler);
+ result = resultListener.getCaptureResultForRequest(previewRequest,
+ NUM_RESULTS_WAIT_TIMEOUT);
+ }
+
+ dynamicBlackLevels[i] = getValueNotNull(result,
+ CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
+ dynamicWhiteLevels[i] = getValueNotNull(result,
+ CaptureResult.SENSOR_DYNAMIC_WHITE_LEVEL);
+ }
+
+ if (VERBOSE) {
+ Log.v(TAG, "Different sensitivities tested: " + Arrays.toString(sensitivities));
+ Log.v(TAG, "Dynamic black level results: " + Arrays.deepToString(dynamicBlackLevels));
+ Log.v(TAG, "Dynamic white level results: " + Arrays.toString(dynamicWhiteLevels));
+ if (canCaptureBlackRaw) {
+ Log.v(TAG, "Optical black level results " +
+ Arrays.deepToString(opticalBlackLevels));
+ }
+ }
+
+ // check the dynamic black level against global black level.
+ // Implicit guarantee: if the dynamic black level is supported, fixed black level must be
+ // supported as well (tested in ExtendedCameraCharacteristicsTest#testOpticalBlackRegions).
+ BlackLevelPattern blackPattern = mStaticInfo.getCharacteristics().get(
+ CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN);
+ int[] fixedBlackLevels = new int[4];
+ int fixedWhiteLevel = mStaticInfo.getCharacteristics().get(
+ CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL);
+ blackPattern.copyTo(fixedBlackLevels, 0);
+ float maxBlackDeviation = 0;
+ int maxWhiteDeviation = 0;
+ for (int i = 0; i < dynamicBlackLevels.length; i++) {
+ for (int j = 0; j < dynamicBlackLevels[i].length; j++) {
+ if (maxBlackDeviation < Math.abs(fixedBlackLevels[j] - dynamicBlackLevels[i][j])) {
+ maxBlackDeviation = Math.abs(fixedBlackLevels[j] - dynamicBlackLevels[i][j]);
+ }
+ }
+ if (maxWhiteDeviation < Math.abs(dynamicWhiteLevels[i] - fixedWhiteLevel)) {
+ maxWhiteDeviation = Math.abs(dynamicWhiteLevels[i] - fixedWhiteLevel);
+ }
+ }
+ mCollector.expectLessOrEqual("Max deviation of the dynamic black level vs fixed black level"
+ + " exceed threshold."
+ + " Dynamic black level results: " + Arrays.deepToString(dynamicBlackLevels),
+ fixedBlackLevels[0] * DYNAMIC_VS_FIXED_BLK_WH_LVL_ERROR_MARGIN, maxBlackDeviation);
+ mCollector.expectLessOrEqual("Max deviation of the dynamic white level exceed threshold."
+ + " Dynamic white level results: " + Arrays.toString(dynamicWhiteLevels),
+ fixedWhiteLevel * DYNAMIC_VS_FIXED_BLK_WH_LVL_ERROR_MARGIN,
+ (float)maxWhiteDeviation);
+
+ // Validate against optical black levels if it is available
+ if (canCaptureBlackRaw) {
+ maxBlackDeviation = 0;
+ for (int i = 0; i < dynamicBlackLevels.length; i++) {
+ for (int j = 0; j < dynamicBlackLevels[i].length; j++) {
+ if (maxBlackDeviation <
+ Math.abs(opticalBlackLevels[i][j] - dynamicBlackLevels[i][j])) {
+ maxBlackDeviation =
+ Math.abs(opticalBlackLevels[i][j] - dynamicBlackLevels[i][j]);
+ }
+ }
+ }
+
+ mCollector.expectLessOrEqual("Max deviation of the dynamic black level vs optical black"
+ + " exceed threshold."
+ + " Dynamic black level results: " + Arrays.deepToString(dynamicBlackLevels)
+ + " Optical black level results: " + Arrays.deepToString(opticalBlackLevels),
+ fixedBlackLevels[0] * DYNAMIC_VS_OPTICAL_BLK_LVL_ERROR_MARGIN,
+ maxBlackDeviation);
+ }
+ }
+
private void noiseReductionModeTestByCamera() throws Exception {
Size maxPrevSize = mOrderedPreviewSizes.get(0);
CaptureRequest.Builder requestBuilder =
@@ -2111,7 +2304,7 @@
* @param result Result sensitivity
*/
private void validateSensitivity(int request, int result) {
- float sensitivityDelta = (float)(request - result);
+ float sensitivityDelta = request - result;
float sensitivityErrorMargin = request * SENSITIVITY_ERROR_MARGIN_RATE;
// First, round down not up, second, need close enough.
mCollector.expectTrue("Sensitivity is invalid for AE manaul control test, request: "
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
index 2ae29c3..199552f 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -509,6 +509,12 @@
waiverKeys.add(CaptureResult.CONTROL_AF_REGIONS);
}
+ // Keys for dynamic black/white levels
+ if (!mStaticInfo.isOpticalBlackRegionSupported()) {
+ waiverKeys.add(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
+ waiverKeys.add(CaptureResult.SENSOR_DYNAMIC_WHITE_LEVEL);
+ }
+
if (mStaticInfo.isHardwareLevelFull()) {
return waiverKeys;
}
@@ -775,6 +781,8 @@
resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
resultKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
+ resultKeys.add(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
+ resultKeys.add(CaptureResult.SENSOR_DYNAMIC_WHITE_LEVEL);
resultKeys.add(CaptureResult.SHADING_MODE);
resultKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index 28693c6..5b21e4d 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -24,6 +24,7 @@
import android.hardware.camera2.CameraCharacteristics.Key;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.cts.helpers.CameraErrorCollector;
import android.hardware.camera2.params.BlackLevelPattern;
import android.hardware.camera2.params.ColorSpaceTransform;
@@ -1181,6 +1182,82 @@
}
/**
+ * Sanity check of optical black regions.
+ */
+ public void testOpticalBlackRegions() {
+ int counter = 0;
+ for (CameraCharacteristics c : mCharacteristics) {
+ List<CaptureResult.Key<?>> resultKeys = c.getAvailableCaptureResultKeys();
+ boolean hasDynamicBlackLevel =
+ resultKeys.contains(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
+ boolean hasDynamicWhiteLevel =
+ resultKeys.contains(CaptureResult.SENSOR_DYNAMIC_WHITE_LEVEL);
+ boolean hasFixedBlackLevel =
+ c.getKeys().contains(CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN);
+ boolean hasFixedWhiteLevel =
+ c.getKeys().contains(CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL);
+ // The black and white levels should be either all supported or none of them is
+ // supported.
+ mCollector.expectTrue("Dynamic black and white level should be all or none of them"
+ + " be supported", hasDynamicWhiteLevel == hasDynamicBlackLevel);
+ mCollector.expectTrue("Fixed black and white level should be all or none of them"
+ + " be supported", hasFixedBlackLevel == hasFixedWhiteLevel);
+ mCollector.expectTrue("Fixed black level should be supported if dynamic black"
+ + " level is supported", !hasDynamicBlackLevel || hasFixedBlackLevel);
+
+ if (c.getKeys().contains(CameraCharacteristics.SENSOR_OPTICAL_BLACK_REGIONS)) {
+ // Regions shouldn't be null or empty.
+ Rect[] regions = CameraTestUtils.getValueNotNull(c,
+ CameraCharacteristics.SENSOR_OPTICAL_BLACK_REGIONS);
+ CameraTestUtils.assertArrayNotEmpty(regions, "Optical back region arrays must not"
+ + " be empty");
+
+ // Dynamic black level should be supported if the optical black region is
+ // advertised.
+ mCollector.expectTrue("Dynamic black and white level keys should be advertised in "
+ + "available capture result key list", hasDynamicWhiteLevel);
+
+ // Range check.
+ for (Rect region : regions) {
+ mCollector.expectTrue("Camera " + mIds[counter] + ": optical black region" +
+ " shouldn't be empty!", !region.isEmpty());
+ mCollector.expectGreaterOrEqual("Optical black region left", 0/*expected*/,
+ region.left/*actual*/);
+ mCollector.expectGreaterOrEqual("Optical black region top", 0/*expected*/,
+ region.top/*actual*/);
+ mCollector.expectTrue("Optical black region left/right/width/height must be"
+ + " even number, otherwise, the bayer CFA pattern in this region will"
+ + " be messed up",
+ region.left % 2 == 0 && region.top % 2 == 0 &&
+ region.width() % 2 == 0 && region.height() % 2 == 0);
+ mCollector.expectGreaterOrEqual("Optical black region top", 0/*expected*/,
+ region.top/*actual*/);
+ Size size = CameraTestUtils.getValueNotNull(c,
+ CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE);
+ mCollector.expectLessOrEqual("Optical black region width",
+ size.getWidth()/*expected*/, region.width());
+ mCollector.expectLessOrEqual("Optical black region height",
+ size.getHeight()/*expected*/, region.height());
+ Rect activeArray = CameraTestUtils.getValueNotNull(c,
+ CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+ mCollector.expectTrue("Optical black region" + region + " should be outside of"
+ + " active array " + activeArray,
+ !region.intersect(activeArray));
+ // Region need to be disjoint:
+ for (Rect region2 : regions) {
+ mCollector.expectTrue("Optical black region" + region + " should have no "
+ + "overlap with " + region2,
+ region == region2 || !region.intersect(region2));
+ }
+ }
+ } else {
+ Log.i(TAG, "Camera " + mIds[counter] + " doesn't support optical black regions,"
+ + " skip the region test");
+ }
+ counter++;
+ }
+ }
+ /**
* Create an invalid size that's close to one of the good sizes in the list, but not one of them
*/
private Size findInvalidSize(Size[] goodSizes) {
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
index 9c783e0..1e9fe55 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -160,6 +160,20 @@
}
}
+ public void testRawPrivate() throws Exception {
+ for (String id : mCameraIds) {
+ try {
+ Log.v(TAG, "Testing raw capture for camera " + id);
+ openDevice(id);
+
+ bufferFormatTestByCamera(ImageFormat.RAW_PRIVATE, /*repeating*/false);
+ } finally {
+ closeDevice(id);
+ }
+ }
+ }
+
+
public void testRepeatingJpeg() throws Exception {
for (String id : mCameraIds) {
try {
@@ -185,6 +199,19 @@
}
}
+ public void testRepeatingRawPrivate() throws Exception {
+ for (String id : mCameraIds) {
+ try {
+ Log.v(TAG, "Testing repeating raw capture for camera " + id);
+ openDevice(id);
+
+ bufferFormatTestByCamera(ImageFormat.RAW_PRIVATE, /*repeating*/true);
+ } finally {
+ closeDevice(id);
+ }
+ }
+ }
+
public void testLongProcessingRepeatingRaw() throws Exception {
for (String id : mCameraIds) {
try {
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 39eb1dc..666292c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -16,7 +16,7 @@
package android.hardware.camera2.cts;
-import static com.android.ex.camera2.blocking.BlockingSessionCallback.*;
+import static com.android.ex.camera2.blocking.BlockingSessionCallback.SESSION_CLOSED;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
@@ -32,20 +32,20 @@
import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.hardware.camera2.params.InputConfiguration;
-import android.util.Log;
-import android.util.Pair;
-import android.util.Size;
-import android.view.Surface;
-import android.cts.util.DeviceReportLog;
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
import android.os.ConditionVariable;
import android.os.SystemClock;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Size;
+import android.view.Surface;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.Stat;
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
import com.android.ex.camera2.blocking.BlockingSessionCallback;
import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
@@ -95,7 +95,7 @@
@Override
protected void tearDown() throws Exception {
// Deliver the report to host will automatically clear the report log.
- mReportLog.deliverReportToHost(getInstrumentation());
+ mReportLog.submit(getInstrumentation());
super.tearDown();
}
@@ -180,22 +180,22 @@
avgCameraLaunchTimes[counter] = Stat.getAverage(cameraLaunchTimes);
// Finish the data collection, report the KPIs.
- mReportLog.printArray("Camera " + id
+ mReportLog.addValues("Camera " + id
+ ": Camera open time", cameraOpenTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printArray("Camera " + id
+ mReportLog.addValues("Camera " + id
+ ": Camera configure stream time", configureStreamTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printArray("Camera " + id
+ mReportLog.addValues("Camera " + id
+ ": Camera start preview time", startPreviewTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printArray("Camera " + id
+ mReportLog.addValues("Camera " + id
+ ": Camera stop preview", stopPreviewTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printArray("Camera " + id
+ mReportLog.addValues("Camera " + id
+ ": Camera close time", cameraCloseTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printArray("Camera " + id
+ mReportLog.addValues("Camera " + id
+ ": Camera launch time", cameraLaunchTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
}
@@ -205,7 +205,7 @@
counter++;
}
if (mCameraIds.length != 0) {
- mReportLog.printSummary("Camera launch average time for all cameras ",
+ mReportLog.setSummary("Camera launch average time for all cameras ",
Stat.getAverage(avgCameraLaunchTimes), ResultType.LOWER_BETTER, ResultUnit.MS);
}
}
@@ -297,19 +297,19 @@
// simulate real scenario (preview runs a bit)
waitForNumResults(previewResultListener, NUM_RESULTS_WAIT);
- blockingStopPreview();
+ stopPreview();
}
- mReportLog.printArray("Camera " + id
+ mReportLog.addValues("Camera " + id
+ ": Camera capture latency", captureTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
// If any of the partial results do not contain AE and AF state, then no report
if (isPartialTimingValid) {
- mReportLog.printArray("Camera " + id
+ mReportLog.addValues("Camera " + id
+ ": Camera partial result latency", getPartialTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
}
- mReportLog.printArray("Camera " + id
+ mReportLog.addValues("Camera " + id
+ ": Camera capture result latency", getResultTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
@@ -324,7 +324,7 @@
// Result will not be reported in CTS report if no summary is printed.
if (mCameraIds.length != 0) {
- mReportLog.printSummary("Camera capture result average latency for all cameras ",
+ mReportLog.setSummary("Camera capture result average latency for all cameras ",
Stat.getAverage(avgResultTimes), ResultType.LOWER_BETTER, ResultUnit.MS);
}
}
@@ -481,13 +481,13 @@
reprocessType = " opaque reprocessing ";
}
- mReportLog.printArray("Camera " + mCamera.getId()
+ mReportLog.addValues("Camera " + mCamera.getId()
+ ":" + reprocessType + " max capture timestamp gaps", maxCaptureGapsMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printArray("Camera " + mCamera.getId()
+ mReportLog.addValues("Camera " + mCamera.getId()
+ ":" + reprocessType + "capture average frame duration", averageFrameDurationMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printSummary("Camera reprocessing average max capture timestamp gaps for Camera "
+ mReportLog.setSummary("Camera reprocessing average max capture timestamp gaps for Camera "
+ mCamera.getId(), Stat.getAverage(maxCaptureGapsMs), ResultType.LOWER_BETTER,
ResultUnit.MS);
@@ -575,17 +575,17 @@
// Report the performance data
if (asyncMode) {
- mReportLog.printArray("Camera " + mCamera.getId()
+ mReportLog.addValues("Camera " + mCamera.getId()
+ ":" + reprocessType + "capture latency", getImageLatenciesMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printSummary("Camera reprocessing average latency for Camera " +
+ mReportLog.setSummary("Camera reprocessing average latency for Camera " +
mCamera.getId(), Stat.getAverage(getImageLatenciesMs), ResultType.LOWER_BETTER,
ResultUnit.MS);
} else {
- mReportLog.printArray("Camera " + mCamera.getId()
+ mReportLog.addValues("Camera " + mCamera.getId()
+ ":" + reprocessType + "shot to shot latency", getImageLatenciesMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printSummary("Camera reprocessing shot to shot average latency for Camera " +
+ mReportLog.setSummary("Camera reprocessing shot to shot average latency for Camera " +
mCamera.getId(), Stat.getAverage(getImageLatenciesMs), ResultType.LOWER_BETTER,
ResultUnit.MS);
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index feade79..4acbffe 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -104,7 +104,7 @@
super.tearDown();
}
- private void doBasicRecording() throws Exception {
+ private void doBasicRecording(boolean useVideoStab) throws Exception {
for (int i = 0; i < mCameraIds.length; i++) {
try {
Log.i(TAG, "Testing basic recording for camera " + mCameraIds[i]);
@@ -116,9 +116,17 @@
" does not support color outputs, skipping");
continue;
}
+
+ if (!mStaticInfo.isVideoStabilizationSupported() && useVideoStab) {
+ Log.i(TAG, "Camera " + mCameraIds[i] +
+ " does not support video stabilization, skipping the stabilization"
+ + " test");
+ continue;
+ }
+
initSupportedVideoSize(mCameraIds[i]);
- basicRecordingTestByCamera(mCamcorderProfileList);
+ basicRecordingTestByCamera(mCamcorderProfileList, useVideoStab);
} finally {
closeDevice();
releaseRecorder();
@@ -128,6 +136,23 @@
/**
* <p>
+ * Test basic video stabilitzation camera recording.
+ * </p>
+ * <p>
+ * This test covers the typical basic use case of camera recording with video
+ * stabilization is enabled, if video stabilization is supported.
+ * MediaRecorder is used to record the audio and video, CamcorderProfile is
+ * used to configure the MediaRecorder. It goes through the pre-defined
+ * CamcorderProfile list, test each profile configuration and validate the
+ * recorded video. Preview is set to the video size.
+ * </p>
+ */
+ public void testBasicVideoStabilizationRecording() throws Exception {
+ doBasicRecording(/*useVideoStab*/true);
+ }
+
+ /**
+ * <p>
* Test basic camera recording.
* </p>
* <p>
@@ -139,7 +164,7 @@
* </p>
*/
public void testBasicRecording() throws Exception {
- doBasicRecording();
+ doBasicRecording(/*useVideoStab*/false);
}
/**
@@ -159,7 +184,7 @@
assertNotNull("Failed to create persistent input surface!", mPersistentSurface);
try {
- doBasicRecording();
+ doBasicRecording(/*useVideoStab*/false);
} finally {
mPersistentSurface.release();
mPersistentSurface = null;
@@ -311,7 +336,7 @@
}
int camcorderProfileList[] = new int[] {minFpsProfileId, maxFpsProfileId};
- basicRecordingTestByCamera(camcorderProfileList);
+ basicRecordingTestByCamera(camcorderProfileList, /*useVideoStab*/false);
} finally {
closeDevice();
releaseRecorder();
@@ -594,7 +619,8 @@
* Test camera recording by using each available CamcorderProfile for a
* given camera. preview size is set to the video size.
*/
- private void basicRecordingTestByCamera(int[] camcorderProfileList) throws Exception {
+ private void basicRecordingTestByCamera(int[] camcorderProfileList, boolean useVideoStab)
+ throws Exception {
Size maxPreviewSize = mOrderedPreviewSizes.get(0);
List<Range<Integer> > fpsRanges = Arrays.asList(
mStaticInfo.getAeAvailableTargetFpsRangesChecked());
@@ -643,7 +669,7 @@
// Start recording
SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
- startRecording(/* useMediaRecorder */true, resultListener);
+ startRecording(/* useMediaRecorder */true, resultListener, useVideoStab);
// Record certain duration.
SystemClock.sleep(RECORDING_DURATION_MS);
@@ -698,7 +724,7 @@
// Start recording
SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
- startRecording(/* useMediaRecorder */true, resultListener);
+ startRecording(/* useMediaRecorder */true, resultListener, /*useVideoStab*/false);
// Record certain duration.
SystemClock.sleep(RECORDING_DURATION_MS);
@@ -920,7 +946,7 @@
CaptureRequest request = videoSnapshotRequestBuilder.build();
// Start recording
- startRecording(/* useMediaRecorder */true, resultListener);
+ startRecording(/* useMediaRecorder */true, resultListener, /*useVideoStab*/false);
long startTime = SystemClock.elapsedRealtime();
// Record certain duration.
@@ -1111,7 +1137,11 @@
}
private void startRecording(boolean useMediaRecorder,
- CameraCaptureSession.CaptureCallback listener) throws Exception {
+ CameraCaptureSession.CaptureCallback listener, boolean useVideoStab) throws Exception {
+ if (!mStaticInfo.isVideoStabilizationSupported() && useVideoStab) {
+ throw new IllegalArgumentException("Video stabilization is not supported");
+ }
+
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
assertTrue("Both preview and recording surfaces should be valid",
mPreviewSurface.isValid() && mRecordingSurface.isValid());
@@ -1129,6 +1159,10 @@
// Make sure camera output frame rate is set to correct value.
Range<Integer> fpsRange = Range.create(mVideoFrameRate, mVideoFrameRate);
recordingRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
+ if (useVideoStab) {
+ recordingRequestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
+ CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON);
+ }
recordingRequestBuilder.addTarget(mRecordingSurface);
recordingRequestBuilder.addTarget(mPreviewSurface);
mSession.setRepeatingRequest(recordingRequestBuilder.build(), listener, mHandler);
@@ -1142,7 +1176,7 @@
}
private void startRecording(boolean useMediaRecorder) throws Exception {
- startRecording(useMediaRecorder, null);
+ startRecording(useMediaRecorder, /*listener*/null, /*useVideoStab*/false);
}
private void stopCameraStreaming() throws Exception {
diff --git a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataCollectionTest.java b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataCollectionTest.java
index 145c2d1..4f4c5fe 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataCollectionTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataCollectionTest.java
@@ -17,13 +17,13 @@
package android.hardware.camera2.cts;
import android.content.pm.PackageManager;
-import android.cts.util.DeviceReportLog;
import android.hardware.camera2.cts.helpers.CameraMetadataGetter;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.util.Log;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -48,7 +48,7 @@
@Override
protected void tearDown() throws Exception {
// Deliver the report to host will automatically clear the report log.
- mReportLog.deliverReportToHost(getInstrumentation());
+ mReportLog.submit(getInstrumentation());
super.tearDown();
}
@@ -80,7 +80,7 @@
Log.e(TAG, "Unable to close camera info getter " + e.getMessage());
}
- mReportLog.printSummary("Camera data collection for static info and capture request"
+ mReportLog.setSummary("Camera data collection for static info and capture request"
+ " templates",
0.0, ResultType.NEUTRAL, ResultUnit.NONE);
}
@@ -88,11 +88,11 @@
}
private void dumpDoubleAsCtsResult(String name, double value) {
- mReportLog.printValue(name, value, ResultType.NEUTRAL, ResultUnit.NONE);
+ mReportLog.addValue(name, value, ResultType.NEUTRAL, ResultUnit.NONE);
}
public void dumpDoubleArrayAsCtsResult(String name, double[] values) {
- mReportLog.printArray(name, values, ResultType.NEUTRAL, ResultUnit.NONE);
+ mReportLog.addValues(name, values, ResultType.NEUTRAL, ResultUnit.NONE);
}
private double getJsonValueAsDouble(String name, Object obj) throws Exception {
diff --git a/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index e892e42..cb6b04c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -1626,6 +1626,13 @@
return modes;
}
+ public boolean isVideoStabilizationSupported() {
+ Integer[] videoStabModes =
+ CameraTestUtils.toObject(getAvailableVideoStabilizationModesChecked());
+ return Arrays.asList(videoStabModes).contains(
+ CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON);
+ }
+
/**
* Get availableOpticalStabilization and do the sanity check.
*
@@ -2195,6 +2202,25 @@
}
/**
+ * Check if optical black regions key is supported.
+ */
+ public boolean isOpticalBlackRegionSupported() {
+ return areKeysAvailable(CameraCharacteristics.SENSOR_OPTICAL_BLACK_REGIONS);
+ }
+
+ /**
+ * Check if the dynamic black level is supported.
+ *
+ * <p>
+ * Note that: This also indicates if the white level is supported, as dynamic black and white
+ * level must be all supported or none of them is supported.
+ * </p>
+ */
+ public boolean isDynamicBlackLevelSupported() {
+ return areKeysAvailable(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
+ }
+
+ /**
* Get the value in index for a fixed-size array from a given key.
*
* <p>If the camera device is incorrectly reporting values, log a warning and return
diff --git a/tests/camera/src/android/hardware/cts/CameraGLTest.java b/tests/camera/src/android/hardware/cts/CameraGLTest.java
index 8b0756e..cb83a36 100644
--- a/tests/camera/src/android/hardware/cts/CameraGLTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraGLTest.java
@@ -62,7 +62,7 @@
@LargeTest
public class CameraGLTest extends ActivityInstrumentationTestCase2<GLSurfaceViewCtsActivity> {
private static final String TAG = "CameraGLTest";
- private static final String PACKAGE = "com.android.cts.hardware";
+ private static final String PACKAGE = "android.hardware.cts";
private static final boolean LOGV = false;
private static final boolean LOGVV = false;
private static final int EGL_OPENGL_ES2_BIT = 0x0004;
diff --git a/tests/camera/src/android/hardware/cts/CameraTest.java b/tests/camera/src/android/hardware/cts/CameraTest.java
index 6869ed1..1ea4b0d 100644
--- a/tests/camera/src/android/hardware/cts/CameraTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraTest.java
@@ -67,7 +67,7 @@
@LargeTest
public class CameraTest extends ActivityInstrumentationTestCase2<CameraCtsActivity> {
private static final String TAG = "CameraTest";
- private static final String PACKAGE = "com.android.cts.hardware";
+ private static final String PACKAGE = "android.hardware.cts";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
private final String JPEG_PATH = Environment.getExternalStorageDirectory().getPath() +
"/test.jpg";
diff --git a/tests/deviceadmin/Android.mk b/tests/deviceadmin/Android.mk
deleted file mode 100644
index 2e89d34..0000000
--- a/tests/deviceadmin/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2011 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_JAVA_LIBRARIES := guava
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsDeviceAdmin
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/deviceadmin/AndroidManifest.xml b/tests/deviceadmin/AndroidManifest.xml
deleted file mode 100644
index f70a677..0000000
--- a/tests/deviceadmin/AndroidManifest.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2011 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.deviceadmin.cts">
- <application>
-
- <uses-library android:name="android.test.runner"/>
-
- <receiver android:name="android.deviceadmin.cts.CtsDeviceAdminReceiver"
- android:permission="android.permission.BIND_DEVICE_ADMIN">
- <meta-data android:name="android.app.device_admin"
- android:resource="@xml/device_admin" />
- <intent-filter>
- <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
- </intent-filter>
- </receiver>
-
- <receiver android:name="android.deviceadmin.cts.CtsDeviceAdminReceiver2"
- android:permission="android.permission.BIND_DEVICE_ADMIN">
- <meta-data android:name="android.app.device_admin"
- android:resource="@xml/device_admin_2" />
- <intent-filter>
- <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
- </intent-filter>
- </receiver>
-
- <!-- Device Admin that needs to be in the deactivated state in order
- for tests to pass. -->
- <receiver android:name="android.deviceadmin.cts.CtsDeviceAdminDeactivatedReceiver"
- android:permission="android.permission.BIND_DEVICE_ADMIN">
- <meta-data android:name="android.app.device_admin"
- android:resource="@xml/device_admin" />
- <intent-filter>
- <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
- </intent-filter>
- </receiver>
-
- <!-- Helper Activity used by Device Admin activation tests -->
- <activity android:name="android.deviceadmin.cts.CtsDeviceAdminActivationTestActivity"
- android:label="Device Admin activation test" />
-
- <!-- Broken device admin: meta-data missing -->
- <receiver android:name="android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver"
- android:permission="android.permission.BIND_DEVICE_ADMIN">
- <intent-filter>
- <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
- </intent-filter>
- </receiver>
-
- <!-- Broken device admin: filter doesn't match an Intent with action
- android.app.action.DEVICE_ADMIN_ENABLED and nothing else (e.g.,
- data) set -->
- <receiver android:name="android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver2"
- android:permission="android.permission.BIND_DEVICE_ADMIN">
- <meta-data android:name="android.app.device_admin"
- android:resource="@xml/device_admin" />
- <intent-filter>
- <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
- <data android:scheme="https" />
- </intent-filter>
- </receiver>
-
- <!-- Broken device admin: meta-data element doesn't point to valid
- Device Admin configuration/description -->
- <receiver android:name="android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver3"
- android:permission="android.permission.BIND_DEVICE_ADMIN">
- <meta-data android:name="android.app.device_admin"
- android:resource="@xml/broken_device_admin" />
- <intent-filter>
- <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
- </intent-filter>
- </receiver>
-
- <!-- Broken device admin: filter doesn't match Intents with action
- android.app.action.DEVICE_ADMIN_ENABLED -->
- <receiver android:name="android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver4"
- android:permission="android.permission.BIND_DEVICE_ADMIN">
- <meta-data android:name="android.app.device_admin"
- android:resource="@xml/device_admin" />
- <intent-filter>
- <action android:name="android.app.action.DEVICE_ADMIN_DISABLED" />
- </intent-filter>
- </receiver>
-
- <!-- Broken device admin: no intent-filter -->
- <receiver android:name="android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver5"
- android:permission="android.permission.BIND_DEVICE_ADMIN">
- <meta-data android:name="android.app.device_admin"
- android:resource="@xml/device_admin" />
- </receiver>
-
- </application>
-
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.admin"
- android:label="Tests for the device admin APIs."/>
-</manifest>
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminActivationTestActivity.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminActivationTestActivity.java
deleted file mode 100644
index 1779ec8..0000000
--- a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminActivationTestActivity.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2013 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.deviceadmin.cts;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.WindowManager;
-
-import com.google.common.annotations.VisibleForTesting;
-
-/**
- * Helper {@link Activity} for CTS tests of Device Admin activation. The {@code Activity}
- * enables tests to capture the invocations of its {@link #onActivityResult(int, int, Intent)} by
- * providing a {@link OnActivityResultListener}.
- */
-public class CtsDeviceAdminActivationTestActivity extends Activity {
- public interface OnActivityResultListener {
- void onActivityResult(int requestCode, int resultCode, Intent data);
- }
-
- private OnActivityResultListener mOnActivityResultListener;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Dismiss keyguard and keep screen on while this Activity is displayed.
- // This is needed because on older platforms, when the keyguard is on, onActivityResult is
- // not invoked when a Device Admin activation is rejected without user interaction.
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
- | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
-
- @VisibleForTesting
- public void setOnActivityResultListener(OnActivityResultListener listener) {
- mOnActivityResultListener = listener;
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (mOnActivityResultListener != null) {
- mOnActivityResultListener.onActivityResult(requestCode, resultCode, data);
- return;
- }
-
- super.onActivityResult(requestCode, resultCode, data);
- }
-}
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver.java
deleted file mode 100644
index f64c6b6..0000000
--- a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013 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.deviceadmin.cts;
-
-import android.app.admin.DeviceAdminReceiver;
-
-public class CtsDeviceAdminBrokenReceiver extends DeviceAdminReceiver {
-}
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver2.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver2.java
deleted file mode 100644
index 492a7cb..0000000
--- a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver2.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013 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.deviceadmin.cts;
-
-import android.app.admin.DeviceAdminReceiver;
-
-public class CtsDeviceAdminBrokenReceiver2 extends DeviceAdminReceiver {
-}
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver3.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver3.java
deleted file mode 100644
index 92bc878..0000000
--- a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver3.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013 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.deviceadmin.cts;
-
-import android.app.admin.DeviceAdminReceiver;
-
-public class CtsDeviceAdminBrokenReceiver3 extends DeviceAdminReceiver {
-}
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver4.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver4.java
deleted file mode 100644
index 53f15a7..0000000
--- a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver4.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013 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.deviceadmin.cts;
-
-import android.app.admin.DeviceAdminReceiver;
-
-public class CtsDeviceAdminBrokenReceiver4 extends DeviceAdminReceiver {
-}
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver5.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver5.java
deleted file mode 100644
index 2dc7100..0000000
--- a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminBrokenReceiver5.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013 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.deviceadmin.cts;
-
-import android.app.admin.DeviceAdminReceiver;
-
-public class CtsDeviceAdminBrokenReceiver5 extends DeviceAdminReceiver {
-}
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminDeactivatedReceiver.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminDeactivatedReceiver.java
deleted file mode 100644
index ec59f63..0000000
--- a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminDeactivatedReceiver.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013 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.deviceadmin.cts;
-
-import android.app.admin.DeviceAdminReceiver;
-
-public class CtsDeviceAdminDeactivatedReceiver extends DeviceAdminReceiver {
-}
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminReceiver.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminReceiver.java
deleted file mode 100644
index 43485d7..0000000
--- a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminReceiver.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 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.deviceadmin.cts;
-
-import android.app.admin.DeviceAdminReceiver;
-
-public class CtsDeviceAdminReceiver extends DeviceAdminReceiver {
-}
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminReceiver2.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminReceiver2.java
deleted file mode 100644
index eadf31b..0000000
--- a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminReceiver2.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 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.deviceadmin.cts;
-
-import android.app.admin.DeviceAdminReceiver;
-
-public class CtsDeviceAdminReceiver2 extends DeviceAdminReceiver {
-}
diff --git a/tests/dram/Android.mk b/tests/dram/Android.mk
new file mode 100644
index 0000000..e7cd0bb
--- /dev/null
+++ b/tests/dram/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner
+
+LOCAL_JNI_SHARED_LIBRARIES := libctsdram_jni
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsDramTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/dram/AndroidManifest.xml b/tests/dram/AndroidManifest.xml
new file mode 100644
index 0000000..d43fe79
--- /dev/null
+++ b/tests/dram/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.dram.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.dram.cts"
+ android:label="DRAM bandwidth measurement" />
+</manifest>
diff --git a/tests/dram/AndroidTest.xml b/tests/dram/AndroidTest.xml
new file mode 100644
index 0000000..019c15d
--- /dev/null
+++ b/tests/dram/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Dram test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsDramTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.dram.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/suite/cts/deviceTests/dram/jni/Android.mk b/tests/dram/jni/Android.mk
similarity index 100%
rename from suite/cts/deviceTests/dram/jni/Android.mk
rename to tests/dram/jni/Android.mk
diff --git a/tests/dram/jni/MemoryNativeJni.cpp b/tests/dram/jni/MemoryNativeJni.cpp
new file mode 100644
index 0000000..cbf145c
--- /dev/null
+++ b/tests/dram/jni/MemoryNativeJni.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <jni.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+double currentTimeMillis()
+{
+ struct timeval tv;
+ gettimeofday(&tv, (struct timezone *) NULL);
+ return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
+}
+
+extern "C" JNIEXPORT jdouble JNICALL Java_android_dram_cts_MemoryNative_runMemcpy(JNIEnv* env,
+ jclass clazz, jint bufferSize, jint repetition)
+{
+ char* src = new char[bufferSize];
+ char* dst = new char[bufferSize];
+ if ((src == NULL) || (dst == NULL)) {
+ delete[] src;
+ delete[] dst;
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "No memory");
+ return -1;
+ }
+ memset(src, 0, bufferSize);
+ memset(dst, 0, bufferSize);
+ double start = currentTimeMillis();
+ for (int i = 0; i < repetition; i++) {
+ memcpy(dst, src, bufferSize);
+ src[bufferSize - 1] = i & 0xff;
+ }
+ double end = currentTimeMillis();
+ delete[] src;
+ delete[] dst;
+ return end - start;
+}
+
+extern "C" JNIEXPORT jdouble JNICALL Java_android_dram_cts_MemoryNative_runMemset(JNIEnv* env,
+ jclass clazz, jint bufferSize, jint repetition, jint c)
+{
+ char* dst = new char[bufferSize];
+ if (dst == NULL) {
+ delete[] dst;
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "No memory");
+ return -1;
+ }
+ memset(dst, 0, bufferSize);
+ double start = currentTimeMillis();
+ for (int i = 0; i < repetition; i++) {
+ memset(dst, (c + i) & 0xff, bufferSize);
+ }
+ double end = currentTimeMillis();
+ delete[] dst;
+ return end - start;
+}
+
diff --git a/tests/dram/src/android/dram/cts/BandwidthTest.java b/tests/dram/src/android/dram/cts/BandwidthTest.java
new file mode 100644
index 0000000..2096402
--- /dev/null
+++ b/tests/dram/src/android/dram/cts/BandwidthTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2012 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.dram.cts;
+
+import android.content.Context;
+import android.cts.util.CtsAndroidTestCase;
+import android.graphics.Point;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+
+/**
+ * check how many screens the memcpy function can copy in a sec.
+ * Note that this does not represent the total memory bandwidth available in the system
+ * as typically CPU cannot use the whole bandwidth.
+ * Smaller buffers can fit into L1 or L2 cache, which can show big boost.
+ */
+public class BandwidthTest extends CtsAndroidTestCase {
+ private static final String TAG = BandwidthTest.class.getSimpleName();
+ private static final int MEMCPY_REPETITION = 10;
+ private static final int MEMSET_REPETITION = 30;
+ private static final int REPEAT_IN_EACH_CALL = 100;
+ private static final int KB = 1024;
+ private static final int MB = 1024 * 1024;
+ private static final int MEMSET_CHAR = 0xa5;
+ // reject data outside +/- this value * median
+ private static final double OUTLIER_THRESHOLD = 0.1;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // warm-up
+ MemoryNative.runMemcpy(2 * MB, 100);
+ }
+
+ public void testMemcpyK004() {
+ doRunMemcpy(4 * KB);
+ }
+
+ public void testMemcpyK008() {
+ doRunMemcpy(8 * KB);
+ }
+
+ public void testMemcpyK016() {
+ doRunMemcpy(16 * KB);
+ }
+
+ public void testMemcpyK032() {
+ doRunMemcpy(32 * KB);
+ }
+
+ public void testMemcpyK064() {
+ doRunMemcpy(64 * KB);
+ }
+
+ public void testMemcpyK128() {
+ doRunMemcpy(128 * KB);
+ }
+
+ public void testMemcpyK256() {
+ doRunMemcpy(256 * KB);
+ }
+
+ public void testMemcpyK512() {
+ doRunMemcpy(512 * KB);
+ }
+
+ public void testMemcpyM001() {
+ doRunMemcpy(1 * MB);
+ }
+
+ public void testMemcpyM002() {
+ doRunMemcpy(2 * MB);
+ }
+
+ public void testMemcpyM004() {
+ doRunMemcpy(4 * MB);
+ }
+
+ public void testMemcpyM008() {
+ doRunMemcpy(8 * MB);
+ }
+
+ public void testMemcpyM016() {
+ doRunMemcpy(16 * MB);
+ }
+
+ public void testMemsetK004() {
+ doRunMemset(4 * KB);
+ }
+
+ public void testMemsetK008() {
+ doRunMemset(8 * KB);
+ }
+
+ public void testMemsetK016() {
+ doRunMemset(16 * KB);
+ }
+
+ public void testMemsetK032() {
+ doRunMemset(32 * KB);
+ }
+
+ public void testMemsetK064() {
+ doRunMemset(64 * KB);
+ }
+
+ public void testMemsetK128() {
+ doRunMemset(128 * KB);
+ }
+
+ public void testMemsetK256() {
+ doRunMemset(256 * KB);
+ }
+
+ public void testMemsetK512() {
+ doRunMemset(512 * KB);
+ }
+
+ public void testMemsetM001() {
+ doRunMemset(1 * MB);
+ }
+
+ public void testMemsetM002() {
+ doRunMemset(2 * MB);
+ }
+
+ public void testMemsetM004() {
+ doRunMemset(4 * MB);
+ }
+
+ public void testMemsetM008() {
+ doRunMemset(8 * MB);
+ }
+
+ public void testMemsetM016() {
+ doRunMemset(16 * MB);
+ }
+
+ private void doRunMemcpy(int bufferSize) {
+ double[] result = new double[MEMCPY_REPETITION];
+ int repeatInEachCall = REPEAT_IN_EACH_CALL;
+ if (bufferSize < (1 * MB)) {
+ // too small buffer size finishes too early to give accurate result.
+ repeatInEachCall *= (1 * MB / bufferSize);
+ }
+ for (int i = 0; i < MEMCPY_REPETITION; i++) {
+ result[i] = MemoryNative.runMemcpy(bufferSize, repeatInEachCall);
+ }
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValues("memcpy time", result, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ double[] mbps = Stat.calcRatePerSecArray(
+ (double)bufferSize * repeatInEachCall / 1024.0 / 1024.0, result);
+ report.addValues("memcpy throughput", mbps, ResultType.HIGHER_BETTER,
+ ResultUnit.MBPS);
+ Stat.StatResult stat = Stat.getStatWithOutlierRejection(mbps, OUTLIER_THRESHOLD);
+ if (stat.mDataCount != result.length) {
+ Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
+ }
+ WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+ Point size = new Point();
+ wm.getDefaultDisplay().getSize(size);
+ Log.i(TAG, " x " + size.x + " y " + size.y);
+ double pixels = size.x * size.y;
+ // now this represents how many times the whole screen can be copied in a sec.
+ double screensPerSecAverage = stat.mAverage / pixels * 1024.0 * 1024.0 / 4.0;
+ report.addValue("memcpy in fps", screensPerSecAverage,
+ ResultType.HIGHER_BETTER, ResultUnit.FPS);
+ report.setSummary("memcpy throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ ResultUnit.MBPS);
+ report.submit(getInstrumentation());
+ }
+
+ private void doRunMemset(int bufferSize) {
+ double[] result = new double[MEMSET_REPETITION];
+ int repeatInEachCall = REPEAT_IN_EACH_CALL;
+ if (bufferSize < (1 * MB)) {
+ // too small buffer size finishes too early to give accurate result.
+ repeatInEachCall *= (1 * MB / bufferSize);
+ }
+ for (int i = 0; i < MEMSET_REPETITION; i++) {
+ result[i] = MemoryNative.runMemset(bufferSize, repeatInEachCall, MEMSET_CHAR);
+ }
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValues("memset time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
+ double[] mbps = Stat.calcRatePerSecArray(
+ (double)bufferSize * repeatInEachCall / 1024.0 / 1024.0, result);
+ report.addValues("memset throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ Stat.StatResult stat = Stat.getStatWithOutlierRejection(mbps, OUTLIER_THRESHOLD);
+ if (stat.mDataCount != result.length) {
+ Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
+ }
+ WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+ Point size = new Point();
+ wm.getDefaultDisplay().getSize(size);
+ Log.i(TAG, " x " + size.x + " y " + size.y);
+ double pixels = size.x * size.y;
+ // now this represents how many times the whole screen can be copied in a sec.
+ double screensPerSecAverage = stat.mAverage / pixels * 1024.0 * 1024.0 / 4.0;
+ report.addValue("memset in fps", screensPerSecAverage,
+ ResultType.HIGHER_BETTER, ResultUnit.FPS);
+ report.setSummary("memset throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ ResultUnit.MBPS);
+ report.submit(getInstrumentation());
+ }
+}
diff --git a/tests/dram/src/android/dram/cts/MemoryNative.java b/tests/dram/src/android/dram/cts/MemoryNative.java
new file mode 100644
index 0000000..7fa4c46
--- /dev/null
+++ b/tests/dram/src/android/dram/cts/MemoryNative.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 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.dram.cts;
+
+public class MemoryNative {
+ static {
+ System.loadLibrary("ctsdram_jni");
+ }
+ /**
+ * run memcpy for given number of repetition from a source to a destination buffers
+ * with each having the size of bufferSize.
+ * @param bufferSize
+ * @param repetition
+ * @return time spent in copying in ms.
+ */
+ public static native double runMemcpy(int bufferSize, int repetition);
+
+ /**
+ * run memset for given number of repetition from a source to a destination buffers
+ * with each having the size of bufferSize.
+ * @param bufferSize
+ * @param repetition
+ * @param c char to set. Only LSBs will be used to get char value.
+ * @return time spent in memset in ms.
+ */
+ public static native double runMemset(int bufferSize, int repetition, int c);
+}
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index acab74e..8e8981b 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -237,14 +237,6 @@
bug: 17989532
},
{
- description: "The new long processing test is not yet passing on all devices",
- names: [
- "android.hardware.camera2.cts.ImageReaderTest#testLongProcessingRepeatingRaw",
- "android.hardware.camera2.cts.ImageReaderTest#testLongProcessingRepeatingFlexibleYuv"
- ],
- bug: 22861512
-},
-{
description: "The timing measurements for preview callbacks are not reliable",
names: [
"android.hardware.cts.CameraTest#testPreviewFpsRange"
@@ -254,7 +246,7 @@
{
description: "Light status bar CTS coming in late",
names: [
- "com.android.cts.systemui.LightStatusBarTests#testLightStatusBarIcons"
+ "android.systemui.cts.LightStatusBarTests#testLightStatusBarIcons"
],
bug: 23427621
},
@@ -359,10 +351,17 @@
bug: 25652250
},
{
- description: "Wired headset tests are no longer a requirement per CDD",
+ description: "unit testing for MediaPreparer lives within mediastress module",
names: [
- "android.telecom.cts.WiredHeadsetTest"
+ "android.mediastress.cts.preconditions.MediaPreparerTest"
],
- bug: 26149528
+ bug: 25850508
+},
+{
+ description: "Tests for the signature tests should not be in CTS",
+ names: [
+ "android.signature.cts.tests"
+ ],
+ bug: 26150806
}
]
diff --git a/tests/filesystem/Android.mk b/tests/filesystem/Android.mk
new file mode 100644
index 0000000..00e5ee7
--- /dev/null
+++ b/tests/filesystem/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsFileSystemTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/tests/filesystem/AndroidManifest.xml b/tests/filesystem/AndroidManifest.xml
new file mode 100644
index 0000000..c02ac77
--- /dev/null
+++ b/tests/filesystem/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.filesystem.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.filesystem.cts"
+ android:label="CTS tests for file system" />
+</manifest>
diff --git a/tests/filesystem/AndroidTest.xml b/tests/filesystem/AndroidTest.xml
new file mode 100644
index 0000000..1962357
--- /dev/null
+++ b/tests/filesystem/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS File System test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsFileSystemTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.filesystem.cts" />
+ <option name="runtime-hint" value="9m" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/filesystem/src/android/filesystem/cts/AlmostFullTest.java b/tests/filesystem/src/android/filesystem/cts/AlmostFullTest.java
new file mode 100644
index 0000000..991f9bf
--- /dev/null
+++ b/tests/filesystem/src/android/filesystem/cts/AlmostFullTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2012 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.filesystem.cts;
+
+import android.util.Log;
+
+import android.cts.util.CtsAndroidTestCase;
+import android.cts.util.SystemUtil;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.cts.util.TimeoutReq;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AlmostFullTest extends CtsAndroidTestCase {
+
+ private static final String DIR_INITIAL_FILL = "INITIAL_FILL";
+ private static final String DIR_SEQ_UPDATE = "SEQ_UPDATE";
+ private static final String DIR_RANDOM_WR = "RANDOM_WR";
+ private static final String DIR_RANDOM_RD = "RANDOM_RD";
+ private static final String TAG = "AlmostFullTest";
+
+ private static final long FREE_SPACE_FINAL = 1000L * 1024 * 1024L;
+
+ // test runner creates multiple instances at the begging.
+ // use that to fill disk only once.
+ // set as final to initialize it only once
+ private static final AtomicInteger mRefCounter = new AtomicInteger(0);
+ private static final AtomicBoolean mDiskFilled = new AtomicBoolean(false);
+
+ public AlmostFullTest() {
+ int currentCounter = mRefCounter.incrementAndGet();
+ Log.i(TAG, "++currentCounter: " + currentCounter);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (mDiskFilled.compareAndSet(false, true)) {
+ Log.i(TAG, "Filling disk");
+ // initial fill done in two stage as disk can be filled by other
+ // components
+ long freeDisk = SystemUtil.getFreeDiskSize(getContext());
+ long diskToFill = freeDisk - FREE_SPACE_FINAL;
+ if (diskToFill >= 0) {
+ Log.i(TAG, "free disk " + freeDisk + ", to fill " + diskToFill);
+ } else {
+ Log.i(TAG, "free disk " + freeDisk + " too small, needs " + FREE_SPACE_FINAL);
+ return;
+ }
+ final long MAX_FILE_SIZE_TO_FILL = 1024L * 1024L * 1024L;
+ long filled = 0;
+ while (filled < diskToFill) {
+ long toFill = diskToFill - filled;
+ if (toFill > MAX_FILE_SIZE_TO_FILL) {
+ toFill = MAX_FILE_SIZE_TO_FILL;
+ }
+ Log.i(TAG, "Generating file " + toFill);
+ FileUtil.createNewFilledFile(getContext(),
+ DIR_INITIAL_FILL, toFill);
+ filled += toFill;
+ }
+ }
+ Log.i(TAG, "free disk " + SystemUtil.getFreeDiskSize(getContext()));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ Log.i(TAG, "tearDown free disk " + SystemUtil.getFreeDiskSize(getContext()));
+ int currentCounter = mRefCounter.decrementAndGet();
+ Log.i(TAG, "--currentCounter: " + currentCounter);
+ if (currentCounter == 0) {
+ FileUtil.removeFileOrDir(getContext(), DIR_INITIAL_FILL);
+ }
+ FileUtil.removeFileOrDir(getContext(), DIR_SEQ_UPDATE);
+ FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_WR);
+ FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_RD);
+ Log.i(TAG, "tearDown free disk " + SystemUtil.getFreeDiskSize(getContext()));
+ super.tearDown();
+ }
+
+ @TimeoutReq(minutes = 30)
+ public void testSequentialUpdate() throws Exception {
+ // now about freeSpaceToLeave should be left
+ // and try updating exceeding the free space size
+ final long FILE_SIZE = 400L * 1024L * 1024L;
+ long freeDisk = SystemUtil.getFreeDiskSize(getContext());
+ Log.i(TAG, "Now free space is " + freeDisk);
+ if (freeDisk < FILE_SIZE) {
+ Log.w(TAG, "too little space: " + freeDisk);
+ return;
+ }
+ final int BUFFER_SIZE = 10 * 1024 * 1024;
+ final int NUMBER_REPETITION = 10;
+ DeviceReportLog report = new DeviceReportLog();
+ FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, report, FILE_SIZE,
+ BUFFER_SIZE, NUMBER_REPETITION);
+ report.submit(getInstrumentation());
+ }
+
+ // TODO: file size too small and caching will give wrong better result.
+ // needs to flush cache by reading big files per each read.
+ @TimeoutReq(minutes = 60)
+ public void testRandomRead() throws Exception {
+ final int BUFFER_SIZE = 4 * 1024;
+ final long fileSize = 400L * 1024L * 1024L;
+ long freeDisk = SystemUtil.getFreeDiskSize(getContext());
+ if (freeDisk < fileSize) {
+ Log.w(TAG, "too little space: " + freeDisk);
+ return;
+ }
+ DeviceReportLog report = new DeviceReportLog();
+ FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, report, fileSize, BUFFER_SIZE);
+ report.submit(getInstrumentation());
+ }
+
+ @TimeoutReq(minutes = 60)
+ public void testRandomUpdate() throws Exception {
+ final int BUFFER_SIZE = 4 * 1024;
+ final long fileSize = 256L * 1024L * 1024L;
+ long freeDisk = SystemUtil.getFreeDiskSize(getContext());
+ if (freeDisk < fileSize) {
+ Log.w(TAG, "too little space: " + freeDisk);
+ return;
+ }
+ DeviceReportLog report = new DeviceReportLog();
+ FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, report, fileSize, BUFFER_SIZE);
+ report.submit(getInstrumentation());
+ }
+}
diff --git a/tests/filesystem/src/android/filesystem/cts/FileUtil.java b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
new file mode 100755
index 0000000..baefaa0
--- /dev/null
+++ b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2012 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.filesystem.cts;
+
+import android.content.Context;
+import android.cts.util.SystemUtil;
+import android.util.Log;
+
+import com.android.compatibility.common.util.MeasureRun;
+import com.android.compatibility.common.util.MeasureTime;
+import com.android.compatibility.common.util.ReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.RandomAccessFile;
+import java.util.Random;
+
+public class FileUtil {
+ private static final String TAG = "FileUtil";
+ private static final Random mRandom = new Random(0);
+ private static long mFileId = 0;
+ /**
+ * create array with different data per each call
+ *
+ * @param length
+ * @param randomSeed
+ * @return
+ */
+ public static byte[] generateRandomData(int length) {
+ byte[] buffer = new byte[length];
+ int val = mRandom.nextInt();
+ for (int i = 0; i < length / 4; i++) {
+ // in little-endian
+ buffer[i * 4] = (byte)(val & 0x000000ff);
+ buffer[i * 4 + 1] = (byte)((val & 0x0000ff00) >> 8);
+ buffer[i * 4 + 2] = (byte)((val & 0x00ff0000) >> 16);
+ buffer[i * 4 + 3] = (byte)((val & 0xff000000) >> 24);
+ val++;
+ }
+ for (int i = (length / 4) * 4; i < length; i++) {
+ buffer[i] = 0;
+ }
+ return buffer;
+ }
+
+ /**
+ * create a new file under the given dirName.
+ * Existing files will not be affected.
+ * @param context
+ * @param dirName
+ * @return
+ */
+ public static File createNewFile(Context context, String dirName) {
+ File topDir = new File(context.getFilesDir(), dirName);
+ topDir.mkdir();
+ String[] list = topDir.list();
+
+ String newFileName;
+ while (true) {
+ newFileName = Long.toString(mFileId);
+ boolean fileExist = false;
+ for (String child : list) {
+ if (child.equals(newFileName)) {
+ fileExist = true;
+ break;
+ }
+ }
+ if (!fileExist) {
+ break;
+ }
+ mFileId++;
+ }
+ mFileId++;
+ //Log.i(TAG, "filename" + Long.toString(mFileId));
+ return new File(topDir, newFileName);
+ }
+
+ /**
+ * create multiple new files
+ * @param context
+ * @param dirName
+ * @param count number of files to create
+ * @return
+ */
+ public static File[] createNewFiles(Context context, String dirName, int count) {
+ File[] files = new File[count];
+ for (int i = 0; i < count; i++) {
+ files[i] = createNewFile(context, dirName);
+ }
+ return files;
+ }
+
+ /**
+ * write file with given byte array
+ * @param file
+ * @param data
+ * @param append will append if set true. Otherwise, write from beginning
+ * @throws IOException
+ */
+ public static void writeFile(File file, byte[] data, boolean append) throws IOException {
+ final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
+ if (append) {
+ randomFile.seek(randomFile.length());
+ } else {
+ randomFile.seek(0L);
+ }
+ randomFile.write(data);
+ randomFile.close();
+ }
+
+ /**
+ * create a new file with given length.
+ * @param context
+ * @param dirName
+ * @param length
+ * @return
+ * @throws IOException
+ */
+ public static File createNewFilledFile(Context context, String dirName, long length)
+ throws IOException {
+ final int BUFFER_SIZE = 10 * 1024 * 1024;
+ File file = createNewFile(context, dirName);
+ FileOutputStream out = new FileOutputStream(file);
+ byte[] data = generateRandomData(BUFFER_SIZE);
+ long written = 0;
+ while (written < length) {
+ out.write(data);
+ written += BUFFER_SIZE;
+ }
+ out.flush();
+ out.close();
+ return file;
+ }
+
+ /**
+ * remove given file or directory under the current app's files dir.
+ * @param context
+ * @param name
+ */
+ public static void removeFileOrDir(Context context, String name) {
+ File entry = new File(context.getFilesDir(), name);
+ if (entry.exists()) {
+ removeEntry(entry);
+ }
+ }
+
+ private static void removeEntry(File entry) {
+ if (entry.isDirectory()) {
+ String[] children = entry.list();
+ for (String child : children) {
+ removeEntry(new File(entry, child));
+ }
+ }
+ Log.i(TAG, "delete file " + entry.getAbsolutePath());
+ entry.delete();
+ }
+
+ /**
+ * measure time taken for each IO run with amount R/W
+ * @param count
+ * @param run
+ * @param readAmount returns amount of read in bytes for each interval.
+ * Value will not be written if /proc/self/io does not exist.
+ * @param writeAmount returns amount of write in bytes for each interval.
+ * @return time per each interval
+ * @throws IOException
+ */
+ public static double[] measureIO(int count, double[] readAmount, double[] writeAmount,
+ MeasureRun run) throws Exception {
+ double[] result = new double[count];
+ File procIo = new File("/proc/self/io");
+ boolean measureIo = procIo.exists() && procIo.canRead();
+ long prev = System.currentTimeMillis();
+ RWAmount prevAmount = new RWAmount();
+ if (measureIo) {
+ prevAmount = getRWAmount(procIo);
+ }
+ for (int i = 0; i < count; i++) {
+ run.run(i);
+ long current = System.currentTimeMillis();
+ result[i] = current - prev;
+ prev = current;
+ if (measureIo) {
+ RWAmount currentAmount = getRWAmount(procIo);
+ readAmount[i] = currentAmount.mRd - prevAmount.mRd;
+ writeAmount[i] = currentAmount.mWr - prevAmount.mWr;
+ prevAmount = currentAmount;
+ }
+ }
+ return result;
+ }
+
+ private static class RWAmount {
+ public double mRd = 0.0;
+ public double mWr = 0.0;
+ };
+
+ private static RWAmount getRWAmount(File file) throws IOException {
+ RWAmount amount = new RWAmount();
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
+ String line;
+ while((line = br.readLine())!= null) {
+ if (line.startsWith("read_bytes")) {
+ amount.mRd = Double.parseDouble(line.split(" ")[1]);
+ } else if (line.startsWith("write_bytes")) {
+ amount.mWr = Double.parseDouble(line.split(" ")[1]);
+ }
+ }
+ br.close();
+ return amount;
+ }
+
+ /**
+ * get file size exceeding total memory size ( 2x total memory).
+ * The size is rounded in bufferSize. And the size will be bigger than 400MB.
+ * @param context
+ * @param bufferSize
+ * @return file size or 0 if there is not enough space.
+ */
+ public static long getFileSizeExceedingMemory(Context context, int bufferSize) {
+ long freeDisk = SystemUtil.getFreeDiskSize(context);
+ long memSize = SystemUtil.getTotalMemory(context);
+ long diskSizeTarget = (2 * memSize / bufferSize) * bufferSize;
+ final long minimumDiskSize = (512L * 1024L * 1024L / bufferSize) * bufferSize;
+ final long reservedDiskSize = (50L * 1024L * 1024L / bufferSize) * bufferSize;
+ if ( diskSizeTarget < minimumDiskSize ) {
+ diskSizeTarget = minimumDiskSize;
+ }
+ if (diskSizeTarget > freeDisk) {
+ Log.i(TAG, "Free disk size " + freeDisk + " too small");
+ return 0;
+ }
+ if ((freeDisk - diskSizeTarget) < reservedDiskSize) {
+ diskSizeTarget -= reservedDiskSize;
+ }
+ return diskSizeTarget;
+ }
+
+ /**
+ *
+ * @param context
+ * @param dirName
+ * @param report
+ * @param fileSize
+ * @param bufferSize should be power of two
+ * @throws IOException
+ */
+ public static void doRandomReadTest(Context context, String dirName, ReportLog report,
+ long fileSize, int bufferSize) throws Exception {
+ File file = FileUtil.createNewFilledFile(context,
+ dirName, fileSize);
+
+ final byte[] data = FileUtil.generateRandomData(bufferSize);
+ Random random = new Random(0);
+ final int totalReadCount = (int)(fileSize / bufferSize);
+ final int[] readOffsets = new int[totalReadCount];
+ for (int i = 0; i < totalReadCount; i++) {
+ // align in buffer size
+ readOffsets[i] = (int)(random.nextFloat() * (fileSize - bufferSize)) &
+ ~(bufferSize - 1);
+ }
+ final int runsInOneGo = 16;
+ final int readsInOneMeasure = totalReadCount / runsInOneGo;
+
+ final RandomAccessFile randomFile = new RandomAccessFile(file, "rw"); // do not need O_SYNC
+ double[] rdAmount = new double[runsInOneGo];
+ double[] wrAmount = new double[runsInOneGo];
+ double[] times = FileUtil.measureIO(runsInOneGo, rdAmount, wrAmount, new MeasureRun() {
+
+ @Override
+ public void run(int i) throws IOException {
+ Log.i(TAG, "starting " + i + " -th round");
+ int start = i * readsInOneMeasure;
+ int end = (i + 1) * readsInOneMeasure;
+ for (int j = start; j < end; j++) {
+ randomFile.seek(readOffsets[j]);
+ randomFile.read(data);
+ }
+ }
+ });
+ randomFile.close();
+ double[] mbps = Stat.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
+ times);
+ report.addValues("read throughput",
+ mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ // This is just the amount of IO returned from kernel. So this is performance neutral.
+ report.addValues("read amount", rdAmount, ResultType.NEUTRAL, ResultUnit.BYTE);
+ Stat.StatResult stat = Stat.getStat(mbps);
+
+ report.setSummary("read throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ ResultUnit.MBPS);
+ }
+
+ /**
+ *
+ * @param context
+ * @param dirName
+ * @param report
+ * @param fileSize
+ * @param bufferSize should be power of two
+ * @throws IOException
+ */
+ public static void doRandomWriteTest(Context context, String dirName, ReportLog report,
+ long fileSize, int bufferSize) throws Exception {
+ File file = FileUtil.createNewFilledFile(context,
+ dirName, fileSize);
+ final byte[] data = FileUtil.generateRandomData(bufferSize);
+ Random random = new Random(0);
+ final int totalWriteCount = (int)(fileSize / bufferSize);
+ final int[] writeOffsets = new int[totalWriteCount];
+ for (int i = 0; i < totalWriteCount; i++) {
+ writeOffsets[i] = (int)(random.nextFloat() * (fileSize - bufferSize)) &
+ ~(bufferSize - 1);
+ }
+ final int runsInOneGo = 16;
+ final int writesInOneMeasure = totalWriteCount / runsInOneGo;
+
+ final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
+ double[] rdAmount = new double[runsInOneGo];
+ double[] wrAmount = new double[runsInOneGo];
+ double[] times = FileUtil.measureIO(runsInOneGo, rdAmount, wrAmount, new MeasureRun() {
+
+ @Override
+ public void run(int i) throws IOException {
+ Log.i(TAG, "starting " + i + " -th round");
+ int start = i * writesInOneMeasure;
+ int end = (i + 1) * writesInOneMeasure;
+ for (int j = start; j < end; j++) {
+ randomFile.seek(writeOffsets[j]);
+ randomFile.write(data);
+ }
+ }
+ });
+ randomFile.close();
+ double[] mbps = Stat.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
+ times);
+ report.addValues("write throughput",
+ mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ report.addValues("write amount", wrAmount, ResultType.NEUTRAL,
+ ResultUnit.BYTE);
+ Stat.StatResult stat = Stat.getStat(mbps);
+
+ report.setSummary("write throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ ResultUnit.MBPS);
+ }
+
+ /**
+ *
+ * @param context
+ * @param dirName
+ * @param report
+ * @param fileSize fileSize should be multiple of bufferSize.
+ * @param bufferSize
+ * @param numberRepetition
+ * @throws IOException
+ */
+ public static void doSequentialUpdateTest(Context context, String dirName, ReportLog report,
+ long fileSize, int bufferSize, int numberRepetition) throws Exception {
+ File file = FileUtil.createNewFilledFile(context,
+ dirName, fileSize);
+ final byte[] data = FileUtil.generateRandomData(bufferSize);
+ int numberRepeatInOneRun = (int)(fileSize / bufferSize);
+ double[] mbpsAll = new double[numberRepetition * numberRepeatInOneRun];
+ for (int i = 0; i < numberRepetition; i++) {
+ Log.i(TAG, "starting " + i + " -th round");
+ final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
+ randomFile.seek(0L);
+ double[] times = MeasureTime.measure(numberRepeatInOneRun, new MeasureRun() {
+
+ @Override
+ public void run(int i) throws IOException {
+ randomFile.write(data);
+ }
+ });
+ randomFile.close();
+ double[] mbps = Stat.calcRatePerSecArray((double)bufferSize / 1024 / 1024,
+ times);
+ report.addValues(i + "-th round throughput",
+ mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ int offset = i * numberRepeatInOneRun;
+ for (int j = 0; j < mbps.length; j++) {
+ mbpsAll[offset + j] = mbps[j];
+ }
+ }
+ Stat.StatResult stat = Stat.getStat(mbpsAll);
+ report.setSummary("update throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ ResultUnit.MBPS);
+ }
+}
diff --git a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
new file mode 100644
index 0000000..dff3723
--- /dev/null
+++ b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 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.filesystem.cts;
+
+import android.cts.util.CtsAndroidTestCase;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.cts.util.TimeoutReq;
+
+public class RandomRWTest extends CtsAndroidTestCase {
+ private static final String DIR_RANDOM_WR = "RANDOM_WR";
+ private static final String DIR_RANDOM_RD = "RANDOM_RD";
+
+ @Override
+ protected void tearDown() throws Exception {
+ FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_WR);
+ FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_RD);
+ super.tearDown();
+ }
+
+ @TimeoutReq(minutes = 60)
+ public void testRandomRead() throws Exception {
+ final int READ_BUFFER_SIZE = 4 * 1024;
+ final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), READ_BUFFER_SIZE);
+ if (fileSize == 0) { // not enough space, give up
+ return;
+ }
+ DeviceReportLog report = new DeviceReportLog();
+ FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, report, fileSize,
+ READ_BUFFER_SIZE);
+ report.submit(getInstrumentation());
+ }
+
+ // It is taking too long in some device, and thus cannot run multiple times
+ @TimeoutReq(minutes = 60)
+ public void testRandomUpdate() throws Exception {
+ final int WRITE_BUFFER_SIZE = 4 * 1024;
+ final long fileSize = 256 * 1024 * 1024;
+ DeviceReportLog report = new DeviceReportLog();
+ FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, report, fileSize,
+ WRITE_BUFFER_SIZE);
+ report.submit(getInstrumentation());
+ }
+}
diff --git a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
new file mode 100644
index 0000000..3b7a45f
--- /dev/null
+++ b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 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.filesystem.cts;
+
+import android.cts.util.CtsAndroidTestCase;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.MeasureRun;
+import com.android.compatibility.common.util.MeasureTime;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+import com.android.cts.util.TimeoutReq;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class SequentialRWTest extends CtsAndroidTestCase {
+ private static final String DIR_SEQ_WR = "SEQ_WR";
+ private static final String DIR_SEQ_UPDATE = "SEQ_UPDATE";
+ private static final String DIR_SEQ_RD = "SEQ_RD";
+ private static final int BUFFER_SIZE = 10 * 1024 * 1024;
+
+ @Override
+ protected void tearDown() throws Exception {
+ FileUtil.removeFileOrDir(getContext(), DIR_SEQ_WR);
+ FileUtil.removeFileOrDir(getContext(), DIR_SEQ_UPDATE);
+ FileUtil.removeFileOrDir(getContext(), DIR_SEQ_RD);
+ super.tearDown();
+ }
+
+ @TimeoutReq(minutes = 30)
+ public void testSingleSequentialWrite() throws Exception {
+ final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
+ if (fileSize == 0) { // not enough space, give up
+ return;
+ }
+ final int numberOfFiles =(int)(fileSize / BUFFER_SIZE);
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValue("files", numberOfFiles, ResultType.NEUTRAL, ResultUnit.COUNT);
+ final byte[] data = FileUtil.generateRandomData(BUFFER_SIZE);
+ final File[] files = FileUtil.createNewFiles(getContext(), DIR_SEQ_WR,
+ numberOfFiles);
+ double[] rdAmount = new double[numberOfFiles];
+ double[] wrAmount = new double[numberOfFiles];
+ double[] times = FileUtil.measureIO(numberOfFiles, rdAmount, wrAmount, new MeasureRun() {
+
+ @Override
+ public void run(int i) throws IOException {
+ FileUtil.writeFile(files[i], data, false);
+ }
+ });
+ double[] mbps = Stat.calcRatePerSecArray((double)BUFFER_SIZE / 1024 / 1024, times);
+ report.addValues("write throughput",
+ mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ report.addValues("write amount", wrAmount, ResultType.NEUTRAL,
+ ResultUnit.BYTE);
+ Stat.StatResult stat = Stat.getStat(mbps);
+ report.setSummary("write throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ ResultUnit.MBPS);
+ report.submit(getInstrumentation());
+ }
+
+ @TimeoutReq(minutes = 60)
+ public void testSingleSequentialUpdate() throws Exception {
+ final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
+ if (fileSize == 0) { // not enough space, give up
+ return;
+ }
+ final int NUMBER_REPETITION = 6;
+ DeviceReportLog report = new DeviceReportLog();
+ FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, report, fileSize,
+ BUFFER_SIZE, NUMBER_REPETITION);
+ report.submit(getInstrumentation());
+ }
+
+ @TimeoutReq(minutes = 30)
+ public void testSingleSequentialRead() throws Exception {
+ final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
+ if (fileSize == 0) { // not enough space, give up
+ return;
+ }
+ long start = System.currentTimeMillis();
+ final File file = FileUtil.createNewFilledFile(getContext(),
+ DIR_SEQ_RD, fileSize);
+ long finish = System.currentTimeMillis();
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValue("write throughput for test file of length " + fileSize,
+ Stat.calcRatePerSec((double)fileSize / 1024 / 1024, finish - start),
+ ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+
+ final int NUMBER_READ = 10;
+
+ final byte[] data = new byte[BUFFER_SIZE];
+ double[] times = MeasureTime.measure(NUMBER_READ, new MeasureRun() {
+
+ @Override
+ public void run(int i) throws IOException {
+ final FileInputStream in = new FileInputStream(file);
+ long read = 0;
+ while (read < fileSize) {
+ in.read(data);
+ read += BUFFER_SIZE;
+ }
+ in.close();
+ }
+ });
+ double[] mbps = Stat.calcRatePerSecArray((double)fileSize / 1024 / 1024, times);
+ report.addValues("read throughput",
+ mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ Stat.StatResult stat = Stat.getStat(mbps);
+ report.setSummary("read throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ ResultUnit.MBPS);
+ report.submit(getInstrumentation());
+ }
+}
diff --git a/tests/inputmethod/Android.mk b/tests/inputmethod/Android.mk
new file mode 100644
index 0000000..6b9a6dc
--- /dev/null
+++ b/tests/inputmethod/Android.mk
@@ -0,0 +1,24 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PACKAGE_NAME := CtsInputMethodTestCases
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/inputmethod/AndroidManifest.xml b/tests/inputmethod/AndroidManifest.xml
new file mode 100644
index 0000000..f283f61
--- /dev/null
+++ b/tests/inputmethod/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.inputmethod">
+
+ <application >
+ <uses-library android:name="android.test.runner"/>
+
+ <activity android:name="android.inputmethod.cts.TestActivity" />
+ <service android:name="android.inputmethod.cts.MockInputMethodService"
+ android:permission="android.permission.BIND_INPUT_METHOD">
+ <intent-filter>
+ <action android:name="android.view.InputMethod" />
+ </intent-filter>
+ <meta-data android:name="android.view.im" android:resource="@xml/method" />
+ </service>
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.inputmethod"
+ android:label="Tests for the InputMethod APIs."/>
+
+</manifest>
diff --git a/tests/inputmethod/res/xml/method.xml b/tests/inputmethod/res/xml/method.xml
new file mode 100644
index 0000000..fc2ec95
--- /dev/null
+++ b/tests/inputmethod/res/xml/method.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<input-method xmlns:android="http://schemas.android.com/apk/res/android"
+ android:isDefault="True">
+ <subtype android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" />
+</input-method>
diff --git a/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java
new file mode 100644
index 0000000..c68d448
--- /dev/null
+++ b/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+package android.inputmethod.cts;
+
+import android.annotation.NonNull;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.inputmethodservice.InputMethodService;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.inputmethod.InputMethodManager;
+
+import java.util.List;
+
+public class InputMethodServiceTest extends InstrumentationTestCase {
+ private String mTestImeId;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mTestImeId = getInstrumentation().getContext().getPackageName() +
+ "/" + MockInputMethodService.class.getName();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Ensures that the IME with {@code imeId} is not enabled.
+ *
+ * This method ensures that no IME with {@code imeId} is enabled. If the given IME is currently
+ * in use, switches to another IME first. Then, if the given IME is enabled, disables it.
+ */
+ private void ensureImeNotEnabled(@NonNull final String imeId) {
+ final String currentImeId =
+ InputMethodServiceTestUtil.getCurrentImeId(getInstrumentation());
+ if (currentImeId.equals(imeId)) {
+ // Requested IME is already used. This typically happens if the previous test case is
+ // not finished gracefully. In this case, selects another IME.
+ String otherImeCandidate = null;
+ final List<String> enabledImes =
+ InputMethodServiceTestUtil.getEnabledImeIds(getInstrumentation());
+ for (final String enabledIme : enabledImes) {
+ if (!enabledIme.equals(imeId)) {
+ otherImeCandidate = imeId;
+ break;
+ }
+ }
+ if (otherImeCandidate == null) {
+ // When PackageManager.hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS)
+ // returns true, this case must not happen.
+ throw new IllegalStateException(
+ "No other IME is available. Unable to continue tests.");
+ }
+ assertTrue(InputMethodServiceTestUtil.setIme(getInstrumentation(), otherImeCandidate));
+ }
+
+ if (InputMethodServiceTestUtil.isImeEnabled(getInstrumentation(), imeId)) {
+ assertTrue(InputMethodServiceTestUtil.disableIme(getInstrumentation(), imeId));
+ }
+ }
+
+ /**
+ * Asserts the given service is not running.
+ */
+ private void assertServiceNotRunning() {
+ assertTrue(MockInputMethodService.getInstance() == null ||
+ MockInputMethodService.getInstance().getCallCount("onCreate") == 0);
+ }
+
+ /**
+ * This test checks the following APIs.
+ * <ul>
+ * <li>{@link InputMethodManager#getEnabledInputMethodList()}</li>
+ * <li>{@link InputMethodManager#getInputMethodList()}</li>
+ * <li>{@link InputMethodManager#setInputMethod(IBinder, String)}</li>
+ * <li>{@link InputMethodService#onCreate()}</li>
+ * <li>{@link InputMethodService#onDestroy()}</li>
+ * </ul>
+ */
+ @MediumTest
+ public void testCreateAndDestroy() {
+ if (!getInstrumentation().getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_INPUT_METHODS)) {
+ // The "input method" system feature is not supported on this device.
+ return;
+ }
+
+ // Clear the counter in the mock service, since it might have been used in a previous test.
+ MockInputMethodService.resetCounter();
+
+ ensureImeNotEnabled(mTestImeId);
+
+ final String ImeIdToRestore =
+ InputMethodServiceTestUtil.getCurrentImeId(getInstrumentation());
+ MockInputMethodService service = MockInputMethodService.getInstance();
+ assertServiceNotRunning();
+
+ try {
+ // Enable test IME.
+ assertTrue(InputMethodServiceTestUtil.enableIme(getInstrumentation(), mTestImeId));
+ service = MockInputMethodService.getInstance();
+ assertServiceNotRunning();
+
+ // Select test IME.
+ assertTrue(InputMethodServiceTestUtil.setIme(getInstrumentation(), mTestImeId));
+ service = MockInputMethodService.getInstance();
+ assertNotNull(service);
+ assertEquals(1, MockInputMethodService.getCallCount("<init>"));
+ assertEquals(1, MockInputMethodService.getCallCount("onCreate"));
+ } finally {
+ // Restores IMEs to original one.
+ InputMethodServiceTestUtil.setIme(getInstrumentation(), ImeIdToRestore);
+ InputMethodServiceTestUtil.disableIme(getInstrumentation(), mTestImeId);
+ assertEquals(1, MockInputMethodService.getCallCount("onDestroy"));
+ }
+ }
+}
diff --git a/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTestUtil.java b/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTestUtil.java
new file mode 100644
index 0000000..aa46c38
--- /dev/null
+++ b/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTestUtil.java
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+package android.inputmethod.cts;
+
+import android.annotation.NonNull;
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility functions for testing of input method stuff.
+ */
+public final class InputMethodServiceTestUtil {
+ private static final String TAG = InputMethodServiceTestUtil.class.getSimpleName();
+
+ // Prevents this from being instantiated.
+ private InputMethodServiceTestUtil() {}
+
+ @NonNull
+ private static String executeShellCommand(final UiAutomation uiAutomation, final String[] cmd) {
+ final String flattenCmd = TextUtils.join(" ", cmd);
+ List<String> output = new ArrayList<>();
+
+ try (final ParcelFileDescriptor fd = uiAutomation.executeShellCommand(flattenCmd);
+ final FileReader fr = new FileReader(fd.getFileDescriptor());
+ final BufferedReader br = new BufferedReader(fr)) {
+
+ String line;
+ while ((line = br.readLine()) != null) {
+ output.add(line);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ // The output from the "ime" command should be only one line.
+ if (output.size() != 1) {
+ throw new IllegalStateException(
+ "The output from 'ime' command should be one line, but it outputs multiples: " +
+ TextUtils.join("\n", output));
+ }
+ return output.get(0);
+ }
+
+ @NonNull
+ public static String getCurrentImeId(final Instrumentation inst) {
+ return Settings.Secure.getString(inst.getContext().getContentResolver(),
+ Settings.Secure.DEFAULT_INPUT_METHOD);
+ }
+
+ public static boolean isImeEnabled(final Instrumentation inst, final String imeId) {
+ final List<String> enabledImes = getEnabledImeIds(inst);
+ return enabledImes.contains(imeId);
+ }
+
+ @NonNull
+ public static List<String> getEnabledImeIds(final Instrumentation inst) {
+ InputMethodManager imm = (InputMethodManager) inst.getContext().getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ final List<InputMethodInfo> enabledImes = imm.getEnabledInputMethodList();
+ List<String> result = new ArrayList<>();
+ for (final InputMethodInfo enabledIme : enabledImes) {
+ result.add(enabledIme.getId());
+ }
+ return result;
+ }
+
+ /**
+ * Puts the specified IME into the available input method list.
+ *
+ * This operation will be done synchronously in "ime" command using
+ * {@link com.android.server.InputMethodManagerService#setInputMethodEnabled(String, boolean)},
+ * which is synchronous.
+ *
+ * @param imeId IME ID to be enabled.
+ * @return {@code true} if the target IME gets enabled successfully. {@code false} if failed.
+ */
+ public static boolean enableIme(final Instrumentation inst, final String imeId) {
+ // Needs to check the output message from the checking command, since executeShellCommand()
+ // does not pass the exit status code back to the test.
+ final String output = executeShellCommand(
+ inst.getUiAutomation(), new String[]{"ime", "enable", imeId});
+ final String expectedOutput = "Input method " + imeId + ": now enabled";
+ if (!output.equals(expectedOutput)) {
+ Log.e(TAG, "Unexpected output message. Expected: " + expectedOutput +
+ ", Actual: " + output);
+ return false;
+ }
+
+ final InputMethodManager imm = (InputMethodManager) inst.getContext().getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
+ for (final InputMethodInfo imi : enabledInputMethods) {
+ if (imi.getId().equals(imeId))
+ return true;
+ }
+
+ Log.e(TAG, "Failed to enable the given IME (IME ID: " + imeId + ").");
+ return false;
+ }
+
+ /**
+ * Removes the specified IME from the available input method list.
+ *
+ * This operation will {@code @NonNull} final be done synchronously in "ime" command using
+ * {@link com.android.server.InputMethodManagerService#setInputMethodEnabled(String, boolean)},
+ * which is synchronous.
+ *
+ * @param imeId IME ID to be disabled.
+ * @return {@code true} if the target IME gets disabled successfully. {@code false} if failed.
+ */
+ public static boolean disableIme(final Instrumentation inst, final String imeId) {
+ // Needs to check the output message from the checking command, since executeShellCommand()
+ // does not pass the exit status code back to the test.
+ final String output = executeShellCommand(
+ inst.getUiAutomation(), new String[]{"ime", "disable", imeId});
+ final String expectedOutput = "Input method " + imeId + ": now disabled";
+ if (!output.equals(expectedOutput)) {
+ Log.w(TAG, "Unexpected output message. Expected: " + expectedOutput +
+ ", Actual: " + output);
+ return false;
+ }
+
+ final InputMethodManager imm = (InputMethodManager) inst.getContext().getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
+ for (final InputMethodInfo imi : enabledInputMethods) {
+ if (imi.getId().equals(imeId)) {
+ Log.e(TAG, "Failed to disable the given IME (IME ID: " + imeId + ").");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Switches to the specified IME.
+ *
+ * This operation will be done synchronously in the "ime" command using
+ * {@link InputMethodManager#setInputMethod(IBinder, String)}, which is synchronous.
+ *
+ * @param imeId IME ID to be switched to.
+ * @return {@code true} if the target IME gets active successfully. {@code false} if failed.
+ */
+ public static boolean setIme(final Instrumentation inst, final String imeId) {
+ // Needs to check the output message from the checking command, since executeShellCommand()
+ // does not pass the exit status code back to the test.
+ final String output = executeShellCommand(
+ inst.getUiAutomation(), new String[]{"ime", "set", imeId});
+ final String expectedOutput = "Input method " + imeId + " selected";
+ if (!output.equals(expectedOutput)) {
+ Log.w(TAG, "Unexpected output message. Expected: " + expectedOutput + ", Actual: " +
+ output);
+ return false;
+ }
+
+ final String currentImeId = getCurrentImeId(inst);
+ if (!TextUtils.equals(currentImeId, imeId)) {
+ Log.e(TAG, "Failed to switch the current IME. Expected: " + imeId + ", Actual: " +
+ currentImeId);
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/tests/inputmethod/src/android/inputmethod/cts/MockInputMethodService.java b/tests/inputmethod/src/android/inputmethod/cts/MockInputMethodService.java
new file mode 100644
index 0000000..12b80a5
--- /dev/null
+++ b/tests/inputmethod/src/android/inputmethod/cts/MockInputMethodService.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package android.inputmethod.cts;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.inputmethodservice.InputMethodService;
+
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * A mock implementation of {@link InputMethodService} for testing purpose.
+ */
+public class MockInputMethodService extends InputMethodService {
+ private static AtomicReference<MockInputMethodService> sCurrentInstance =
+ new AtomicReference<>();
+ private static final HashMap<String, Integer> mCallCounter = new HashMap<>();
+
+ /**
+ * @return The instance of {@code MockInputMethodService}. If the service has not been created
+ * yet or already been destroyed, returns {@code null}.
+ */
+ @Nullable
+ public static MockInputMethodService getInstance() {
+ return sCurrentInstance.get();
+ }
+
+ public static void resetCounter() {
+ synchronized (mCallCounter) {
+ mCallCounter.clear();
+ }
+ }
+
+ private static void incrementCallCount(@NonNull final String methodName) {
+ synchronized (mCallCounter) {
+ if (!mCallCounter.containsKey(methodName)) {
+ mCallCounter.put(methodName, 0);
+ }
+ mCallCounter.put(methodName, mCallCounter.get(methodName) + 1);
+ }
+ }
+
+ public static int getCallCount(@NonNull final String methodName) {
+ synchronized (mCallCounter) {
+ if (!mCallCounter.containsKey(methodName)) {
+ return 0;
+ }
+ return mCallCounter.get(methodName);
+ }
+ }
+
+ public MockInputMethodService() {
+ incrementCallCount("<init>");
+ }
+
+ @Override
+ public void onCreate() {
+ if (!sCurrentInstance.compareAndSet(null, this)) {
+ throw new IllegalStateException("New MockInputMethodService instance is being created "
+ + "before the existing instance is destroyed.");
+ }
+
+ super.onCreate();
+ incrementCallCount("onCreate");
+ }
+
+ @Override
+ public void onDestroy() {
+ sCurrentInstance.lazySet(null);
+ super.onDestroy();
+ incrementCallCount("onDestroy");
+ }
+}
+
diff --git a/tests/jank/Android.mk b/tests/jank/Android.mk
new file mode 100644
index 0000000..46db307
--- /dev/null
+++ b/tests/jank/Android.mk
@@ -0,0 +1,34 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsJankDeviceTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner ub-uiautomator ub-janktesthelper
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/jank/AndroidManifest.xml b/tests/jank/AndroidManifest.xml
new file mode 100644
index 0000000..cbb4cba
--- /dev/null
+++ b/tests/jank/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.jank.cts">
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.jank.cts"
+ android:label="Jank tests">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
diff --git a/tests/jank/AndroidTest.xml b/tests/jank/AndroidTest.xml
new file mode 100644
index 0000000..c7e476a
--- /dev/null
+++ b/tests/jank/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Jank test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsUiDeviceTestCases.apk" />
+ <option name="test-file-name" value="CtsJankDeviceTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.jank.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/jank/OldAndroidTest.xml b/tests/jank/OldAndroidTest.xml
new file mode 100644
index 0000000..633f650
--- /dev/null
+++ b/tests/jank/OldAndroidTest.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+<configuration description="Config for CTS Jank Test Cases">
+ <include name="common-config" />
+ <option name="cts-apk-installer:test-file-name" value="CtsUiDeviceTestCases.apk" />
+</configuration>
diff --git a/tests/jank/src/android/jank/cts/CtsJankTestBase.java b/tests/jank/src/android/jank/cts/CtsJankTestBase.java
new file mode 100644
index 0000000..fb2f867
--- /dev/null
+++ b/tests/jank/src/android/jank/cts/CtsJankTestBase.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+package android.jank.cts;
+
+import android.os.Bundle;
+import android.support.test.jank.JankTestBase;
+import android.support.test.jank.WindowContentFrameStatsMonitor;
+import android.support.test.uiautomator.UiDevice;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+
+public abstract class CtsJankTestBase extends JankTestBase {
+
+ private UiDevice mDevice;
+ private DeviceReportLog mLog;
+
+ @Override
+ public void afterTest(Bundle metrics) {
+ String source = String.format("%s#%s", getClass().getCanonicalName(), getName());
+ mLog.addValue(source, WindowContentFrameStatsMonitor.KEY_AVG_FPS,
+ metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_FPS),
+ ResultType.HIGHER_BETTER, ResultUnit.FPS);
+ mLog.addValue(source, WindowContentFrameStatsMonitor.KEY_AVG_LONGEST_FRAME,
+ metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_LONGEST_FRAME),
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ mLog.addValue(source, WindowContentFrameStatsMonitor.KEY_MAX_NUM_JANKY,
+ metrics.getInt(WindowContentFrameStatsMonitor.KEY_MAX_NUM_JANKY),
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ mLog.setSummary(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY,
+ metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY),
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mLog = new DeviceReportLog();
+ // fix device orientation
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mDevice.setOrientationNatural();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mLog.submit(getInstrumentation());
+ // restore device orientation
+ mDevice.unfreezeRotation();
+ super.tearDown();
+ }
+
+ protected UiDevice getUiDevice() {
+ return mDevice;
+ }
+}
diff --git a/tests/jank/src/android/jank/cts/ui/CtsDeviceJankUi.java b/tests/jank/src/android/jank/cts/ui/CtsDeviceJankUi.java
new file mode 100644
index 0000000..2e389d7
--- /dev/null
+++ b/tests/jank/src/android/jank/cts/ui/CtsDeviceJankUi.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+package android.jank.cts.ui;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.jank.cts.CtsJankTestBase;
+import android.os.SystemClock;
+import android.support.test.jank.JankTest;
+import android.support.test.jank.WindowContentFrameStatsMonitor;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.Until;
+import android.widget.ListView;
+
+import java.io.IOException;
+
+public class CtsDeviceJankUi extends CtsJankTestBase {
+ private final static int NUM_ELEMENTS = 1000;
+ private static final long DEFAULT_ANIMATION_TIME = 2 * 1000;
+ private static final long POST_SCROLL_IDLE_TIME = 2 *1000;
+ private final static String PACKAGE = "android.ui.cts";
+ private final static String CLASS = PACKAGE + ".ScrollingActivity";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // launch the activity as part of the set up
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setComponent(new ComponentName(PACKAGE, CLASS));
+ intent.putExtra("num_elements", NUM_ELEMENTS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getInstrumentation().getTargetContext().startActivity(intent);
+ getUiDevice().wait(Until.hasObject(By.pkg(PACKAGE)), DEFAULT_ANIMATION_TIME);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ getUiDevice().pressHome();
+ super.tearDown();
+ }
+
+ @JankTest(expectedFrames=50, defaultIterationCount=5)
+ @WindowContentFrameStatsMonitor
+ public void testScrolling() throws IOException {
+ getUiDevice().findObject(By.clazz(ListView.class)).fling(Direction.DOWN);
+ SystemClock.sleep(POST_SCROLL_IDLE_TIME);
+ }
+}
diff --git a/tests/leanbackjank/Android.mk b/tests/leanbackjank/Android.mk
index b3adfb1..45d194f 100644
--- a/tests/leanbackjank/Android.mk
+++ b/tests/leanbackjank/Android.mk
@@ -21,11 +21,22 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
- ./app/src/android/cts/jank/leanback/IntentKeys.java
+ ./app/src/android/leanbackjank/app/IntentKeys.java
LOCAL_PACKAGE_NAME := CtsLeanbackJankTestCases
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ub-uiautomator ub-janktesthelper android-support-v17-leanback
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ ctsdeviceutil \
+ ctstestrunner \
+ ub-uiautomator \
+ ub-janktesthelper \
+ android-support-v17-leanback \
+ android-support-v4
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/leanbackjank/AndroidManifest.xml b/tests/leanbackjank/AndroidManifest.xml
index 1cd552d..27cdbe6 100644
--- a/tests/leanbackjank/AndroidManifest.xml
+++ b/tests/leanbackjank/AndroidManifest.xml
@@ -17,15 +17,15 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.cts.leanbackjank">
+ package="android.leanbackjank.cts">
<application>
<uses-library android:name="android.test.runner"/>
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.cts.leanbackjank"
- android:label="Jank tests">
+ android:targetPackage="android.leanbackjank.cts"
+ android:label="LeanbackJank tests">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/leanbackjank/AndroidTest.xml b/tests/leanbackjank/AndroidTest.xml
index e61c58d..a07c2eb 100644
--- a/tests/leanbackjank/AndroidTest.xml
+++ b/tests/leanbackjank/AndroidTest.xml
@@ -13,7 +13,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="CTS Jank test config">
- <include name="common-config" />
- <option name="cts-apk-installer:test-file-name" value="CtsLeanbackJank.apk" />
+<configuration description="Config for CTS LeanbackJank test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsLeanbackJankTestCases.apk" />
+ <option name="test-file-name" value="CtsLeanbackJankApp.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.leanbackjank.cts" />
+ </test>
</configuration>
diff --git a/tests/leanbackjank/OldAndroidTest.xml b/tests/leanbackjank/OldAndroidTest.xml
new file mode 100644
index 0000000..1ee5722
--- /dev/null
+++ b/tests/leanbackjank/OldAndroidTest.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+<configuration description="Config for CTS LeanbackJank Test Cases">
+ <include name="common-config" />
+ <option name="cts-apk-installer:test-file-name" value="CtsLeanbackJankApp.apk" />
+</configuration>
diff --git a/tests/leanbackjank/app/Android.mk b/tests/leanbackjank/app/Android.mk
index 5abe1a7..c2bab35 100644
--- a/tests/leanbackjank/app/Android.mk
+++ b/tests/leanbackjank/app/Android.mk
@@ -22,7 +22,10 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := CtsLeanbackJank
+LOCAL_PACKAGE_NAME := CtsLeanbackJankApp
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
LOCAL_RESOURCE_DIR := \
$(TOP)/frameworks/support/v17/leanback/res \
diff --git a/tests/leanbackjank/app/AndroidManifest.xml b/tests/leanbackjank/app/AndroidManifest.xml
index 333399e..1e1ff3b 100644
--- a/tests/leanbackjank/app/AndroidManifest.xml
+++ b/tests/leanbackjank/app/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.cts.jank.leanback"
+ package="android.leanbackjank.app"
android:versionCode="1"
android:versionName="1.1" >
diff --git a/tests/leanbackjank/app/src/android/cts/jank/leanback/IntentKeys.java b/tests/leanbackjank/app/src/android/cts/jank/leanback/IntentKeys.java
deleted file mode 100644
index e9c5e6e..0000000
--- a/tests/leanbackjank/app/src/android/cts/jank/leanback/IntentKeys.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package android.cts.jank.leanback;
-
-/**
- * Intent key strings of the leanback jank test helper app.
- */
-public class IntentKeys {
- public static final String SCROLL_COUNT = "SCROLL_COUNT";
- public static final String SCROLL_DELAY = "SCROLL_DELAY";
- public static final String SCROLL_INTERVAL = "SCROLL_INTERVAL";
-}
diff --git a/tests/leanbackjank/app/src/android/cts/jank/leanback/Utils.java b/tests/leanbackjank/app/src/android/cts/jank/leanback/Utils.java
deleted file mode 100644
index de6d6af..0000000
--- a/tests/leanbackjank/app/src/android/cts/jank/leanback/Utils.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank.leanback;
-
-import android.app.Activity;
-import android.content.Context;
-import android.graphics.Point;
-import android.media.MediaMetadataRetriever;
-import android.os.Build;
-import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.widget.Toast;
-import android.widget.VideoView;
-
-import java.util.HashMap;
-
-/**
- * A collection of utility methods, all static.
- */
-public class Utils {
-
- public interface MediaDimensions {
- double MEDIA_HEIGHT = 0.95;
- double MEDIA_WIDTH = 0.95;
- double MEDIA_TOP_MARGIN = 0.025;
- double MEDIA_RIGHT_MARGIN = 0.025;
- double MEDIA_BOTTOM_MARGIN = 0.025;
- double MEDIA_LEFT_MARGIN = 0.025;
- }
-
- /*
- * Making sure public utility methods remain static
- */
- private Utils() {
- }
-
- /**
- * Returns the screen/display size
- */
- public static Point getDisplaySize(Context context) {
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- Point size = new Point();
- display.getSize(size);
- return size;
- }
-
- /**
- * Shows a (long) toast
- */
- public static void showToast(Context context, String msg) {
- Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
- }
-
- /**
- * Shows a (long) toast.
- */
- public static void showToast(Context context, int resourceId) {
- Toast.makeText(context, context.getString(resourceId), Toast.LENGTH_LONG).show();
- }
-
- public static int convertDpToPixel(Context ctx, int dp) {
- float density = ctx.getResources().getDisplayMetrics().density;
- return Math.round((float) dp * density);
- }
-
-
- /**
- * Example for handling resizing content for overscan. Typically you won't need to resize
- * when using the Leanback support library.
- */
- public void overScan(Activity activity, VideoView videoView) {
- DisplayMetrics metrics = new DisplayMetrics();
- activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
- int w = (int) (metrics.widthPixels * MediaDimensions.MEDIA_WIDTH);
- int h = (int) (metrics.heightPixels * MediaDimensions.MEDIA_HEIGHT);
- int marginLeft = (int) (metrics.widthPixels * MediaDimensions.MEDIA_LEFT_MARGIN);
- int marginTop = (int) (metrics.heightPixels * MediaDimensions.MEDIA_TOP_MARGIN);
- int marginRight = (int) (metrics.widthPixels * MediaDimensions.MEDIA_RIGHT_MARGIN);
- int marginBottom = (int) (metrics.heightPixels * MediaDimensions.MEDIA_BOTTOM_MARGIN);
- FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(w, h);
- lp.setMargins(marginLeft, marginTop, marginRight, marginBottom);
- videoView.setLayoutParams(lp);
- }
-
-
- public static long getDuration(String videoUrl) {
- MediaMetadataRetriever mmr = new MediaMetadataRetriever();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- mmr.setDataSource(videoUrl, new HashMap<String, String>());
- } else {
- mmr.setDataSource(videoUrl);
- }
- return Long.parseLong(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
- }
-}
diff --git a/tests/leanbackjank/app/src/android/cts/jank/leanback/data/VideoProvider.java b/tests/leanbackjank/app/src/android/cts/jank/leanback/data/VideoProvider.java
deleted file mode 100644
index fa317ed..0000000
--- a/tests/leanbackjank/app/src/android/cts/jank/leanback/data/VideoProvider.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank.leanback.data;
-
-import android.cts.jank.leanback.model.Movie;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Provides synthesized movie data.
- */
-public class VideoProvider {
- private static HashMap<String, List<Movie>> sMovieList;
- private static HashMap<String, Movie> sMovieListById;
-
- public static Movie getMovieById(String mediaId) {
- return sMovieListById.get(mediaId);
- }
-
- public static HashMap<String, List<Movie>> getMovieList() {
- return sMovieList;
- }
-
- public static HashMap<String, List<Movie>> buildMedia(int nCategories) {
- if (null != sMovieList) {
- return sMovieList;
- }
- sMovieList = new HashMap<>();
- sMovieListById = new HashMap<>();
-
- String title = new String();
- String studio = new String();
- for (int i = 0; i < nCategories; i++) {
- String category_name = String.format("Category %d", i);
- List<Movie> categoryList = new ArrayList<Movie>();
- for (int j = 0; j < 20; j++) {
- String description = "This is description of a movie.";
- title = String.format("Video %d-%d", i, j);
- studio = String.format("Studio %d", (i + j) % 7);
- Movie movie = buildMovieInfo(category_name, title, description, studio);
- sMovieListById.put(movie.getId(), movie);
- categoryList.add(movie);
- }
- sMovieList.put(category_name, categoryList);
- }
- return sMovieList;
- }
-
- private static Movie buildMovieInfo(String category,
- String title,
- String description,
- String studio) {
- Movie movie = new Movie();
- movie.setId(Movie.getCount());
- Movie.incrementCount();
- movie.setTitle(title);
- movie.setDescription(description);
- movie.setStudio(studio);
- movie.setCategory(category);
-
- return movie;
- }
-}
diff --git a/tests/leanbackjank/app/src/android/cts/jank/leanback/model/Movie.java b/tests/leanbackjank/app/src/android/cts/jank/leanback/model/Movie.java
deleted file mode 100644
index 874bb00..0000000
--- a/tests/leanbackjank/app/src/android/cts/jank/leanback/model/Movie.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank.leanback.model;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Movie class represents video entity with title, description, image thumbs and video url.
- */
-public class Movie implements Parcelable {
- static final long serialVersionUID = 727566175075960653L;
- private static int sCount = 0;
- private String mId;
- private String mTitle;
- private String mDescription;
- private String mStudio;
- private String mCategory;
-
- public Movie() {
- }
-
- public Movie(Parcel in){
- String[] data = new String[5];
-
- in.readStringArray(data);
- mId = data[0];
- mTitle = data[1];
- mDescription = data[2];
- mStudio = data[3];
- mCategory = data[4];
- }
-
- public static String getCount() {
- return Integer.toString(sCount);
- }
-
- public static void incrementCount() {
- sCount++;
- }
-
- public String getId() {
- return mId;
- }
-
- public void setId(String id) {
- mId = id;
- }
-
- public String getTitle() {
- return mTitle;
- }
-
- public void setTitle(String title) {
- mTitle = title;
- }
-
- public String getDescription() {
- return mDescription;
- }
-
- public void setDescription(String description) {
- mDescription = description;
- }
-
- public String getStudio() {
- return mStudio;
- }
-
- public void setStudio(String studio) {
- mStudio = studio;
- }
-
- public String getCategory() {
- return mCategory;
- }
-
- public void setCategory(String category) {
- mCategory = category;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStringArray(new String[] {mId,
- mTitle,
- mDescription,
- mStudio,
- mCategory});
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder(200);
- sb.append("Movie{");
- sb.append("mId=" + mId);
- sb.append(", mTitle='" + mTitle + '\'');
- sb.append('}');
- return sb.toString();
- }
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public Movie createFromParcel(Parcel in) {
- return new Movie(in);
- }
-
- public Movie[] newArray(int size) {
- return new Movie[size];
- }
- };
-}
diff --git a/tests/leanbackjank/app/src/android/cts/jank/leanback/presenter/CardPresenter.java b/tests/leanbackjank/app/src/android/cts/jank/leanback/presenter/CardPresenter.java
deleted file mode 100644
index 9f425ca..0000000
--- a/tests/leanbackjank/app/src/android/cts/jank/leanback/presenter/CardPresenter.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank.leanback.presenter;
-
-import android.graphics.drawable.Drawable;
-import android.support.v17.leanback.widget.ImageCardView;
-import android.support.v17.leanback.widget.Presenter;
-import android.view.ViewGroup;
-
-import com.bumptech.glide.Glide;
-import android.cts.jank.leanback.R;
-import android.cts.jank.leanback.model.Movie;
-
-/**
- * A CardPresenter is used to generate Views and bind Objects to them on demand.
- * It contains an Image CardView
- */
-public class CardPresenter extends Presenter {
- private static int CARD_WIDTH = 313;
- private static int CARD_HEIGHT = 176;
- private static int sSelectedBackgroundColor;
- private static int sDefaultBackgroundColor;
- private Drawable mDefaultCardImage;
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent) {
- sDefaultBackgroundColor = parent.getResources().getColor(R.color.default_background, null);
- sSelectedBackgroundColor =
- parent.getResources().getColor(R.color.selected_background, null);
- mDefaultCardImage = parent.getResources().getDrawable(R.drawable.movie, null);
-
- ImageCardView cardView = new ImageCardView(parent.getContext()) {
- @Override
- public void setSelected(boolean selected) {
- updateCardBackgroundColor(this, selected);
- super.setSelected(selected);
- }
- };
-
- cardView.setFocusable(true);
- cardView.setFocusableInTouchMode(true);
- updateCardBackgroundColor(cardView, false);
- return new ViewHolder(cardView);
- }
-
- private static void updateCardBackgroundColor(ImageCardView view, boolean selected) {
- int color = selected ? sSelectedBackgroundColor : sDefaultBackgroundColor;
- // Both background colors should be set because the view's background is temporarily visible
- // during animations.
- view.setBackgroundColor(color);
- view.findViewById(R.id.info_field).setBackgroundColor(color);
- }
-
- @Override
- public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
- Movie movie = (Movie) item;
- ImageCardView cardView = (ImageCardView) viewHolder.view;
-
- cardView.setTitleText(movie.getTitle());
- cardView.setContentText(movie.getStudio());
- cardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT);
- Glide.with(viewHolder.view.getContext())
- .load(R.drawable.gradation)
- .centerCrop()
- .error(mDefaultCardImage)
- .into(cardView.getMainImageView());
- }
-
- @Override
- public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
- ImageCardView cardView = (ImageCardView) viewHolder.view;
- // Remove references to images so that the garbage collector can free up memory
- cardView.setBadgeImage(null);
- cardView.setMainImage(null);
- }
-}
diff --git a/tests/leanbackjank/app/src/android/cts/jank/leanback/presenter/GridItemPresenter.java b/tests/leanbackjank/app/src/android/cts/jank/leanback/presenter/GridItemPresenter.java
deleted file mode 100644
index 4084383..0000000
--- a/tests/leanbackjank/app/src/android/cts/jank/leanback/presenter/GridItemPresenter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank.leanback.presenter;
-
-import android.graphics.Color;
-import android.support.v17.leanback.widget.Presenter;
-import android.view.Gravity;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import android.cts.jank.leanback.R;
-import android.cts.jank.leanback.ui.MainFragment;
-
-public class GridItemPresenter extends Presenter {
- private static int GRID_ITEM_WIDTH = 200;
- private static int GRID_ITEM_HEIGHT = 200;
-
- private MainFragment mainFragment;
-
- public GridItemPresenter(MainFragment mainFragment) {
- this.mainFragment = mainFragment;
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent) {
- TextView view = new TextView(parent.getContext());
- view.setLayoutParams(new ViewGroup.LayoutParams(GRID_ITEM_WIDTH, GRID_ITEM_HEIGHT));
- view.setFocusable(true);
- view.setFocusableInTouchMode(true);
- view.setBackgroundColor(
- mainFragment.getResources().getColor(R.color.default_background, null));
- view.setTextColor(Color.WHITE);
- view.setGravity(Gravity.CENTER);
- return new ViewHolder(view);
- }
-
- @Override
- public void onBindViewHolder(ViewHolder viewHolder, Object item) {
- ((TextView) viewHolder.view).setText((String) item);
- }
-
- @Override
- public void onUnbindViewHolder(ViewHolder viewHolder) {
- }
-}
diff --git a/tests/leanbackjank/app/src/android/cts/jank/leanback/presenter/IconHeaderItemPresenter.java b/tests/leanbackjank/app/src/android/cts/jank/leanback/presenter/IconHeaderItemPresenter.java
deleted file mode 100644
index 42e4c0c..0000000
--- a/tests/leanbackjank/app/src/android/cts/jank/leanback/presenter/IconHeaderItemPresenter.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank.leanback.presenter;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.RowHeaderPresenter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import android.cts.jank.leanback.R;
-
-public class IconHeaderItemPresenter extends RowHeaderPresenter {
- private float mUnselectedAlpha;
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
- mUnselectedAlpha = viewGroup.getResources()
- .getFraction(R.fraction.lb_browse_header_unselect_alpha, 1, 1);
- LayoutInflater inflater = (LayoutInflater) viewGroup.getContext()
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- View view = inflater.inflate(R.layout.icon_header_item, null);
-
- return new ViewHolder(view);
- }
-
- @Override
- public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object o) {
- HeaderItem headerItem = ((ListRow) o).getHeaderItem();
- View rootView = viewHolder.view;
-
- ImageView iconView = (ImageView) rootView.findViewById(R.id.header_icon);
- Drawable icon = rootView.getResources().getDrawable(R.drawable.android_header, null);
- iconView.setImageDrawable(icon);
-
- TextView label = (TextView) rootView.findViewById(R.id.header_label);
- label.setText(headerItem.getName());
- }
-
- @Override
- public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
- }
-
- // TODO: TEMP - remove me when leanback onCreateViewHolder no longer sets the mUnselectAlpha,AND
- // also assumes the xml inflation will return a RowHeaderView
- @Override
- protected void onSelectLevelChanged(RowHeaderPresenter.ViewHolder holder) {
- // this is a temporary fix
- holder.view.setAlpha(mUnselectedAlpha + holder.getSelectLevel() *
- (1.0f - mUnselectedAlpha));
- }
-}
\ No newline at end of file
diff --git a/tests/leanbackjank/app/src/android/cts/jank/leanback/ui/MainActivity.java b/tests/leanbackjank/app/src/android/cts/jank/leanback/ui/MainActivity.java
deleted file mode 100644
index fb27fa1..0000000
--- a/tests/leanbackjank/app/src/android/cts/jank/leanback/ui/MainActivity.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank.leanback.ui;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.cts.jank.leanback.R;
-
-/**
- * MainActivity class that loads MainFragment
- */
-public class MainActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
-
- @Override
- public boolean onSearchRequested() {
- return false;
- }
-}
diff --git a/tests/leanbackjank/app/src/android/cts/jank/leanback/ui/MainFragment.java b/tests/leanbackjank/app/src/android/cts/jank/leanback/ui/MainFragment.java
deleted file mode 100644
index e645f6b..0000000
--- a/tests/leanbackjank/app/src/android/cts/jank/leanback/ui/MainFragment.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.jank.leanback.ui;
-
-import android.content.Intent;
-import android.content.res.Resources.Theme;
-import android.cts.jank.leanback.IntentKeys;
-import android.cts.jank.leanback.R;
-import android.cts.jank.leanback.data.VideoProvider;
-import android.cts.jank.leanback.model.Movie;
-import android.cts.jank.leanback.presenter.CardPresenter;
-import android.cts.jank.leanback.presenter.GridItemPresenter;
-import android.cts.jank.leanback.presenter.IconHeaderItemPresenter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v17.leanback.app.BackgroundManager;
-import android.support.v17.leanback.app.BrowseFragment;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.Presenter;
-import android.support.v17.leanback.widget.PresenterSelector;
-import android.util.DisplayMetrics;
-import android.view.View;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-
-/**
- * Main class to show BrowseFragment with header and rows of videos
- */
-public class MainFragment extends BrowseFragment {
- private static final int NUM_ROWS = 20;
- private final Handler mHandler = new Handler();
- private Timer mAutoScrollTimer;
- private int mAutoScrollCount;
-
- private ArrayObjectAdapter mRowsAdapter;
- private DisplayMetrics mMetrics;
- private BackgroundManager mBackgroundManager;
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- buildRowAdapterItems(VideoProvider.buildMedia(NUM_ROWS));
- prepareBackgroundManager();
- setupUIElements();
- setupEventListeners();
- Intent intent = getActivity().getIntent();
- if (intent.getExtras() != null) {
- int initialDelay = intent.getExtras().getInt(IntentKeys.SCROLL_DELAY);
- int scrollCount = intent.getExtras().getInt(IntentKeys.SCROLL_COUNT);
- int scrollInterval = intent.getExtras().getInt(IntentKeys.SCROLL_INTERVAL);
- if (scrollInterval != 0 && scrollCount != 0) {
- startAutoScrollTimer(initialDelay, scrollInterval, scrollCount);
- }
- }
- }
-
- @Override
- public void onDestroy() {
- if (null != mAutoScrollTimer) {
- mAutoScrollTimer.cancel();
- mAutoScrollTimer = null;
- }
- super.onDestroy();
- }
-
- @Override
- public void onStop() {
- mBackgroundManager.release();
- super.onStop();
- }
-
- private void prepareBackgroundManager() {
- mBackgroundManager = BackgroundManager.getInstance(getActivity());
- mBackgroundManager.attach(getActivity().getWindow());
- mBackgroundManager.setDrawable(getActivity().getResources().getDrawable(
- R.drawable.default_background, getContext().getTheme()));
- mMetrics = new DisplayMetrics();
- getActivity().getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
- }
-
- private void setupUIElements() {
- setBadgeDrawable(getActivity().getResources().getDrawable(
- R.drawable.videos_by_google_banner, getContext().getTheme()));
- setTitle(getString(R.string.browse_title));
- setHeadersState(HEADERS_ENABLED);
- setHeadersTransitionOnBackEnabled(true);
-
- Theme theme = getContext().getTheme();
- setBrandColor(getResources().getColor(R.color.fastlane_background, theme));
-
- setSearchAffordanceColor(getResources().getColor(R.color.search_opaque, theme));
-
- setHeaderPresenterSelector(new PresenterSelector() {
- @Override
- public Presenter getPresenter(Object o) {
- return new IconHeaderItemPresenter();
- }
- });
- }
-
- private void setupEventListeners() {
- // Add lister to show the search button.
- setOnSearchClickedListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- }
- });
- }
-
- public void buildRowAdapterItems(HashMap<String, List<Movie>> data) {
- mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
- CardPresenter cardPresenter = new CardPresenter();
-
- int i = 0;
-
- for (Map.Entry<String, List<Movie>> entry : data.entrySet()) {
- ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
- List<Movie> list = entry.getValue();
-
- for (int j = 0; j < list.size(); j++) {
- listRowAdapter.add(list.get(j));
- }
- HeaderItem header = new HeaderItem(i, entry.getKey());
- i++;
- mRowsAdapter.add(new ListRow(header, listRowAdapter));
- }
-
- HeaderItem gridHeader = new HeaderItem(i, getString(R.string.settings));
-
- GridItemPresenter gridPresenter = new GridItemPresenter(this);
- ArrayObjectAdapter gridRowAdapter = new ArrayObjectAdapter(gridPresenter);
- for (int j = 0; j < 10; j++) {
- gridRowAdapter.add(getString(R.string.grid_item_template, j));
- }
- mRowsAdapter.add(new ListRow(gridHeader, gridRowAdapter));
-
- setAdapter(mRowsAdapter);
- }
-
- private class UpdateAutoScrollTask extends TimerTask {
- @Override
- public void run() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (mAutoScrollCount == 0) {
- mAutoScrollTimer.cancel();
- return;
- }
- if (mAutoScrollCount % 2 == 0) {
- setSelectedPosition(NUM_ROWS - 1);
- } else {
- setSelectedPosition(0);
- }
- mAutoScrollCount--;
- }
- });
- }
- }
-
- private void startAutoScrollTimer(int initialDelay, int interval, int count) {
- if (null != mAutoScrollTimer) {
- mAutoScrollTimer.cancel();
- }
- mAutoScrollCount = count;
- mAutoScrollTimer = new Timer();
- mAutoScrollTimer.schedule(new UpdateAutoScrollTask(), initialDelay, interval);
- }
-
- public void selectRow(int row) {
- setSelectedPosition(row);
- }
-}
diff --git a/tests/leanbackjank/app/src/android/leanbackjank/app/IntentKeys.java b/tests/leanbackjank/app/src/android/leanbackjank/app/IntentKeys.java
new file mode 100644
index 0000000..b459aa9
--- /dev/null
+++ b/tests/leanbackjank/app/src/android/leanbackjank/app/IntentKeys.java
@@ -0,0 +1,10 @@
+package android.leanbackjank.app;
+
+/**
+ * Intent key strings of the leanback jank test helper app.
+ */
+public class IntentKeys {
+ public static final String SCROLL_COUNT = "SCROLL_COUNT";
+ public static final String SCROLL_DELAY = "SCROLL_DELAY";
+ public static final String SCROLL_INTERVAL = "SCROLL_INTERVAL";
+}
diff --git a/tests/leanbackjank/app/src/android/leanbackjank/app/Utils.java b/tests/leanbackjank/app/src/android/leanbackjank/app/Utils.java
new file mode 100644
index 0000000..b464abf
--- /dev/null
+++ b/tests/leanbackjank/app/src/android/leanbackjank/app/Utils.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.app;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Point;
+import android.media.MediaMetadataRetriever;
+import android.os.Build;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.Toast;
+import android.widget.VideoView;
+
+import java.util.HashMap;
+
+/**
+ * A collection of utility methods, all static.
+ */
+public class Utils {
+
+ public interface MediaDimensions {
+ double MEDIA_HEIGHT = 0.95;
+ double MEDIA_WIDTH = 0.95;
+ double MEDIA_TOP_MARGIN = 0.025;
+ double MEDIA_RIGHT_MARGIN = 0.025;
+ double MEDIA_BOTTOM_MARGIN = 0.025;
+ double MEDIA_LEFT_MARGIN = 0.025;
+ }
+
+ /*
+ * Making sure public utility methods remain static
+ */
+ private Utils() {
+ }
+
+ /**
+ * Returns the screen/display size
+ */
+ public static Point getDisplaySize(Context context) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ Point size = new Point();
+ display.getSize(size);
+ return size;
+ }
+
+ /**
+ * Shows a (long) toast
+ */
+ public static void showToast(Context context, String msg) {
+ Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
+ }
+
+ /**
+ * Shows a (long) toast.
+ */
+ public static void showToast(Context context, int resourceId) {
+ Toast.makeText(context, context.getString(resourceId), Toast.LENGTH_LONG).show();
+ }
+
+ public static int convertDpToPixel(Context ctx, int dp) {
+ float density = ctx.getResources().getDisplayMetrics().density;
+ return Math.round((float) dp * density);
+ }
+
+
+ /**
+ * Example for handling resizing content for overscan. Typically you won't need to resize
+ * when using the Leanback support library.
+ */
+ public void overScan(Activity activity, VideoView videoView) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ int w = (int) (metrics.widthPixels * MediaDimensions.MEDIA_WIDTH);
+ int h = (int) (metrics.heightPixels * MediaDimensions.MEDIA_HEIGHT);
+ int marginLeft = (int) (metrics.widthPixels * MediaDimensions.MEDIA_LEFT_MARGIN);
+ int marginTop = (int) (metrics.heightPixels * MediaDimensions.MEDIA_TOP_MARGIN);
+ int marginRight = (int) (metrics.widthPixels * MediaDimensions.MEDIA_RIGHT_MARGIN);
+ int marginBottom = (int) (metrics.heightPixels * MediaDimensions.MEDIA_BOTTOM_MARGIN);
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(w, h);
+ lp.setMargins(marginLeft, marginTop, marginRight, marginBottom);
+ videoView.setLayoutParams(lp);
+ }
+
+
+ public static long getDuration(String videoUrl) {
+ MediaMetadataRetriever mmr = new MediaMetadataRetriever();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ mmr.setDataSource(videoUrl, new HashMap<String, String>());
+ } else {
+ mmr.setDataSource(videoUrl);
+ }
+ return Long.parseLong(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
+ }
+}
diff --git a/tests/leanbackjank/app/src/android/leanbackjank/app/data/VideoProvider.java b/tests/leanbackjank/app/src/android/leanbackjank/app/data/VideoProvider.java
new file mode 100644
index 0000000..6ea19c1
--- /dev/null
+++ b/tests/leanbackjank/app/src/android/leanbackjank/app/data/VideoProvider.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.app.data;
+
+import android.leanbackjank.app.model.Movie;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Provides synthesized movie data.
+ */
+public class VideoProvider {
+ private static HashMap<String, List<Movie>> sMovieList;
+ private static HashMap<String, Movie> sMovieListById;
+
+ public static Movie getMovieById(String mediaId) {
+ return sMovieListById.get(mediaId);
+ }
+
+ public static HashMap<String, List<Movie>> getMovieList() {
+ return sMovieList;
+ }
+
+ public static HashMap<String, List<Movie>> buildMedia(int nCategories) {
+ if (null != sMovieList) {
+ return sMovieList;
+ }
+ sMovieList = new HashMap<>();
+ sMovieListById = new HashMap<>();
+
+ String title = new String();
+ String studio = new String();
+ for (int i = 0; i < nCategories; i++) {
+ String category_name = String.format("Category %d", i);
+ List<Movie> categoryList = new ArrayList<Movie>();
+ for (int j = 0; j < 20; j++) {
+ String description = "This is description of a movie.";
+ title = String.format("Video %d-%d", i, j);
+ studio = String.format("Studio %d", (i + j) % 7);
+ Movie movie = buildMovieInfo(category_name, title, description, studio);
+ sMovieListById.put(movie.getId(), movie);
+ categoryList.add(movie);
+ }
+ sMovieList.put(category_name, categoryList);
+ }
+ return sMovieList;
+ }
+
+ private static Movie buildMovieInfo(String category,
+ String title,
+ String description,
+ String studio) {
+ Movie movie = new Movie();
+ movie.setId(Movie.getCount());
+ Movie.incrementCount();
+ movie.setTitle(title);
+ movie.setDescription(description);
+ movie.setStudio(studio);
+ movie.setCategory(category);
+
+ return movie;
+ }
+}
diff --git a/tests/leanbackjank/app/src/android/leanbackjank/app/model/Movie.java b/tests/leanbackjank/app/src/android/leanbackjank/app/model/Movie.java
new file mode 100644
index 0000000..1b68aee
--- /dev/null
+++ b/tests/leanbackjank/app/src/android/leanbackjank/app/model/Movie.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.app.model;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Movie class represents video entity with title, description, image thumbs and video url.
+ */
+public class Movie implements Parcelable {
+ static final long serialVersionUID = 727566175075960653L;
+ private static int sCount = 0;
+ private String mId;
+ private String mTitle;
+ private String mDescription;
+ private String mStudio;
+ private String mCategory;
+
+ public Movie() {
+ }
+
+ public Movie(Parcel in){
+ String[] data = new String[5];
+
+ in.readStringArray(data);
+ mId = data[0];
+ mTitle = data[1];
+ mDescription = data[2];
+ mStudio = data[3];
+ mCategory = data[4];
+ }
+
+ public static String getCount() {
+ return Integer.toString(sCount);
+ }
+
+ public static void incrementCount() {
+ sCount++;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) {
+ mId = id;
+ }
+
+ public String getTitle() {
+ return mTitle;
+ }
+
+ public void setTitle(String title) {
+ mTitle = title;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public void setDescription(String description) {
+ mDescription = description;
+ }
+
+ public String getStudio() {
+ return mStudio;
+ }
+
+ public void setStudio(String studio) {
+ mStudio = studio;
+ }
+
+ public String getCategory() {
+ return mCategory;
+ }
+
+ public void setCategory(String category) {
+ mCategory = category;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStringArray(new String[] {mId,
+ mTitle,
+ mDescription,
+ mStudio,
+ mCategory});
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(200);
+ sb.append("Movie{");
+ sb.append("mId=" + mId);
+ sb.append(", mTitle='" + mTitle + '\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+ public Movie createFromParcel(Parcel in) {
+ return new Movie(in);
+ }
+
+ public Movie[] newArray(int size) {
+ return new Movie[size];
+ }
+ };
+}
diff --git a/tests/leanbackjank/app/src/android/leanbackjank/app/presenter/CardPresenter.java b/tests/leanbackjank/app/src/android/leanbackjank/app/presenter/CardPresenter.java
new file mode 100644
index 0000000..f237438
--- /dev/null
+++ b/tests/leanbackjank/app/src/android/leanbackjank/app/presenter/CardPresenter.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.app.presenter;
+
+import android.graphics.drawable.Drawable;
+import android.support.v17.leanback.widget.ImageCardView;
+import android.support.v17.leanback.widget.Presenter;
+import android.view.ViewGroup;
+
+import com.bumptech.glide.Glide;
+import android.leanbackjank.app.R;
+import android.leanbackjank.app.model.Movie;
+
+/**
+ * A CardPresenter is used to generate Views and bind Objects to them on demand.
+ * It contains an Image CardView
+ */
+public class CardPresenter extends Presenter {
+ private static int CARD_WIDTH = 313;
+ private static int CARD_HEIGHT = 176;
+ private static int sSelectedBackgroundColor;
+ private static int sDefaultBackgroundColor;
+ private Drawable mDefaultCardImage;
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent) {
+ sDefaultBackgroundColor = parent.getResources().getColor(R.color.default_background, null);
+ sSelectedBackgroundColor =
+ parent.getResources().getColor(R.color.selected_background, null);
+ mDefaultCardImage = parent.getResources().getDrawable(R.drawable.movie, null);
+
+ ImageCardView cardView = new ImageCardView(parent.getContext()) {
+ @Override
+ public void setSelected(boolean selected) {
+ updateCardBackgroundColor(this, selected);
+ super.setSelected(selected);
+ }
+ };
+
+ cardView.setFocusable(true);
+ cardView.setFocusableInTouchMode(true);
+ updateCardBackgroundColor(cardView, false);
+ return new ViewHolder(cardView);
+ }
+
+ private static void updateCardBackgroundColor(ImageCardView view, boolean selected) {
+ int color = selected ? sSelectedBackgroundColor : sDefaultBackgroundColor;
+ // Both background colors should be set because the view's background is temporarily visible
+ // during animations.
+ view.setBackgroundColor(color);
+ view.findViewById(R.id.info_field).setBackgroundColor(color);
+ }
+
+ @Override
+ public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
+ Movie movie = (Movie) item;
+ ImageCardView cardView = (ImageCardView) viewHolder.view;
+
+ cardView.setTitleText(movie.getTitle());
+ cardView.setContentText(movie.getStudio());
+ cardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT);
+ Glide.with(viewHolder.view.getContext())
+ .load(R.drawable.gradation)
+ .centerCrop()
+ .error(mDefaultCardImage)
+ .into(cardView.getMainImageView());
+ }
+
+ @Override
+ public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
+ ImageCardView cardView = (ImageCardView) viewHolder.view;
+ // Remove references to images so that the garbage collector can free up memory
+ cardView.setBadgeImage(null);
+ cardView.setMainImage(null);
+ }
+}
diff --git a/tests/leanbackjank/app/src/android/leanbackjank/app/presenter/GridItemPresenter.java b/tests/leanbackjank/app/src/android/leanbackjank/app/presenter/GridItemPresenter.java
new file mode 100644
index 0000000..1ab7e8d
--- /dev/null
+++ b/tests/leanbackjank/app/src/android/leanbackjank/app/presenter/GridItemPresenter.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.app.presenter;
+
+import android.graphics.Color;
+import android.support.v17.leanback.widget.Presenter;
+import android.view.Gravity;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import android.leanbackjank.app.R;
+import android.leanbackjank.app.ui.MainFragment;
+
+public class GridItemPresenter extends Presenter {
+ private static int GRID_ITEM_WIDTH = 200;
+ private static int GRID_ITEM_HEIGHT = 200;
+
+ private MainFragment mainFragment;
+
+ public GridItemPresenter(MainFragment mainFragment) {
+ this.mainFragment = mainFragment;
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent) {
+ TextView view = new TextView(parent.getContext());
+ view.setLayoutParams(new ViewGroup.LayoutParams(GRID_ITEM_WIDTH, GRID_ITEM_HEIGHT));
+ view.setFocusable(true);
+ view.setFocusableInTouchMode(true);
+ view.setBackgroundColor(
+ mainFragment.getResources().getColor(R.color.default_background, null));
+ view.setTextColor(Color.WHITE);
+ view.setGravity(Gravity.CENTER);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder viewHolder, Object item) {
+ ((TextView) viewHolder.view).setText((String) item);
+ }
+
+ @Override
+ public void onUnbindViewHolder(ViewHolder viewHolder) {
+ }
+}
diff --git a/tests/leanbackjank/app/src/android/leanbackjank/app/presenter/IconHeaderItemPresenter.java b/tests/leanbackjank/app/src/android/leanbackjank/app/presenter/IconHeaderItemPresenter.java
new file mode 100644
index 0000000..32dae35
--- /dev/null
+++ b/tests/leanbackjank/app/src/android/leanbackjank/app/presenter/IconHeaderItemPresenter.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.app.presenter;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.RowHeaderPresenter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import android.leanbackjank.app.R;
+
+public class IconHeaderItemPresenter extends RowHeaderPresenter {
+ private float mUnselectedAlpha;
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
+ mUnselectedAlpha = viewGroup.getResources()
+ .getFraction(R.fraction.lb_browse_header_unselect_alpha, 1, 1);
+ LayoutInflater inflater = (LayoutInflater) viewGroup.getContext()
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ View view = inflater.inflate(R.layout.icon_header_item, null);
+
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object o) {
+ HeaderItem headerItem = ((ListRow) o).getHeaderItem();
+ View rootView = viewHolder.view;
+
+ ImageView iconView = (ImageView) rootView.findViewById(R.id.header_icon);
+ Drawable icon = rootView.getResources().getDrawable(R.drawable.android_header, null);
+ iconView.setImageDrawable(icon);
+
+ TextView label = (TextView) rootView.findViewById(R.id.header_label);
+ label.setText(headerItem.getName());
+ }
+
+ @Override
+ public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
+ }
+
+ // TODO: TEMP - remove me when leanback onCreateViewHolder no longer sets the mUnselectAlpha,AND
+ // also assumes the xml inflation will return a RowHeaderView
+ @Override
+ protected void onSelectLevelChanged(RowHeaderPresenter.ViewHolder holder) {
+ // this is a temporary fix
+ holder.view.setAlpha(mUnselectedAlpha + holder.getSelectLevel() *
+ (1.0f - mUnselectedAlpha));
+ }
+}
diff --git a/tests/leanbackjank/app/src/android/leanbackjank/app/ui/MainActivity.java b/tests/leanbackjank/app/src/android/leanbackjank/app/ui/MainActivity.java
new file mode 100644
index 0000000..356c2ac
--- /dev/null
+++ b/tests/leanbackjank/app/src/android/leanbackjank/app/ui/MainActivity.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.app.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.leanbackjank.app.R;
+
+/**
+ * MainActivity class that loads MainFragment
+ */
+public class MainActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+
+ @Override
+ public boolean onSearchRequested() {
+ return false;
+ }
+}
diff --git a/tests/leanbackjank/app/src/android/leanbackjank/app/ui/MainFragment.java b/tests/leanbackjank/app/src/android/leanbackjank/app/ui/MainFragment.java
new file mode 100644
index 0000000..2119b2f
--- /dev/null
+++ b/tests/leanbackjank/app/src/android/leanbackjank/app/ui/MainFragment.java
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.app.ui;
+
+import android.content.Intent;
+import android.content.res.Resources.Theme;
+import android.leanbackjank.app.IntentKeys;
+import android.leanbackjank.app.R;
+import android.leanbackjank.app.data.VideoProvider;
+import android.leanbackjank.app.model.Movie;
+import android.leanbackjank.app.presenter.CardPresenter;
+import android.leanbackjank.app.presenter.GridItemPresenter;
+import android.leanbackjank.app.presenter.IconHeaderItemPresenter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v17.leanback.app.BackgroundManager;
+import android.support.v17.leanback.app.BrowseFragment;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.PresenterSelector;
+import android.util.DisplayMetrics;
+import android.view.View;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * Main class to show BrowseFragment with header and rows of videos
+ */
+public class MainFragment extends BrowseFragment {
+ private static final int NUM_ROWS = 20;
+ private final Handler mHandler = new Handler();
+ private Timer mAutoScrollTimer;
+ private int mAutoScrollCount;
+
+ private ArrayObjectAdapter mRowsAdapter;
+ private DisplayMetrics mMetrics;
+ private BackgroundManager mBackgroundManager;
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ buildRowAdapterItems(VideoProvider.buildMedia(NUM_ROWS));
+ prepareBackgroundManager();
+ setupUIElements();
+ setupEventListeners();
+ Intent intent = getActivity().getIntent();
+ if (intent.getExtras() != null) {
+ int initialDelay = intent.getExtras().getInt(IntentKeys.SCROLL_DELAY);
+ int scrollCount = intent.getExtras().getInt(IntentKeys.SCROLL_COUNT);
+ int scrollInterval = intent.getExtras().getInt(IntentKeys.SCROLL_INTERVAL);
+ if (scrollInterval != 0 && scrollCount != 0) {
+ startAutoScrollTimer(initialDelay, scrollInterval, scrollCount);
+ }
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ if (null != mAutoScrollTimer) {
+ mAutoScrollTimer.cancel();
+ mAutoScrollTimer = null;
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public void onStop() {
+ mBackgroundManager.release();
+ super.onStop();
+ }
+
+ private void prepareBackgroundManager() {
+ mBackgroundManager = BackgroundManager.getInstance(getActivity());
+ mBackgroundManager.attach(getActivity().getWindow());
+ mBackgroundManager.setDrawable(getActivity().getResources().getDrawable(
+ R.drawable.default_background, getContext().getTheme()));
+ mMetrics = new DisplayMetrics();
+ getActivity().getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
+ }
+
+ private void setupUIElements() {
+ setBadgeDrawable(getActivity().getResources().getDrawable(
+ R.drawable.videos_by_google_banner, getContext().getTheme()));
+ setTitle(getString(R.string.browse_title));
+ setHeadersState(HEADERS_ENABLED);
+ setHeadersTransitionOnBackEnabled(true);
+
+ Theme theme = getContext().getTheme();
+ setBrandColor(getResources().getColor(R.color.fastlane_background, theme));
+
+ setSearchAffordanceColor(getResources().getColor(R.color.search_opaque, theme));
+
+ setHeaderPresenterSelector(new PresenterSelector() {
+ @Override
+ public Presenter getPresenter(Object o) {
+ return new IconHeaderItemPresenter();
+ }
+ });
+ }
+
+ private void setupEventListeners() {
+ // Add lister to show the search button.
+ setOnSearchClickedListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ }
+ });
+ }
+
+ public void buildRowAdapterItems(HashMap<String, List<Movie>> data) {
+ mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+ CardPresenter cardPresenter = new CardPresenter();
+
+ int i = 0;
+
+ for (Map.Entry<String, List<Movie>> entry : data.entrySet()) {
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
+ List<Movie> list = entry.getValue();
+
+ for (int j = 0; j < list.size(); j++) {
+ listRowAdapter.add(list.get(j));
+ }
+ HeaderItem header = new HeaderItem(i, entry.getKey());
+ i++;
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+ }
+
+ HeaderItem gridHeader = new HeaderItem(i, getString(R.string.settings));
+
+ GridItemPresenter gridPresenter = new GridItemPresenter(this);
+ ArrayObjectAdapter gridRowAdapter = new ArrayObjectAdapter(gridPresenter);
+ for (int j = 0; j < 10; j++) {
+ gridRowAdapter.add(getString(R.string.grid_item_template, j));
+ }
+ mRowsAdapter.add(new ListRow(gridHeader, gridRowAdapter));
+
+ setAdapter(mRowsAdapter);
+ }
+
+ private class UpdateAutoScrollTask extends TimerTask {
+ @Override
+ public void run() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mAutoScrollCount == 0) {
+ mAutoScrollTimer.cancel();
+ return;
+ }
+ if (mAutoScrollCount % 2 == 0) {
+ setSelectedPosition(NUM_ROWS - 1);
+ } else {
+ setSelectedPosition(0);
+ }
+ mAutoScrollCount--;
+ }
+ });
+ }
+ }
+
+ private void startAutoScrollTimer(int initialDelay, int interval, int count) {
+ if (null != mAutoScrollTimer) {
+ mAutoScrollTimer.cancel();
+ }
+ mAutoScrollCount = count;
+ mAutoScrollTimer = new Timer();
+ mAutoScrollTimer.schedule(new UpdateAutoScrollTask(), initialDelay, interval);
+ }
+
+ public void selectRow(int row) {
+ setSelectedPosition(row);
+ }
+}
diff --git a/tests/leanbackjank/src/android/cts/leanbackjank/CtsDeviceLeanback.java b/tests/leanbackjank/src/android/cts/leanbackjank/CtsDeviceLeanback.java
deleted file mode 100644
index 241535e..0000000
--- a/tests/leanbackjank/src/android/cts/leanbackjank/CtsDeviceLeanback.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.leanbackjank;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.cts.jank.leanback.IntentKeys;
-import android.os.SystemClock;
-import android.support.test.jank.GfxMonitor;
-import android.support.test.jank.JankTest;
-import android.support.test.jank.WindowContentFrameStatsMonitor;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.Until;
-import android.util.Log;
-
-public class CtsDeviceLeanback extends CtsJankTestBase {
- private static final String TAG = "CtsDeviceLeanback";
- private static final int MILLIS_PER_SECOND = 1000;
- private static final long WAIT_TIMEOUT = 5 * MILLIS_PER_SECOND;
- private static final int SCROLL_COUNT = 100;
- private static final int SCROLL_INTERVAL_MILLIS = 200;
- private static final int PRE_SCROLL_DELAY_MILLIS = 0;
- private static final int PRE_SCROLL_IDLE_TIME = 2 * MILLIS_PER_SECOND;
- private static final int SAMPLING_DURATION_SECONDS = 3;
- private static final int SAMPLING_DURATION_MILLIS =
- SAMPLING_DURATION_SECONDS * MILLIS_PER_SECOND;
- private final static String APP_PACKAGE = "android.cts.jank.leanback";
- private final static String JAVA_PACKAGE = "android.cts.jank.leanback.ui";
- private final static String CLASS = JAVA_PACKAGE + ".MainActivity";
-
- private boolean shouldSkip() {
- PackageManager packageManager =
- getInstrumentation().getTargetContext().getPackageManager();
- if (!packageManager.hasSystemFeature(
- PackageManager.FEATURE_LEANBACK)) {
- return true;
- }
- return false;
- }
-
- @Override
- protected void runTest() throws Throwable {
- if (shouldSkip()) {
- return;
- }
- super.runTest();
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- if (shouldSkip()) {
- return;
- }
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setComponent(new ComponentName(APP_PACKAGE, CLASS));
-
- // Trigger automated scroll of the helper app.
- intent.putExtra(IntentKeys.SCROLL_DELAY, PRE_SCROLL_DELAY_MILLIS);
- intent.putExtra(IntentKeys.SCROLL_COUNT, SCROLL_COUNT);
- intent.putExtra(IntentKeys.SCROLL_INTERVAL, SCROLL_INTERVAL_MILLIS);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getInstrumentation().getTargetContext().startActivity(intent);
- if (!getUiDevice().wait(Until.hasObject(By.pkg(APP_PACKAGE)), WAIT_TIMEOUT)) {
- fail("Test helper app package not found on device");
- }
-
- // Wait until scroll animation starts.
- SystemClock.sleep(PRE_SCROLL_IDLE_TIME);
- }
-
- @Override
- protected void tearDown() throws Exception {
- getUiDevice().pressHome();
- super.tearDown();
- }
-
- // Requires at least 30 fps on average to pass the test.
- @JankTest(expectedFrames = 30 * SAMPLING_DURATION_SECONDS, defaultIterationCount = 2)
- @GfxMonitor(processName = APP_PACKAGE)
- @WindowContentFrameStatsMonitor
- public void testScrollingByTimer() {
- SystemClock.sleep(SAMPLING_DURATION_MILLIS);
- }
-}
diff --git a/tests/leanbackjank/src/android/cts/leanbackjank/CtsJankTestBase.java b/tests/leanbackjank/src/android/cts/leanbackjank/CtsJankTestBase.java
deleted file mode 100644
index 4de0702..0000000
--- a/tests/leanbackjank/src/android/cts/leanbackjank/CtsJankTestBase.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.
- */
-
-package android.cts.leanbackjank;
-
-import android.cts.util.DeviceReportLog;
-import android.os.Bundle;
-import android.support.test.jank.GfxMonitor;
-import android.support.test.jank.JankTestBase;
-import android.support.test.jank.WindowContentFrameStatsMonitor;
-import android.support.test.uiautomator.UiDevice;
-
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-
-public abstract class CtsJankTestBase extends JankTestBase {
-
- private UiDevice mDevice;
- private DeviceReportLog mLog;
-
- private void printIntValueWithKey(String source, Bundle metrics, String key,
- ResultType resultType, ResultUnit resultUnit) {
- if (!metrics.containsKey(key)) {
- return;
- }
- mLog.printValue(source, key, metrics.getInt(key), resultType, resultUnit);
- }
-
- private void printDoubleValueWithKey(String source, Bundle metrics, String key,
- ResultType resultType, ResultUnit resultUnit) {
- if (!metrics.containsKey(key)) {
- return;
- }
- mLog.printValue(source, key, metrics.getDouble(key), resultType, resultUnit);
- }
-
- @Override
- public void afterTest(Bundle metrics) {
- String source = String.format("%s#%s", getClass().getCanonicalName(), getName());
- printDoubleValueWithKey(source, metrics, WindowContentFrameStatsMonitor.KEY_AVG_FPS,
- ResultType.HIGHER_BETTER, ResultUnit.FPS);
- printDoubleValueWithKey(source, metrics,
- WindowContentFrameStatsMonitor.KEY_AVG_LONGEST_FRAME,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- printIntValueWithKey(source, metrics, WindowContentFrameStatsMonitor.KEY_MAX_NUM_JANKY,
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- mLog.printSummary(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY,
- metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY),
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
-
- printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_NUM_JANKY,
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_FRAME_TIME_90TH_PERCENTILE,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_FRAME_TIME_95TH_PERCENTILE,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_FRAME_TIME_99TH_PERCENTILE,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_MISSED_VSYNC,
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_SLOW_UI_THREAD,
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_SLOW_BITMAP_UPLOADS,
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_SLOW_DRAW,
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_HIGH_INPUT_LATENCY,
- ResultType.LOWER_BETTER, ResultUnit.COUNT);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mLog = new DeviceReportLog();
- // fix device orientation
- mDevice = UiDevice.getInstance(getInstrumentation());
- mDevice.setOrientationNatural();
- }
-
- @Override
- protected void tearDown() throws Exception {
- mLog.deliverReportToHost(getInstrumentation());
- // restore device orientation
- mDevice.unfreezeRotation();
- super.tearDown();
- }
-
- protected UiDevice getUiDevice() {
- return mDevice;
- }
-}
diff --git a/tests/leanbackjank/src/android/leanbackjank/cts/CtsDeviceLeanback.java b/tests/leanbackjank/src/android/leanbackjank/cts/CtsDeviceLeanback.java
new file mode 100644
index 0000000..c52fe09
--- /dev/null
+++ b/tests/leanbackjank/src/android/leanbackjank/cts/CtsDeviceLeanback.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.cts;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.leanbackjank.app.IntentKeys;
+import android.os.SystemClock;
+import android.support.test.jank.GfxMonitor;
+import android.support.test.jank.JankTest;
+import android.support.test.jank.WindowContentFrameStatsMonitor;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Until;
+import android.util.Log;
+
+public class CtsDeviceLeanback extends CtsJankTestBase {
+ private static final String TAG = "CtsDeviceLeanback";
+ private static final int MILLIS_PER_SECOND = 1000;
+ private static final long WAIT_TIMEOUT = 5 * MILLIS_PER_SECOND;
+ private static final int SCROLL_COUNT = 100;
+ private static final int SCROLL_INTERVAL_MILLIS = 200;
+ private static final int PRE_SCROLL_DELAY_MILLIS = 0;
+ private static final int PRE_SCROLL_IDLE_TIME = 2 * MILLIS_PER_SECOND;
+ private static final int SAMPLING_DURATION_SECONDS = 3;
+ private static final int SAMPLING_DURATION_MILLIS =
+ SAMPLING_DURATION_SECONDS * MILLIS_PER_SECOND;
+ private final static String APP_PACKAGE = "android.leanbackjank.app";
+ private final static String JAVA_PACKAGE = "android.leanbackjank.app.ui";
+ private final static String CLASS = JAVA_PACKAGE + ".MainActivity";
+
+ private boolean shouldSkip() {
+ PackageManager packageManager =
+ getInstrumentation().getTargetContext().getPackageManager();
+ if (!packageManager.hasSystemFeature(
+ PackageManager.FEATURE_LEANBACK)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ if (shouldSkip()) {
+ return;
+ }
+ super.runTest();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (shouldSkip()) {
+ return;
+ }
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setComponent(new ComponentName(APP_PACKAGE, CLASS));
+
+ // Trigger automated scroll of the helper app.
+ intent.putExtra(IntentKeys.SCROLL_DELAY, PRE_SCROLL_DELAY_MILLIS);
+ intent.putExtra(IntentKeys.SCROLL_COUNT, SCROLL_COUNT);
+ intent.putExtra(IntentKeys.SCROLL_INTERVAL, SCROLL_INTERVAL_MILLIS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getInstrumentation().getTargetContext().startActivity(intent);
+ if (!getUiDevice().wait(Until.hasObject(By.pkg(APP_PACKAGE)), WAIT_TIMEOUT)) {
+ fail("Test helper app package not found on device");
+ }
+
+ // Wait until scroll animation starts.
+ SystemClock.sleep(PRE_SCROLL_IDLE_TIME);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ getUiDevice().pressHome();
+ super.tearDown();
+ }
+
+ // Requires at least 30 fps on average to pass the test.
+ @JankTest(expectedFrames = 30 * SAMPLING_DURATION_SECONDS, defaultIterationCount = 2)
+ @GfxMonitor(processName = APP_PACKAGE)
+ @WindowContentFrameStatsMonitor
+ public void testScrollingByTimer() {
+ SystemClock.sleep(SAMPLING_DURATION_MILLIS);
+ }
+}
diff --git a/tests/leanbackjank/src/android/leanbackjank/cts/CtsJankTestBase.java b/tests/leanbackjank/src/android/leanbackjank/cts/CtsJankTestBase.java
new file mode 100644
index 0000000..77a1d1c
--- /dev/null
+++ b/tests/leanbackjank/src/android/leanbackjank/cts/CtsJankTestBase.java
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+package android.leanbackjank.cts;
+
+import android.cts.util.DeviceReportLog;
+import android.os.Bundle;
+import android.support.test.jank.GfxMonitor;
+import android.support.test.jank.JankTestBase;
+import android.support.test.jank.WindowContentFrameStatsMonitor;
+import android.support.test.uiautomator.UiDevice;
+
+import com.android.cts.util.ResultType;
+import com.android.cts.util.ResultUnit;
+
+public abstract class CtsJankTestBase extends JankTestBase {
+
+ private UiDevice mDevice;
+ private DeviceReportLog mLog;
+
+ private void printIntValueWithKey(String source, Bundle metrics, String key,
+ ResultType resultType, ResultUnit resultUnit) {
+ if (!metrics.containsKey(key)) {
+ return;
+ }
+ mLog.printValue(source, key, metrics.getInt(key), resultType, resultUnit);
+ }
+
+ private void printDoubleValueWithKey(String source, Bundle metrics, String key,
+ ResultType resultType, ResultUnit resultUnit) {
+ if (!metrics.containsKey(key)) {
+ return;
+ }
+ mLog.printValue(source, key, metrics.getDouble(key), resultType, resultUnit);
+ }
+
+ @Override
+ public void afterTest(Bundle metrics) {
+ String source = String.format("%s#%s", getClass().getCanonicalName(), getName());
+ printDoubleValueWithKey(source, metrics, WindowContentFrameStatsMonitor.KEY_AVG_FPS,
+ ResultType.HIGHER_BETTER, ResultUnit.FPS);
+ printDoubleValueWithKey(source, metrics,
+ WindowContentFrameStatsMonitor.KEY_AVG_LONGEST_FRAME,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ printIntValueWithKey(source, metrics, WindowContentFrameStatsMonitor.KEY_MAX_NUM_JANKY,
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ mLog.printSummary(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY,
+ metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY),
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+
+ printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_NUM_JANKY,
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_FRAME_TIME_90TH_PERCENTILE,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_FRAME_TIME_95TH_PERCENTILE,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_FRAME_TIME_99TH_PERCENTILE,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_MISSED_VSYNC,
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_SLOW_UI_THREAD,
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_SLOW_BITMAP_UPLOADS,
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_SLOW_DRAW,
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ printDoubleValueWithKey(source, metrics, GfxMonitor.KEY_AVG_HIGH_INPUT_LATENCY,
+ ResultType.LOWER_BETTER, ResultUnit.COUNT);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mLog = new DeviceReportLog();
+ // fix device orientation
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mDevice.setOrientationNatural();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mLog.deliverReportToHost(getInstrumentation());
+ // restore device orientation
+ mDevice.unfreezeRotation();
+ super.tearDown();
+ }
+
+ protected UiDevice getUiDevice() {
+ return mDevice;
+ }
+}
diff --git a/tests/libcore/Android.mk b/tests/libcore/Android.mk
new file mode 100644
index 0000000..cd1905d
--- /dev/null
+++ b/tests/libcore/Android.mk
@@ -0,0 +1,54 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsLibcoreTestCases
+
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests mockito-target
+
+LOCAL_JAVA_LIBRARIES := android-support-test android.test.runner bouncycastle conscrypt
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_JNI_SHARED_LIBRARIES := libjavacoretests
+
+# Include both the 32 and 64 bit versions of libjavacoretests,
+# where applicable.
+LOCAL_MULTILIB := both
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+# Copy the expectation files to CTS
+LOCAL_COMPATIBILITY_SUPPORT_FILES += \
+ ../../../art/tools/libcore_failures.txt:$(LOCAL_PACKAGE_NAME).failures.expectations \
+ ../../../libcore/expectations/brokentests.txt:$(LOCAL_PACKAGE_NAME).brokentests.expectations \
+ ../../../libcore/expectations/icebox.txt:$(LOCAL_PACKAGE_NAME).icebox.expectations \
+ ../../../libcore/expectations/knownfailures.txt:$(LOCAL_PACKAGE_NAME).knownfailures.expectations \
+ ../../../libcore/expectations/taggedtests.txt:$(LOCAL_PACKAGE_NAME).taggedtests.expectations
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/libcore/AndroidManifest.xml b/tests/libcore/AndroidManifest.xml
new file mode 100644
index 0000000..0389be6
--- /dev/null
+++ b/tests/libcore/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.libcore.cts">
+ <uses-permission android:name="android.permission.INTERNET" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.libcore.cts"
+ android:label="CTS Libcore test cases" />
+
+</manifest>
diff --git a/tests/libcore/AndroidTest.xml b/tests/libcore/AndroidTest.xml
new file mode 100644
index 0000000..e71669a
--- /dev/null
+++ b/tests/libcore/AndroidTest.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+<configuration description="Config for CTS Libcore test cases">
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/ctslibcore/java.io.tmpdir" />
+ <option name="run-command" value="mkdir -p /data/local/tmp/ctslibcore/user.home" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/ctslibcore" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="cts-dalvik-device-test-runner.jar->/data/local/tmp/ctslibcore/cts-dalvik-device-test-runner.jar" />
+ <option name="push" value="CtsLibcoreTestCases.apk->/data/local/tmp/ctslibcore/CtsLibcoreTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.compatibility.testtype.DalvikTest" >
+ <option name="run-name" value="CtsLibcoreTestCases" />
+ <option name="classpath" value="/data/local/tmp/ctslibcore/cts-dalvik-device-test-runner.jar" />
+ <option name="expectations" value="CtsLibcoreTestCases.brokentests.expectations" />
+ <option name="expectations" value="CtsLibcoreTestCases.icebox.expectations" />
+ <option name="expectations" value="CtsLibcoreTestCases.knownfailures.expectations" />
+ <option name="expectations" value="CtsLibcoreTestCases.taggedtests.expectations" />
+ <option name="expectations" value="CtsLibcoreTestCases.failures.expectations" />
+ <option name="dalvik-arg" value="-Djava.io.tmpdir=/data/local/tmp/ctslibcore/java.io.tmpdir" />
+ <option name="dalvik-arg" value="-Duser.home=/data/local/tmp/ctslibcore/user.home" />
+ <option name="dalvik-arg" value="-Duser.name=shell" />
+ <option name="dalvik-arg" value="-Duser.language=en" />
+ <option name="dalvik-arg" value="-Duser.region=US" />
+ <option name="dalvik-arg" value="-Xcheck:jni" />
+ <option name="dalvik-arg" value="-Xjnigreflimit:2000" />
+ <option name="runner-arg" value="--apk=/data/local/tmp/ctslibcore/CtsLibcoreTestCases.apk" />
+ </test>
+</configuration>
diff --git a/tests/libcore/runner/Android.mk b/tests/libcore/runner/Android.mk
new file mode 100644
index 0000000..6b441a5
--- /dev/null
+++ b/tests/libcore/runner/Android.mk
@@ -0,0 +1,15 @@
+# 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.
+
+include $(call all-subdir-makefiles)
\ No newline at end of file
diff --git a/tests/libcore/runner/device-side/Android.mk b/tests/libcore/runner/device-side/Android.mk
new file mode 100644
index 0000000..ac5b0ca
--- /dev/null
+++ b/tests/libcore/runner/device-side/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := cts-dalvik-device-test-runner
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
+
+# don't include these packages in any target
+LOCAL_MODULE_TAGS := optional
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+include $(BUILD_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/tests/libcore/runner/device-side/src/com/android/compatibility/dalvik/DalvikTestRunner.java b/tests/libcore/runner/device-side/src/com/android/compatibility/dalvik/DalvikTestRunner.java
new file mode 100644
index 0000000..56f48af
--- /dev/null
+++ b/tests/libcore/runner/device-side/src/com/android/compatibility/dalvik/DalvikTestRunner.java
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.dalvik;
+
+import com.android.compatibility.common.util.TestSuiteFilter;
+
+import dalvik.system.DexFile;
+import dalvik.system.PathClassLoader;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestListener;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Scanner;
+import java.util.Set;
+
+/**
+ * Runs tests against the Dalvik VM.
+ */
+public class DalvikTestRunner {
+
+ private static final String ABI = "--abi=";
+ private static final String APK = "--apk=";
+ private static final String INCLUDE = "--include-filter=";
+ private static final String EXCLUDE = "--exclude-filter=";
+ private static final String INCLUDE_FILE = "--include-filter-file=";
+ private static final String EXCLUDE_FILE = "--exclude-filter-file=";
+ private static final String JUNIT_IGNORE = "org.junit.Ignore";
+
+ public static void main(String[] args) {
+ String abiName = null;
+ Set<String> apks = new HashSet<>();
+ Set<String> includes = new HashSet<>();
+ Set<String> excludes = new HashSet<>();
+ for (String arg : args) {
+ if (arg.startsWith(ABI)) {
+ abiName = arg.substring(ABI.length());
+ } else if (arg.startsWith(APK)) {
+ apks.add(arg.substring(APK.length()));
+ } else if (arg.startsWith(INCLUDE)) {
+ for (String include : arg.substring(INCLUDE.length()).split(",")) {
+ includes.add(include);
+ }
+ } else if (arg.startsWith(EXCLUDE)) {
+ for (String exclude : arg.substring(EXCLUDE.length()).split(",")) {
+ excludes.add(exclude);
+ }
+ } else if (arg.startsWith(INCLUDE_FILE)) {
+ loadFilters(arg.substring(INCLUDE_FILE.length()), includes);
+ } else if (arg.startsWith(EXCLUDE_FILE)) {
+ loadFilters(arg.substring(EXCLUDE_FILE.length()), excludes);
+ }
+ }
+ TestListener listener = new DalvikTestListener();
+ List<Class<?>> classes = getClasses(apks, abiName);
+ TestSuite suite = TestSuiteFilter.createSuite(classes, includes, excludes);
+ int count = suite.countTestCases();
+ System.out.println(String.format("start-run:%d", count));
+ long start = System.currentTimeMillis();
+ TestResult result = new TestResult();
+ result.addListener(listener);
+ suite.run(result);
+ long end = System.currentTimeMillis();
+ System.out.println(String.format("end-run:%d", end - start));
+ }
+
+ private static void loadFilters(String filename, Set<String> filters) {
+ try {
+ Scanner in = new Scanner(new File(filename));
+ while (in.hasNextLine()) {
+ filters.add(in.nextLine());
+ }
+ in.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static List<Class<?>> getClasses(Set<String> apks, String abiName) {
+ List<Class<?>> classes = new ArrayList<>();
+ for (String apk : apks) {
+ try {
+ ClassLoader loader = createClassLoader(apk, abiName);
+ DexFile file = new DexFile(apk);
+ Enumeration<String> entries = file.entries();
+ while (entries.hasMoreElements()) {
+ String e = entries.nextElement();
+ Class<?> cls = loader.loadClass(e);
+ if (isTestClass(cls)) {
+ classes.add(cls);
+ }
+ }
+ } catch (IllegalAccessError | IOException | ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ return classes;
+ }
+
+ private static ClassLoader createClassLoader(String apk, String abiName) {
+ StringBuilder libPath = new StringBuilder();
+ libPath.append(apk).append("!/lib/").append(abiName);
+ return new PathClassLoader(apk, libPath.toString(), DalvikTestRunner.class.getClassLoader());
+ }
+
+ private static boolean isTestClass(Class<?> cls) {
+ // FIXME(b/25154702): have to have a null check here because some
+ // classes such as
+ // SQLite.JDBC2z.JDBCPreparedStatement can be found in the classes.dex
+ // by DexFile.entries
+ // but trying to load them with DexFile.loadClass returns null.
+ if (cls == null) {
+ return false;
+ }
+ for (Annotation a : cls.getAnnotations()) {
+ if (a.annotationType().getName().equals(JUNIT_IGNORE)) {
+ return false;
+ }
+ }
+ // TODO: Add junit4 support here
+ int modifiers = cls.getModifiers();
+ return (Test.class.isAssignableFrom(cls)
+ && Modifier.isPublic(modifiers)
+ && !Modifier.isStatic(modifiers)
+ && !Modifier.isInterface(modifiers)
+ && !Modifier.isAbstract(modifiers));
+ }
+
+ // TODO: expand this to setup and teardown things needed by Dalvik tests.
+ private static class DalvikTestListener implements TestListener {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void startTest(Test test) {
+ System.out.println(String.format("start-test:%s", getId(test)));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void endTest(Test test) {
+ System.out.println(String.format("end-test:%s", getId(test)));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addFailure(Test test, AssertionFailedError error) {
+ System.out.println(String.format("failure:%s", stringify(error)));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addError(Test test, Throwable error) {
+ System.out.println(String.format("failure:%s", stringify(error)));
+ }
+
+ private String getId(Test test) {
+ String className = test.getClass().getName();
+ if (test instanceof TestCase) {
+ return String.format("%s#%s", className, ((TestCase) test).getName());
+ }
+ return className;
+ }
+
+ private String stringify(Throwable error) {
+ return Arrays.toString(error.getStackTrace()).replaceAll("\n", " ");
+ }
+ }
+}
diff --git a/tests/libcore/runner/host-side/Android.mk b/tests/libcore/runner/host-side/Android.mk
new file mode 100644
index 0000000..a0756cb
--- /dev/null
+++ b/tests/libcore/runner/host-side/Android.mk
@@ -0,0 +1,33 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := cts-dalvik-host-test-runner
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed_v2 tradefed-prebuilt compatibility-host-util
+
+LOCAL_STATIC_JAVA_LIBRARIES := vogarexpectlib
+
+# don't include these packages in any target
+LOCAL_MODULE_TAGS := optional
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+include $(BUILD_HOST_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/tests/libcore/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java b/tests/libcore/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
new file mode 100644
index 0000000..4fc711c
--- /dev/null
+++ b/tests/libcore/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
@@ -0,0 +1,269 @@
+/*
+ * 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.
+ */
+
+package com.android.compatibility.testtype;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.ddmlib.IShellOutputReceiver;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmlib.MultiLineReceiver;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.ITestFilterReceiver;
+import com.android.tradefed.util.ArrayUtil;
+
+import vogar.ExpectationStore;
+import vogar.ModeId;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A wrapper to run tests against Dalvik.
+ */
+public class DalvikTest implements IAbiReceiver, IBuildReceiver, IDeviceTest, IRemoteTest,
+ ITestFilterReceiver {
+
+ private static final String TAG = DalvikTest.class.getSimpleName();
+
+ // Command to run the VM, args are bitness, classpath, dalvik-args, abi, runner-args,
+ // include and exclude filters, and exclude filters file.
+ private static final String COMMAND = "dalvikvm%s -classpath %s %s "
+ + "com.android.compatibility.dalvik.DalvikTestRunner --abi=%s %s %s %s %s %s";
+ private static final String INCLUDE_FILE = "/data/local/tmp/ctslibcore/includes";
+ private static final String EXCLUDE_FILE = "/data/local/tmp/ctslibcore/excludes";
+ private static String START_RUN = "start-run";
+ private static String END_RUN = "end-run";
+ private static String START_TEST = "start-test";
+ private static String END_TEST = "end-test";
+ private static String FAILURE = "failure";
+
+ @Option(name = "run-name", description = "The name to use when reporting results")
+ private String mRunName;
+
+ @Option(name = "expectations", description = "The names of the expectation files")
+ private Set<String> mExpectations = new HashSet<>();
+
+ @Option(name = "classpath", description = "Holds the paths to search when loading tests")
+ private List<String> mClasspath = new ArrayList<>();
+
+ @Option(name = "dalvik-arg", description = "Holds arguments to pass to Dalvik")
+ private List<String> mDalvikArgs = new ArrayList<>();
+
+ @Option(name = "runner-arg",
+ description = "Holds arguments to pass to the device-side test runner")
+ private List<String> mRunnerArgs = new ArrayList<>();
+
+ @Option(name = "include-filter",
+ description = "The include filters of the test name to run.")
+ private List<String> mIncludeFilters = new ArrayList<>();
+
+ @Option(name = "exclude-filter",
+ description = "The exclude filters of the test name to run.")
+ private List<String> mExcludeFilters = new ArrayList<>();
+
+ private IAbi mAbi;
+ private CompatibilityBuildHelper mBuildHelper;
+ private ITestDevice mDevice;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo build) {
+ mBuildHelper = new CompatibilityBuildHelper(build);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setDevice(ITestDevice device) {
+ mDevice = device;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ITestDevice getDevice() {
+ return mDevice;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addIncludeFilter(String filter) {
+ mIncludeFilters.add(filter);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addAllIncludeFilters(List<String> filters) {
+ mIncludeFilters.addAll(filters);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addExcludeFilter(String filter) {
+ mExcludeFilters.add(filter);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addAllExcludeFilters(List<String> filters) {
+ mExcludeFilters.addAll(filters);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run(final ITestInvocationListener listener) throws DeviceNotAvailableException {
+ String abiName = mAbi.getName();
+ String bitness = AbiUtils.getBitness(abiName);
+
+ File temp = null;
+ PrintWriter out = null;
+ try {
+ Set<File> expectationFiles = new HashSet<>();
+ for (String file : mExpectations) {
+ expectationFiles.add(new File(mBuildHelper.getTestsDir(), file));
+ }
+ ExpectationStore store = ExpectationStore.parse(expectationFiles, ModeId.DEVICE);
+
+ // Work around because there are to many expectations to pass via command line
+ temp = File.createTempFile("excludes", "txt");
+ out = new PrintWriter(temp);
+ for (String exclude : store.getAllFailures().keySet()) {
+ out.println(exclude);
+ }
+ for (String exclude : store.getAllOutComes().keySet()) {
+ out.println(exclude);
+ }
+ out.flush();
+ if (!mDevice.pushFile(temp, EXCLUDE_FILE)) {
+ Log.logAndDisplay(LogLevel.ERROR, TAG, "Couldn't push file: " + temp);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ temp.delete();
+ }
+
+ // Create command
+ String dalvikArgs = ArrayUtil.join(" ", mDalvikArgs);
+ String runnerArgs = ArrayUtil.join(" ", mRunnerArgs);
+ // Filters
+ StringBuilder includeFilters = new StringBuilder();
+ if (!mIncludeFilters.isEmpty()) {
+ includeFilters.append("--include-filter=");
+ includeFilters.append(ArrayUtil.join(",", mIncludeFilters));
+ }
+ StringBuilder excludeFilters = new StringBuilder();
+ if (!mExcludeFilters.isEmpty()) {
+ excludeFilters.append("--exclude-filter=");
+ excludeFilters.append(ArrayUtil.join(",", mExcludeFilters));
+ }
+ // Filter files
+ String includeFile = ""; // String.format("--include-filter-file=%s", INCLUDE);
+ String excludeFile = String.format("--exclude-filter-file=%s", EXCLUDE_FILE);
+ String command = String.format(COMMAND, bitness,
+ ArrayUtil.join(File.pathSeparator, mClasspath),
+ dalvikArgs, abiName, runnerArgs,
+ includeFilters, excludeFilters, includeFile, excludeFile);
+ IShellOutputReceiver receiver = new MultiLineReceiver() {
+ private TestIdentifier test;
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+
+ @Override
+ public void processNewLines(String[] lines) {
+ for (String line : lines) {
+ String[] parts = line.split(":");
+ String tag = parts[0];
+ if (tag.equals(START_RUN)) {
+ listener.testRunStarted(mRunName, Integer.parseInt(parts[1]));
+ } else if (tag.equals(END_RUN)) {
+ listener.testRunEnded(Integer.parseInt(parts[1]),
+ new HashMap<String, String>());
+ } else if (tag.equals(START_TEST)) {
+ test = getTestIdentifier(parts[1]);
+ listener.testStarted(test);
+ } else if (tag.equals(FAILURE)) {
+ listener.testFailed(test, parts[1]);
+ } else if (tag.equals(END_TEST)) {
+ listener.testEnded(getTestIdentifier(parts[1]),
+ new HashMap<String, String>());
+ } else {
+ Log.logAndDisplay(LogLevel.INFO, TAG, line);
+ }
+ }
+ }
+
+ private TestIdentifier getTestIdentifier(String name) {
+ String[] parts = name.split("#");
+ String className = parts[0];
+ String testName = "";
+ if (parts.length > 1) {
+ testName = parts[1];
+ }
+ return new TestIdentifier(className, testName);
+ }
+
+ };
+ mDevice.executeShellCommand(command, receiver, 1, TimeUnit.HOURS, 1);
+ }
+
+}
diff --git a/tests/netlegacy22.api/Android.mk b/tests/netlegacy22.api/Android.mk
index 68fd6f8..c08a5a8 100644
--- a/tests/netlegacy22.api/Android.mk
+++ b/tests/netlegacy22.api/Android.mk
@@ -29,4 +29,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/netlegacy22.api/AndroidManifest.xml b/tests/netlegacy22.api/AndroidManifest.xml
index f13805c..e900ceb 100644
--- a/tests/netlegacy22.api/AndroidManifest.xml
+++ b/tests/netlegacy22.api/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.netlegacy22.api">
+ package="android.netlegacy22.api.cts">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -30,7 +30,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.netlegacy22.api"
+ android:targetPackage="android.netlegacy22.api.cts"
android:label="CTS tests of legacy android.net APIs as of API 22">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/netlegacy22.api/AndroidTest.xml b/tests/netlegacy22.api/AndroidTest.xml
new file mode 100644
index 0000000..b40f21a
--- /dev/null
+++ b/tests/netlegacy22.api/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS Legacy android.net APIs test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsNetTestCasesLegacyApi22.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.netlegacy22.api.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/netlegacy22.permission/Android.mk b/tests/netlegacy22.permission/Android.mk
index fff9d85..37a7cde 100644
--- a/tests/netlegacy22.permission/Android.mk
+++ b/tests/netlegacy22.permission/Android.mk
@@ -29,4 +29,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/netlegacy22.permission/AndroidManifest.xml b/tests/netlegacy22.permission/AndroidManifest.xml
index cd1d2ba..af22b47 100644
--- a/tests/netlegacy22.permission/AndroidManifest.xml
+++ b/tests/netlegacy22.permission/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.netlegacy22.permission">
+ package="android.netlegacy22.permission.cts">
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<application>
@@ -41,7 +41,7 @@
relies on hidden APIs.
-->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.netlegacy22.permission"
+ android:targetPackage="android.netlegacy22.permission.cts"
android:label="CTS tests of legacy android.net permissions as of API 22">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/netlegacy22.permission/AndroidTest.xml b/tests/netlegacy22.permission/AndroidTest.xml
new file mode 100644
index 0000000..490e979
--- /dev/null
+++ b/tests/netlegacy22.permission/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS Legacy android.net Permission test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsNetTestCasesLegacyPermission22.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.netlegacy22.permission.cts" />
+ </test>
+</configuration>
diff --git a/tests/openglperf2/Android.mk b/tests/openglperf2/Android.mk
new file mode 100644
index 0000000..a0488c2
--- /dev/null
+++ b/tests/openglperf2/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2013 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner
+
+LOCAL_JNI_SHARED_LIBRARIES := libctsopengl_jni
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsOpenGlPerf2TestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/openglperf2/AndroidManifest.xml b/tests/openglperf2/AndroidManifest.xml
new file mode 100644
index 0000000..b1051a4d
--- /dev/null
+++ b/tests/openglperf2/AndroidManifest.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.opengl2.cts"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="17" />
+
+ <uses-feature
+ android:glEsVersion="0x00020000"
+ android:required="true" />
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+ <application android:allowBackup="false" >
+ <uses-library android:name="android.test.runner" />
+
+ <activity
+ android:name=".primitive.GLPrimitiveActivity"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".reference.GLReferenceActivity"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".reference.GLGameActivity"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:label="OpenGL ES Benchmark"
+ android:targetPackage="android.opengl2.cts" />
+
+</manifest>
\ No newline at end of file
diff --git a/tests/openglperf2/AndroidTest.xml b/tests/openglperf2/AndroidTest.xml
new file mode 100644
index 0000000..b4ca796
--- /dev/null
+++ b/tests/openglperf2/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS OpenGL test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsOpenGlPerf2TestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.opengl2.cts" />
+ <option name="runtime-hint" value="4m" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/suite/cts/deviceTests/opengl/README b/tests/openglperf2/README
similarity index 100%
rename from suite/cts/deviceTests/opengl/README
rename to tests/openglperf2/README
diff --git a/suite/cts/deviceTests/opengl/assets/fragment/basic b/tests/openglperf2/assets/fragment/basic
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/fragment/basic
rename to tests/openglperf2/assets/fragment/basic
diff --git a/suite/cts/deviceTests/opengl/assets/fragment/blur b/tests/openglperf2/assets/fragment/blur
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/fragment/blur
rename to tests/openglperf2/assets/fragment/blur
diff --git a/suite/cts/deviceTests/opengl/assets/fragment/perspective b/tests/openglperf2/assets/fragment/perspective
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/fragment/perspective
rename to tests/openglperf2/assets/fragment/perspective
diff --git a/suite/cts/deviceTests/opengl/assets/fragment/water b/tests/openglperf2/assets/fragment/water
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/fragment/water
rename to tests/openglperf2/assets/fragment/water
diff --git a/suite/cts/deviceTests/opengl/assets/mesh/arc.cob b/tests/openglperf2/assets/mesh/arc.cob
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/mesh/arc.cob
rename to tests/openglperf2/assets/mesh/arc.cob
Binary files differ
diff --git a/suite/cts/deviceTests/opengl/assets/mesh/fish.cob b/tests/openglperf2/assets/mesh/fish.cob
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/mesh/fish.cob
rename to tests/openglperf2/assets/mesh/fish.cob
Binary files differ
diff --git a/suite/cts/deviceTests/opengl/assets/mesh/plane.cob b/tests/openglperf2/assets/mesh/plane.cob
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/mesh/plane.cob
rename to tests/openglperf2/assets/mesh/plane.cob
Binary files differ
diff --git a/suite/cts/deviceTests/opengl/assets/texture/arc.png b/tests/openglperf2/assets/texture/arc.png
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/texture/arc.png
rename to tests/openglperf2/assets/texture/arc.png
Binary files differ
diff --git a/suite/cts/deviceTests/opengl/assets/texture/background.png b/tests/openglperf2/assets/texture/background.png
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/texture/background.png
rename to tests/openglperf2/assets/texture/background.png
Binary files differ
diff --git a/suite/cts/deviceTests/opengl/assets/texture/fish.png b/tests/openglperf2/assets/texture/fish.png
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/texture/fish.png
rename to tests/openglperf2/assets/texture/fish.png
Binary files differ
diff --git a/suite/cts/deviceTests/opengl/assets/texture/fish_dark.png b/tests/openglperf2/assets/texture/fish_dark.png
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/texture/fish_dark.png
rename to tests/openglperf2/assets/texture/fish_dark.png
Binary files differ
diff --git a/suite/cts/deviceTests/opengl/assets/texture/water1.png b/tests/openglperf2/assets/texture/water1.png
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/texture/water1.png
rename to tests/openglperf2/assets/texture/water1.png
Binary files differ
diff --git a/suite/cts/deviceTests/opengl/assets/texture/water2.png b/tests/openglperf2/assets/texture/water2.png
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/texture/water2.png
rename to tests/openglperf2/assets/texture/water2.png
Binary files differ
diff --git a/suite/cts/deviceTests/opengl/assets/vertex/basic b/tests/openglperf2/assets/vertex/basic
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/vertex/basic
rename to tests/openglperf2/assets/vertex/basic
diff --git a/suite/cts/deviceTests/opengl/assets/vertex/blur b/tests/openglperf2/assets/vertex/blur
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/vertex/blur
rename to tests/openglperf2/assets/vertex/blur
diff --git a/suite/cts/deviceTests/opengl/assets/vertex/perspective b/tests/openglperf2/assets/vertex/perspective
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/vertex/perspective
rename to tests/openglperf2/assets/vertex/perspective
diff --git a/suite/cts/deviceTests/opengl/assets/vertex/water b/tests/openglperf2/assets/vertex/water
similarity index 100%
rename from suite/cts/deviceTests/opengl/assets/vertex/water
rename to tests/openglperf2/assets/vertex/water
diff --git a/suite/cts/deviceTests/opengl/cob_exporter.py b/tests/openglperf2/cob_exporter.py
similarity index 100%
rename from suite/cts/deviceTests/opengl/cob_exporter.py
rename to tests/openglperf2/cob_exporter.py
diff --git a/suite/cts/deviceTests/opengl/jni/Android.mk b/tests/openglperf2/jni/Android.mk
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/Android.mk
rename to tests/openglperf2/jni/Android.mk
diff --git a/suite/cts/deviceTests/opengl/jni/Trace.h b/tests/openglperf2/jni/Trace.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/Trace.h
rename to tests/openglperf2/jni/Trace.h
diff --git a/tests/openglperf2/jni/graphics/GLUtils.cpp b/tests/openglperf2/jni/graphics/GLUtils.cpp
new file mode 100644
index 0000000..7786447
--- /dev/null
+++ b/tests/openglperf2/jni/graphics/GLUtils.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include "GLUtils.h"
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include <android/asset_manager_jni.h>
+
+#define LOG_TAG "CTS_OPENGL"
+#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+static JNIEnv* sEnv = NULL;
+static jobject sAssetManager = NULL;
+
+void GLUtils::setEnvAndAssetManager(JNIEnv* env, jobject assetManager) {
+ sEnv = env;
+ sAssetManager = assetManager;
+}
+
+static AAsset* loadAsset(const char* path) {
+ AAssetManager* nativeManager = AAssetManager_fromJava(sEnv, sAssetManager);
+ if (nativeManager == NULL) {
+ return NULL;
+ }
+ return AAssetManager_open(nativeManager, path, AASSET_MODE_UNKNOWN);;
+}
+
+char* GLUtils::openTextFile(const char* path) {
+ AAsset* asset = loadAsset(path);
+ if (asset == NULL) {
+ ALOGE("Couldn't load %s", path);
+ return NULL;
+ }
+ off_t length = AAsset_getLength(asset);
+ char* buffer = new char[length + 1];
+ int num = AAsset_read(asset, buffer, length);
+ AAsset_close(asset);
+ if (num != length) {
+ ALOGE("Couldn't read %s", path);
+ delete[] buffer;
+ return NULL;
+ }
+ buffer[length] = '\0';
+ return buffer;
+}
+
+GLuint GLUtils::loadTexture(const char* path) {
+ GLuint textureId = 0;
+ jclass activityClass = sEnv->FindClass("android/opengl2/cts/reference/GLGameActivity");
+ if (activityClass == NULL) {
+ ALOGE("Couldn't find activity class");
+ return -1;
+ }
+ jmethodID loadTexture = sEnv->GetStaticMethodID(activityClass, "loadTexture",
+ "(Landroid/content/res/AssetManager;Ljava/lang/String;)I");
+ if (loadTexture == NULL) {
+ ALOGE("Couldn't find loadTexture method");
+ return -1;
+ }
+ jstring pathStr = sEnv->NewStringUTF(path);
+ textureId = sEnv->CallStaticIntMethod(activityClass, loadTexture, sAssetManager, pathStr);
+ sEnv->DeleteLocalRef(pathStr);
+ return textureId;
+}
+
+static int readInt(char* b) {
+ unsigned char* ub = (unsigned char*) b;
+ return (((int) ub[0]) << 24) | (((int) ub[1]) << 16) | (((int) ub[2]) << 8) | ((int) ub[3]);
+}
+
+static float readFloat(char* b) {
+ union {
+ int input;
+ float output;
+ } data;
+ data.input = readInt(b);
+ return data.output;
+}
+
+Mesh* GLUtils::loadMesh(const char* path) {
+ char* buffer = openTextFile(path);
+ if (buffer == NULL) {
+ return NULL;
+ }
+ int index = 0;
+ int numVertices = readInt(buffer + index);
+ index += 4;
+ float* vertices = new float[numVertices * 3];
+ float* normals = new float[numVertices * 3];
+ float* texCoords = new float[numVertices * 2];
+ for (int i = 0; i < numVertices; i++) {
+ // Vertices
+ int vIndex = i * 3;
+ vertices[vIndex + 0] = readFloat(buffer + index);
+ index += 4;
+ vertices[vIndex + 1] = readFloat(buffer + index);
+ index += 4;
+ vertices[vIndex + 2] = readFloat(buffer + index);
+ index += 4;
+ // Normals
+ normals[vIndex + 0] = readFloat(buffer + index);
+ index += 4;
+ normals[vIndex + 1] = readFloat(buffer + index);
+ index += 4;
+ normals[vIndex + 2] = readFloat(buffer + index);
+ index += 4;
+ // Texture Coordinates
+ int tIndex = i * 2;
+ texCoords[tIndex + 0] = readFloat(buffer + index);
+ index += 4;
+ texCoords[tIndex + 1] = readFloat(buffer + index);
+ index += 4;
+ }
+ return new Mesh(vertices, normals, texCoords, numVertices);
+}
+
+// Loads the given source code as a shader of the given type.
+static GLuint loadShader(GLenum shaderType, const char** source) {
+ GLuint shader = glCreateShader(shaderType);
+ if (shader) {
+ glShaderSource(shader, 1, source, NULL);
+ glCompileShader(shader);
+ GLint compiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ GLint infoLen = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 0) {
+ char* infoLog = (char*) malloc(sizeof(char) * infoLen);
+ glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
+ ALOGE("Error compiling shader:\n%s\n", infoLog);
+ free(infoLog);
+ }
+ glDeleteShader(shader);
+ shader = 0;
+ }
+ }
+ return shader;
+}
+
+GLuint GLUtils::createProgram(const char** vertexSource, const char** fragmentSource) {
+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource);
+ if (!vertexShader) {
+ return 0;
+ }
+
+ GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
+ if (!fragmentShader) {
+ return 0;
+ }
+
+ GLuint program = glCreateProgram();
+ if (program) {
+ glAttachShader(program, vertexShader);
+ glAttachShader(program, fragmentShader);
+
+ GLint linkStatus;
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+ if (!linkStatus) {
+ GLint infoLen = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 0) {
+ char* infoLog = (char*) malloc(sizeof(char) * infoLen);
+ glGetProgramInfoLog(program, infoLen, NULL, infoLog);
+ ALOGE("Error linking program:\n%s\n", infoLog);
+ free(infoLog);
+ }
+ glDeleteProgram(program);
+ program = 0;
+ }
+ }
+ return program;
+}
+
+double GLUtils::currentTimeMillis() {
+ struct timeval tv;
+ gettimeofday(&tv, (struct timezone *) NULL);
+ return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
+}
+
+// Rounds a number up to the smallest power of 2 that is greater than or equal to x.
+int GLUtils::roundUpToSmallestPowerOf2(int x) {
+ if (x < 0) {
+ return 0;
+ }
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return x + 1;
+}
+
+GLuint GLUtils::genTexture(int texWidth, int texHeight, int fill) {
+ GLuint textureId = 0;
+ int w = roundUpToSmallestPowerOf2(texWidth);
+ int h = roundUpToSmallestPowerOf2(texHeight);
+ uint32_t* m = new uint32_t[w * h];
+ if (m != NULL) {
+ uint32_t* d = m;
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ if (fill == RANDOM_FILL) {
+ *d = 0xff000000 | ((y & 0xff) << 16) | ((x & 0xff) << 8) | ((x + y) & 0xff);
+ } else {
+ *d = 0xff000000 | fill;
+ }
+ d++;
+ }
+ }
+ glGenTextures(1, &textureId);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, m);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ }
+ delete[] m;
+ return textureId;
+}
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/GLUtils.h b/tests/openglperf2/jni/graphics/GLUtils.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/GLUtils.h
rename to tests/openglperf2/jni/graphics/GLUtils.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Matrix.cpp b/tests/openglperf2/jni/graphics/Matrix.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Matrix.cpp
rename to tests/openglperf2/jni/graphics/Matrix.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Matrix.h b/tests/openglperf2/jni/graphics/Matrix.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Matrix.h
rename to tests/openglperf2/jni/graphics/Matrix.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Mesh.cpp b/tests/openglperf2/jni/graphics/Mesh.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Mesh.cpp
rename to tests/openglperf2/jni/graphics/Mesh.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Mesh.h b/tests/openglperf2/jni/graphics/Mesh.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Mesh.h
rename to tests/openglperf2/jni/graphics/Mesh.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/MeshNode.cpp b/tests/openglperf2/jni/graphics/MeshNode.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/MeshNode.cpp
rename to tests/openglperf2/jni/graphics/MeshNode.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/MeshNode.h b/tests/openglperf2/jni/graphics/MeshNode.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/MeshNode.h
rename to tests/openglperf2/jni/graphics/MeshNode.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/PerspectiveMeshNode.cpp b/tests/openglperf2/jni/graphics/PerspectiveMeshNode.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/PerspectiveMeshNode.cpp
rename to tests/openglperf2/jni/graphics/PerspectiveMeshNode.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/PerspectiveMeshNode.h b/tests/openglperf2/jni/graphics/PerspectiveMeshNode.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/PerspectiveMeshNode.h
rename to tests/openglperf2/jni/graphics/PerspectiveMeshNode.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/PerspectiveProgram.cpp b/tests/openglperf2/jni/graphics/PerspectiveProgram.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/PerspectiveProgram.cpp
rename to tests/openglperf2/jni/graphics/PerspectiveProgram.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/PerspectiveProgram.h b/tests/openglperf2/jni/graphics/PerspectiveProgram.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/PerspectiveProgram.h
rename to tests/openglperf2/jni/graphics/PerspectiveProgram.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Program.cpp b/tests/openglperf2/jni/graphics/Program.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Program.cpp
rename to tests/openglperf2/jni/graphics/Program.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Program.h b/tests/openglperf2/jni/graphics/Program.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Program.h
rename to tests/openglperf2/jni/graphics/Program.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/ProgramNode.cpp b/tests/openglperf2/jni/graphics/ProgramNode.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/ProgramNode.cpp
rename to tests/openglperf2/jni/graphics/ProgramNode.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/ProgramNode.h b/tests/openglperf2/jni/graphics/ProgramNode.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/ProgramNode.h
rename to tests/openglperf2/jni/graphics/ProgramNode.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Renderer.cpp b/tests/openglperf2/jni/graphics/Renderer.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Renderer.cpp
rename to tests/openglperf2/jni/graphics/Renderer.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Renderer.h b/tests/openglperf2/jni/graphics/Renderer.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Renderer.h
rename to tests/openglperf2/jni/graphics/Renderer.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/SceneGraphNode.cpp b/tests/openglperf2/jni/graphics/SceneGraphNode.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/SceneGraphNode.cpp
rename to tests/openglperf2/jni/graphics/SceneGraphNode.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/SceneGraphNode.h b/tests/openglperf2/jni/graphics/SceneGraphNode.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/SceneGraphNode.h
rename to tests/openglperf2/jni/graphics/SceneGraphNode.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/TexturedMeshNode.cpp b/tests/openglperf2/jni/graphics/TexturedMeshNode.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/TexturedMeshNode.cpp
rename to tests/openglperf2/jni/graphics/TexturedMeshNode.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/TexturedMeshNode.h b/tests/openglperf2/jni/graphics/TexturedMeshNode.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/TexturedMeshNode.h
rename to tests/openglperf2/jni/graphics/TexturedMeshNode.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/TransformationNode.cpp b/tests/openglperf2/jni/graphics/TransformationNode.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/TransformationNode.cpp
rename to tests/openglperf2/jni/graphics/TransformationNode.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/TransformationNode.h b/tests/openglperf2/jni/graphics/TransformationNode.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/TransformationNode.h
rename to tests/openglperf2/jni/graphics/TransformationNode.h
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Vector2D.cpp b/tests/openglperf2/jni/graphics/Vector2D.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Vector2D.cpp
rename to tests/openglperf2/jni/graphics/Vector2D.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/Vector2D.h b/tests/openglperf2/jni/graphics/Vector2D.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/graphics/Vector2D.h
rename to tests/openglperf2/jni/graphics/Vector2D.h
diff --git a/tests/openglperf2/jni/primitive/GLPrimitive.cpp b/tests/openglperf2/jni/primitive/GLPrimitive.cpp
new file mode 100644
index 0000000..825cadf
--- /dev/null
+++ b/tests/openglperf2/jni/primitive/GLPrimitive.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+#include <jni.h>
+
+#include <stdlib.h>
+
+#include <android/native_window.h>
+#include <android/native_window_jni.h>
+
+#include <graphics/GLUtils.h>
+#include <graphics/Renderer.h>
+
+#include "fullpipeline/FullPipelineRenderer.h"
+#include "pixeloutput/PixelOutputRenderer.h"
+#include "shaderperf/ShaderPerfRenderer.h"
+#include "contextswitch/ContextSwitchRenderer.h"
+
+// Holds the current benchmark's renderer.
+Renderer* gRenderer = NULL;
+ANativeWindow* gNativeWindow = NULL;
+
+enum {
+ FULL_PIPELINE_BENCHMARK = 0,
+ PIXEL_OUTPUT_BENCHMARK = 1,
+ SHADER_PERF_BENCHMARK = 2,
+ CONTEXT_SWITCH_BENCHMARK = 3
+};
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_android_opengl2_cts_primitive_GLPrimitiveActivity_startBenchmark(
+ JNIEnv* env, jclass /*clazz*/, jint workload, jint numFrames, jdoubleArray frameTimes) {
+ if (gRenderer == NULL) {
+ return false;
+ }
+
+ // Sets up the renderer.
+ bool success = gRenderer->setUp(workload);
+
+ // Records the start time.
+ double start = GLUtils::currentTimeMillis();
+
+ // Offscreen renders 100 tiles per frame so reduce the number of frames to render.
+ if (gRenderer->mOffscreen) {
+ numFrames /= Renderer::OFFSCREEN_INNER_FRAMES;
+ }
+
+ // Draw off the screen.
+ for (int i = 0; i < numFrames && success; i++) {
+ // Draw a frame.
+ success = gRenderer->draw();
+ }
+
+ // Records the end time.
+ double end = GLUtils::currentTimeMillis();
+
+ // Sets the times in the Java array.
+ double times[] = {start, end};
+ env->SetDoubleArrayRegion(frameTimes, 0, 2, times);
+
+ success = gRenderer->tearDown() && success;
+ return success;
+}
+
+// The following functions create the renderers for the various benchmarks.
+extern "C" JNIEXPORT void JNICALL
+Java_android_opengl2_cts_primitive_GLPrimitiveActivity_setupBenchmark(
+ JNIEnv* env, jclass /*clazz*/, jobject surface, jint benchmark,
+ jboolean offscreen) {
+ gNativeWindow = ANativeWindow_fromSurface(env, surface);
+ switch (benchmark) {
+ case FULL_PIPELINE_BENCHMARK:
+ gRenderer = new FullPipelineRenderer(gNativeWindow, offscreen);
+ break;
+ case PIXEL_OUTPUT_BENCHMARK:
+ gRenderer = new PixelOutputRenderer(gNativeWindow, offscreen);
+ break;
+ case SHADER_PERF_BENCHMARK:
+ gRenderer = new ShaderPerfRenderer(gNativeWindow, offscreen);
+ break;
+ case CONTEXT_SWITCH_BENCHMARK:
+ gRenderer = new ContextSwitchRenderer(gNativeWindow, offscreen);
+ break;
+ default:
+ ALOGE("Unknown benchmark '%d'", benchmark);
+ ANativeWindow_release(gNativeWindow);
+ gNativeWindow = NULL;
+ return;
+ }
+
+ // Set up call will log error conditions
+ if (!gRenderer->eglSetUp()) {
+ delete gRenderer;
+ gRenderer = NULL;
+
+ ANativeWindow_release(gNativeWindow);
+ gNativeWindow = NULL;
+ }
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_opengl2_cts_primitive_GLPrimitiveActivity_tearDownBenchmark(
+ JNIEnv* /*env*/, jclass /*clazz*/) {
+ if (gRenderer == NULL) {
+ return;
+ }
+ gRenderer->eglTearDown();
+ delete gRenderer;
+ gRenderer = NULL;
+
+ ANativeWindow_release(gNativeWindow);
+ gNativeWindow = NULL;
+}
diff --git a/suite/cts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp b/tests/openglperf2/jni/primitive/contextswitch/ContextSwitchRenderer.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp
rename to tests/openglperf2/jni/primitive/contextswitch/ContextSwitchRenderer.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.h b/tests/openglperf2/jni/primitive/contextswitch/ContextSwitchRenderer.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.h
rename to tests/openglperf2/jni/primitive/contextswitch/ContextSwitchRenderer.h
diff --git a/suite/cts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp b/tests/openglperf2/jni/primitive/fullpipeline/FullPipelineRenderer.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp
rename to tests/openglperf2/jni/primitive/fullpipeline/FullPipelineRenderer.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.h b/tests/openglperf2/jni/primitive/fullpipeline/FullPipelineRenderer.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.h
rename to tests/openglperf2/jni/primitive/fullpipeline/FullPipelineRenderer.h
diff --git a/suite/cts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp b/tests/openglperf2/jni/primitive/pixeloutput/PixelOutputRenderer.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp
rename to tests/openglperf2/jni/primitive/pixeloutput/PixelOutputRenderer.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.h b/tests/openglperf2/jni/primitive/pixeloutput/PixelOutputRenderer.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.h
rename to tests/openglperf2/jni/primitive/pixeloutput/PixelOutputRenderer.h
diff --git a/suite/cts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp b/tests/openglperf2/jni/primitive/shaderperf/ShaderPerfRenderer.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp
rename to tests/openglperf2/jni/primitive/shaderperf/ShaderPerfRenderer.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.h b/tests/openglperf2/jni/primitive/shaderperf/ShaderPerfRenderer.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.h
rename to tests/openglperf2/jni/primitive/shaderperf/ShaderPerfRenderer.h
diff --git a/tests/openglperf2/jni/reference/GLReference.cpp b/tests/openglperf2/jni/reference/GLReference.cpp
new file mode 100644
index 0000000..9af018a
--- /dev/null
+++ b/tests/openglperf2/jni/reference/GLReference.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+#include <jni.h>
+
+#include <android/native_window.h>
+#include <android/native_window_jni.h>
+
+#include <graphics/GLUtils.h>
+#include <graphics/Renderer.h>
+
+#include "ReferenceRenderer.h"
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_android_opengl2_cts_reference_GLGameActivity_startBenchmark(
+ JNIEnv* env, jclass /*clazz*/, jobject assetManager, jobject surface, jint numFrames,
+ jdoubleArray setUpTimes, jdoubleArray updateTimes, jdoubleArray renderTimes) {
+
+ GLUtils::setEnvAndAssetManager(env, assetManager);
+
+ if (numFrames > (ReferenceRenderer::FRAMES_PER_SCENE * ReferenceRenderer::NUM_SCENES)) {
+ return false;
+ }
+
+ ANativeWindow* nativeWindow = ANativeWindow_fromSurface(env, surface);
+ ReferenceRenderer* renderer = new ReferenceRenderer(nativeWindow);
+ bool success = renderer->eglSetUp();
+ success = renderer->setUp(0) && success;
+ env->SetDoubleArrayRegion(
+ setUpTimes, 0, ReferenceRenderer::NUM_SETUP_TIMES, renderer->mSetUpTimes);
+
+ double updates[numFrames];
+ double renders[numFrames];
+ for (int i = 0; i < numFrames && success; i++) {
+ double t0 = GLUtils::currentTimeMillis();
+ success = renderer->update(i);
+ double t1 = GLUtils::currentTimeMillis();
+ success = success && renderer->draw();
+ double t2 = GLUtils::currentTimeMillis();
+ updates[i] = t1 - t0;
+ renders[i] = t2 - t1;
+ }
+
+ env->SetDoubleArrayRegion(updateTimes, 0, numFrames, updates);
+ env->SetDoubleArrayRegion(renderTimes, 0, numFrames, renders);
+
+ success = renderer->tearDown() && success;
+ renderer->eglTearDown();
+ delete renderer;
+ renderer = NULL;
+
+ ANativeWindow_release(nativeWindow);
+
+ return success;
+}
diff --git a/suite/cts/deviceTests/opengl/jni/reference/ReferenceRenderer.cpp b/tests/openglperf2/jni/reference/ReferenceRenderer.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/ReferenceRenderer.cpp
rename to tests/openglperf2/jni/reference/ReferenceRenderer.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/reference/ReferenceRenderer.h b/tests/openglperf2/jni/reference/ReferenceRenderer.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/ReferenceRenderer.h
rename to tests/openglperf2/jni/reference/ReferenceRenderer.h
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/Scene.cpp b/tests/openglperf2/jni/reference/scene/Scene.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/Scene.cpp
rename to tests/openglperf2/jni/reference/scene/Scene.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/Scene.h b/tests/openglperf2/jni/reference/scene/Scene.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/Scene.h
rename to tests/openglperf2/jni/reference/scene/Scene.h
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/flocking/Boid.cpp b/tests/openglperf2/jni/reference/scene/flocking/Boid.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/flocking/Boid.cpp
rename to tests/openglperf2/jni/reference/scene/flocking/Boid.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/flocking/Boid.h b/tests/openglperf2/jni/reference/scene/flocking/Boid.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/flocking/Boid.h
rename to tests/openglperf2/jni/reference/scene/flocking/Boid.h
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.cpp b/tests/openglperf2/jni/reference/scene/flocking/FlockingScene.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.cpp
rename to tests/openglperf2/jni/reference/scene/flocking/FlockingScene.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.h b/tests/openglperf2/jni/reference/scene/flocking/FlockingScene.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.h
rename to tests/openglperf2/jni/reference/scene/flocking/FlockingScene.h
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/flocking/WaterMeshNode.cpp b/tests/openglperf2/jni/reference/scene/flocking/WaterMeshNode.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/flocking/WaterMeshNode.cpp
rename to tests/openglperf2/jni/reference/scene/flocking/WaterMeshNode.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/flocking/WaterMeshNode.h b/tests/openglperf2/jni/reference/scene/flocking/WaterMeshNode.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/flocking/WaterMeshNode.h
rename to tests/openglperf2/jni/reference/scene/flocking/WaterMeshNode.h
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/glowing/BlurMeshNode.cpp b/tests/openglperf2/jni/reference/scene/glowing/BlurMeshNode.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/glowing/BlurMeshNode.cpp
rename to tests/openglperf2/jni/reference/scene/glowing/BlurMeshNode.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/glowing/BlurMeshNode.h b/tests/openglperf2/jni/reference/scene/glowing/BlurMeshNode.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/glowing/BlurMeshNode.h
rename to tests/openglperf2/jni/reference/scene/glowing/BlurMeshNode.h
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/glowing/GlowingScene.cpp b/tests/openglperf2/jni/reference/scene/glowing/GlowingScene.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/glowing/GlowingScene.cpp
rename to tests/openglperf2/jni/reference/scene/glowing/GlowingScene.cpp
diff --git a/suite/cts/deviceTests/opengl/jni/reference/scene/glowing/GlowingScene.h b/tests/openglperf2/jni/reference/scene/glowing/GlowingScene.h
similarity index 100%
rename from suite/cts/deviceTests/opengl/jni/reference/scene/glowing/GlowingScene.h
rename to tests/openglperf2/jni/reference/scene/glowing/GlowingScene.h
diff --git a/tests/openglperf2/src/android/opengl2/cts/GLActivityIntentKeys.java b/tests/openglperf2/src/android/opengl2/cts/GLActivityIntentKeys.java
new file mode 100644
index 0000000..fcd5f1a
--- /dev/null
+++ b/tests/openglperf2/src/android/opengl2/cts/GLActivityIntentKeys.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 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.opengl2.cts;
+
+public class GLActivityIntentKeys {
+ /**
+ * Holds the name of the benchmark to run.
+ */
+ public final static String INTENT_EXTRA_BENCHMARK_NAME = "benchmark_name";
+ /**
+ * Holds whether or not the benchmark is to be run offscreen.
+ */
+ public final static String INTENT_EXTRA_OFFSCREEN = "offscreen";
+ /**
+ * The number of frames to render for each workload.
+ */
+ public final static String INTENT_EXTRA_NUM_FRAMES = "num_frames";
+ /**
+ * The number of iterations to run, the workload increases with each iteration.
+ */
+ public final static String INTENT_EXTRA_NUM_ITERATIONS = "num_iterations";
+ /**
+ * The number of milliseconds to wait before timing out.
+ */
+ public final static String INTENT_EXTRA_TIMEOUT = "timeout";
+}
diff --git a/tests/openglperf2/src/android/opengl2/cts/primitive/BenchmarkName.java b/tests/openglperf2/src/android/opengl2/cts/primitive/BenchmarkName.java
new file mode 100644
index 0000000..02acfdc
--- /dev/null
+++ b/tests/openglperf2/src/android/opengl2/cts/primitive/BenchmarkName.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 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.opengl2.cts.primitive;
+
+/**
+ * Represents the different primitive benchmarks.
+ */
+public enum BenchmarkName {
+ FullPipeline,
+ PixelOutput,
+ ShaderPerf,
+ ContextSwitch;
+}
diff --git a/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveActivity.java b/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveActivity.java
new file mode 100644
index 0000000..6558786
--- /dev/null
+++ b/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveActivity.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2013 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.opengl2.cts.primitive;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.cts.util.WatchDog;
+import android.opengl2.cts.GLActivityIntentKeys;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
+
+public class GLPrimitiveActivity extends Activity {
+
+ public final static String TAG = "GLPrimitiveActivity";
+
+ private volatile Exception mException;
+ private volatile Surface mSurface = null;
+ private CountDownLatch mStartSignal = new CountDownLatch(1);
+ private Semaphore mSemaphore = new Semaphore(0);
+
+ private BenchmarkName mBenchmark;
+ private boolean mOffscreen;
+ private int mNumFrames;
+ private int mNumIterations;
+ private int mTimeout;
+ public double[] mFpsValues;
+
+ @Override
+ public void onCreate(Bundle data) {
+ super.onCreate(data);
+ System.loadLibrary("ctsopengl_jni");
+ Intent intent = getIntent();
+ mBenchmark = BenchmarkName.valueOf(
+ intent.getStringExtra(GLActivityIntentKeys.INTENT_EXTRA_BENCHMARK_NAME));
+ mOffscreen = intent.getBooleanExtra(GLActivityIntentKeys.INTENT_EXTRA_OFFSCREEN, false);
+ mNumFrames = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, 0);
+ mNumIterations = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_ITERATIONS, 0);
+ mTimeout = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, 0);
+ mFpsValues = new double[mNumIterations];
+
+ Log.i(TAG, "Benchmark: " + mBenchmark);
+ Log.i(TAG, "Offscreen: " + mOffscreen);
+ Log.i(TAG, "Num Frames: " + mNumFrames);
+ Log.i(TAG, "Num Iterations: " + mNumIterations);
+ Log.i(TAG, "Time Out: " + mTimeout);
+
+ SurfaceView surfaceView = new SurfaceView(this);
+ surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ mSurface = holder.getSurface();
+ mStartSignal.countDown();
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {}
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {}
+ });
+ setContentView(surfaceView);
+ // Spawns a worker to run the benchmark.
+ Worker worker = new Worker();
+ worker.start();
+ }
+
+ public void waitForCompletion() throws Exception {
+ // Wait for semiphore.
+ mSemaphore.acquire();
+ if (mException != null) {
+ throw mException;
+ }
+ }
+
+ private void complete() {
+ // Release semiphore.
+ mSemaphore.release();
+ finish();
+ }
+
+ private synchronized void setException(Exception e) {
+ if (mException == null) {
+ mException = e;
+ }
+ }
+
+ private static native boolean setupBenchmark(
+ Surface surface, int benchmark, boolean offscreen);
+
+ private static native boolean startBenchmark(int workload, int numFrames, double[] frameTimes);
+
+ private static native void tearDownBenchmark();
+
+ /**
+ * This thread runs the benchmarks, freeing the UI thread.
+ */
+ private class Worker extends Thread implements WatchDog.TimeoutCallback {
+
+ private WatchDog watchDog;
+ private volatile boolean success = true;
+
+ @Override
+ public void run() {
+ try {
+ mStartSignal.await();
+ } catch (InterruptedException e) {
+ setException(e);
+ complete();
+ return;
+ }
+ Log.i(TAG, mBenchmark + " Benchmark Started");
+ // Creates a watchdog to ensure a iteration doesn't exceed the timeout.
+ watchDog = new WatchDog(mTimeout, this);
+ // Used to record the start and end time of the iteration.
+ double[] times = new double[2];
+ try {
+ // Setup the benchmark.
+ setupBenchmark(mSurface, mBenchmark.ordinal(), mOffscreen);
+ for (int i = 0; i < mNumIterations && success; i++) {
+ // The workload to use for this iteration.
+ int workload = i + 1;
+ watchDog.start();
+ // Start benchmark.
+ success = startBenchmark(workload, mNumFrames, times);
+ watchDog.stop();
+ if (!success) {
+ setException(new Exception("Benchmark failed to run"));
+ } else {
+ // Calculate FPS.
+ mFpsValues[i] = mNumFrames * 1000.0f / (times[1] - times[0]);
+ }
+ }
+ }
+ finally
+ {
+ tearDownBenchmark();
+ }
+
+ complete();
+ Log.i(TAG, mBenchmark + " Benchmark Completed");
+ }
+
+ public void onTimeout() {
+ setException(new Exception("Benchmark timed out"));
+ complete();
+ }
+
+ }
+}
diff --git a/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveBenchmark.java b/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveBenchmark.java
new file mode 100644
index 0000000..d737dbf
--- /dev/null
+++ b/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveBenchmark.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013 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.opengl2.cts.primitive;
+
+import android.content.Intent;
+import android.opengl2.cts.GLActivityIntentKeys;
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.util.TimeoutReq;
+
+/**
+ * Runs the Primitive OpenGL ES 2.0 Benchmarks.
+ */
+public class GLPrimitiveBenchmark extends ActivityInstrumentationTestCase2<GLPrimitiveActivity> {
+
+ private static final int NUM_FRAMES = 100;
+ private static final int NUM_ITERATIONS = 8;
+ private static final int TIMEOUT = 1000000;
+
+ public GLPrimitiveBenchmark() {
+ super(GLPrimitiveActivity.class);
+ }
+
+ /**
+ * Runs the full OpenGL ES 2.0 pipeline test offscreen.
+ */
+ @TimeoutReq(minutes = 100)
+ public void testFullPipelineOffscreen() throws Exception {
+ runBenchmark(BenchmarkName.FullPipeline, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ }
+
+ /**
+ * Runs the full OpenGL ES 2.0 pipeline test onscreen.
+ */
+ @TimeoutReq(minutes = 100)
+ public void testFullPipelineOnscreen() throws Exception {
+ runBenchmark(BenchmarkName.FullPipeline, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ }
+
+ /**
+ * Runs the pixel output test offscreen.
+ */
+ @TimeoutReq(minutes = 100)
+ public void testPixelOutputOffscreen() throws Exception {
+ runBenchmark(BenchmarkName.PixelOutput, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ }
+
+ /**
+ * Runs the pixel output test onscreen.
+ */
+ @TimeoutReq(minutes = 100)
+ public void testPixelOutputOnscreen() throws Exception {
+ runBenchmark(BenchmarkName.PixelOutput, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ }
+
+ /**
+ * Runs the shader performance test offscreen.
+ */
+ @TimeoutReq(minutes = 100)
+ public void testShaderPerfOffscreen() throws Exception {
+ runBenchmark(BenchmarkName.ShaderPerf, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ }
+
+ /**
+ * Runs the shader performance test onscreen.
+ */
+ @TimeoutReq(minutes = 100)
+ public void testShaderPerfOnscreen() throws Exception {
+ runBenchmark(BenchmarkName.ShaderPerf, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ }
+
+ /**
+ * Runs the context switch overhead test offscreen.
+ */
+ @TimeoutReq(minutes = 100)
+ public void testContextSwitchOffscreen() throws Exception {
+ runBenchmark(BenchmarkName.ContextSwitch, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ }
+
+ /**
+ * Runs the context switch overhead test onscreen.
+ */
+ @TimeoutReq(minutes = 100)
+ public void testContextSwitchOnscreen() throws Exception {
+ runBenchmark(BenchmarkName.ContextSwitch, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ }
+
+ /**
+ * Runs the specified test.
+ *
+ * @param benchmark An enum representing the benchmark to run.
+ * @param offscreen Whether to render to an offscreen framebuffer rather than the screen.
+ * @param numFrames The number of frames to render.
+ * @param numIterations The number of iterations to run, each iteration has a bigger workload.
+ * @param timeout The milliseconds to wait for an iteration of the benchmark before timing out.
+ * @throws Exception If the benchmark could not be run.
+ */
+ private void runBenchmark(BenchmarkName benchmark, boolean offscreen, int numFrames,
+ int numIterations, int timeout) throws Exception {
+ String benchmarkName = benchmark.toString();
+ Intent intent = new Intent();
+ intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_BENCHMARK_NAME, benchmarkName);
+ intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_OFFSCREEN, offscreen);
+ intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, numFrames);
+ intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_ITERATIONS, numIterations);
+ intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, timeout);
+
+ setActivityIntent(intent);
+ GLPrimitiveActivity activity = getActivity();
+ if (activity != null) {
+ activity.waitForCompletion();
+ double[] fpsValues = activity.mFpsValues;
+ double score = 0;
+ for (double d : fpsValues) {
+ score += d;
+ }
+ score /= numIterations;// Average.
+
+ // TODO: maybe standard deviation / RMSE will be useful?
+
+ DeviceReportLog report = new DeviceReportLog();
+ report.setSummary("Average FPS", score, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
+ report.submit(getInstrumentation());
+ }
+ }
+}
diff --git a/tests/openglperf2/src/android/opengl2/cts/reference/GLGameActivity.java b/tests/openglperf2/src/android/opengl2/cts/reference/GLGameActivity.java
new file mode 100644
index 0000000..0bfb38b
--- /dev/null
+++ b/tests/openglperf2/src/android/opengl2/cts/reference/GLGameActivity.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2013 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.opengl2.cts.reference;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.res.AssetManager;
+import android.cts.util.WatchDog;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLUtils;
+import android.opengl2.cts.GLActivityIntentKeys;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.CountDownLatch;
+
+public class GLGameActivity extends Activity {
+
+ public final static String SET_UP_TIME = "set_up_time";
+ public final static String UPDATE_TIMES = "update_times";
+ public final static String RENDER_TIMES = "render_times";
+
+ private int mNumFrames;
+ private int mTimeout;
+ private double[] mSetUpTimes;
+ private double[] mUpdateTimes;
+ private double[] mRenderTimes;
+ private volatile Surface mSurface = null;
+ private CountDownLatch mStartSignal = new CountDownLatch(1);
+
+ @Override
+ public void onCreate(Bundle data) {
+ super.onCreate(data);
+ System.loadLibrary("ctsopengl_jni");
+
+ Intent intent = getIntent();
+ mNumFrames = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, 1000);
+ mTimeout = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, 1000000);
+
+ SurfaceView surfaceView = new SurfaceView(this);
+ surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ mSurface = holder.getSurface();
+ mStartSignal.countDown();
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {}
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {}
+ });
+ setContentView(surfaceView);
+
+ // Spawns a worker.
+ Worker worker = new Worker(new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ Intent intent = new Intent();
+ intent.putExtra(SET_UP_TIME, mSetUpTimes);
+ intent.putExtra(UPDATE_TIMES, mUpdateTimes);
+ intent.putExtra(RENDER_TIMES, mRenderTimes);
+ setResult((msg.what == 1) ? RESULT_OK : RESULT_CANCELED, intent);
+ finish();
+ }
+ });
+ worker.start();
+ }
+
+ private static native boolean startBenchmark(AssetManager manager,
+ Surface surface,
+ int numFrames,
+ double[] setUpTimes,
+ double[] updateTimes,
+ double[] renderTimes);
+
+ /**
+ * This thread renderers the benchmarks, freeing the UI thread.
+ */
+ private class Worker extends Thread implements WatchDog.TimeoutCallback {
+
+ private WatchDog watchDog;
+ private Handler mHandler;
+
+ public Worker(Handler handler) {
+ mHandler = handler;
+ }
+
+ @Override
+ public void run() {
+ try {
+ mStartSignal.await();
+ } catch (InterruptedException e) {
+ mHandler.sendEmptyMessage(0);
+ return;
+ }
+ // Creates a watchdog to ensure a iteration doesn't exceed the timeout.
+ watchDog = new WatchDog(mTimeout, this);
+ watchDog.start();
+
+ // Used to record the time taken to setup (GL, context, textures, meshes).
+ mSetUpTimes = new double[4];
+ // Used to record the times taken to update.
+ mUpdateTimes = new double[mNumFrames];
+ // Used to record the times taken to render.
+ mRenderTimes = new double[mNumFrames];
+ boolean success = startBenchmark(getAssets(),
+ mSurface,
+ mNumFrames,
+ mSetUpTimes,
+ mUpdateTimes,
+ mRenderTimes);
+
+ watchDog.stop();
+ mHandler.sendEmptyMessage((success) ? 1 : 0);
+ }
+
+ @Override
+ public void onTimeout() {
+ mHandler.sendEmptyMessage(0);
+ }
+
+ }
+
+ public static int loadTexture(AssetManager manager, String path) {
+ InputStream in = null;
+ try {
+ in = manager.open(path);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ BitmapFactory.Options op = new BitmapFactory.Options();
+ op.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ Bitmap bmp = BitmapFactory.decodeStream(in, null, op);
+ // generate textureID
+ int[] textures = new int[1];
+ GLES20.glGenTextures(1, textures, 0);
+ int textureID = textures[0];
+
+ // create texture
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
+ GLES20.glTexParameteri(
+ GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
+ GLES20.glTexParameteri(
+ GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
+ GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
+ GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
+ GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
+
+ // clean up
+ try {
+ in.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ bmp.recycle();
+ }
+ return textureID;
+ }
+}
diff --git a/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceActivity.java b/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceActivity.java
new file mode 100644
index 0000000..7a800a5
--- /dev/null
+++ b/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceActivity.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 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.opengl2.cts.reference;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.opengl2.cts.GLActivityIntentKeys;
+import android.os.Bundle;
+
+import java.util.concurrent.Semaphore;
+
+public class GLReferenceActivity extends Activity {
+
+ private final static int GAME_ACTIVITY_CODE = 1;
+
+ private volatile Exception mException;
+ private int mNumFrames;
+ private int mTimeout;
+
+ public double[] mSetUpTimes;
+ public double[] mUpdateTimes;
+ public double[] mRenderTimes;
+
+ private Semaphore mSemaphore = new Semaphore(0);
+
+ @Override
+ public void onCreate(Bundle data) {
+ super.onCreate(data);
+ Intent intent = getIntent();
+ mNumFrames = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, 0);
+ mTimeout = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, 0);
+
+ // Start benchmark
+ intent = new Intent(this, GLGameActivity.class);
+ intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, mNumFrames);
+ intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, mTimeout);
+ startActivityForResult(intent, GAME_ACTIVITY_CODE);
+ }
+
+ public void waitForCompletion() throws Exception {
+ // Wait for semiphore.
+ mSemaphore.acquire();
+ if (mException != null) {
+ throw mException;
+ }
+ }
+
+ private synchronized void setException(Exception e) {
+ if (mException == null) {
+ mException = e;
+ }
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == GAME_ACTIVITY_CODE) {
+ if (resultCode == RESULT_OK) {
+ // Benchmark passed
+ mSetUpTimes = data.getDoubleArrayExtra(GLGameActivity.SET_UP_TIME);
+ mUpdateTimes = data.getDoubleArrayExtra(GLGameActivity.UPDATE_TIMES);
+ mRenderTimes = data.getDoubleArrayExtra(GLGameActivity.RENDER_TIMES);
+ } else {
+ setException(new Exception("Benchmark failed to run"));
+ }
+ // Release semiphore.
+ mSemaphore.release();
+ finish();
+ }
+ }
+
+}
diff --git a/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceBenchmark.java b/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceBenchmark.java
new file mode 100644
index 0000000..196207c
--- /dev/null
+++ b/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceBenchmark.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 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.opengl2.cts.reference;
+
+import android.content.Intent;
+import android.opengl2.cts.GLActivityIntentKeys;
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.util.TimeoutReq;
+
+/**
+ * Runs the Reference OpenGL ES 2.0 Benchmark.
+ */
+public class GLReferenceBenchmark extends ActivityInstrumentationTestCase2<GLReferenceActivity> {
+
+ private static final int NUM_FRAMES_PER_SCENE = 500;
+ private static final int NUM_SCENES = 2;
+ private static final int NUM_FRAMES = NUM_FRAMES_PER_SCENE * NUM_SCENES;
+ private static final int TIMEOUT = 1000000;
+
+ public GLReferenceBenchmark() {
+ super(GLReferenceActivity.class);
+ }
+
+ /**
+ * Runs the reference benchmark.
+ */
+ @TimeoutReq(minutes = 30)
+ public void testReferenceBenchmark() throws Exception {
+ Intent intent = new Intent();
+ intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, NUM_FRAMES);
+ intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, TIMEOUT);
+
+ GLReferenceActivity activity = null;
+ setActivityIntent(intent);
+ activity = getActivity();
+ if (activity != null) {
+ activity.waitForCompletion();
+ double totalTime = 0;
+ double[] setUpTimes = activity.mSetUpTimes;
+ double[] updateTimes = activity.mUpdateTimes;
+ double[] renderTimes = activity.mRenderTimes;
+
+ // Calculate update and render average.
+ double updateSum = updateTimes[0];
+ double renderSum = renderTimes[0];
+ for (int i = 0; i < NUM_FRAMES - 1; i++) {
+ updateSum += updateTimes[i + 1];
+ renderSum += renderTimes[i + 1];
+ }
+ double updateAverage = updateSum / NUM_FRAMES;
+ double renderAverage = renderSum / NUM_FRAMES;
+
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValues("Set Up Times", setUpTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValue("Update Time Average", updateAverage, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ report.addValue("Render Time Average", renderAverage, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ totalTime = setUpTimes[0] + setUpTimes[1] + setUpTimes[2] + setUpTimes[3] +
+ updateAverage + renderAverage;
+ report.setSummary("Total Time Average", totalTime, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ report.submit(getInstrumentation());
+ }
+ }
+}
diff --git a/suite/cts/deviceTests/opengl/test/Android.mk b/tests/openglperf2/test/Android.mk
similarity index 100%
rename from suite/cts/deviceTests/opengl/test/Android.mk
rename to tests/openglperf2/test/Android.mk
diff --git a/suite/cts/deviceTests/opengl/test/MatrixTest.cpp b/tests/openglperf2/test/MatrixTest.cpp
similarity index 100%
rename from suite/cts/deviceTests/opengl/test/MatrixTest.cpp
rename to tests/openglperf2/test/MatrixTest.cpp
diff --git a/tests/sample/Android.mk b/tests/sample/Android.mk
index 5e8f571..1255032 100755
--- a/tests/sample/Android.mk
+++ b/tests/sample/Android.mk
@@ -16,19 +16,24 @@
include $(CLEAR_VARS)
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
-
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-# Must match the package name in CtsTestCaseList.mk
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsSampleDeviceTestCases
LOCAL_SDK_VERSION := current
-include $(BUILD_CTS_PACKAGE)
+include $(BUILD_PACKAGE)
diff --git a/tests/sample/AndroidManifest.xml b/tests/sample/AndroidManifest.xml
index f07ebbe..2f32e86 100755
--- a/tests/sample/AndroidManifest.xml
+++ b/tests/sample/AndroidManifest.xml
@@ -18,7 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.sample.cts">
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application>
<uses-library android:name="android.test.runner" />
<activity android:name="android.sample.SampleDeviceActivity" >
@@ -34,9 +34,6 @@
android:name="android.support.test.runner.AndroidJUnitRunner"
android:label="CTS sample tests"
android:targetPackage="android.sample.cts" >
- <meta-data
- android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/tests/sample/AndroidTest.xml b/tests/sample/AndroidTest.xml
new file mode 100644
index 0000000..ae790fb
--- /dev/null
+++ b/tests/sample/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Sample test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSampleDeviceTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.sample.cts" />
+ </test>
+</configuration>
diff --git a/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java b/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
index 6bf883f..7bd434e 100644
--- a/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
+++ b/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
@@ -15,21 +15,25 @@
*/
package android.sample.cts;
-import com.android.cts.util.MeasureRun;
-import com.android.cts.util.MeasureTime;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import com.android.cts.util.Stat;
+import android.sample.SampleDeviceActivity;
+import android.test.ActivityInstrumentationTestCase2;
-import android.cts.util.CtsAndroidTestCase;
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.MeasureRun;
+import com.android.compatibility.common.util.MeasureTime;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+
+import java.util.Arrays;
+import java.util.Random;
/**
* A simple compatibility test which includes results in the report.
*
* This test measures the time taken to run a workload and adds in the report.
*/
-public class SampleDeviceResultTest extends CtsAndroidTestCase {
+public class SampleDeviceResultTest extends ActivityInstrumentationTestCase2<SampleDeviceActivity> {
/**
* The number of times to repeat the test.
@@ -37,86 +41,74 @@
private static final int REPEAT = 5;
/**
- * The input number for the factorial.
+ * A {@link Random} to generate random integers to test the sort.
*/
- private static final int IN = 15;
+ private static final Random random = new Random(12345);
/**
- * The expected output number for the factorial.
+ * Constructor which passes the class of the activity to be instrumented.
*/
- private static final long OUT = 1307674368000L;
-
- /**
- * Measures the time taken to compute the factorial of 15 with a recursive method.
- *
- * @throws Exception
- */
- public void testFactorialRecursive() throws Exception {
- runTest(new MeasureRun() {
- @Override
- public void run(int i) throws Exception {
- // Compute the factorial and assert it is correct.
- assertEquals("Incorrect result", OUT, factorialRecursive(IN));
- }
- });
+ public SampleDeviceResultTest() {
+ super(SampleDeviceActivity.class);
}
/**
- * Measures the time taken to compute the factorial of 15 with a iterative method.
- *
- * @throws Exception
+ * Creates an array filled with random numbers of the given size.
*/
- public void testFactorialIterative() throws Exception {
- runTest(new MeasureRun() {
- @Override
- public void run(int i) throws Exception {
- // Compute the factorial and assert it is correct.
- assertEquals("Incorrect result", OUT, factorialIterative(IN));
- }
- });
- }
-
- /**
- * Computes the factorial of a number with a recursive method.
- *
- * @param num The number to compute the factorial of.
- */
- private static long factorialRecursive(int num) {
- if (num <= 0) {
- return 1;
+ private static int[] createArray(int size) {
+ int[] array = new int[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = random.nextInt();
}
- return num * factorialRecursive(num - 1);
+ return array;
}
/**
- * Computes the factorial of a number with a iterative method.
- *
- * @param num The number to compute the factorial of.
+ * Tests an array is sorted.
*/
- private static long factorialIterative(int num) {
- long result = 1;
- for (int i = 2; i <= num; i++) {
- result *= i;
+ private static boolean isSorted(int[] array) {
+ int len = array.length;
+ for (int i = 0, j = 1; j < len; i++, j++) {
+ if (array[i] > array[j]) {
+ return false;
+ }
}
- return result;
+ return true;
}
/**
- * Runs the workload and records the result to the report log.
- *
- * @param workload
+ * Measures the time taken to sort an array.
*/
- private void runTest(MeasureRun workload) throws Exception {
+ public void testSort() throws Exception {
// MeasureTime runs the workload N times and records the time taken by each run.
- double[] result = MeasureTime.measure(REPEAT, workload);
+ double[] result = MeasureTime.measure(REPEAT, new MeasureRun() {
+ /**
+ * The size of the array to sort.
+ */
+ private static final int ARRAY_SIZE = 100000;
+ private int[] array;
+ @Override
+ public void prepare(int i) throws Exception {
+ array = createArray(ARRAY_SIZE);
+ }
+ @Override
+ public void run(int i) throws Exception {
+ Arrays.sort(array);
+ assertTrue("Array not sorted", isSorted(array));
+ }
+ });
// Compute the stats.
Stat.StatResult stat = Stat.getStat(result);
- // Get the report for this test and add the results to record.
- ReportLog log = getReportLog();
- log.printArray("Times", result, ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue("Min", stat.mMin, ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue("Max", stat.mMax, ResultType.LOWER_BETTER, ResultUnit.MS);
+ // Create a new report to hold the metrics.
+ DeviceReportLog reportLog = new DeviceReportLog();
+ // Add the results to the report.
+ reportLog.addValues("Times", result, ResultType.LOWER_BETTER, ResultUnit.MS);
+ reportLog.addValue("Min", stat.mMin, ResultType.LOWER_BETTER, ResultUnit.MS);
+ reportLog.addValue("Max", stat.mMax, ResultType.LOWER_BETTER, ResultUnit.MS);
// Every report must have a summary,
- log.printSummary("Average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
+ reportLog.setSummary("Average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
+ // Submit the report to the given instrumentation.
+ reportLog.submit(getInstrumentation());
}
+
}
diff --git a/tests/sample/src/android/sample/cts/SampleJUnit4DeviceTest.java b/tests/sample/src/android/sample/cts/SampleJUnit4DeviceTest.java
new file mode 100755
index 0000000..c8863b3
--- /dev/null
+++ b/tests/sample/src/android/sample/cts/SampleJUnit4DeviceTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package android.sample.cts;
+
+import org.junit.Assert;
+import org.junit.runner.RunWith;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import android.app.Activity;
+import android.sample.SampleDeviceActivity;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * A simple compatibility test which tests the SharedPreferences API.
+ *
+ * This test uses {@link ActivityTestRule} to instrument the
+ * {@link android.sample.SampleDeviceActivity}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class SampleJUnit4DeviceTest {
+
+ private static final String KEY = "foo";
+
+ private static final String VALUE = "bar";
+
+ @Rule
+ public ActivityTestRule<SampleDeviceActivity> mActivityRule =
+ new ActivityTestRule(SampleDeviceActivity.class);
+
+
+ /**
+ * This inserts the key value pair and assert they can be retrieved. Then it clears the
+ * preferences and asserts they can no longer be retrieved.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldSaveSharedPreferences() throws Exception {
+ // Save the key value pair to the preferences and assert they were saved.
+ mActivityRule.getActivity().savePreference(KEY, VALUE);
+ Assert.assertEquals("Preferences were not saved", VALUE,
+ mActivityRule.getActivity().getPreference(KEY));
+
+ // Clear the shared preferences and assert the data was removed.
+ mActivityRule.getActivity().clearPreferences();
+ Assert.assertNull("Preferences were not cleared",
+ mActivityRule.getActivity().getPreference(KEY));
+ }
+}
diff --git a/tests/signature/Android.mk b/tests/signature/Android.mk
index 53ba50d..516f5ec 100644
--- a/tests/signature/Android.mk
+++ b/tests/signature/Android.mk
@@ -22,68 +22,18 @@
LOCAL_PACKAGE_NAME := CtsSignatureTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+# For CTS v1
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
-# To be passed in on command line
-CTS_API_VERSION ?= current
-ifeq (current,$(CTS_API_VERSION))
-android_api_description := frameworks/base/api/$(CTS_API_VERSION).txt
-else
-android_api_description := $(SRC_API_DIR)/$(CTS_API_VERSION).txt
-endif
-
-# Can't call local-intermediates-dir directly here because we have to
-# include BUILD_CTS_PACKAGE first. Can't include BUILD_CTS_PACKAGE first
-# because we have to override LOCAL_RESOURCE_DIR first. Hence this
-# hack.
-intermediates.COMMON := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)
-signature_res_dir := $(intermediates.COMMON)/genres
-LOCAL_RESOURCE_DIR := $(signature_res_dir) $(LOCAL_PATH)/res
-
include $(BUILD_CTS_PACKAGE)
-generated_res_stamp := $(intermediates.COMMON)/genres.stamp
-api_ver_file := $(intermediates.COMMON)/api_ver_is_$(CTS_API_VERSION)
-
-# The api_ver_file keeps track of which api version was last built.
-# By only ever having one of these magic files in existence and making
-# sure the generated resources rule depend on it, we can ensure that
-# the proper version of the api resource gets generated.
-$(api_ver_file):
- $(hide) rm -f $(dir $@)/api_ver_is_* \
- && mkdir -p $(dir $@) && touch $@
-
-android_api_xml_description := $(intermediates.COMMON)/api.xml
-$(android_api_xml_description): $(android_api_description) | $(APICHECK)
- @ echo "Convert api file to xml: $@"
- @ mkdir -p $(dir $@)
- $(hide) $(APICHECK_COMMAND) -convert2xml $< $@
-
-# Split up config/api/1.xml by "package" and save the files as the
-# resource files of SignatureTest.
-$(generated_res_stamp): PRIVATE_PATH := $(LOCAL_PATH)
-$(generated_res_stamp): PRIVATE_MODULE := $(LOCAL_MODULE)
-$(generated_res_stamp): PRIVATE_RES_DIR := $(signature_res_dir)
-$(generated_res_stamp): PRIVATE_API_XML_DESC := $(android_api_xml_description)
-$(generated_res_stamp): $(api_ver_file)
-$(generated_res_stamp): $(android_api_xml_description)
- @ echo "Copy generated resources: $(PRIVATE_MODULE)"
- $(hide) python cts/tools/utils/android_api_description_splitter.py \
- $(PRIVATE_API_XML_DESC) $(PRIVATE_RES_DIR) package
- $(hide) touch $@
-
-$(R_file_stamp): $(generated_res_stamp)
-
-# clean up temp vars
-android_api_xml_description :=
-api_ver_file :=
-generated_res_stamp :=
-signature_res_dir :=
-android_api_description :=
-CTS_API_VERSION :=
-
# signature-hostside java library (for testing)
# ============================================================
@@ -98,4 +48,6 @@
LOCAL_MODULE_TAGS := optional
-include $(BUILD_HOST_JAVA_LIBRARY)
\ No newline at end of file
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/signature/AndroidManifest.xml b/tests/signature/AndroidManifest.xml
index e42302e..52090ce 100644
--- a/tests/signature/AndroidManifest.xml
+++ b/tests/signature/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature">
+ package="android.signature.cts">
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application>
@@ -24,7 +24,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.signature"
+ android:targetPackage="android.signature.cts"
android:label="API Signature Test"/>
</manifest>
\ No newline at end of file
diff --git a/tests/signature/AndroidTest.xml b/tests/signature/AndroidTest.xml
new file mode 100644
index 0000000..e3561cc
--- /dev/null
+++ b/tests/signature/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<configuration description="Config for CTS Signature test cases">
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSignatureTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.signature.cts" />
+ <option name="runtime-hint" value="1m11s" />
+ </test>
+</configuration>
diff --git a/tests/signature/OldAndroidTest.xml b/tests/signature/OldAndroidTest.xml
new file mode 100644
index 0000000..b4338da
--- /dev/null
+++ b/tests/signature/OldAndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Signature test cases">
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
+ </target_preparer>
+ <target_preparer class="com.android.cts.tradefed.targetprep.CtsFilePusher">
+ <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
+ </target_preparer>
+</configuration>
diff --git a/tests/signature/api/Android.mk b/tests/signature/api/Android.mk
new file mode 100644
index 0000000..39a4337
--- /dev/null
+++ b/tests/signature/api/Android.mk
@@ -0,0 +1,42 @@
+# 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.
+
+# We define this in a subdir so that it won't pick up the parent's Android.xml by default.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# current api, in XML format.
+# ============================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := cts-current-api
+LOCAL_MODULE_STEM := current.api
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_ETC)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+include $(BUILD_SYSTEM)/base_rules.mk
+$(LOCAL_BUILT_MODULE) : frameworks/base/api/current.txt | $(APICHECK)
+ @echo "Convert API file $@"
+ @mkdir -p $(dir $@)
+ $(hide) $(APICHECK_COMMAND) -convert2xml $< $@
+
+# For CTS v1
+cts_api_xml_v1 := $(CTS_TESTCASES_OUT)/current.api
+$(cts_api_xml_v1): $(LOCAL_BUILT_MODULE) | $(ACP)
+ $(call copy-file-to-new-target)
+
+$(CTS_TESTCASES_OUT)/CtsSignatureTestCases.xml: $(cts_api_xml_v1)
diff --git a/tests/signature/src/android/signature/cts/SignatureTest.java b/tests/signature/src/android/signature/cts/SignatureTest.java
index 85b77f8..139fb30 100644
--- a/tests/signature/src/android/signature/cts/SignatureTest.java
+++ b/tests/signature/src/android/signature/cts/SignatureTest.java
@@ -17,7 +17,6 @@
package android.signature.cts;
import android.content.res.Resources;
-import android.signature.R;
import android.signature.cts.JDiffClassDescription.JDiffConstructor;
import android.signature.cts.JDiffClassDescription.JDiffField;
import android.signature.cts.JDiffClassDescription.JDiffMethod;
@@ -26,13 +25,17 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.Scanner;
/**
* Performs the signature check via a JUnit test.
@@ -40,6 +43,7 @@
public class SignatureTest extends AndroidTestCase {
private static final String TAG = SignatureTest.class.getSimpleName();
+ private static final String CURRENT_API_FILE = "/data/local/tmp/signature-test/current.api";
private static final String TAG_ROOT = "api";
private static final String TAG_PACKAGE = "package";
@@ -104,25 +108,21 @@
* Will check the entire API, and then report the complete list of failures
*/
public void testSignature() {
- Resources r = getContext().getResources();
- Class rClass = R.xml.class;
- logd(String.format("Class: %s", rClass.toString()));
- Field[] fs = rClass.getFields();
- for (Field f : fs) {
- logd(String.format("Field: %s", f.toString()));
- try {
- start(r.getXml(f.getInt(rClass)));
- } catch (Exception e) {
- mResultObserver.notifyFailure(FailureType.CAUGHT_EXCEPTION, e.getMessage(),
- e.getMessage());
- }
+ try {
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ XmlPullParser parser = factory.newPullParser();
+ parser.setInput(new FileInputStream(new File(CURRENT_API_FILE)), null);
+ start(parser);
+ } catch (Exception e) {
+ mResultObserver.notifyFailure(FailureType.CAUGHT_EXCEPTION, e.getMessage(),
+ e.getMessage());
}
if (mResultObserver.mDidFail) {
fail(mResultObserver.mErrorString.toString());
}
}
- private void beginDocument(XmlPullParser parser, String firstElementName)
+ private void beginDocument(XmlPullParser parser, String firstElementName)
throws XmlPullParserException, IOException {
int type;
while ((type=parser.next()) != XmlPullParser.START_TAG
diff --git a/tests/signature-tests/Android.mk b/tests/signature/tests/Android.mk
similarity index 100%
rename from tests/signature-tests/Android.mk
rename to tests/signature/tests/Android.mk
diff --git a/tests/signature-tests/run_unit_tests.sh b/tests/signature/tests/run_unit_tests.sh
similarity index 100%
rename from tests/signature-tests/run_unit_tests.sh
rename to tests/signature/tests/run_unit_tests.sh
diff --git a/tests/signature-tests/src/android/signature/cts/tests/AllTests.java b/tests/signature/tests/src/android/signature/cts/tests/AllTests.java
similarity index 100%
rename from tests/signature-tests/src/android/signature/cts/tests/AllTests.java
rename to tests/signature/tests/src/android/signature/cts/tests/AllTests.java
diff --git a/tests/signature-tests/src/android/signature/cts/tests/JDiffClassDescriptionTest.java b/tests/signature/tests/src/android/signature/cts/tests/JDiffClassDescriptionTest.java
similarity index 100%
rename from tests/signature-tests/src/android/signature/cts/tests/JDiffClassDescriptionTest.java
rename to tests/signature/tests/src/android/signature/cts/tests/JDiffClassDescriptionTest.java
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/AbstractClass.java b/tests/signature/tests/src/android/signature/cts/tests/data/AbstractClass.java
similarity index 100%
rename from tests/signature-tests/src/android/signature/cts/tests/data/AbstractClass.java
rename to tests/signature/tests/src/android/signature/cts/tests/data/AbstractClass.java
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/FinalClass.java b/tests/signature/tests/src/android/signature/cts/tests/data/FinalClass.java
similarity index 100%
rename from tests/signature-tests/src/android/signature/cts/tests/data/FinalClass.java
rename to tests/signature/tests/src/android/signature/cts/tests/data/FinalClass.java
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/NormalClass.java b/tests/signature/tests/src/android/signature/cts/tests/data/NormalClass.java
similarity index 100%
rename from tests/signature-tests/src/android/signature/cts/tests/data/NormalClass.java
rename to tests/signature/tests/src/android/signature/cts/tests/data/NormalClass.java
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/NormalException.java b/tests/signature/tests/src/android/signature/cts/tests/data/NormalException.java
similarity index 100%
rename from tests/signature-tests/src/android/signature/cts/tests/data/NormalException.java
rename to tests/signature/tests/src/android/signature/cts/tests/data/NormalException.java
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/NormalInterface.java b/tests/signature/tests/src/android/signature/cts/tests/data/NormalInterface.java
similarity index 100%
rename from tests/signature-tests/src/android/signature/cts/tests/data/NormalInterface.java
rename to tests/signature/tests/src/android/signature/cts/tests/data/NormalInterface.java
diff --git a/tests/simplecpu/Android.mk b/tests/simplecpu/Android.mk
new file mode 100644
index 0000000..707a380
--- /dev/null
+++ b/tests/simplecpu/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner
+
+LOCAL_JNI_SHARED_LIBRARIES := libctscpu_jni
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSimpleCpuTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/simplecpu/AndroidManifest.xml b/tests/simplecpu/AndroidManifest.xml
new file mode 100644
index 0000000..4b5febf
--- /dev/null
+++ b/tests/simplecpu/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.simplecpu.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.simplecpu.cts"
+ android:label="CTS tests for simple CPU" />
+</manifest>
diff --git a/tests/simplecpu/AndroidTest.xml b/tests/simplecpu/AndroidTest.xml
new file mode 100644
index 0000000..2a347f2
--- /dev/null
+++ b/tests/simplecpu/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS File System test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSimpleCpuTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.simplecpu.cts" />
+ <option name="runtime-hint" value="6m51s" />
+ </test>
+</configuration>
diff --git a/suite/cts/deviceTests/simplecpu/jni/Android.mk b/tests/simplecpu/jni/Android.mk
similarity index 100%
rename from suite/cts/deviceTests/simplecpu/jni/Android.mk
rename to tests/simplecpu/jni/Android.mk
diff --git a/tests/simplecpu/jni/CpuNativeJni.cpp b/tests/simplecpu/jni/CpuNativeJni.cpp
new file mode 100644
index 0000000..4ea0dc0
--- /dev/null
+++ b/tests/simplecpu/jni/CpuNativeJni.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <jni.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+/* Code from now to qsort_local all copied from bionic source.
+ * The code is duplicated here to remove dependency on optimized bionic
+ */
+static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
+static __inline void swapfunc(char *, char *, int, int);
+
+#define min(a, b) (a) < (b) ? a : b
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof (TYPE); \
+ TYPE *pi = (TYPE *) (parmi); \
+ TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static __inline void
+swapfunc(char *a, char *b, int n, int swaptype)
+{
+ if (swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b); \
+ *(long *)(b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype)
+
+#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
+
+static __inline char *
+med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
+{
+ return cmp(a, b) < 0 ?
+ (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
+ :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
+}
+
+void
+qsort_local(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ int d, r, swaptype, swap_cnt;
+ char *a = (char*)aa;
+
+loop: SWAPINIT(a, es);
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+ pm = (char *)a + (n / 2) * es;
+ if (n > 7) {
+ pl = (char *)a;
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp);
+ pm = med3(pm - d, pm, pm + d, cmp);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp);
+ }
+ pm = med3(pl, pm, pn, cmp);
+ }
+ swap(a, pm);
+ pa = pb = (char *)a + es;
+
+ pc = pd = (char *)a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (r = cmp(pb, a)) <= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (r = cmp(pc, a)) >= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+
+ pn = (char *)a + n * es;
+ r = min(pa - (char *)a, pb - pa);
+ vecswap(a, pb - r, r);
+ r = min(pd - pc, pn - pd - (int)es);
+ vecswap(pb, pn - r, r);
+ if ((r = pb - pa) > (int)es)
+ qsort_local(a, r / es, es, cmp);
+ if ((r = pd - pc) > (int)es) {
+ /* Iterate rather than recurse to save stack space */
+ a = pn - r;
+ n = r / es;
+ goto loop;
+ }
+ /* qsort(pn - r, r / es, es, cmp); */
+}
+
+/* code duplication ends here */
+
+/**
+ * Util for getting time stamp
+ */
+double currentTimeMillis()
+{
+ struct timeval tv;
+ gettimeofday(&tv, (struct timezone *) NULL);
+ return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
+}
+
+/**
+ * Initialize given array randomly for the given seed
+ */
+template <typename T> void randomInitArray(T* array, int len, unsigned int seed)
+{
+ srand(seed);
+ for (int i = 0; i < len; i++) {
+ array[i] = (T) rand();
+ }
+}
+
+/**
+ * comparison function for int, for qsort
+ */
+int cmpint(const void* p1, const void* p2)
+{
+ return *(int*)p1 - *(int*)p2;
+}
+
+extern "C" JNIEXPORT jdouble JNICALL Java_android_simplecpu_cts_CpuNative_runSort(JNIEnv* env,
+ jclass clazz, jint numberElements, jint repetition)
+{
+ int* data = new int[numberElements];
+ if (data == NULL) {
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "No memory");
+ return -1;
+ }
+ double totalTime = 0;
+ for (int i = 0; i < repetition; i++) {
+ randomInitArray<int>(data, numberElements, 0);
+ double start = currentTimeMillis();
+ qsort_local(data, numberElements, sizeof(int), cmpint);
+ double end = currentTimeMillis();
+ totalTime += (end - start);
+ }
+ delete[] data;
+ return totalTime;
+}
+
+
+/**
+ * Do matrix multiplication, C = A x B with all matrices having dimension of n x n
+ * The implementation is not in the most efficient, but it is good enough for benchmarking purpose.
+ * @param n should be multiple of 8
+ */
+void doMatrixMultiplication(float* A, float* B, float* C, int n)
+{
+ // batch size
+ const int M = 8;
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j += M) {
+ float sum[M];
+ for (int k = 0; k < M; k++) {
+ sum[k] = 0;
+ }
+ // re-use the whole cache line for accessing B.
+ // otherwise, the whole line will be read and only one value will be used.
+
+ for (int k = 0; k < n; k++) {
+ float a = A[i * n + k];
+ sum[0] += a * B[k * n + j];
+ sum[1] += a * B[k * n + j + 1];
+ sum[2] += a * B[k * n + j + 2];
+ sum[3] += a * B[k * n + j + 3];
+ sum[4] += a * B[k * n + j + 4];
+ sum[5] += a * B[k * n + j + 5];
+ sum[6] += a * B[k * n + j + 6];
+ sum[7] += a * B[k * n + j + 7];
+ }
+ for (int k = 0; k < M; k++) {
+ C[i * n + j + k] = sum[k];
+ }
+ }
+ }
+}
+
+extern "C" JNIEXPORT jdouble JNICALL Java_android_simplecpu_cts_CpuNative_runMatrixMultiplication(
+ JNIEnv* env, jclass clazz, jint n, jint repetition)
+{
+ // C = A x B
+ float* A = new float[n * n];
+ float* B = new float[n * n];
+ float* C = new float[n * n];
+ if ((A == NULL) || (B == NULL) || (C == NULL)) {
+ delete[] A;
+ delete[] B;
+ delete[] C;
+ env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "No memory");
+ return -1;
+ }
+ double totalTime = 0;
+ for (int i = 0; i < repetition; i++) {
+ randomInitArray<float>(A, n * n, 0);
+ randomInitArray<float>(B, n * n, 1);
+ double start = currentTimeMillis();
+ doMatrixMultiplication(A, B, C, n);
+ double end = currentTimeMillis();
+ totalTime += (end - start);
+ }
+ delete[] A;
+ delete[] B;
+ delete[] C;
+ return totalTime;
+}
+
diff --git a/tests/simplecpu/src/android/simplecpu/cts/CpuNative.java b/tests/simplecpu/src/android/simplecpu/cts/CpuNative.java
new file mode 100644
index 0000000..231cba6
--- /dev/null
+++ b/tests/simplecpu/src/android/simplecpu/cts/CpuNative.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 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.simplecpu.cts;
+
+public class CpuNative {
+ static {
+ System.loadLibrary("ctscpu_jni");
+ }
+ /**
+ * run qsort for given number of repetition
+ * with each having the size of bufferSize.
+ * @param numberElements
+ * @param repeatition
+ * @return time taken for computation, added for all repetition in ms
+ */
+ public static native double runSort(int numberElements, int repetition);
+
+ /**
+ * run matrix multiplication of (n x n) x (n x n)
+ *
+ * @param n dimension, should be multiple of 8
+ * @param repetition
+ * @return time taken for computation, added for all repetition in ms
+ */
+ public static native double runMatrixMultiplication(int n, int repetition);
+}
diff --git a/tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java b/tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java
new file mode 100644
index 0000000..fa7f402
--- /dev/null
+++ b/tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 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.simplecpu.cts;
+
+import android.cts.util.CtsAndroidTestCase;
+import android.util.Log;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+import com.android.cts.util.TimeoutReq;
+
+/**
+ * Very simple CPU benchmarking to check the basic capability of CPU.
+ * Cases include
+ * qsort
+ * matrix multiplication (for floating point performance)
+ */
+public class SimpleCpuTest extends CtsAndroidTestCase {
+ private static final String TAG = "BandwidthTest";
+ private static final int KB = 1024;
+ private static final int MB = 1024 * 1024;
+ private static final int NUMBER_REPEAT = 20;
+ // reject data outside +/- this value * median
+ private static final double OUTLIER_THRESHOLD = 0.1;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ warmUpCpu();
+ }
+
+ public void testSort004KB() {
+ doTestSort(NUMBER_REPEAT, 4 * KB);
+ }
+
+ public void testSort128KB() {
+ doTestSort(NUMBER_REPEAT, 128 * KB);
+ }
+
+ public void testSort001MB() {
+ doTestSort(NUMBER_REPEAT, 1 * MB);
+ }
+
+ // will fit into L1
+ public void testMatrixMultiplication032() {
+ doMatrixMultiplication(NUMBER_REPEAT, 32);
+ }
+
+ // mostly fit into L2
+ public void testMatrixMultiplication128() {
+ doMatrixMultiplication(NUMBER_REPEAT, 128);
+ }
+
+ // may fit into L2
+ public void testMatrixMultiplication200() {
+ doMatrixMultiplication(NUMBER_REPEAT, 200);
+ }
+
+ public void testMatrixMultiplication400() {
+ doMatrixMultiplication(NUMBER_REPEAT, 400);
+ }
+
+ // will exceed L2
+ @TimeoutReq(minutes = 30)
+ public void testMatrixMultiplication600() {
+ doMatrixMultiplication(NUMBER_REPEAT, 600);
+ }
+
+ /**
+ * run some code to force full CPU freq.
+ */
+ private void warmUpCpu() {
+ CpuNative.runSort(1 * MB, 10);
+ }
+
+ /**
+ * qsort test
+ * @param numberRepeat
+ * @param arrayLength
+ */
+ private void doTestSort(int numberRepeat, int arrayLength) {
+ final int numberRepeatInEachCall = 10;
+ double[] result = new double[numberRepeat];
+ for (int i = 0; i < numberRepeat; i++) {
+ result[i] = CpuNative.runSort(arrayLength, numberRepeatInEachCall);
+ }
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValues("sorting time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
+ Stat.StatResult stat = Stat.getStatWithOutlierRejection(result, OUTLIER_THRESHOLD);
+ if (stat.mDataCount != result.length) {
+ Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
+ }
+ report.setSummary("sorting time", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.submit(getInstrumentation());
+ }
+
+ /**
+ * Matrix multiplication test, nxn matrix multiplication
+ * @param numberRepeat
+ * @param n should be multiple of 8
+ */
+ private void doMatrixMultiplication(int numberRepeat, int n) {
+ assertTrue(n % 8 == 0);
+ final int numberRepeatInEachCall = 10;
+ double[] result = new double[numberRepeat];
+ for (int i = 0; i < numberRepeat; i++) {
+ result[i] = CpuNative.runMatrixMultiplication(n, numberRepeatInEachCall);
+ }
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValues("matrix mutiplication time", result, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ Stat.StatResult stat = Stat.getStatWithOutlierRejection(result, OUTLIER_THRESHOLD);
+ if (stat.mDataCount != result.length) {
+ Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
+ }
+ report.setSummary("matrix mutiplication time", stat.mAverage,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.submit(getInstrumentation());
+ }
+
+}
diff --git a/tests/tests/acceleration/Android.mk b/tests/tests/acceleration/Android.mk
deleted file mode 100644
index d417371..0000000
--- a/tests/tests/acceleration/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2011 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsAccelerationTestCases
-
-LOCAL_INSTRUMENTATION_FOR := CtsAccelerationTestStubs
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/acceleration/AndroidManifest.xml b/tests/tests/acceleration/AndroidManifest.xml
deleted file mode 100644
index 0dd2722..0000000
--- a/tests/tests/acceleration/AndroidManifest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2011 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.acceleration">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.acceleration.stub"
- android:label="Tests for the Hardware Acceleration APIs." >
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
diff --git a/tests/tests/acceleration/src/android/acceleration/cts/BaseAccelerationTest.java b/tests/tests/acceleration/src/android/acceleration/cts/BaseAccelerationTest.java
deleted file mode 100644
index d2f1d9f..0000000
--- a/tests/tests/acceleration/src/android/acceleration/cts/BaseAccelerationTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2011 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.acceleration.cts;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.FeatureInfo;
-import android.test.ActivityInstrumentationTestCase2;
-import android.view.View;
-
-abstract class BaseAccelerationTest<B extends BaseAcceleratedActivity>
- extends ActivityInstrumentationTestCase2<B> {
-
- protected B mActivity;
-
- /** View with android:layerType="hardware" set */
- protected AcceleratedView mHardwareView;
-
- /** View with android:layerType="software" set */
- protected AcceleratedView mSoftwareView;
-
- /** View with setLayerType(HARDWARE) called */
- protected AcceleratedView mManualHardwareView;
-
- /** View with setLayerType(SOFTWARE) called */
- protected AcceleratedView mManualSoftwareView;
-
- BaseAccelerationTest(Class<B> clazz) {
- super(clazz);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mActivity = getActivity();
- mHardwareView = mActivity.getHardwareAcceleratedView();
- mSoftwareView = mActivity.getSoftwareAcceleratedView();
- mManualHardwareView = mActivity.getManualHardwareAcceleratedView();
- mManualSoftwareView = mActivity.getManualSoftwareAcceleratedView();
- }
-
- public void testNotAttachedView() {
- // Views that are not attached can't be attached to an accelerated window.
- View view = new View(mActivity);
- assertFalse(view.isHardwareAccelerated());
- }
-
- protected static int getGlEsVersion(Context context) {
- ActivityManager activityManager =
- (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
- if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) {
- return getMajorVersion(configInfo.reqGlEsVersion);
- } else {
- return 1; // Lack of property means OpenGL ES version 1
- }
- }
-
- /** @see FeatureInfo#getGlEsVersion() */
- private static int getMajorVersion(int glEsVersion) {
- return ((glEsVersion & 0xffff0000) >> 16);
- }
-}
diff --git a/tests/tests/acceleration/src/android/acceleration/cts/HardwareAccelerationTest.java b/tests/tests/acceleration/src/android/acceleration/cts/HardwareAccelerationTest.java
deleted file mode 100644
index eddd34f..0000000
--- a/tests/tests/acceleration/src/android/acceleration/cts/HardwareAccelerationTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2011 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.acceleration.cts;
-
-/**
- * Test that uses an Activity with hardware acceleration enabled.
- */
-public class HardwareAccelerationTest
- extends BaseAccelerationTest<HardwareAcceleratedActivity> {
-
- public HardwareAccelerationTest() {
- super(HardwareAcceleratedActivity.class);
- }
-
- public void testIsHardwareAccelerated() {
- // Hardware acceleration should be available on devices with GL ES 2 or higher...
- if (getGlEsVersion(mActivity) >= 2) {
- // Both of the views are attached to a hardware accelerated window
- assertTrue(mHardwareView.isHardwareAccelerated());
- assertTrue(mSoftwareView.isHardwareAccelerated());
- assertTrue(mManualHardwareView.isHardwareAccelerated());
- assertTrue(mManualSoftwareView.isHardwareAccelerated());
-
- assertTrue(mHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
- assertTrue(mManualHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
- } else {
- assertFalse(mHardwareView.isHardwareAccelerated());
- assertFalse(mSoftwareView.isHardwareAccelerated());
- assertFalse(mManualHardwareView.isHardwareAccelerated());
- assertFalse(mManualSoftwareView.isHardwareAccelerated());
-
- assertFalse(mHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
- assertFalse(mManualHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
- }
- }
-}
diff --git a/tests/tests/acceleration/src/android/acceleration/cts/SoftwareAccelerationTest.java b/tests/tests/acceleration/src/android/acceleration/cts/SoftwareAccelerationTest.java
deleted file mode 100644
index 146fa6a..0000000
--- a/tests/tests/acceleration/src/android/acceleration/cts/SoftwareAccelerationTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2011 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.acceleration.cts;
-
-/**
- * Test that uses an Activity with hardware acceleration explicitly disabled
- * and makes sure that all views are rendered using software acceleration.
- */
-public class SoftwareAccelerationTest
- extends BaseAccelerationTest<SoftwareAcceleratedActivity> {
-
- public SoftwareAccelerationTest() {
- super(SoftwareAcceleratedActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mActivity = getActivity();
- }
-
- public void testIsHardwareAccelerated() {
- // Both of the views are not attached to a hardware accelerated window
- assertFalse(mHardwareView.isHardwareAccelerated());
- assertFalse(mSoftwareView.isHardwareAccelerated());
- assertFalse(mManualHardwareView.isHardwareAccelerated());
- assertFalse(mManualSoftwareView.isHardwareAccelerated());
-
- assertFalse(mHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
- assertFalse(mManualHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
- }
-}
diff --git a/tests/tests/acceleration/src/android/acceleration/cts/WindowFlagHardwareAccelerationTest.java b/tests/tests/acceleration/src/android/acceleration/cts/WindowFlagHardwareAccelerationTest.java
deleted file mode 100644
index bfbbe63..0000000
--- a/tests/tests/acceleration/src/android/acceleration/cts/WindowFlagHardwareAccelerationTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2011 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.acceleration.cts;
-
-/**
- * Test that uses an Activity with hardware acceleration enabled.
- */
-public class WindowFlagHardwareAccelerationTest
- extends BaseAccelerationTest<WindowFlagHardwareAcceleratedActivity> {
-
- public WindowFlagHardwareAccelerationTest() {
- super(WindowFlagHardwareAcceleratedActivity.class);
- }
-
- public void testIsHardwareAccelerated() {
- // Hardware acceleration should be available on devices with GL ES 2 or higher...
- if (getGlEsVersion(mActivity) >= 2) {
- // Both of the views are attached to a hardware accelerated window
- assertTrue(mHardwareView.isHardwareAccelerated());
- assertTrue(mSoftwareView.isHardwareAccelerated());
- assertTrue(mManualHardwareView.isHardwareAccelerated());
- assertTrue(mManualSoftwareView.isHardwareAccelerated());
-
- assertTrue(mHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
- assertTrue(mManualHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
- } else {
- assertFalse(mHardwareView.isHardwareAccelerated());
- assertFalse(mSoftwareView.isHardwareAccelerated());
- assertFalse(mManualHardwareView.isHardwareAccelerated());
- assertFalse(mManualSoftwareView.isHardwareAccelerated());
-
- assertFalse(mHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mSoftwareView.isCanvasHardwareAccelerated());
- assertFalse(mManualHardwareView.isCanvasHardwareAccelerated());
- assertFalse(mManualSoftwareView.isCanvasHardwareAccelerated());
- }
- }
-}
diff --git a/tests/tests/accessibility/Android.mk b/tests/tests/accessibility/Android.mk
deleted file mode 100644
index 263c47b..0000000
--- a/tests/tests/accessibility/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsAccessibilityTestCases
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/accessibility/AndroidManifest.xml b/tests/tests/accessibility/AndroidManifest.xml
deleted file mode 100644
index b3bcbc8..0000000
--- a/tests/tests/accessibility/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2012 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.view.cts.accessibility">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-
- <application android:theme="@android:style/Theme.Holo.NoActionBar" >
- <uses-library android:name="android.test.runner"/>
- </application>
-
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.view.cts.accessibility"
- android:label="Tests for the accessibility APIs.">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
diff --git a/tests/tests/accessibility/AndroidTest.xml b/tests/tests/accessibility/AndroidTest.xml
deleted file mode 100644
index 7832508..0000000
--- a/tests/tests/accessibility/AndroidTest.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?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.
--->
-<configuration description="Base config for CTS package preparer">
- <include name="common-config" />
- <option name="run-command:run-command" value="settings put secure enabled_accessibility_services android.view.accessibility.services/.SpeakingAccessibilityService:android.view.accessibility.services/.VibratingAccessibilityService" />
- <option name="run-command:run-command" value="settings put secure touch_exploration_granted_accessibility_services android.view.accessibility.services/.SpeakingAccessibilityService:android.view.accessibility.services/.VibratingAccessibilityService" />
- <option name="run-command:run-command" value="settings put secure accessibility_enabled 1" />
- <option name="run-command:teardown-command" value="settings put secure enabled_accessibility_services """ />
- <option name="run-command:teardown-command" value="settings put secure touch_exploration_granted_accessibility_services """ />
- <option name="run-command:teardown-command" value="settings put secure accessibility_enabled 0" />
- <option name="cts-apk-installer:test-file-name" value="CtsSomeAccessibilityServices.apk" />
-</configuration>
diff --git a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java b/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
deleted file mode 100644
index 506c022..0000000
--- a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2012 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.accessibility.cts;
-
-import android.graphics.Rect;
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import android.view.cts.accessibility.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Class for testing {@link AccessibilityNodeInfo}.
- */
-public class AccessibilityNodeInfoTest extends AndroidTestCase {
-
- /** The number of properties of the {@link AccessibilityNodeInfo} class. */
- private static final int NON_STATIC_FIELD_COUNT = 30;
-
- @SmallTest
- public void testMarshaling() throws Exception {
- // no new fields, so we are testing marshaling of all such
- AccessibilityRecordTest.assertNoNewNonStaticFieldsAdded(AccessibilityNodeInfo.class,
- NON_STATIC_FIELD_COUNT);
-
- // fully populate the node info to marshal
- AccessibilityNodeInfo sentInfo = AccessibilityNodeInfo.obtain(new View(getContext()));
- fullyPopulateAccessibilityNodeInfo(sentInfo);
-
- // marshal and unmarshal the node info
- Parcel parcel = Parcel.obtain();
- sentInfo.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- AccessibilityNodeInfo receivedInfo = AccessibilityNodeInfo.CREATOR.createFromParcel(parcel);
-
- // make sure all fields properly marshaled
- assertEqualsAccessibilityNodeInfo(sentInfo, receivedInfo);
- }
-
- /**
- * Tests if {@link AccessibilityNodeInfo}s are properly reused.
- */
- @SmallTest
- public void testReuse() {
- AccessibilityEvent firstInfo = AccessibilityEvent.obtain();
- firstInfo.recycle();
- AccessibilityEvent secondInfo = AccessibilityEvent.obtain();
- assertSame("AccessibilityNodeInfo not properly reused", firstInfo, secondInfo);
- }
-
- /**
- * Tests if {@link AccessibilityNodeInfo} are properly recycled.
- */
- @SmallTest
- public void testRecycle() {
- // obtain and populate an node info
- AccessibilityNodeInfo populatedInfo = AccessibilityNodeInfo.obtain();
- fullyPopulateAccessibilityNodeInfo(populatedInfo);
-
- // recycle and obtain the same recycled instance
- populatedInfo.recycle();
- AccessibilityNodeInfo recycledInfo = AccessibilityNodeInfo.obtain();
-
- // check expectations
- assertAccessibilityNodeInfoCleared(recycledInfo);
- }
-
- /**
- * Tests whether the event describes its contents consistently.
- */
- @SmallTest
- public void testDescribeContents() {
- AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
- assertSame("Accessibility node infos always return 0 for this method.", 0,
- info.describeContents());
- fullyPopulateAccessibilityNodeInfo(info);
- assertSame("Accessibility node infos always return 0 for this method.", 0,
- info.describeContents());
- }
-
- /**
- * Tests whether accessibility actions are properly added.
- */
- @SmallTest
- public void testAddActions() {
- List<AccessibilityAction> customActions = new ArrayList<AccessibilityAction>();
- customActions.add(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo"));
- customActions.add(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
-
- AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
- info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
- info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
- for (AccessibilityAction customAction : customActions) {
- info.addAction(customAction);
- }
-
- assertSame(info.getActions(), (AccessibilityNodeInfo.ACTION_FOCUS
- | AccessibilityNodeInfo.ACTION_CLEAR_FOCUS));
-
- List<AccessibilityAction> allActions = new ArrayList<AccessibilityAction>();
- allActions.add(AccessibilityAction.ACTION_CLEAR_FOCUS);
- allActions.addAll(customActions);
- assertEquals(info.getActionList(), allActions);
- }
-
- /**
- * Tests whether we catch addition of an action with invalid id.
- */
- @SmallTest
- public void testCreateInvalidActionId() {
- try {
- new AccessibilityAction(3, null);
- } catch (IllegalArgumentException iae) {
- /* expected */
- }
- }
-
- /**
- * Tests whether accessibility actions are properly removed.
- */
- @SmallTest
- public void testRemoveActions() {
- AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
-
- info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
- assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS);
-
- info.removeAction(AccessibilityNodeInfo.ACTION_FOCUS);
- assertSame(info.getActions(), 0);
- assertTrue(info.getActionList().isEmpty());
-
- AccessibilityAction customFocus = new AccessibilityAction(
- AccessibilityNodeInfo.ACTION_FOCUS, "Foo");
- info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
- info.addAction(customFocus);
- assertSame(info.getActionList().size(), 1);
- assertEquals(info.getActionList().get(0), customFocus);
- assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS);
-
- info.removeAction(customFocus);
- assertSame(info.getActions(), 0);
- assertTrue(info.getActionList().isEmpty());
- }
-
- /**
- * Fully populates the {@link AccessibilityNodeInfo} to marshal.
- *
- * @param info The node info to populate.
- */
- private void fullyPopulateAccessibilityNodeInfo(AccessibilityNodeInfo info) {
- info.setParent(new View(getContext()));
- info.setSource(new View(getContext()));
- info.addChild(new View(getContext()));
- info.addChild(new View(getContext()), 1);
- info.setBoundsInParent(new Rect(1,1,1,1));
- info.setBoundsInScreen(new Rect(2,2,2,2));
- info.setClassName("foo.bar.baz.Class");
- info.setContentDescription("content description");
- info.setPackageName("foo.bar.baz");
- info.setText("text");
- info.setCheckable(true);
- info.setChecked(true);
- info.setClickable(true);
- info.setEnabled(true);
- info.setFocusable(true);
- info.setFocused(true);
- info.setLongClickable(true);
- info.setContextClickable(true);
- info.setPassword(true);
- info.setScrollable(true);
- info.setSelected(true);
- info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
- info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
- info.addAction(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo"));
- info.addAction(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
- info.setAccessibilityFocused(true);
- info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- info.setLabeledBy(new View(getContext()));
- info.setLabelFor(new View(getContext()));
- info.setViewIdResourceName("foo.bar:id/baz");
- }
-
- /**
- * Compares all properties of the <code>expectedInfo</code> and the
- * <code>receviedInfo</code> to verify that the received node info is
- * the one that is expected.
- */
- public static void assertEqualsAccessibilityNodeInfo(AccessibilityNodeInfo expectedInfo,
- AccessibilityNodeInfo receivedInfo) {
- Rect expectedBounds = new Rect();
- Rect receivedBounds = new Rect();
- expectedInfo.getBoundsInParent(expectedBounds);
- receivedInfo.getBoundsInParent(receivedBounds);
- assertEquals("boundsInParent has incorrect value", expectedBounds, receivedBounds);
- expectedInfo.getBoundsInScreen(expectedBounds);
- receivedInfo.getBoundsInScreen(receivedBounds);
- assertEquals("boundsInScreen has incorrect value", expectedBounds, receivedBounds);
- assertEquals("className has incorrect value", expectedInfo.getClassName(),
- receivedInfo.getClassName());
- assertEquals("contentDescription has incorrect value", expectedInfo.getContentDescription(),
- receivedInfo.getContentDescription());
- assertEquals("packageName has incorrect value", expectedInfo.getPackageName(),
- receivedInfo.getPackageName());
- assertEquals("text has incorrect value", expectedInfo.getText(), receivedInfo.getText());
- assertSame("checkable has incorrect value", expectedInfo.isCheckable(),
- receivedInfo.isCheckable());
- assertSame("checked has incorrect value", expectedInfo.isChecked(),
- receivedInfo.isChecked());
- assertSame("clickable has incorrect value", expectedInfo.isClickable(),
- receivedInfo.isClickable());
- assertSame("enabled has incorrect value", expectedInfo.isEnabled(),
- receivedInfo.isEnabled());
- assertSame("focusable has incorrect value", expectedInfo.isFocusable(),
- receivedInfo.isFocusable());
- assertSame("focused has incorrect value", expectedInfo.isFocused(),
- receivedInfo.isFocused());
- assertSame("longClickable has incorrect value", expectedInfo.isLongClickable(),
- receivedInfo.isLongClickable());
- assertSame("contextClickable has incorrect value", expectedInfo.isContextClickable(),
- receivedInfo.isContextClickable());
- assertSame("password has incorrect value", expectedInfo.isPassword(),
- receivedInfo.isPassword());
- assertSame("scrollable has incorrect value", expectedInfo.isScrollable(),
- receivedInfo.isScrollable());
- assertSame("selected has incorrect value", expectedInfo.isSelected(),
- receivedInfo.isSelected());
- assertSame("actions has incorrect value", expectedInfo.getActions(),
- receivedInfo.getActions());
- assertEquals("actionsSet has incorrect value", expectedInfo.getActionList(),
- receivedInfo.getActionList());
- assertSame("childCount has incorrect value", expectedInfo.getChildCount(),
- receivedInfo.getChildCount());
- assertSame("childCount has incorrect value", expectedInfo.getChildCount(),
- receivedInfo.getChildCount());
- assertSame("accessibilityFocused has incorrect value",
- expectedInfo.isAccessibilityFocused(),
- receivedInfo.isAccessibilityFocused());
- assertSame("movementGranularities has incorrect value",
- expectedInfo.getMovementGranularities(),
- receivedInfo.getMovementGranularities());
- assertEquals("viewId has incorrect value", expectedInfo.getViewIdResourceName(),
- receivedInfo.getViewIdResourceName());
- }
-
- /**
- * Asserts that an {@link AccessibilityNodeInfo} is cleared.
- *
- * @param info The node info to check.
- */
- public static void assertAccessibilityNodeInfoCleared(AccessibilityNodeInfo info) {
- Rect bounds = new Rect();
- info.getBoundsInParent(bounds);
- assertTrue("boundsInParent not properly recycled", bounds.isEmpty());
- info.getBoundsInScreen(bounds);
- assertTrue("boundsInScreen not properly recycled", bounds.isEmpty());
- assertNull("className not properly recycled", info.getClassName());
- assertNull("contentDescription not properly recycled", info.getContentDescription());
- assertNull("packageName not properly recycled", info.getPackageName());
- assertNull("text not properly recycled", info.getText());
- assertFalse("checkable not properly recycled", info.isCheckable());
- assertFalse("checked not properly recycled", info.isChecked());
- assertFalse("clickable not properly recycled", info.isClickable());
- assertFalse("enabled not properly recycled", info.isEnabled());
- assertFalse("focusable not properly recycled", info.isFocusable());
- assertFalse("focused not properly recycled", info.isFocused());
- assertFalse("longClickable not properly recycled", info.isLongClickable());
- assertFalse("contextClickable not properly recycled", info.isContextClickable());
- assertFalse("password not properly recycled", info.isPassword());
- assertFalse("scrollable not properly recycled", info.isScrollable());
- assertFalse("selected not properly recycled", info.isSelected());
- assertSame("actions not properly recycled", 0, info.getActions());
- assertFalse("accessibilityFocused not properly recycled", info.isAccessibilityFocused());
- assertSame("movementGranularities not properly recycled", 0,
- info.getMovementGranularities());
- assertNull("viewId not properly recycled", info.getViewIdResourceName());
- }
-}
diff --git a/tests/tests/accessibilityservice/Android.mk b/tests/tests/accessibilityservice/Android.mk
deleted file mode 100644
index b27dbcc..0000000
--- a/tests/tests/accessibilityservice/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (C) 2010 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsAccessibilityServiceTestCases
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/accessibilityservice/AndroidManifest.xml b/tests/tests/accessibilityservice/AndroidManifest.xml
deleted file mode 100644
index e172913..0000000
--- a/tests/tests/accessibilityservice/AndroidManifest.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2010 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.accessibilityservice">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-
- <application android:theme="@android:style/Theme.Holo.NoActionBar" >
-
- <uses-library android:name="android.test.runner"/>
-
- <activity android:label="@string/accessibility_end_to_end_test_activity"
- android:name="android.accessibilityservice.cts.AccessibilityEndToEndActivity"/>
-
- <activity android:label="@string/accessibility_query_window_test_activity"
- android:name="android.accessibilityservice.cts.AccessibilityWindowQueryActivity"/>
-
- <activity android:label="@string/accessibility_view_tree_reporting_test_activity"
- android:name="android.accessibilityservice.cts.AccessibilityViewTreeReportingActivity"/>
-
- <activity android:label="@string/accessibility_focus_and_input_focus_sync_test_activity"
- android:name="android.accessibilityservice.cts.AccessibilityFocusAndInputFocusSyncActivity"/>
-
- <activity android:label="@string/accessibility_text_traversal_test_activity"
- android:name="android.accessibilityservice.cts.AccessibilityTextTraversalActivity"/>
-
- </application>
-
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.accessibilityservice"
- android:label="Tests for the accessibility APIs.">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndActivity.java
deleted file mode 100644
index 157a3dc..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndActivity.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2010 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.accessibilityservice.cts;
-
-import com.android.cts.accessibilityservice.R;
-
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-
-/**
- * This class is an {@link android.app.Activity} used to perform end-to-end
- * testing of the accessibility feature by interaction with the
- * UI widgets.
- */
-public class AccessibilityEndToEndActivity extends AccessibilityTestActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.end_to_end_test);
-
- ListAdapter listAdapter = new BaseAdapter() {
- public View getView(int position, View convertView, ViewGroup parent) {
- TextView textView = (TextView) View
- .inflate(AccessibilityEndToEndActivity.this, R.layout.list_view_row, null);
- textView.setText((String) getItem(position));
- return textView;
- }
-
- public long getItemId(int position) {
- return position;
- }
-
- public Object getItem(int position) {
- if (position == 0) {
- return AccessibilityEndToEndActivity.this.getString(R.string.first_list_item);
- } else {
- return AccessibilityEndToEndActivity.this.getString(R.string.second_list_item);
- }
- }
-
- public int getCount() {
- return 2;
- }
- };
-
- ListView listView = (ListView) findViewById(R.id.listview);
- listView.setAdapter(listAdapter);
- }
-}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
deleted file mode 100644
index f5b29cf..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright (C) 2010 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.accessibilityservice.cts;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.app.UiAutomation;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ListView;
-
-import com.android.cts.accessibilityservice.R;
-
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * This class performs end-to-end testing of the accessibility feature by
- * creating an {@link Activity} and poking around so {@link AccessibilityEvent}s
- * are generated and their correct dispatch verified.
- */
-public class AccessibilityEndToEndTest extends
- AccessibilityActivityTestCase<AccessibilityEndToEndActivity> {
-
- private static final String LOG_TAG = "AccessibilityEndToEndTest";
-
- /**
- * Creates a new instance for testing {@link AccessibilityEndToEndActivity}.
- */
- public AccessibilityEndToEndTest() {
- super(AccessibilityEndToEndActivity.class);
- }
-
- @MediumTest
- public void testTypeViewSelectedAccessibilityEvent() throws Throwable {
- // create and populate the expected event
- final AccessibilityEvent expected = AccessibilityEvent.obtain();
- expected.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
- expected.setClassName(ListView.class.getName());
- expected.setPackageName(getActivity().getPackageName());
- expected.getText().add(getActivity().getString(R.string.second_list_item));
- expected.setItemCount(2);
- expected.setCurrentItemIndex(1);
- expected.setEnabled(true);
- expected.setScrollable(false);
- expected.setFromIndex(0);
- expected.setToIndex(1);
-
- final ListView listView = (ListView) getActivity().findViewById(R.id.listview);
-
- AccessibilityEvent awaitedEvent =
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(
- new Runnable() {
- @Override
- public void run() {
- // trigger the event
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- listView.setSelection(1);
- }
- });
- }},
- new UiAutomation.AccessibilityEventFilter() {
- // check the received event
- @Override
- public boolean accept(AccessibilityEvent event) {
- return equalsAccessiblityEvent(event, expected);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
- assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
- }
-
- @MediumTest
- public void testTypeViewClickedAccessibilityEvent() throws Throwable {
- // create and populate the expected event
- final AccessibilityEvent expected = AccessibilityEvent.obtain();
- expected.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED);
- expected.setClassName(Button.class.getName());
- expected.setPackageName(getActivity().getPackageName());
- expected.getText().add(getActivity().getString(R.string.button_title));
- expected.setEnabled(true);
-
- final Button button = (Button) getActivity().findViewById(R.id.button);
-
- AccessibilityEvent awaitedEvent =
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(
- new Runnable() {
- @Override
- public void run() {
- // trigger the event
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- button.performClick();
- }
- });
- }},
- new UiAutomation.AccessibilityEventFilter() {
- // check the received event
- @Override
- public boolean accept(AccessibilityEvent event) {
- return equalsAccessiblityEvent(event, expected);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
- assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
- }
-
- @MediumTest
- public void testTypeViewLongClickedAccessibilityEvent() throws Throwable {
- // create and populate the expected event
- final AccessibilityEvent expected = AccessibilityEvent.obtain();
- expected.setEventType(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
- expected.setClassName(Button.class.getName());
- expected.setPackageName(getActivity().getPackageName());
- expected.getText().add(getActivity().getString(R.string.button_title));
- expected.setEnabled(true);
-
- final Button button = (Button) getActivity().findViewById(R.id.button);
-
- AccessibilityEvent awaitedEvent =
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(
- new Runnable() {
- @Override
- public void run() {
- // trigger the event
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- button.performLongClick();
- }
- });
- }},
- new UiAutomation.AccessibilityEventFilter() {
- // check the received event
- @Override
- public boolean accept(AccessibilityEvent event) {
- return equalsAccessiblityEvent(event, expected);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
- assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
- }
-
- @MediumTest
- public void testTypeViewFocusedAccessibilityEvent() throws Throwable {
- // create and populate the expected event
- final AccessibilityEvent expected = AccessibilityEvent.obtain();
- expected.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
- expected.setClassName(Button.class.getName());
- expected.setPackageName(getActivity().getPackageName());
- expected.getText().add(getActivity().getString(R.string.button_title));
- expected.setItemCount(3);
- expected.setCurrentItemIndex(2);
- expected.setEnabled(true);
-
- final Button button = (Button) getActivity().findViewById(R.id.button);
-
- AccessibilityEvent awaitedEvent =
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(
- new Runnable() {
- @Override
- public void run() {
- // trigger the event
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- button.requestFocus();
- }
- });
- }},
- new UiAutomation.AccessibilityEventFilter() {
- // check the received event
- @Override
- public boolean accept(AccessibilityEvent event) {
- return equalsAccessiblityEvent(event, expected);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
- assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
- }
-
- @MediumTest
- public void testTypeViewTextChangedAccessibilityEvent() throws Throwable {
- // focus the edit text
- final EditText editText = (EditText) getActivity().findViewById(R.id.edittext);
-
- AccessibilityEvent awaitedFocusEvent =
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(
- new Runnable() {
- @Override
- public void run() {
- // trigger the event
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- editText.requestFocus();
- }
- });
- }},
- new UiAutomation.AccessibilityEventFilter() {
- // check the received event
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED;
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
- assertNotNull("Did not receive expected focuss event.", awaitedFocusEvent);
-
- final String beforeText = getActivity().getString(R.string.text_input_blah);
- final String newText = getActivity().getString(R.string.text_input_blah_blah);
- final String afterText = beforeText.substring(0, 3) + newText;
-
- // create and populate the expected event
- final AccessibilityEvent expected = AccessibilityEvent.obtain();
- expected.setEventType(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
- expected.setClassName(EditText.class.getName());
- expected.setPackageName(getActivity().getPackageName());
- expected.getText().add(afterText);
- expected.setBeforeText(beforeText);
- expected.setFromIndex(3);
- expected.setAddedCount(9);
- expected.setRemovedCount(1);
- expected.setEnabled(true);
-
- AccessibilityEvent awaitedTextChangeEvent =
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(
- new Runnable() {
- @Override
- public void run() {
- // trigger the event
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- editText.getEditableText().replace(3, 4, newText);
- }
- });
- }},
- new UiAutomation.AccessibilityEventFilter() {
- // check the received event
- @Override
- public boolean accept(AccessibilityEvent event) {
- return equalsAccessiblityEvent(event, expected);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
- assertNotNull("Did not receive expected event: " + expected, awaitedTextChangeEvent);
- }
-
- @MediumTest
- public void testTypeWindowStateChangedAccessibilityEvent() throws Throwable {
- // create and populate the expected event
- final AccessibilityEvent expected = AccessibilityEvent.obtain();
- expected.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- expected.setClassName(AlertDialog.class.getName());
- expected.setPackageName(getActivity().getPackageName());
- expected.getText().add(getActivity().getString(R.string.alert_title));
- expected.getText().add(getActivity().getString(R.string.alert_message));
- expected.setEnabled(true);
-
- AccessibilityEvent awaitedEvent =
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(
- new Runnable() {
- @Override
- public void run() {
- // trigger the event
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- (new AlertDialog.Builder(getActivity()).setTitle(R.string.alert_title)
- .setMessage(R.string.alert_message)).create().show();
- }
- });
- }},
- new UiAutomation.AccessibilityEventFilter() {
- // check the received event
- @Override
- public boolean accept(AccessibilityEvent event) {
- return equalsAccessiblityEvent(event, expected);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
- assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
- }
-
- @MediumTest
- @SuppressWarnings("deprecation")
- public void testTypeNotificationStateChangedAccessibilityEvent() throws Throwable {
- // No notification UI on televisions.
- if((getActivity().getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
- Log.i(LOG_TAG, "Skipping: testTypeNotificationStateChangedAccessibilityEvent" +
- " - No notification UI on televisions.");
- return;
- }
-
- String message = getActivity().getString(R.string.notification_message);
-
- // create the notification to send
- final int notificationId = 1;
- final Notification notification = new Notification.Builder(getActivity())
- .setSmallIcon(android.R.drawable.stat_notify_call_mute)
- .setContentIntent(PendingIntent.getActivity(getActivity(), 0, new Intent(),
- PendingIntent.FLAG_CANCEL_CURRENT))
- .setTicker(message)
- .setContentTitle("")
- .setContentText("")
- // Mark the notification as "interruptive" by specifying a vibration pattern. This
- // ensures it's announced properly on watch-type devices.
- .setVibrate(new long[] {})
- .build();
-
- // create and populate the expected event
- final AccessibilityEvent expected = AccessibilityEvent.obtain();
- expected.setEventType(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
- expected.setClassName(Notification.class.getName());
- expected.setPackageName(getActivity().getPackageName());
- expected.getText().add(message);
- expected.setParcelableData(notification);
-
- AccessibilityEvent awaitedEvent =
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(
- new Runnable() {
- @Override
- public void run() {
- // trigger the event
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- // trigger the event
- NotificationManager notificationManager =
- (NotificationManager) getActivity().getSystemService(
- Service.NOTIFICATION_SERVICE);
- notificationManager.notify(notificationId, notification);
- getActivity().finish();
- }
- });
- }},
- new UiAutomation.AccessibilityEventFilter() {
- // check the received event
- @Override
- public boolean accept(AccessibilityEvent event) {
- return equalsAccessiblityEvent(event, expected);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
- assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
- }
-
- /**
- * Compares all properties of the <code>first</code> and the
- * <code>second</code>.
- */
- private boolean equalsAccessiblityEvent(AccessibilityEvent first, AccessibilityEvent second) {
- return first.getEventType() == second.getEventType()
- && first.isChecked() == second.isChecked()
- && first.getCurrentItemIndex() == second.getCurrentItemIndex()
- && first.isEnabled() == second.isEnabled()
- && first.getFromIndex() == second.getFromIndex()
- && first.getItemCount() == second.getItemCount()
- && first.isPassword() == second.isPassword()
- && first.getRemovedCount() == second.getRemovedCount()
- && first.isScrollable()== second.isScrollable()
- && first.getToIndex() == second.getToIndex()
- && first.getRecordCount() == second.getRecordCount()
- && first.getScrollX() == second.getScrollX()
- && first.getScrollY() == second.getScrollY()
- && first.getAddedCount() == second.getAddedCount()
- && TextUtils.equals(first.getBeforeText(), second.getBeforeText())
- && TextUtils.equals(first.getClassName(), second.getClassName())
- && TextUtils.equals(first.getContentDescription(), second.getContentDescription())
- && equalsNotificationAsParcelableData(first, second)
- && equalsText(first, second);
- }
-
- /**
- * Compares the {@link android.os.Parcelable} data of the
- * <code>first</code> and <code>second</code>.
- */
- private boolean equalsNotificationAsParcelableData(AccessibilityEvent first,
- AccessibilityEvent second) {
- Notification firstNotification = (Notification) first.getParcelableData();
- Notification secondNotification = (Notification) second.getParcelableData();
- if (firstNotification == null) {
- return (secondNotification == null);
- } else if (secondNotification == null) {
- return false;
- }
- return TextUtils.equals(firstNotification.tickerText, secondNotification.tickerText);
- }
-
- /**
- * Compares the text of the <code>first</code> and <code>second</code> text.
- */
- private boolean equalsText(AccessibilityEvent first, AccessibilityEvent second) {
- List<CharSequence> firstText = first.getText();
- List<CharSequence> secondText = second.getText();
- if (firstText.size() != secondText.size()) {
- return false;
- }
- Iterator<CharSequence> firstIterator = firstText.iterator();
- Iterator<CharSequence> secondIterator = secondText.iterator();
- for (int i = 0; i < firstText.size(); i++) {
- if (!firstIterator.next().toString().equals(secondIterator.next().toString())) {
- return false;
- }
- }
- return true;
- }
-}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncActivity.java
deleted file mode 100644
index 46f04aa..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncActivity.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright (C) 2012 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.accessibilityservice.cts;
-
-import android.os.Bundle;
-
-import com.android.cts.accessibilityservice.R;
-
-/**
- * Activity for testing the accessibility focus APIs exposed to
- * accessibility services. These APIs allow moving accessibility
- * focus in the view tree from an AccessiiblityService. Specifically,
- * this activity is for verifying the the sync between accessibility
- * and input focus.
- */
-public class AccessibilityFocusAndInputFocusSyncActivity extends AccessibilityTestActivity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.accessibility_focus_and_input_focus_sync_test);
- }
-}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java
deleted file mode 100644
index 93b026c..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/**
- * Copyright (C) 2012 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.accessibilityservice.cts;
-
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
-
-import android.app.UiAutomation;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import com.android.cts.accessibilityservice.R;
-
-import java.util.LinkedList;
-import java.util.Queue;
-
-/**
- * Test cases for testing the accessibility focus APIs exposed to accessibility
- * services. These APIs allow moving accessibility focus in the view tree from
- * an AccessiiblityService. Specifically, this activity is for verifying the the
- * sync between accessibility and input focus.
- */
-public class AccessibilityFocusAndInputFocusSyncTest
- extends AccessibilityActivityTestCase<AccessibilityFocusAndInputFocusSyncActivity>{
-
- public AccessibilityFocusAndInputFocusSyncTest() {
- super(AccessibilityFocusAndInputFocusSyncActivity.class);
- }
-
- @MediumTest
- public void testFindAccessibilityFocus() throws Exception {
- // Get the view that has input and accessibility focus.
- final AccessibilityNodeInfo expected = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.firstEditText)).get(0);
- assertNotNull(expected);
- assertFalse(expected.isAccessibilityFocused());
- assertTrue(expected.isFocused());
-
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- // Perform a focus action and check for success.
- assertTrue(expected.performAction(ACTION_ACCESSIBILITY_FOCUS));
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Get the second expected node info.
- AccessibilityNodeInfo received = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
- assertNotNull(received);
- assertTrue(received.isAccessibilityFocused());
-
- // Make sure we got the expected focusable.
- assertEquals(expected, received);
- }
-
- @MediumTest
- public void testInitialStateNoAccessibilityFocus() throws Exception {
- // Get the root which is only accessibility focused.
- AccessibilityNodeInfo focused = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
- assertNull(focused);
- }
-
- @MediumTest
- public void testActionAccessibilityFocus() throws Exception {
- // Get the root linear layout info.
- final AccessibilityNodeInfo rootLinearLayout = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.rootLinearLayout)).get(0);
- assertNotNull(rootLinearLayout);
- assertFalse(rootLinearLayout.isAccessibilityFocused());
-
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- // Perform a focus action and check for success.
- assertTrue(rootLinearLayout.performAction(ACTION_ACCESSIBILITY_FOCUS));
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Get the node info again.
- rootLinearLayout.refresh();
-
- // Check if the node info is focused.
- assertTrue(rootLinearLayout.isAccessibilityFocused());
- }
-
- @MediumTest
- public void testActionClearAccessibilityFocus() throws Exception {
- // Get the root linear layout info.
- final AccessibilityNodeInfo rootLinearLayout = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.rootLinearLayout)).get(0);
- assertNotNull(rootLinearLayout);
-
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- // Perform a focus action and check for success.
- assertTrue(rootLinearLayout.performAction(ACTION_ACCESSIBILITY_FOCUS));
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Refresh the node info.
- rootLinearLayout.refresh();
-
- // Check if the node info is focused.
- assertTrue(rootLinearLayout.isAccessibilityFocused());
-
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- // Perform a clear focus action and check for success.
- assertTrue(rootLinearLayout.performAction(ACTION_CLEAR_ACCESSIBILITY_FOCUS));
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType()
- == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Refresh the node info.
- rootLinearLayout.refresh();
-
- // Check if the node info is not focused.
- assertFalse(rootLinearLayout.isAccessibilityFocused());
- }
-
- @MediumTest
- public void testOnlyOneNodeHasAccessibilityFocus() throws Exception {
- // Get the first not focused edit text.
- final AccessibilityNodeInfo firstEditText = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.firstEditText)).get(0);
- assertNotNull(firstEditText);
- assertTrue(firstEditText.isFocusable());
- assertTrue(firstEditText.isFocused());
- assertFalse(firstEditText.isAccessibilityFocused());
-
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- // Perform a set focus action and check for success.
- assertTrue(firstEditText.performAction(ACTION_ACCESSIBILITY_FOCUS));
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Get the second not focused edit text.
- final AccessibilityNodeInfo secondEditText = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.secondEditText)).get(0);
- assertNotNull(secondEditText);
- assertTrue(secondEditText.isFocusable());
- assertFalse(secondEditText.isFocused());
- assertFalse(secondEditText.isAccessibilityFocused());
-
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- // Perform a set focus action and check for success.
- assertTrue(secondEditText.performAction(ACTION_ACCESSIBILITY_FOCUS));
-
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Get the node info again.
- secondEditText.refresh();
-
- // Make sure no other node has accessibility focus.
- AccessibilityNodeInfo root = getInstrumentation().getUiAutomation().getRootInActiveWindow();
- Queue<AccessibilityNodeInfo> workQueue = new LinkedList<AccessibilityNodeInfo>();
- workQueue.add(root);
- while (!workQueue.isEmpty()) {
- AccessibilityNodeInfo current = workQueue.poll();
- if (current.isAccessibilityFocused() && !current.equals(secondEditText)) {
- fail();
- }
- final int childCount = current.getChildCount();
- for (int i = 0; i < childCount; i++) {
- AccessibilityNodeInfo child = current.getChild(i);
- if (child != null) {
- workQueue.offer(child);
- }
- }
- }
- }
-}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalActivity.java
deleted file mode 100644
index 4a4a4ba..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright (C) 2012 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.accessibilityservice.cts;
-
-import android.os.Bundle;
-
-import com.android.cts.accessibilityservice.R;
-
-/**
- * Activity for testing the accessibility APIs for traversing the
- * text content of a View at several granularities.
- */
-public class AccessibilityTextTraversalActivity extends AccessibilityTestActivity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.accessibility_text_traversal_test);
- }
-}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
deleted file mode 100644
index cb0877d..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
+++ /dev/null
@@ -1,4646 +0,0 @@
-/**
- * Copyright (C) 2012 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.accessibilityservice.cts;
-
-import android.app.UiAutomation;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.text.Selection;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.EditText;
-import android.widget.TextView;
-
-import com.android.cts.accessibilityservice.R;
-
-/**
- * Test cases for testing the accessibility APIs for traversing the text content of
- * a View at several granularities.
- */
-public class AccessibilityTextTraversalTest
- extends AccessibilityActivityTestCase<AccessibilityTextTraversalActivity>{
-
- public AccessibilityTextTraversalTest() {
- super(AccessibilityTextTraversalActivity.class);
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityCharacterOverContentDescription()
- throws Exception {
- final View view = getActivity().findViewById(R.id.view);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- view.setVisibility(View.VISIBLE);
- view.setContentDescription(getString(R.string.a_b));
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.a_b)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
- arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.a_b))
- && event.getFromIndex() == 0
- && event.getToIndex() == 1
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
- arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.a_b))
- && event.getFromIndex() == 1
- && event.getToIndex() == 2
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
- arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.a_b))
- && event.getFromIndex() == 2
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Make sure there is no next.
- assertFalse(text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
- arguments));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
- arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.a_b))
- && event.getFromIndex() == 2
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
- arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.a_b))
- && event.getFromIndex() == 1
- && event.getToIndex() == 2
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
- arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.a_b))
- && event.getFromIndex() == 0
- && event.getToIndex() == 1
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityWordOverContentDescription()
- throws Exception {
- final View view = getActivity().findViewById(R.id.view);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- view.setVisibility(View.VISIBLE);
- view.setContentDescription(getString(R.string.foo_bar_baz));
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.foo_bar_baz)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Move to the next character and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(View.class.getName())
- && event.getContentDescription().toString().equals(
- getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityCharacterOverText()
- throws Exception {
- final TextView textView = (TextView) getActivity().findViewById(R.id.text);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- textView.setVisibility(View.VISIBLE);
- textView.setText(getString(R.string.a_b));
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.a_b)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 0
- && event.getToIndex() == 1
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(1, Selection.getSelectionStart(textView.getText()));
- assertEquals(1, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next character and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 1
- && event.getToIndex() == 2
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(textView.getText()));
- assertEquals(2, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next character and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 2
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(textView.getText()));
- assertEquals(3, Selection.getSelectionEnd(textView.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(textView.getText()));
- assertEquals(3, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 2
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(textView.getText()));
- assertEquals(2, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 1
- && event.getToIndex() == 2
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(1, Selection.getSelectionStart(textView.getText()));
- assertEquals(1, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 0
- && event.getToIndex() == 1
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(seventhExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(textView.getText()));
- assertEquals(0, Selection.getSelectionEnd(textView.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(textView.getText()));
- assertEquals(0, Selection.getSelectionEnd(textView.getText()));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityCharacterOverTextExtend()
- throws Exception {
- final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setVisibility(View.VISIBLE);
- editText.setText(getString(R.string.a_b));
- Selection.removeSelection(editText.getText());
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.a_b)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
-
- // Move to the next character and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 0
- && event.getToIndex() == 1
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(1, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next character and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 1
- && event.getToIndex() == 2
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(2, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next character and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 2
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(3, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(3, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 2
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(2, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 1
- && event.getToIndex() == 2
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(1, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 0
- && event.getToIndex() == 1
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Focus the view so we can change selection.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setFocusable(true);
- editText.requestFocus();
- }
- });
-
- // Put selection at the end of the text.
- Bundle setSelectionArgs = new Bundle();
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 3);
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 3);
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(editText.getText()));
- assertEquals(3, Selection.getSelectionEnd(editText.getText()));
-
- // Unfocus the view so we can get rid of the soft-keyboard.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.clearFocus();
- editText.setFocusable(false);
- }
- });
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 2
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(seventhExpected);
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(editText.getText()));
- assertEquals(2, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 1
- && event.getToIndex() == 2
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eightExpected);
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(editText.getText()));
- assertEquals(1, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 0
- && event.getToIndex() == 1
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(ninethExpected);
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next character and wait for an event.
- AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 0
- && event.getToIndex() == 1
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(tenthExpected);
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(editText.getText()));
- assertEquals(1, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next character and wait for an event.
- AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 1
- && event.getToIndex() == 2
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eleventhExpected);
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(editText.getText()));
- assertEquals(2, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next character and wait for an event.
- AccessibilityEvent twelvethExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.a_b))
- && event.getFromIndex() == 2
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(twelvethExpected);
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(editText.getText()));
- assertEquals(3, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(editText.getText()));
- assertEquals(3, Selection.getSelectionEnd(editText.getText()));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityWordOverText() throws Exception {
- final TextView textView = (TextView) getActivity().findViewById(R.id.text);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- textView.setVisibility(View.VISIBLE);
- textView.setText(getString(R.string.foo_bar_baz));
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.foo_bar_baz)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
-
- // Move to the next word and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(3, Selection.getSelectionStart(textView.getText()));
- assertEquals(3, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next word and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(7, Selection.getSelectionStart(textView.getText()));
- assertEquals(7, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next word and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(textView.getText()));
- assertEquals(11, Selection.getSelectionEnd(textView.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(textView.getText()));
- assertEquals(11, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next word and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(8, Selection.getSelectionStart(textView.getText()));
- assertEquals(8, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next word and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(4, Selection.getSelectionStart(textView.getText()));
- assertEquals(4, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next character and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(textView.getText()));
- assertEquals(0, Selection.getSelectionEnd(textView.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(textView.getText()));
- assertEquals(0, Selection.getSelectionEnd(textView.getText()));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityWordOverEditTextWithContentDescription()
- throws Exception {
- final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setVisibility(View.VISIBLE);
- editText.setText(getString(R.string.foo_bar_baz));
- editText.setContentDescription(getString(R.string.android_wiki));
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.foo_bar_baz)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
-
- // Move to the next word and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getContentDescription().equals(getString(R.string.android_wiki))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(3, editText.getSelectionStart());
- assertEquals(3, editText.getSelectionEnd());
-
- // Move to the next word and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getContentDescription().equals(getString(R.string.android_wiki))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(7, editText.getSelectionStart());
- assertEquals(7, editText.getSelectionEnd());
-
- // Move to the next word and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getContentDescription().equals(getString(R.string.android_wiki))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(11, editText.getSelectionStart());
- assertEquals(11, editText.getSelectionEnd());
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(11, editText.getSelectionStart());
- assertEquals(11, editText.getSelectionEnd());
-
- // Move to the next word and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getContentDescription().equals(getString(R.string.android_wiki))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(8, editText.getSelectionStart());
- assertEquals(8, editText.getSelectionEnd());
-
- // Move to the next word and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getContentDescription().equals(getString(R.string.android_wiki))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(4, editText.getSelectionStart());
- assertEquals(4, editText.getSelectionEnd());
-
- // Move to the next character and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getContentDescription().equals(getString(R.string.android_wiki))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(0, editText.getSelectionStart());
- assertEquals(0, editText.getSelectionEnd());
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, editText.getSelectionStart());
- assertEquals(0, editText.getSelectionEnd());
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityWordOverTextExtend() throws Exception {
- final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setVisibility(View.VISIBLE);
- editText.setText(getString(R.string.foo_bar_baz));
- Selection.removeSelection(editText.getText());
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.foo_bar_baz)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
-
- // Move to the next word and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(3, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next word and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(7, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next word and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(11, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Move to the previous word and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(8, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous word and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(4, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Focus the view so we can change selection.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setFocusable(true);
- editText.requestFocus();
- }
- });
-
- // Put selection at the end of the text.
- Bundle setSelectionArgs = new Bundle();
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 11);
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 11);
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(editText.getText()));
- assertEquals(11, Selection.getSelectionEnd(editText.getText()));
-
- // Unfocus the view so we can get rid of the soft-keyboard.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.clearFocus();
- editText.setFocusable(false);
- }
- });
-
- // Move to the previous word and wait for an event.
- AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(seventhExpected);
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(editText.getText()));
- assertEquals(8, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous word and wait for an event.
- AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eightExpected);
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(editText.getText()));
- assertEquals(4, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous character and wait for an event.
- AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(ninethExpected);
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next word and wait for an event.
- AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 0
- && event.getToIndex() == 3
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(tenthExpected);
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(editText.getText()));
- assertEquals(3, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next word and wait for an event.
- AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 4
- && event.getToIndex() == 7
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eleventhExpected);
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(editText.getText()));
- assertEquals(7, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next word and wait for an event.
- AccessibilityEvent twelvthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
- && event.getFromIndex() == 8
- && event.getToIndex() == 11
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(twelvthExpected);
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(editText.getText()));
- assertEquals(11, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(11, Selection.getSelectionStart(editText.getText()));
- assertEquals(11, Selection.getSelectionEnd(editText.getText()));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityLineOverText() throws Exception {
- final TextView textView = (TextView) getActivity().findViewById(R.id.text);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- textView.setVisibility(View.VISIBLE);
- textView.setText(getString(R.string.android_wiki_short));
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.android_wiki_short)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
-
- // Move to the next line and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 0
- && event.getToIndex() == 13
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(13, Selection.getSelectionStart(textView.getText()));
- assertEquals(13, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next line and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 13
- && event.getToIndex() == 25
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(25, Selection.getSelectionStart(textView.getText()));
- assertEquals(25, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next line and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 25
- && event.getToIndex() == 34
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(textView.getText()));
- assertEquals(34, Selection.getSelectionEnd(textView.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(textView.getText()));
- assertEquals(34, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the previous line and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 25
- && event.getToIndex() == 34
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(25, Selection.getSelectionStart(textView.getText()));
- assertEquals(25, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the previous line and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 13
- && event.getToIndex() == 25
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(13, Selection.getSelectionStart(textView.getText()));
- assertEquals(13, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the previous line and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(TextView.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 0
- && event.getToIndex() == 13
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(textView.getText()));
- assertEquals(0, Selection.getSelectionEnd(textView.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(textView.getText()));
- assertEquals(0, Selection.getSelectionEnd(textView.getText()));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityLineOverTextExtend() throws Exception {
- final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setVisibility(View.VISIBLE);
- editText.setText(getString(R.string.android_wiki_short));
- Selection.removeSelection(editText.getText());
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.android_wiki_short)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
-
- // Move to the next line and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 0
- && event.getToIndex() == 13
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(13, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next line and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 13
- && event.getToIndex() == 25
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(25, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next line and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 25
- && event.getToIndex() == 34
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(34, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous line and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 25
- && event.getToIndex() == 34
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(25, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous line and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 13
- && event.getToIndex() == 25
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(13, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous line and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 0
- && event.getToIndex() == 13
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Focus the view so we can change selection.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setFocusable(true);
- editText.requestFocus();
- }
- });
-
- // Put selection at the end of the text.
- Bundle setSelectionArgs = new Bundle();
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 34);
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 34);
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(editText.getText()));
- assertEquals(34, Selection.getSelectionEnd(editText.getText()));
-
- // Unocus the view so we can hide the keyboard.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.clearFocus();
- editText.setFocusable(false);
- }
- });
-
- // Move to the previous line and wait for an event.
- AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 25
- && event.getToIndex() == 34
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(seventhExpected);
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(editText.getText()));
- assertEquals(25, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous line and wait for an event.
- AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 13
- && event.getToIndex() == 25
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eightExpected);
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(editText.getText()));
- assertEquals(13, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous line and wait for an event.
- AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 0
- && event.getToIndex() == 13
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(ninethExpected);
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next line and wait for an event.
- AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 0
- && event.getToIndex() == 13
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(tenthExpected);
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(editText.getText()));
- assertEquals(13, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next line and wait for an event.
- AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 13
- && event.getToIndex() == 25
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eleventhExpected);
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(editText.getText()));
- assertEquals(25, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next line and wait for an event.
- AccessibilityEvent twelvethExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_short))
- && event.getFromIndex() == 25
- && event.getToIndex() == 34
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(twelvethExpected);
-
- // Verify the selection position.
- assertEquals(34, Selection.getSelectionStart(editText.getText()));
- assertEquals(34, Selection.getSelectionEnd(editText.getText()));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityPageOverText() throws Exception {
- final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setVisibility(View.VISIBLE);
- editText.setText(getString(R.string.android_wiki));
- Selection.removeSelection(editText.getText());
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.android_wiki)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- // Move to the next page and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 0
- && event.getToIndex() == 53
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(53, Selection.getSelectionStart(editText.getText()));
- assertEquals(53, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next page and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 53
- && event.getToIndex() == 103
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(103, Selection.getSelectionStart(editText.getText()));
- assertEquals(103, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next page and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 103
- && event.getToIndex() == 153
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(153, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(153, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous page and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 103
- && event.getToIndex() == 153
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(103, Selection.getSelectionStart(editText.getText()));
- assertEquals(103, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous page and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 53
- && event.getToIndex() == 103
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(53, Selection.getSelectionStart(editText.getText()));
- assertEquals(53, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous page and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 0
- && event.getToIndex() == 53
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityPageOverTextExtend() throws Exception {
- final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setVisibility(View.VISIBLE);
- editText.setText(getString(R.string.android_wiki));
- Selection.removeSelection(editText.getText());
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.android_wiki)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
-
- // Move to the next page and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 0
- && event.getToIndex() == 53
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(53, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next page and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 53
- && event.getToIndex() == 103
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(103, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next page and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 103
- && event.getToIndex() == 153
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(153, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Move to the previous page and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 103
- && event.getToIndex() == 153
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(103, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous page and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 53
- && event.getToIndex() == 103
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(53, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous page and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 0
- && event.getToIndex() == 53
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(0, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Focus the view so we can change selection.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setFocusable(true);
- editText.requestFocus();
- }
- });
-
- // Put selection at the end of the text.
- Bundle setSelectionArgs = new Bundle();
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 153);
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 153);
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(153, Selection.getSelectionEnd(editText.getText()));
-
- // Unfocus the view so we can hide the soft-keyboard.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.clearFocus();
- editText.setFocusable(false);
- }
- });
-
- // Move to the previous page and wait for an event.
- AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 103
- && event.getToIndex() == 153
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(seventhExpected);
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(103, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous page and wait for an event.
- AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 53
- && event.getToIndex() == 103
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eightExpected);
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(53, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous page and wait for an event.
- AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 0
- && event.getToIndex() == 53
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(ninethExpected);
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(0, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next page and wait for an event.
- AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 0
- && event.getToIndex() == 53
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(tenthExpected);
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(53, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next page and wait for an event.
- AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 53
- && event.getToIndex() == 103
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eleventhExpected);
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(103, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next page and wait for an event.
- AccessibilityEvent twelvethExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki))
- && event.getFromIndex() == 103
- && event.getToIndex() == 153
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(twelvethExpected);
-
- // Verify the selection position.
- assertEquals(153, Selection.getSelectionStart(editText.getText()));
- assertEquals(153, Selection.getSelectionEnd(editText.getText()));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityParagraphOverText() throws Exception {
- final TextView textView = (TextView) getActivity().findViewById(R.id.edit);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- textView.setVisibility(View.VISIBLE);
- textView.setText(getString(R.string.android_wiki_paragraphs));
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.android_wiki_paragraphs)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
-
- // Move to the next paragraph and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 2
- && event.getToIndex() == 14
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(14, Selection.getSelectionStart(textView.getText()));
- assertEquals(14, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next paragraph and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 16
- && event.getToIndex() == 32
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(32, Selection.getSelectionStart(textView.getText()));
- assertEquals(32, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the next paragraph and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 33
- && event.getToIndex() == 47
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(textView.getText()));
- assertEquals(47, Selection.getSelectionEnd(textView.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(textView.getText()));
- assertEquals(47, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the previous paragraph and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 33
- && event.getToIndex() == 47
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(33, Selection.getSelectionStart(textView.getText()));
- assertEquals(33, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the previous paragraph and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 16
- && event.getToIndex() == 32
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(16, Selection.getSelectionStart(textView.getText()));
- assertEquals(16, Selection.getSelectionEnd(textView.getText()));
-
- // Move to the previous paragraph and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 2
- && event.getToIndex() == 14
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(textView.getText()));
- assertEquals(2, Selection.getSelectionEnd(textView.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(textView.getText()));
- assertEquals(2, Selection.getSelectionEnd(textView.getText()));
- }
-
- @MediumTest
- public void testActionNextAndPreviousAtGranularityParagraphOverTextExtend() throws Exception {
- final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setVisibility(View.VISIBLE);
- editText.setText(getString(R.string.android_wiki_paragraphs));
- Selection.removeSelection(editText.getText());
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.android_wiki_paragraphs)).get(0);
-
- final int granularities = text.getMovementGranularities();
- assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
- | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
-
- final Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
-
- // Move to the next paragraph and wait for an event.
- AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 2
- && event.getToIndex() == 14
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(firstExpected);
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(editText.getText()));
- assertEquals(14, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next paragraph and wait for an event.
- AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 16
- && event.getToIndex() == 32
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(secondExpected);
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(editText.getText()));
- assertEquals(32, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next paragraph and wait for an event.
- AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 33
- && event.getToIndex() == 47
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(thirdExpected);
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(editText.getText()));
- assertEquals(47, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(editText.getText()));
- assertEquals(47, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous paragraph and wait for an event.
- AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 33
- && event.getToIndex() == 47
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fourthExpected);
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(editText.getText()));
- assertEquals(33, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous paragraph and wait for an event.
- AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 16
- && event.getToIndex() == 32
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(fifthExpected);
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(editText.getText()));
- assertEquals(16, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous paragraph and wait for an event.
- AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 2
- && event.getToIndex() == 14
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(sixthExpected);
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(editText.getText()));
- assertEquals(2, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(2, Selection.getSelectionStart(editText.getText()));
- assertEquals(2, Selection.getSelectionEnd(editText.getText()));
-
- // Focus the view so we can change selection.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setFocusable(true);
- editText.requestFocus();
- }
- });
-
- // Put selection at the end of the text.
- Bundle setSelectionArgs = new Bundle();
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 47);
- setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 47);
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(editText.getText()));
- assertEquals(47, Selection.getSelectionEnd(editText.getText()));
-
- // Unfocus the view so we can get rid of the soft-keyboard.
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.clearFocus();
- editText.setFocusable(false);
- }
- });
-
- // Move to the previous paragraph and wait for an event.
- AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 33
- && event.getToIndex() == 47
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(seventhExpected);
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(editText.getText()));
- assertEquals(33, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous paragraph and wait for an event.
- AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 16
- && event.getToIndex() == 32
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eightExpected);
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(editText.getText()));
- assertEquals(16, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the previous paragraph and wait for an event.
- AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 2
- && event.getToIndex() == 14
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(ninethExpected);
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(editText.getText()));
- assertEquals(2, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no previous.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(editText.getText()));
- assertEquals(2, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next paragraph and wait for an event.
- AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 2
- && event.getToIndex() == 14
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(tenthExpected);
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(editText.getText()));
- assertEquals(14, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next paragraph and wait for an event.
- AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 16
- && event.getToIndex() == 32
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(eleventhExpected);
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(editText.getText()));
- assertEquals(32, Selection.getSelectionEnd(editText.getText()));
-
- // Move to the next paragraph and wait for an event.
- AccessibilityEvent twlevethExpected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return
- (event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
- && event.getAction() ==
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
- && event.getPackageName().equals(getActivity().getPackageName())
- && event.getClassName().equals(EditText.class.getName())
- && event.getText().size() > 0
- && event.getText().get(0).toString().equals(getString(
- R.string.android_wiki_paragraphs))
- && event.getFromIndex() == 33
- && event.getToIndex() == 47
- && event.getMovementGranularity() ==
- AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure we got the expected event.
- assertNotNull(twlevethExpected);
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(editText.getText()));
- assertEquals(47, Selection.getSelectionEnd(editText.getText()));
-
- // Make sure there is no next.
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
-
- // Verify the selection position.
- assertEquals(47, Selection.getSelectionStart(editText.getText()));
- assertEquals(47, Selection.getSelectionEnd(editText.getText()));
- }
-
- @MediumTest
- public void testTextEditingActions() throws Exception {
- if (!getActivity().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_INPUT_METHODS)) {
- return;
- }
-
- final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
- final String textContent = getString(R.string.foo_bar_baz);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- editText.setVisibility(View.VISIBLE);
- editText.setFocusable(true);
- editText.requestFocus();
- editText.setText(getString(R.string.foo_bar_baz));
- Selection.removeSelection(editText.getText());
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.foo_bar_baz)).get(0);
-
- // Select all text.
- Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT,
- editText.getText().length());
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
-
- // Copy the selected text.
- text.performAction(AccessibilityNodeInfo.ACTION_COPY);
-
- // Set selection at the end.
- final int textLength = editText.getText().length();
- // Verify the selection position.
- assertEquals(textLength, Selection.getSelectionStart(editText.getText()));
- assertEquals(textLength, Selection.getSelectionEnd(editText.getText()));
-
- // Paste the selected text.
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_PASTE));
-
- // Verify the content.
- assertEquals(editText.getText().toString(), textContent + textContent);
-
- // Select all text.
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT,
- editText.getText().length());
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
-
- // Cut the selected text.
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_CUT));
-
- // Verify the content.
- assertTrue(TextUtils.isEmpty(editText.getText()));
- }
-
- public void testSetSelectionInContentDescription() throws Exception {
- final View view = getActivity().findViewById(R.id.view);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- view.setVisibility(View.VISIBLE);
- view.setContentDescription(getString(R.string.foo_bar_baz));
- }
- });
-
- AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.foo_bar_baz)).get(0);
-
- // Set the cursor position.
- Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 4);
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
-
- // Try and fail to set the selection longer than zero.
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 5);
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
- }
-
- public void testSelectionPositionForNonEditableView() throws Exception {
- final View view = getActivity().findViewById(R.id.view);
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- view.setVisibility(View.VISIBLE);
- view.setContentDescription(getString(R.string.foo_bar_baz));
- }
- });
-
- final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.foo_bar_baz)).get(0);
-
- // Check the initial node properties.
- assertFalse(text.isEditable());
- assertSame(text.getTextSelectionStart(), -1);
- assertSame(text.getTextSelectionEnd(), -1);
-
- // Set the cursor position.
- getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 4);
- assertTrue(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return (event.getEventType()
- == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Refresh the node.
- AccessibilityNodeInfo refreshedText = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.foo_bar_baz)).get(0);
-
- // Check the related node properties.
- assertFalse(refreshedText.isEditable());
- assertSame(refreshedText.getTextSelectionStart(), 4);
- assertSame(refreshedText.getTextSelectionEnd(), 4);
-
- // Try to set to an invalid cursor position.
- Bundle arguments = new Bundle();
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
- arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 5);
- assertFalse(text.performAction(
- AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
-
- // Refresh the node.
- refreshedText = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.foo_bar_baz)).get(0);
-
- // Check the related node properties.
- assertFalse(refreshedText.isEditable());
- assertSame(refreshedText.getTextSelectionStart(), 4);
- assertSame(refreshedText.getTextSelectionEnd(), 4);
- }
-}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingActivity.java
deleted file mode 100644
index 6aa4f44..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingActivity.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright (C) 2012 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.accessibilityservice.cts;
-
-import android.os.Bundle;
-
-import com.android.cts.accessibilityservice.R;
-
-/**
- * Activity for testing the accessibility focus APIs exposed to
- * accessibility services. These APIs allow moving accessibility
- * focus in the view tree from an AccessiiblityService. Specifically,
- * this activity is for verifying the hierarchical movement of the
- * accessibility focus.
- */
-public class AccessibilityViewTreeReportingActivity extends AccessibilityTestActivity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.accessibility_view_tree_reporting_test);
- }
-}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java
deleted file mode 100644
index 9785ab4..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * Copyright (C) 2012 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.accessibilityservice.cts;
-
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import com.android.cts.accessibilityservice.R;
-
-/**
- * Test cases for testing the accessibility focus APIs exposed to accessibility
- * services. This test checks how the view hierarchy is reported to accessibility
- * services.
- */
-public class AccessibilityViewTreeReportingTest
- extends AccessibilityActivityTestCase<AccessibilityViewTreeReportingActivity>{
-
- public AccessibilityViewTreeReportingTest() {
- super(AccessibilityViewTreeReportingActivity.class);
- }
-
- @MediumTest
- public void testDescendantsOfNotImportantViewReportedInOrder1() throws Exception {
- AccessibilityNodeInfo firstFrameLayout = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.firstFrameLayout)).get(0);
- assertNotNull(firstFrameLayout);
- assertSame(3, firstFrameLayout.getChildCount());
-
- // Check if the first child is the right one.
- AccessibilityNodeInfo firstTextView = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.firstTextView)).get(0);
- assertEquals(firstTextView, firstFrameLayout.getChild(0));
-
- // Check if the second child is the right one.
- AccessibilityNodeInfo firstEditText = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
- R.string.firstEditText)).get(0);
- assertEquals(firstEditText, firstFrameLayout.getChild(1));
-
- // Check if the third child is the right one.
- AccessibilityNodeInfo firstButton = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.firstButton)).get(0);
- assertEquals(firstButton, firstFrameLayout.getChild(2));
- }
-
- @MediumTest
- public void testDescendantsOfNotImportantViewReportedInOrder2() throws Exception {
- AccessibilityNodeInfo secondFrameLayout = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.secondFrameLayout)).get(0);
- assertNotNull(secondFrameLayout);
- assertSame(3, secondFrameLayout.getChildCount());
-
- // Check if the first child is the right one.
- AccessibilityNodeInfo secondTextView = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.secondTextView)).get(0);
- assertEquals(secondTextView, secondFrameLayout.getChild(0));
-
- // Check if the second child is the right one.
- AccessibilityNodeInfo secondEditText = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.secondEditText)).get(0);
- assertEquals(secondEditText, secondFrameLayout.getChild(1));
-
- // Check if the third child is the right one.
- AccessibilityNodeInfo secondButton = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.secondButton)).get(0);
- assertEquals(secondButton, secondFrameLayout.getChild(2));
- }
-
- @MediumTest
- public void testDescendantsOfNotImportantViewReportedInOrder3() throws Exception {
- AccessibilityNodeInfo rootLinearLayout = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.rootLinearLayout)).get(0);
- assertNotNull(rootLinearLayout);
- assertSame(4, rootLinearLayout.getChildCount());
-
- // Check if the first child is the right one.
- AccessibilityNodeInfo firstFrameLayout = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.firstFrameLayout)).get(0);
- assertEquals(firstFrameLayout, rootLinearLayout.getChild(0));
-
- // Check if the second child is the right one.
- AccessibilityNodeInfo secondTextView = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.secondTextView)).get(0);
- assertEquals(secondTextView, rootLinearLayout.getChild(1));
-
- // Check if the third child is the right one.
- AccessibilityNodeInfo secondEditText = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.secondEditText)).get(0);
- assertEquals(secondEditText, rootLinearLayout.getChild(2));
-
- // Check if the fourth child is the right one.
- AccessibilityNodeInfo secondButton = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.secondButton)).get(0);
- assertEquals(secondButton, rootLinearLayout.getChild(3));
- }
-}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
deleted file mode 100644
index aa66a45..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Copyright (C) 2011 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.accessibilityservice.cts;
-
-import android.os.Bundle;
-import android.view.View;
-
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import com.android.cts.accessibilityservice.R;
-
-/**
- * Activity for testing the accessibility APIs for querying of
- * the screen content. These APIs allow exploring the screen and
- * requesting an action to be performed on a given view from an
- * AccessibilityService.
- */
-public class AccessibilityWindowQueryActivity extends AccessibilityTestActivity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.query_window_test);
-
- findViewById(R.id.button5).setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- /* do nothing */
- }
- });
- findViewById(R.id.button5).setOnLongClickListener(new View.OnLongClickListener() {
- public boolean onLongClick(View v) {
- return true;
- }
- });
-
- findViewById(R.id.button5).setAccessibilityDelegate(new View.AccessibilityDelegate() {
- @Override
- public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(host, info);
- info.addAction(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
- }
-
- @Override
- public boolean performAccessibilityAction(View host, int action, Bundle args) {
- if (action == R.id.foo_custom_action) {
- return true;
- }
- return super.performAccessibilityAction(host, action, args);
- }
- });
- }
-}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
deleted file mode 100755
index 131b8d6..0000000
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- * Copyright (C) 2012 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.accessibilityservice.cts;
-
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_FOCUS;
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_SELECTION;
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_SELECT;
-
-import android.accessibilityservice.AccessibilityService;
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.app.UiAutomation;
-import android.graphics.Rect;
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.Gravity;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import android.view.accessibility.AccessibilityWindowInfo;
-
-import android.widget.Button;
-import com.android.cts.accessibilityservice.R;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Test cases for testing the accessibility APIs for querying of the screen content.
- * These APIs allow exploring the screen and requesting an action to be performed
- * on a given view from an AccessibilityService.
- */
-public class AccessibilityWindowQueryTest
- extends AccessibilityActivityTestCase<AccessibilityWindowQueryActivity> {
-
- private static final long TIMEOUT_WINDOW_STATE_IDLE = 500;
-
- public AccessibilityWindowQueryTest() {
- super(AccessibilityWindowQueryActivity.class);
- }
-
- @MediumTest
- public void testFindByText() throws Exception {
- // find a view by text
- List<AccessibilityNodeInfo> buttons = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText("b");
- assertEquals(9, buttons.size());
- }
-
- @MediumTest
- public void testFindByContentDescription() throws Exception {
- // find a view by text
- AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.contentDescription)).get(0);
- assertNotNull(button);
- }
-
- @MediumTest
- public void testTraverseWindow() throws Exception {
- verifyNodesInAppWindow(getInstrumentation().getUiAutomation().getRootInActiveWindow());
- }
-
- @MediumTest
- public void testNoWindowsAccessIfFlagNotSet() throws Exception {
- // Make sure the windows cannot be accessed.
- UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
- assertTrue(uiAutomation.getWindows().isEmpty());
-
- // Find a button to click on.
- final AccessibilityNodeInfo button1 = uiAutomation.getRootInActiveWindow()
- .findAccessibilityNodeInfosByViewId(
- "com.android.cts.accessibilityservice:id/button1").get(0);
-
- // Argh...
- final List<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();
-
- // Click the button.
- uiAutomation.executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- button1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
- }
- },
- new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
- events.add(event);
- return true;
- }
- return false;
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure the source window cannot be accessed.
- AccessibilityEvent event = events.get(0);
- assertNull(event.getSource().getWindow());
- }
-
- @MediumTest
- public void testTraverseAllWindows() throws Exception {
- setAccessInteractiveWindowsFlag();
- try {
- UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-
- List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
- Rect boundsInScreen = new Rect();
-
- final int windowCount = windows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = windows.get(i);
-
- window.getBoundsInScreen(boundsInScreen);
- assertFalse(boundsInScreen.isEmpty()); // Varies on screen size, emptiness check.
- assertNull(window.getParent());
- assertSame(0, window.getChildCount());
- assertNull(window.getParent());
- assertNotNull(window.getRoot());
-
- if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) {
- assertTrue(window.isFocused());
- assertTrue(window.isActive());
- verifyNodesInAppWindow(window.getRoot());
- } else if (window.getType() == AccessibilityWindowInfo.TYPE_SYSTEM) {
- assertFalse(window.isFocused());
- assertFalse(window.isActive());
- }
- }
- } finally {
- clearAccessInteractiveWindowsFlag();
- }
- }
-
- @MediumTest
- public void testTraverseWindowFromEvent() throws Exception {
- setAccessInteractiveWindowsFlag();
- try {
- UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-
- // Find a button to click on.
- final AccessibilityNodeInfo button1 = uiAutomation.getRootInActiveWindow()
- .findAccessibilityNodeInfosByViewId(
- "com.android.cts.accessibilityservice:id/button1").get(0);
-
- // Argh...
- final List<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();
-
- // Click the button.
- uiAutomation.executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- button1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
- }
- },
- new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
- events.add(event);
- return true;
- }
- return false;
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
-
- // Get the source window.
- AccessibilityEvent event = events.get(0);
- AccessibilityWindowInfo window = event.getSource().getWindow();
-
- // Verify the application window.
- Rect boundsInScreen = new Rect();
- window.getBoundsInScreen(boundsInScreen);
- assertFalse(boundsInScreen.isEmpty()); // Varies on screen size, so just emptiness check.
- assertSame(window.getType(), AccessibilityWindowInfo.TYPE_APPLICATION);
- assertTrue(window.isFocused());
- assertTrue(window.isActive());
- assertNull(window.getParent());
- assertSame(0, window.getChildCount());
- assertNotNull(window.getRoot());
-
- // Verify the window content.
- verifyNodesInAppWindow(window.getRoot());
- } finally {
- clearAccessInteractiveWindowsFlag();
- }
- }
-
- @MediumTest
- public void testInteractWithAppWindow() throws Exception {
- setAccessInteractiveWindowsFlag();
- try {
- UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-
- // Find a button to click on.
- final AccessibilityNodeInfo button1 = uiAutomation.getRootInActiveWindow()
- .findAccessibilityNodeInfosByViewId(
- "com.android.cts.accessibilityservice:id/button1").get(0);
-
- // Argh...
- final List<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();
-
- // Click the button.
- uiAutomation.executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- button1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
- }
- },
- new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
- events.add(event);
- return true;
- }
- return false;
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
-
- // Get the source window.
- AccessibilityEvent event = events.get(0);
- AccessibilityWindowInfo window = event.getSource().getWindow();
-
- // Find a another button from the event's window.
- final AccessibilityNodeInfo button2 = window.getRoot()
- .findAccessibilityNodeInfosByViewId(
- "com.android.cts.accessibilityservice:id/button2").get(0);
-
- // Click the second button.
- uiAutomation.executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- button2.performAction(AccessibilityNodeInfo.ACTION_CLICK);
- }
- },
- new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED;
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
- } finally {
- clearAccessInteractiveWindowsFlag();
- }
- }
-
- @MediumTest
- public void testSingleAccessibilityFocusAcrossWindows() throws Exception {
- setAccessInteractiveWindowsFlag();
- try {
- // Add two more windows.
- addTwoAppPanelWindows();
-
- // Put accessibility focus in the first app window.
- ensureAppWindowFocusedOrFail(0);
- // Make sure there only one accessibility focus.
- assertSingleAccessibilityFocus();
-
- // Put accessibility focus in the second app window.
- ensureAppWindowFocusedOrFail(1);
- // Make sure there only one accessibility focus.
- assertSingleAccessibilityFocus();
-
- // Put accessibility focus in the third app window.
- ensureAppWindowFocusedOrFail(2);
- // Make sure there only one accessibility focus.
- assertSingleAccessibilityFocus();
- } finally {
- ensureAccessibilityFocusCleared();
- clearAccessInteractiveWindowsFlag();
- }
- }
-
- @MediumTest
- public void testPerformActionFocus() throws Exception {
- // find a view and make sure it is not focused
- AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.button5)).get(0);
- assertFalse(button.isFocused());
-
- // focus the view
- assertTrue(button.performAction(ACTION_FOCUS));
-
- // find the view again and make sure it is focused
- button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
- .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
- assertTrue(button.isFocused());
- }
-
- @MediumTest
- public void testPerformActionClearFocus() throws Exception {
- // find a view and make sure it is not focused
- AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.button5)).get(0);
- assertFalse(button.isFocused());
-
- // focus the view
- assertTrue(button.performAction(ACTION_FOCUS));
-
- // find the view again and make sure it is focused
- button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
- .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
- assertTrue(button.isFocused());
-
- // unfocus the view
- assertTrue(button.performAction(ACTION_CLEAR_FOCUS));
-
- // find the view again and make sure it is not focused
- button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
- .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
- assertFalse(button.isFocused());
- }
-
- @MediumTest
- public void testPerformActionSelect() throws Exception {
- // find a view and make sure it is not selected
- AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.button5)).get(0);
- assertFalse(button.isSelected());
-
- // select the view
- assertTrue(button.performAction(ACTION_SELECT));
-
- // find the view again and make sure it is selected
- button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
- .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
- assertTrue(button.isSelected());
- }
-
- @MediumTest
- public void testPerformActionClearSelection() throws Exception {
- // find a view and make sure it is not selected
- AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.button5)).get(0);
- assertFalse(button.isSelected());
-
- // select the view
- assertTrue(button.performAction(ACTION_SELECT));
-
- // find the view again and make sure it is selected
- button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
- .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
-
- assertTrue(button.isSelected());
-
- // unselect the view
- assertTrue(button.performAction(ACTION_CLEAR_SELECTION));
-
- // find the view again and make sure it is not selected
- button = getInstrumentation().getUiAutomation().getRootInActiveWindow()
- .findAccessibilityNodeInfosByText(getString(R.string.button5)).get(0);
- assertFalse(button.isSelected());
- }
-
- @MediumTest
- public void testPerformActionClick() throws Exception {
- // find a view and make sure it is not selected
- final AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.button5)).get(0);
- assertFalse(button.isSelected());
-
- // Make an action and wait for an event.
- AccessibilityEvent expected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- button.performAction(ACTION_CLICK);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure the expected event was received.
- assertNotNull(expected);
- }
-
- @MediumTest
- public void testPerformActionLongClick() throws Exception {
- // find a view and make sure it is not selected
- final AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.button5)).get(0);
- assertFalse(button.isSelected());
-
- // Make an action and wait for an event.
- AccessibilityEvent expected = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- button.performAction(ACTION_LONG_CLICK);
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return (event.getEventType() == AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
-
- // Make sure the expected event was received.
- assertNotNull(expected);
- }
-
-
- @MediumTest
- public void testPerformCustomAction() throws Exception {
- // find a view and make sure it is not selected
- AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.button5)).get(0);
-
- // find the custom action and perform it
- List<AccessibilityAction> actions = button.getActionList();
- final int actionCount = actions.size();
- for (int i = 0; i < actionCount; i++) {
- AccessibilityAction action = actions.get(i);
- if (action.getId() == R.id.foo_custom_action) {
- assertSame(action.getLabel(), "Foo");
- // perform the action
- assertTrue(button.performAction(action.getId()));
- return;
- }
- }
- }
-
- @MediumTest
- public void testGetEventSource() throws Exception {
- // find a view and make sure it is not focused
- final AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.button5)).get(0);
- assertFalse(button.isSelected());
-
- // focus and wait for the event
- AccessibilityEvent awaitedEvent = getInstrumentation().getUiAutomation()
- .executeAndWaitForEvent(
- new Runnable() {
- @Override
- public void run() {
- assertTrue(button.performAction(ACTION_FOCUS));
- }
- },
- new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED);
- }
- },
- TIMEOUT_ASYNC_PROCESSING);
-
- assertNotNull(awaitedEvent);
-
- // check that last event source
- AccessibilityNodeInfo source = awaitedEvent.getSource();
- assertNotNull(source);
-
- // bounds
- Rect buttonBounds = new Rect();
- button.getBoundsInParent(buttonBounds);
- Rect sourceBounds = new Rect();
- source.getBoundsInParent(sourceBounds);
-
- assertEquals(buttonBounds.left, sourceBounds.left);
- assertEquals(buttonBounds.right, sourceBounds.right);
- assertEquals(buttonBounds.top, sourceBounds.top);
- assertEquals(buttonBounds.bottom, sourceBounds.bottom);
-
- // char sequence attributes
- assertEquals(button.getPackageName(), source.getPackageName());
- assertEquals(button.getClassName(), source.getClassName());
- assertEquals(button.getText().toString(), source.getText().toString());
- assertSame(button.getContentDescription(), source.getContentDescription());
-
- // boolean attributes
- assertSame(button.isFocusable(), source.isFocusable());
- assertSame(button.isClickable(), source.isClickable());
- assertSame(button.isEnabled(), source.isEnabled());
- assertNotSame(button.isFocused(), source.isFocused());
- assertSame(button.isLongClickable(), source.isLongClickable());
- assertSame(button.isPassword(), source.isPassword());
- assertSame(button.isSelected(), source.isSelected());
- assertSame(button.isCheckable(), source.isCheckable());
- assertSame(button.isChecked(), source.isChecked());
- }
-
- @MediumTest
- public void testPerformGlobalActionBack() throws Exception {
- assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_BACK));
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
- }
-
- @MediumTest
- public void testPerformGlobalActionHome() throws Exception {
- assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_HOME));
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
- }
-
- @MediumTest
- public void testPerformGlobalActionRecents() throws Exception {
- // Check whether the action succeeded.
- assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_RECENTS));
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
-
- // This is a necessary since the back action does not
- // dismiss recents until they stop animating. Sigh...
- SystemClock.sleep(5000);
-
- // Clean up.
- getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_BACK);
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
- }
-
- @MediumTest
- public void testPerformGlobalActionNotifications() throws Exception {
- // Perform the action under test
- assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS));
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
-
- // Clean up.
- assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_BACK));
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
- }
-
- @MediumTest
- public void testPerformGlobalActionQuickSettings() throws Exception {
- // Check whether the action succeeded.
- assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS));
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
-
- // Clean up.
- getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_BACK);
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
- }
-
- @MediumTest
- public void testPerformGlobalActionPowerDialog() throws Exception {
- // Check whether the action succeeded.
- assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_POWER_DIALOG));
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
-
- // Clean up.
- getInstrumentation().getUiAutomation().performGlobalAction(
- AccessibilityService.GLOBAL_ACTION_BACK);
-
- // Sleep a bit so the UI is settles.
- waitForIdle();
- }
-
- @MediumTest
- public void testObjectContract() throws Exception {
- try {
- AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
- info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
- getInstrumentation().getUiAutomation().setServiceInfo(info);
-
- // find a view and make sure it is not focused
- AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
- .getRootInActiveWindow().findAccessibilityNodeInfosByText(
- getString(R.string.button5)).get(0);
- AccessibilityNodeInfo parent = button.getParent();
- final int childCount = parent.getChildCount();
- for (int i = 0; i < childCount; i++) {
- AccessibilityNodeInfo child = parent.getChild(i);
- assertNotNull(child);
- if (child.equals(button)) {
- assertEquals("Equal objects must have same hasCode.", button.hashCode(),
- child.hashCode());
- return;
- }
- }
- fail("Parent's children do not have the info whose parent is the parent.");
- } finally {
- AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
- info.flags &= ~AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
- getInstrumentation().getUiAutomation().setServiceInfo(info);
- }
- }
-
- private void assertSingleAccessibilityFocus() {
- UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
- List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
- AccessibilityWindowInfo focused = null;
-
- final int windowCount = windows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = windows.get(i);
-
- if (window.isAccessibilityFocused()) {
- if (focused == null) {
- focused = window;
-
- AccessibilityNodeInfo root = window.getRoot();
- assertEquals(uiAutomation.findFocus(
- AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), root);
- assertEquals(root.findFocus(
- AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), root);
- } else {
- throw new AssertionError("Duplicate accessibility focus");
- }
- } else {
- assertNull(window.getRoot().findFocus(
- AccessibilityNodeInfo.FOCUS_ACCESSIBILITY));
- }
- }
- }
-
- private void ensureAppWindowFocusedOrFail(int appWindowIndex) throws TimeoutException {
- UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
- List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
- AccessibilityWindowInfo focusTareget = null;
-
- int visitedAppWindows = -1;
- final int windowCount = windows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = windows.get(i);
- if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) {
- visitedAppWindows++;
- if (appWindowIndex <= visitedAppWindows) {
- focusTareget = window;
- break;
- }
- }
- }
-
- if (focusTareget == null) {
- throw new IllegalStateException("Couldn't find app window: " + appWindowIndex);
- }
-
- if (focusTareget.isAccessibilityFocused()) {
- return;
- }
-
- final AccessibilityWindowInfo finalFocusTarget = focusTareget;
- uiAutomation.executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- assertTrue(finalFocusTarget.getRoot().performAction(
- AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS));
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- windows = uiAutomation.getWindows();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = windows.get(i);
- if (window.getId() == focusTareget.getId()) {
- assertTrue(window.isAccessibilityFocused());
- break;
- }
- }
- }
-
- private void addTwoAppPanelWindows() throws TimeoutException {
- final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-
- uiAutomation.waitForIdle(TIMEOUT_WINDOW_STATE_IDLE, TIMEOUT_ASYNC_PROCESSING);
-
- // Add the first window.
- uiAutomation.executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- WindowManager.LayoutParams params = new WindowManager.LayoutParams();
- params.gravity = Gravity.TOP;
- params.y = getStatusBarHeight();
- params.width = WindowManager.LayoutParams.MATCH_PARENT;
- params.height = WindowManager.LayoutParams.WRAP_CONTENT;
- params.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
- params.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
- params.token = getActivity().getWindow().getDecorView().getWindowToken();
-
- Button button = new Button(getActivity());
- button.setText(R.string.button1);
- getActivity().getWindowManager().addView(button, params);
- }
- });
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
-
- // Add the second window.
- uiAutomation.executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- WindowManager.LayoutParams params = new WindowManager.LayoutParams();
- params.gravity = Gravity.BOTTOM;
- params.width = WindowManager.LayoutParams.MATCH_PARENT;
- params.height = WindowManager.LayoutParams.WRAP_CONTENT;
- params.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
- params.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
- params.token = getActivity().getWindow().getDecorView().getWindowToken();
-
- Button button = new Button(getActivity());
- button.setText(R.string.button2);
- getActivity().getWindowManager().addView(button, params);
- }
- });
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
- }
-
- private int getStatusBarHeight() {
- final Rect rect = new Rect();
- Window window = getActivity().getWindow();
- window.getDecorView().getWindowVisibleDisplayFrame(rect);
- return rect.top;
- }
-
- private void setAccessInteractiveWindowsFlag () {
- UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
- AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
- info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
- uiAutomation.setServiceInfo(info);
- }
-
- private void clearAccessInteractiveWindowsFlag () {
- UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
- AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
- info.flags &= ~AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
- uiAutomation.setServiceInfo(info);
- }
-
- private void ensureAccessibilityFocusCleared() {
- try {
- final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
- uiAutomation.executeAndWaitForEvent(new Runnable() {
- @Override
- public void run() {
- List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
- final int windowCount = windows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = windows.get(i);
- if (window.isAccessibilityFocused()) {
- window.getRoot().performAction(
- AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
- }
- }
- }
- }, new UiAutomation.AccessibilityEventFilter() {
- @Override
- public boolean accept(AccessibilityEvent event) {
- return event.getEventType() ==
- AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
- }
- }, TIMEOUT_ASYNC_PROCESSING);
- } catch (TimeoutException te) {
- /* ignore */
- }
- }
-
- private void verifyNodesInAppWindow(AccessibilityNodeInfo root) throws Exception {
- try {
- AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
- info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
- getInstrumentation().getUiAutomation().setServiceInfo(info);
-
- root.refresh();
-
- // make list of expected nodes
- List<String> classNameAndTextList = new ArrayList<String>();
- classNameAndTextList.add("android.widget.LinearLayout");
- classNameAndTextList.add("android.widget.LinearLayout");
- classNameAndTextList.add("android.widget.LinearLayout");
- classNameAndTextList.add("android.widget.LinearLayout");
- classNameAndTextList.add("android.widget.ButtonB1");
- classNameAndTextList.add("android.widget.ButtonB2");
- classNameAndTextList.add("android.widget.ButtonB3");
- classNameAndTextList.add("android.widget.ButtonB4");
- classNameAndTextList.add("android.widget.ButtonB5");
- classNameAndTextList.add("android.widget.ButtonB6");
- classNameAndTextList.add("android.widget.ButtonB7");
- classNameAndTextList.add("android.widget.ButtonB8");
- classNameAndTextList.add("android.widget.ButtonB9");
-
- String contentViewIdResName = "com.android.cts.accessibilityservice:id/added_content";
- boolean verifyContent = false;
-
- Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
- fringe.add(root);
-
- // do a BFS traversal and check nodes
- while (!fringe.isEmpty()) {
- AccessibilityNodeInfo current = fringe.poll();
-
- if (!verifyContent
- && contentViewIdResName.equals(current.getViewIdResourceName())) {
- verifyContent = true;
- }
-
- if (verifyContent) {
- CharSequence text = current.getText();
- String receivedClassNameAndText = current.getClassName().toString()
- + ((text != null) ? text.toString() : "");
- String expectedClassNameAndText = classNameAndTextList.remove(0);
-
- assertEquals("Did not get the expected node info",
- expectedClassNameAndText, receivedClassNameAndText);
- }
-
- final int childCount = current.getChildCount();
- for (int i = 0; i < childCount; i++) {
- AccessibilityNodeInfo child = current.getChild(i);
- fringe.add(child);
- }
- }
- } finally {
- AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
- info.flags &= ~AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
- getInstrumentation().getUiAutomation().setServiceInfo(info);
- }
- }
-
- @Override
- protected void scrubClass(Class<?> testCaseClass) {
- /* intentionally do not scrub */
- }
-}
diff --git a/tests/tests/accounts/Android.mk b/tests/tests/accounts/Android.mk
index 6ed35c6..4e56984 100644
--- a/tests/tests/accounts/Android.mk
+++ b/tests/tests/accounts/Android.mk
@@ -29,5 +29,10 @@
LOCAL_SDK_VERSION := current
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/accounts/AndroidTest.xml b/tests/tests/accounts/AndroidTest.xml
index 3e29c9c..c15cdce 100644
--- a/tests/tests/accounts/AndroidTest.xml
+++ b/tests/tests/accounts/AndroidTest.xml
@@ -1,3 +1,4 @@
+<?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");
@@ -12,7 +13,14 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Test module config for Account apis">
- <include name="common-config" />
- <option name="cts-apk-installer:test-file-name" value="CtsUnaffiliatedAccountAuthenticators.apk" />
-</configuration>
+<configuration description="Config for CTS Accounts test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsUnaffiliatedAccountAuthenticators.apk" />
+ <option name="test-file-name" value="CtsAccountManagerTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.accounts.cts" />
+ <option name="runtime-hint" value="1m25s" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/Android.mk b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/Android.mk
index cb504da..3e43eee 100644
--- a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/Android.mk
+++ b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/Android.mk
@@ -26,7 +26,7 @@
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := \
- ctstestrunner \
+ ctstestrunner \
CtsAccountTestsCommon
LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -35,6 +35,9 @@
LOCAL_PACKAGE_NAME := CtsUnaffiliatedAccountAuthenticators
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
diff --git a/tests/tests/accounts/OldAndroidTest.xml b/tests/tests/accounts/OldAndroidTest.xml
new file mode 100644
index 0000000..3e29c9c
--- /dev/null
+++ b/tests/tests/accounts/OldAndroidTest.xml
@@ -0,0 +1,18 @@
+<!-- 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.
+-->
+<configuration description="Test module config for Account apis">
+ <include name="common-config" />
+ <option name="cts-apk-installer:test-file-name" value="CtsUnaffiliatedAccountAuthenticators.apk" />
+</configuration>
diff --git a/tests/tests/admin/Android.mk b/tests/tests/admin/Android.mk
deleted file mode 100644
index 7a5ae34..0000000
--- a/tests/tests/admin/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2011 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner mockito-target
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsAdminTestCases
-
-LOCAL_INSTRUMENTATION_FOR := CtsDeviceAdmin
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/admin/AndroidManifest.xml b/tests/tests/admin/AndroidManifest.xml
deleted file mode 100644
index bbd7918..0000000
--- a/tests/tests/admin/AndroidManifest.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2011 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.admin">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <application>
-
- <uses-library android:name="android.test.runner"/>
-
- </application>
-
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.deviceadmin.cts"
- android:label="Tests for the admin APIs.">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
diff --git a/tests/tests/admin/AndroidTest.xml b/tests/tests/admin/AndroidTest.xml
deleted file mode 100644
index c29d404..0000000
--- a/tests/tests/admin/AndroidTest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?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.
--->
-<configuration description="CTS device admin test config">
- <include name="common-config" />
- <option name="run-command:run-command" value="dpm set-active-admin android.deviceadmin.cts/.CtsDeviceAdminReceiver" />
- <option name="run-command:run-command" value="dpm set-active-admin android.deviceadmin.cts/.CtsDeviceAdminReceiver2" />
-</configuration>
diff --git a/tests/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java b/tests/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java
deleted file mode 100644
index 6fcd0de..0000000
--- a/tests/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2013 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.admin.cts;
-
-import android.app.Activity;
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver;
-import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver2;
-import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver3;
-import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver4;
-import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver5;
-import android.deviceadmin.cts.CtsDeviceAdminDeactivatedReceiver;
-import android.deviceadmin.cts.CtsDeviceAdminActivationTestActivity;
-import android.deviceadmin.cts.CtsDeviceAdminActivationTestActivity.OnActivityResultListener;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for the standard way of activating a Device Admin: by starting system UI via an
- * {@link Intent} with {@link DevicePolicyManager#ACTION_ADD_DEVICE_ADMIN}. The test requires that
- * the {@code CtsDeviceAdmin.apk} be installed.
- */
-public class DeviceAdminActivationTest
- extends ActivityInstrumentationTestCase2<CtsDeviceAdminActivationTestActivity> {
-
- private static final String TAG = DeviceAdminActivationTest.class.getSimpleName();
-
- // IMPLEMENTATION NOTE: Because Device Admin activation requires the use of
- // Activity.startActivityForResult, this test creates an empty Activity which then invokes
- // startActivityForResult.
-
- private static final int REQUEST_CODE_ACTIVATE_ADMIN = 1;
-
- /**
- * Maximum duration of time (milliseconds) after which the effects of programmatic actions in
- * this test should have affected the UI.
- */
- private static final int UI_EFFECT_TIMEOUT_MILLIS = 5000;
-
- private boolean mDeviceAdmin;
- @Mock private OnActivityResultListener mMockOnActivityResultListener;
-
- public DeviceAdminActivationTest() {
- super(CtsDeviceAdminActivationTestActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- MockitoAnnotations.initMocks(this);
- getActivity().setOnActivityResultListener(mMockOnActivityResultListener);
- mDeviceAdmin = getInstrumentation().getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_DEVICE_ADMIN);
- }
-
- @Override
- protected void tearDown() throws Exception {
- try {
- finishActivateDeviceAdminActivity();
- } finally {
- super.tearDown();
- }
- }
-
- public void testActivateGoodReceiverDisplaysActivationUi() throws Exception {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testActivateGoodReceiverDisplaysActivationUi");
- return;
- }
- assertDeviceAdminDeactivated(CtsDeviceAdminDeactivatedReceiver.class);
- startAddDeviceAdminActivityForResult(CtsDeviceAdminDeactivatedReceiver.class);
- assertWithTimeoutOnActivityResultNotInvoked();
- // The UI is up and running. Assert that dismissing the UI returns the corresponding result
- // to the test activity.
- finishActivateDeviceAdminActivity();
- assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
- assertDeviceAdminDeactivated(CtsDeviceAdminDeactivatedReceiver.class);
- }
-
- public void testActivateBrokenReceiverFails() throws Exception {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testActivateBrokenReceiverFails");
- return;
- }
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver.class);
- startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver.class);
- assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver.class);
- }
-
- public void testActivateBrokenReceiver2Fails() throws Exception {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testActivateBrokenReceiver2Fails");
- return;
- }
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver2.class);
- startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver2.class);
- assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver2.class);
- }
-
- public void testActivateBrokenReceiver3Fails() throws Exception {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testActivateBrokenReceiver3Fails");
- return;
- }
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver3.class);
- startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver3.class);
- assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver3.class);
- }
-
- public void testActivateBrokenReceiver4Fails() throws Exception {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testActivateBrokenReceiver4Fails");
- return;
- }
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver4.class);
- startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver4.class);
- assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver4.class);
- }
-
- public void testActivateBrokenReceiver5Fails() throws Exception {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testActivateBrokenReceiver5Fails");
- return;
- }
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver5.class);
- startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver5.class);
- assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
- assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver5.class);
- }
-
- private void startAddDeviceAdminActivityForResult(Class<?> receiverClass) {
- getActivity().startActivityForResult(
- getAddDeviceAdminIntent(receiverClass),
- REQUEST_CODE_ACTIVATE_ADMIN);
- }
-
- private Intent getAddDeviceAdminIntent(Class<?> receiverClass) {
- return new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
- .putExtra(
- DevicePolicyManager.EXTRA_DEVICE_ADMIN,
- new ComponentName(
- getInstrumentation().getTargetContext(),
- receiverClass));
- }
-
- private void assertWithTimeoutOnActivityResultNotInvoked() {
- SystemClock.sleep(UI_EFFECT_TIMEOUT_MILLIS);
- Mockito.verify(mMockOnActivityResultListener, Mockito.never())
- .onActivityResult(
- Mockito.eq(REQUEST_CODE_ACTIVATE_ADMIN),
- Mockito.anyInt(),
- Mockito.any(Intent.class));
- }
-
- private void assertWithTimeoutOnActivityResultInvokedWithResultCode(int expectedResultCode) {
- ArgumentCaptor<Integer> resultCodeCaptor = ArgumentCaptor.forClass(int.class);
- Mockito.verify(mMockOnActivityResultListener, Mockito.timeout(UI_EFFECT_TIMEOUT_MILLIS))
- .onActivityResult(
- Mockito.eq(REQUEST_CODE_ACTIVATE_ADMIN),
- resultCodeCaptor.capture(),
- Mockito.any(Intent.class));
- assertEquals(expectedResultCode, (int) resultCodeCaptor.getValue());
- }
-
- private void finishActivateDeviceAdminActivity() {
- getActivity().finishActivity(REQUEST_CODE_ACTIVATE_ADMIN);
- }
-
- private void assertDeviceAdminDeactivated(Class<?> receiverClass) {
- DevicePolicyManager devicePolicyManager =
- (DevicePolicyManager) getActivity().getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- assertFalse(devicePolicyManager.isAdminActive(
- new ComponentName(getInstrumentation().getTargetContext(), receiverClass)));
- }
-}
diff --git a/tests/tests/admin/src/android/admin/cts/DeviceAdminInfoTest.java b/tests/tests/admin/src/android/admin/cts/DeviceAdminInfoTest.java
deleted file mode 100644
index fe68073..0000000
--- a/tests/tests/admin/src/android/admin/cts/DeviceAdminInfoTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2011 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.admin.cts;
-
-import android.app.admin.DeviceAdminInfo;
-import android.content.ComponentName;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-public class DeviceAdminInfoTest extends AndroidTestCase {
-
- private static final String TAG = DeviceAdminInfoTest.class.getSimpleName();
-
- private PackageManager mPackageManager;
- private ComponentName mComponent;
- private ComponentName mSecondComponent;
- private boolean mDeviceAdmin;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mPackageManager = mContext.getPackageManager();
- mComponent = getReceiverComponent();
- mSecondComponent = getSecondReceiverComponent();
- mDeviceAdmin =
- mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
- }
-
- static ComponentName getReceiverComponent() {
- return new ComponentName("android.deviceadmin.cts",
- "android.deviceadmin.cts.CtsDeviceAdminReceiver");
- }
-
- static ComponentName getSecondReceiverComponent() {
- return new ComponentName("android.deviceadmin.cts",
- "android.deviceadmin.cts.CtsDeviceAdminReceiver2");
- }
-
- public void testDeviceAdminInfo() throws Exception {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testDeviceAdminInfo");
- return;
- }
- ResolveInfo resolveInfo = new ResolveInfo();
- resolveInfo.activityInfo = mPackageManager.getReceiverInfo(mComponent,
- PackageManager.GET_META_DATA);
-
- DeviceAdminInfo info = new DeviceAdminInfo(mContext, resolveInfo);
- assertEquals(mComponent, info.getComponent());
- assertEquals(mComponent.getPackageName(), info.getPackageName());
- assertEquals(mComponent.getClassName(), info.getReceiverName());
-
- assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_FORCE_LOCK));
- assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD));
- assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_RESET_PASSWORD));
- assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_WATCH_LOGIN));
- assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_WIPE_DATA));
-
- assertEquals("force-lock",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_FORCE_LOCK));
- assertEquals("limit-password",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD));
- assertEquals("reset-password",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_RESET_PASSWORD));
- assertEquals("watch-login",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_WATCH_LOGIN));
- assertEquals("wipe-data",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_WIPE_DATA));
- }
-
- public void testDeviceAdminInfo2() throws Exception {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testDeviceAdminInfo2");
- return;
- }
- ResolveInfo resolveInfo = new ResolveInfo();
- resolveInfo.activityInfo = mPackageManager.getReceiverInfo(mSecondComponent,
- PackageManager.GET_META_DATA);
-
- DeviceAdminInfo info = new DeviceAdminInfo(mContext, resolveInfo);
- assertEquals(mSecondComponent, info.getComponent());
- assertEquals(mSecondComponent.getPackageName(), info.getPackageName());
- assertEquals(mSecondComponent.getClassName(), info.getReceiverName());
-
- assertFalse(info.usesPolicy(DeviceAdminInfo.USES_POLICY_FORCE_LOCK));
- assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD));
- assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_RESET_PASSWORD));
- assertFalse(info.usesPolicy(DeviceAdminInfo.USES_POLICY_WATCH_LOGIN));
- assertTrue(info.usesPolicy(DeviceAdminInfo.USES_POLICY_WIPE_DATA));
-
- assertEquals("force-lock",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_FORCE_LOCK));
- assertEquals("limit-password",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD));
- assertEquals("reset-password",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_RESET_PASSWORD));
- assertEquals("watch-login",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_WATCH_LOGIN));
- assertEquals("wipe-data",
- info.getTagForPolicy(DeviceAdminInfo.USES_POLICY_WIPE_DATA));
- }
-}
diff --git a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
deleted file mode 100644
index 66e12c0..0000000
--- a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ /dev/null
@@ -1,1139 +0,0 @@
-/*
- * Copyright (C) 2011 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.admin.cts;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.os.Build;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-import java.util.List;
-
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-
-/**
- * Test that exercises {@link DevicePolicyManager}. The test requires that the
- * CtsDeviceAdminReceiver be installed via the CtsDeviceAdmin.apk and be
- * activated via "Settings > Location & security > Select device administrators".
- */
-public class DevicePolicyManagerTest extends AndroidTestCase {
-
- private static final String TAG = DevicePolicyManagerTest.class.getSimpleName();
-
- private DevicePolicyManager mDevicePolicyManager;
- private ComponentName mComponent;
- private ComponentName mSecondComponent;
- private boolean mDeviceAdmin;
- private boolean mManagedProfiles;
- private PackageManager mPackageManager;
-
- private static final String TEST_CA_STRING1 =
- "-----BEGIN CERTIFICATE-----\n" +
- "MIICVzCCAgGgAwIBAgIJAMvnLHnnfO/IMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD\n" +
- "VQQGEwJJTjELMAkGA1UECAwCQVAxDDAKBgNVBAcMA0hZRDEVMBMGA1UECgwMSU1G\n" +
- "TCBQVlQgTFREMRAwDgYDVQQLDAdJTUZMIE9VMRIwEAYDVQQDDAlJTUZMLklORk8x\n" +
- "HzAdBgkqhkiG9w0BCQEWEHJhbWVzaEBpbWZsLmluZm8wHhcNMTMwODI4MDk0NDA5\n" +
- "WhcNMjMwODI2MDk0NDA5WjCBhjELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAkFQMQww\n" +
- "CgYDVQQHDANIWUQxFTATBgNVBAoMDElNRkwgUFZUIExURDEQMA4GA1UECwwHSU1G\n" +
- "TCBPVTESMBAGA1UEAwwJSU1GTC5JTkZPMR8wHQYJKoZIhvcNAQkBFhByYW1lc2hA\n" +
- "aW1mbC5pbmZvMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ738cbTQlNIO7O6nV/f\n" +
- "DJTMvWbPkyHYX8CQ7yXiAzEiZ5bzKJjDJmpRAkUrVinljKns2l6C4++l/5A7pFOO\n" +
- "33kCAwEAAaNQME4wHQYDVR0OBBYEFOdbZP7LaMbgeZYPuds2CeSonmYxMB8GA1Ud\n" +
- "IwQYMBaAFOdbZP7LaMbgeZYPuds2CeSonmYxMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" +
- "hvcNAQEFBQADQQBdrk6J9koyylMtl/zRfiMAc2zgeC825fgP6421NTxs1rjLs1HG\n" +
- "VcUyQ1/e7WQgOaBHi9TefUJi+4PSVSluOXon\n" +
- "-----END CERTIFICATE-----";
-
- private static final String MANAGED_PROVISIONING_PKG = "com.android.managedprovisioning";
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mDevicePolicyManager = (DevicePolicyManager)
- mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- mComponent = DeviceAdminInfoTest.getReceiverComponent();
- mPackageManager = mContext.getPackageManager();
- mSecondComponent = DeviceAdminInfoTest.getSecondReceiverComponent();
- mDeviceAdmin = mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
- mManagedProfiles = mDeviceAdmin
- && mPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS);
- setBlankPassword();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- setBlankPassword();
- }
-
- private void setBlankPassword() {
- if (!mDeviceAdmin) {
- return;
- }
- // Reset the password to nothing for future tests...
- mDevicePolicyManager.setPasswordQuality(mComponent,
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
- mDevicePolicyManager.setPasswordMinimumLength(mComponent, 0);
- assertTrue(mDevicePolicyManager.resetPassword("", 0));
- }
-
- public void testGetActiveAdmins() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testGetActiveAdmins");
- return;
- }
- List<ComponentName> activeAdmins = mDevicePolicyManager.getActiveAdmins();
- assertFalse(activeAdmins.isEmpty());
- assertTrue(activeAdmins.contains(mComponent));
- assertTrue(mDevicePolicyManager.isAdminActive(mComponent));
- }
-
- public void testGetMaximumFailedPasswordsForWipe() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testGetMaximumFailedPasswordsForWipe");
- return;
- }
- mDevicePolicyManager.setMaximumFailedPasswordsForWipe(mComponent, 3);
- assertEquals(3, mDevicePolicyManager.getMaximumFailedPasswordsForWipe(mComponent));
-
- mDevicePolicyManager.setMaximumFailedPasswordsForWipe(mComponent, 5);
- assertEquals(5, mDevicePolicyManager.getMaximumFailedPasswordsForWipe(mComponent));
- }
-
- public void testPasswordQuality_something() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_something");
- return;
- }
- mDevicePolicyManager.setPasswordQuality(mComponent,
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
- assertEquals(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
- mDevicePolicyManager.getPasswordQuality(mComponent));
- assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
-
- String caseDescription = "initial";
- assertPasswordSucceeds("1234", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordSucceeds("abcd1234", caseDescription);
-
- mDevicePolicyManager.setPasswordMinimumLength(mComponent, 10);
- caseDescription = "minimum password length = 10";
- assertEquals(10, mDevicePolicyManager.getPasswordMinimumLength(mComponent));
- assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
-
- assertPasswordFails("1234", caseDescription);
- assertPasswordFails("abcd", caseDescription);
- assertPasswordFails("abcd1234", caseDescription);
-
- mDevicePolicyManager.setPasswordMinimumLength(mComponent, 4);
- caseDescription = "minimum password length = 4";
- assertEquals(4, mDevicePolicyManager.getPasswordMinimumLength(
- mComponent));
- assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
-
- assertPasswordSucceeds("1234", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordSucceeds("abcd1234", caseDescription);
- }
-
- public void testPasswordQuality_numeric() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_numeric");
- return;
- }
- mDevicePolicyManager.setPasswordQuality(mComponent,
- DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
- assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
- mDevicePolicyManager.getPasswordQuality(mComponent));
- assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
-
- String caseDescription = "initial";
- assertPasswordSucceeds("1234", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordSucceeds("abcd1234", caseDescription);
-
- mDevicePolicyManager.setPasswordMinimumLength(mComponent, 10);
- caseDescription = "minimum password length = 10";
- assertEquals(10, mDevicePolicyManager.getPasswordMinimumLength(mComponent));
- assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
-
- assertPasswordFails("1234", caseDescription);
- assertPasswordFails("abcd", caseDescription);
- assertPasswordFails("abcd1234", caseDescription);
-
- mDevicePolicyManager.setPasswordMinimumLength(mComponent, 4);
- caseDescription = "minimum password length = 4";
- assertEquals(4, mDevicePolicyManager.getPasswordMinimumLength(
- mComponent));
- assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
-
- assertPasswordSucceeds("1234", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordSucceeds("abcd1234", caseDescription);
- }
-
- public void testPasswordQuality_alphabetic() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_alphabetic");
- return;
- }
- mDevicePolicyManager.setPasswordQuality(mComponent,
- DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
- assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
- mDevicePolicyManager.getPasswordQuality(mComponent));
- assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
-
- String caseDescription = "initial";
- assertPasswordFails("1234", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordSucceeds("abcd1234", caseDescription);
-
- mDevicePolicyManager.setPasswordMinimumLength(mComponent, 10);
- caseDescription = "minimum password length = 10";
- assertEquals(10, mDevicePolicyManager.getPasswordMinimumLength(mComponent));
- assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
-
- assertPasswordFails("1234", caseDescription);
- assertPasswordFails("abcd", caseDescription);
- assertPasswordFails("abcd1234", caseDescription);
-
- mDevicePolicyManager.setPasswordMinimumLength(mComponent, 4);
- caseDescription = "minimum password length = 4";
- assertEquals(4, mDevicePolicyManager.getPasswordMinimumLength(
- mComponent));
- assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
-
- assertPasswordFails("1234", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordSucceeds("abcd1234", caseDescription);
- }
-
- public void testPasswordQuality_alphanumeric() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_alphanumeric");
- return;
- }
- mDevicePolicyManager.setPasswordQuality(mComponent,
- DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC);
- assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
- mDevicePolicyManager.getPasswordQuality(mComponent));
- assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
-
- String caseDescription = "initial";
- assertPasswordFails("1234", caseDescription);
- assertPasswordFails("abcd", caseDescription);
- assertPasswordSucceeds("abcd1234", caseDescription);
-
- mDevicePolicyManager.setPasswordMinimumLength(mComponent, 10);
- caseDescription = "minimum password length = 10";
- assertEquals(10, mDevicePolicyManager.getPasswordMinimumLength(mComponent));
- assertFalse(mDevicePolicyManager.isActivePasswordSufficient());
-
- assertPasswordFails("1234", caseDescription);
- assertPasswordFails("abcd", caseDescription);
- assertPasswordFails("abcd1234", caseDescription);
-
- mDevicePolicyManager.setPasswordMinimumLength(mComponent, 4);
- caseDescription = "minimum password length = 4";
- assertEquals(4, mDevicePolicyManager.getPasswordMinimumLength(
- mComponent));
- assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
-
- assertPasswordFails("1234", caseDescription);
- assertPasswordFails("abcd", caseDescription);
- assertPasswordSucceeds("abcd1234", caseDescription);
- }
-
- public void testPasswordQuality_complexUpperCase() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_complexUpperCase");
- return;
- }
-
- mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
- assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
- resetComplexPasswordRestrictions();
-
- String caseDescription = "minimum UpperCase=0";
- assertPasswordSucceeds("abc1", caseDescription);
- assertPasswordSucceeds("aBc1", caseDescription);
- assertPasswordSucceeds("ABC1", caseDescription);
- assertPasswordSucceeds("ABCD", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumUpperCase(mComponent, 1);
- assertEquals(1, mDevicePolicyManager.getPasswordMinimumUpperCase(mComponent));
- caseDescription = "minimum UpperCase=1";
- assertPasswordFails("abc1", caseDescription);
- assertPasswordSucceeds("aBc1", caseDescription);
- assertPasswordSucceeds("ABC1", caseDescription);
- assertPasswordSucceeds("ABCD", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumUpperCase(mComponent, 3);
- assertEquals(3, mDevicePolicyManager.getPasswordMinimumUpperCase(mComponent));
- caseDescription = "minimum UpperCase=3";
- assertPasswordFails("abc1", caseDescription);
- assertPasswordFails("aBC1", caseDescription);
- assertPasswordSucceeds("ABC1", caseDescription);
- assertPasswordSucceeds("ABCD", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
- }
-
- public void testPasswordQuality_complexLowerCase() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_complexLowerCase");
- return;
- }
-
- mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
- assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
- resetComplexPasswordRestrictions();
-
- String caseDescription = "minimum LowerCase=0";
- assertPasswordSucceeds("ABCD", caseDescription);
- assertPasswordSucceeds("aBC1", caseDescription);
- assertPasswordSucceeds("abc1", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumLowerCase(mComponent, 1);
- assertEquals(1, mDevicePolicyManager.getPasswordMinimumLowerCase(mComponent));
- caseDescription = "minimum LowerCase=1";
- assertPasswordFails("ABCD", caseDescription);
- assertPasswordSucceeds("aBC1", caseDescription);
- assertPasswordSucceeds("abc1", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumLowerCase(mComponent, 3);
- assertEquals(3, mDevicePolicyManager.getPasswordMinimumLowerCase(mComponent));
- caseDescription = "minimum LowerCase=3";
- assertPasswordFails("ABCD", caseDescription);
- assertPasswordFails("aBC1", caseDescription);
- assertPasswordSucceeds("abc1", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
- }
-
- public void testPasswordQuality_complexLetters() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_complexLetters");
- return;
- }
-
- mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
- assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
- resetComplexPasswordRestrictions();
-
- String caseDescription = "minimum Letters=0";
- assertPasswordSucceeds("1234", caseDescription);
- assertPasswordSucceeds("a123", caseDescription);
- assertPasswordSucceeds("abc1", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumLetters(mComponent, 1);
- assertEquals(1, mDevicePolicyManager.getPasswordMinimumLetters(mComponent));
- caseDescription = "minimum Letters=1";
- assertPasswordFails("1234", caseDescription);
- assertPasswordSucceeds("a123", caseDescription);
- assertPasswordSucceeds("abc1", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumLetters(mComponent, 3);
- assertEquals(3, mDevicePolicyManager.getPasswordMinimumLetters(mComponent));
- caseDescription = "minimum Letters=3";
- assertPasswordFails("1234", caseDescription);
- assertPasswordFails("a123", caseDescription);
- assertPasswordSucceeds("abc1", caseDescription);
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
- }
-
- public void testPasswordQuality_complexNumeric() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_complexNumeric");
- return;
- }
-
- mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
- assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
- resetComplexPasswordRestrictions();
-
- String caseDescription = "minimum Numeric=0";
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordSucceeds("1abc", caseDescription);
- assertPasswordSucceeds("123a", caseDescription);
- assertPasswordSucceeds("1234", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumNumeric(mComponent, 1);
- assertEquals(1, mDevicePolicyManager.getPasswordMinimumNumeric(mComponent));
- caseDescription = "minimum Numeric=1";
- assertPasswordFails("abcd", caseDescription);
- assertPasswordSucceeds("1abc", caseDescription);
- assertPasswordSucceeds("123a", caseDescription);
- assertPasswordSucceeds("1234", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumNumeric(mComponent, 3);
- assertEquals(3, mDevicePolicyManager.getPasswordMinimumNumeric(mComponent));
- caseDescription = "minimum Numeric=3";
- assertPasswordFails("abcd", caseDescription);
- assertPasswordFails("1abc", caseDescription);
- assertPasswordSucceeds("123a", caseDescription);
- assertPasswordSucceeds("1234", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
- }
-
- public void testPasswordQuality_complexSymbols() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_complexSymbols");
- return;
- }
-
- mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
- assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
- resetComplexPasswordRestrictions();
-
- String caseDescription = "minimum Symbols=0";
- assertPasswordSucceeds("abcd", caseDescription);
- assertPasswordSucceeds("_bc1", caseDescription);
- assertPasswordSucceeds("@#!1", caseDescription);
- assertPasswordSucceeds("_@#!", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumSymbols(mComponent, 1);
- assertEquals(1, mDevicePolicyManager.getPasswordMinimumSymbols(mComponent));
- caseDescription = "minimum Symbols=1";
- assertPasswordFails("abcd", caseDescription);
- assertPasswordSucceeds("_bc1", caseDescription);
- assertPasswordSucceeds("@#!1", caseDescription);
- assertPasswordSucceeds("_@#!", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumSymbols(mComponent, 3);
- assertEquals(3, mDevicePolicyManager.getPasswordMinimumSymbols(mComponent));
- caseDescription = "minimum Symbols=3";
- assertPasswordFails("abcd", caseDescription);
- assertPasswordFails("_bc1", caseDescription);
- assertPasswordSucceeds("@#!1", caseDescription);
- assertPasswordSucceeds("_@#!", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
- }
-
- public void testPasswordQuality_complexNonLetter() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordQuality_complexNonLetter");
- return;
- }
-
- mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
- assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
- resetComplexPasswordRestrictions();
-
- String caseDescription = "minimum NonLetter=0";
- assertPasswordSucceeds("Abcd", caseDescription);
- assertPasswordSucceeds("_bcd", caseDescription);
- assertPasswordSucceeds("3bcd", caseDescription);
- assertPasswordSucceeds("_@3c", caseDescription);
- assertPasswordSucceeds("_25!", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumNonLetter(mComponent, 1);
- assertEquals(1, mDevicePolicyManager.getPasswordMinimumNonLetter(mComponent));
- caseDescription = "minimum NonLetter=1";
- assertPasswordFails("Abcd", caseDescription);
- assertPasswordSucceeds("_bcd", caseDescription);
- assertPasswordSucceeds("3bcd", caseDescription);
- assertPasswordSucceeds("_@3c", caseDescription);
- assertPasswordSucceeds("_25!", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
-
- mDevicePolicyManager.setPasswordMinimumNonLetter(mComponent, 3);
- assertEquals(3, mDevicePolicyManager.getPasswordMinimumNonLetter(mComponent));
- caseDescription = "minimum NonLetter=3";
- assertPasswordFails("Abcd", caseDescription);
- assertPasswordFails("_bcd", caseDescription);
- assertPasswordFails("3bcd", caseDescription);
- assertPasswordSucceeds("_@3c", caseDescription);
- assertPasswordSucceeds("_25!", caseDescription);
- assertPasswordFails("123", caseDescription); // too short
- }
-
- public void testPasswordHistoryLength() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordHistoryLength");
- return;
- }
- // Password history length restriction is only imposed if password quality is at least
- // numeric.
- mDevicePolicyManager.setPasswordQuality(mComponent,
- DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
- int originalValue = mDevicePolicyManager.getPasswordHistoryLength(mComponent);
- try {
- mDevicePolicyManager.setPasswordHistoryLength(mComponent, 3);
- assertEquals(3, mDevicePolicyManager.getPasswordHistoryLength(mComponent));
- // Although it would make sense we cannot test if password history restrictions
- // are enforced as DevicePolicyManagerService.resetPassword fails to do so at the
- // moment. See b/17707820
- } finally {
- mDevicePolicyManager.setPasswordHistoryLength(mComponent, originalValue);
- }
- }
-
- public void testPasswordExpirationTimeout() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testPasswordExpirationTimeout");
- return;
- }
- long originalValue = mDevicePolicyManager.getPasswordExpirationTimeout(mComponent);
- try {
- for (long testLength : new long[] {
- 0L, 864000000L /* ten days */, 8640000000L /* 100 days */}) {
- mDevicePolicyManager.setPasswordExpirationTimeout(mComponent, testLength);
- assertEquals(testLength,
- mDevicePolicyManager.getPasswordExpirationTimeout(mComponent));
- }
- } finally {
- mDevicePolicyManager.setPasswordExpirationTimeout(mComponent, originalValue);
- }
- }
-
- public void testKeyguardDisabledFeatures() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testKeyguardDisabledFeatures");
- return;
- }
- int originalValue = mDevicePolicyManager.getKeyguardDisabledFeatures(mComponent);
- try {
- for (int which = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
- which < 2 * DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT; ++which) {
- mDevicePolicyManager.setKeyguardDisabledFeatures(mComponent, which);
- assertEquals(which, mDevicePolicyManager.getKeyguardDisabledFeatures(mComponent));
- }
- } finally {
- mDevicePolicyManager.setKeyguardDisabledFeatures(mComponent, originalValue);
- }
- }
-
- public void testCreateUser_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testCreateUser_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.createUser(mComponent, "user name");
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertDeviceOwnerMessage(e.getMessage());
- }
- }
-
- public void testRemoveUser_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testRemoveUser_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.removeUser(mComponent, null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertDeviceOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetApplicationHidden_failIfNotDeviceOrProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetApplicationHidden_failIfNotDeviceOrProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setApplicationHidden(mComponent, "com.google.anything", true);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testIsApplicationHidden_failIfNotDeviceOrProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testIsApplicationHidden_failIfNotDeviceOrProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.isApplicationHidden(mComponent, "com.google.anything");
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetGlobalSetting_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetGlobalSetting_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.setGlobalSetting(mComponent,
- Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, "1");
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertDeviceOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetSecureSetting_failIfNotDeviceOrProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetSecureSetting_failIfNotDeviceOrProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setSecureSetting(mComponent,
- Settings.Secure.INSTALL_NON_MARKET_APPS, "1");
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setMasterVolumeMuted(mComponent, true);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testIsMasterVolumeMuted_failIfNotDeviceOrProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.isMasterVolumeMuted(mComponent);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetRecommendedGlobalProxy_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetRecommendedGlobalProxy_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.setRecommendedGlobalProxy(mComponent, null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertDeviceOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetLockTaskPackages_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetLockTaskPackages_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.setLockTaskPackages(mComponent, new String[] {"package"});
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- }
- }
-
- public void testClearDeviceOwnerApp_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testClearDeviceOwnerApp_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.clearDeviceOwnerApp("android.deviceadmin.cts");
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertDeviceOwnerMessage(e.getMessage());
- }
- }
-
- public void testSwitchUser_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSwitchUser_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.switchUser(mComponent, null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertDeviceOwnerMessage(e.getMessage());
- }
- }
-
- public void testCreateAndInitializeUser_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testCreateAndInitializeUser_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.createAndInitializeUser(mComponent, "name", "admin name",
- mComponent, null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertDeviceOwnerMessage(e.getMessage());
- }
- }
-
- public void testInstallCaCert_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testInstallCaCert_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.installCaCert(mComponent,
- TEST_CA_STRING1.getBytes());
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testInstallCaCert_failIfNotCertInstaller() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testInstallCaCert_failIfNotCertInstaller");
- return;
- }
- try {
- // Delegated cert installer is identified by using null as the first argument.
- mDevicePolicyManager.installCaCert(null, TEST_CA_STRING1.getBytes());
- fail("did not throw expected SecurityException");
- } catch (SecurityException expected) {
- }
- }
-
- public void testUninstallCaCert_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testUninstallCaCert_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.uninstallCaCert(mComponent,
- TEST_CA_STRING1.getBytes());
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testUninstallCaCert_failIfNotCertInstaller() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testUninstallCaCert_failIfNotCertInstaller");
- return;
- }
- try {
- // Delegated cert installer is identified by using null as the first argument.
- mDevicePolicyManager.uninstallCaCert(null, TEST_CA_STRING1.getBytes());
- fail("did not throw expected SecurityException");
- } catch (SecurityException expected) {
- }
- }
-
- public void testGetInstalledCaCerts_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testGetInstalledCaCerts_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.getInstalledCaCerts(mComponent);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testGetInstalledCaCerts_failIfNotCertInstaller() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testGetInstalledCaCerts_failIfNotCertInstaller");
- return;
- }
- try {
- // Delegated cert installer is identified by using null as the first argument.
- mDevicePolicyManager.getInstalledCaCerts(null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException expected) {
- }
- }
-
- public void testHasCaCertInstalled_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testHasCaCertInstalled_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.hasCaCertInstalled(mComponent,
- TEST_CA_STRING1.getBytes());
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testHasCaCertInstalled_failIfNotCertInstaller() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testHasCaCertInstalled_failIfNotCertInstaller");
- return;
- }
- try {
- // Delegated cert installer is identified by using null as the first argument.
- mDevicePolicyManager.hasCaCertInstalled(null, TEST_CA_STRING1.getBytes());
- fail("did not throw expected SecurityException");
- } catch (SecurityException expected) {
- }
- }
-
- public void testUninstallAllUserCaCerts_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testUninstallAllUserCaCerts_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.uninstallAllUserCaCerts(mComponent);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testUninstallAllUserCaCerts_failIfNotCertInstaller() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testUninstallAllUserCaCerts_failIfNotCertInstaller");
- return;
- }
- try {
- // Delegated cert installer is identified by using null as the first argument.
- mDevicePolicyManager.uninstallAllUserCaCerts(null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException expected) {
- }
- }
-
- public void testSetScreenCaptureDisabled_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetScreenCaptureDisabled_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setScreenCaptureDisabled(mComponent, true);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetAutoTimeRequired_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetAutoTimeRequired_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.setAutoTimeRequired(mComponent, true);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertDeviceOwnerMessage(e.getMessage());
- }
- }
-
- public void testAddPersistentPreferredActivity_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testAddPersistentPreferredActivity_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.addPersistentPreferredActivity(mComponent,
- new IntentFilter(Intent.ACTION_MAIN),
- new ComponentName("android.admin.cts", "dummy"));
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testClearPackagePersistentPreferredActivities_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testClearPackagePersistentPreferredActivities_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.clearPackagePersistentPreferredActivities(mComponent,
- "android.admin.cts");
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetApplicationRestrictions_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetApplicationRestrictions_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setApplicationRestrictions(mComponent,
- "android.admin.cts", null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testAddUserRestriction_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testAddUserRestriction_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.addUserRestriction(mComponent,
- UserManager.DISALLOW_SMS);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetAccountManagementDisabled_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetAccountManagementDisabled_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setAccountManagementDisabled(mComponent,
- "dummy", true);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetRestrictionsProvider_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetRestrictionsProvider_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setRestrictionsProvider(mComponent,
- new ComponentName("android.admin.cts", "dummy"));
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetUninstallBlocked_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetUninstallBlocked_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setUninstallBlocked(mComponent,
- "android.admin.cts", true);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetPermittedAccessibilityServices_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetPermittedAccessibilityServices_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setPermittedAccessibilityServices(mComponent, null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetBluetoothContactSharingDisabled_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetBluetoothContactSharingDisabled_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setBluetoothContactSharingDisabled(mComponent, true);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetPermittedInputMethods_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetPermittedInputMethods_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setPermittedInputMethods(mComponent, null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- /**
- * Test whether the version of the pre-installed launcher is at least L. This is needed for
- * managed profile support.
- */
- public void testLauncherVersionAtLeastL() throws Exception {
- if (!mManagedProfiles) {
- return;
- }
-
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_HOME);
- List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities(intent,
- 0 /* default flags */);
- assertFalse("No launcher present", resolveInfos.isEmpty());
-
- for (ResolveInfo resolveInfo : resolveInfos) {
- ApplicationInfo launcherAppInfo = mPackageManager.getApplicationInfo(
- resolveInfo.activityInfo.packageName, 0 /* default flags */);
- if ((launcherAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 &&
- launcherAppInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
- return;
- }
- }
- fail("No system launcher with version L+ present present on device.");
- }
-
- /**
- * Test that managed provisioning is pre-installed if and only if the device declares the
- * device admin feature.
- */
- public void testManagedProvisioningPreInstalled() throws Exception {
- assertEquals(mDeviceAdmin, isPackageInstalledOnSystemImage(MANAGED_PROVISIONING_PKG));
- }
-
- private void assertDeviceOwnerMessage(String message) {
- assertTrue("message is: "+ message, message.contains("does not own the device")
- || message.contains("can only be called by the device owner"));
- }
-
- private void assertProfileOwnerMessage(String message) {
- assertTrue("message is: "+ message,
- message.contains("does not own the profile"));
- }
-
- private void resetComplexPasswordRestrictions() {
- /**
- * Not enough to reset only mComponent as
- * {@link DevicePolicyManager#resetPassword(String, int)} checks restrictions across all
- * admin components.
- */
- for (ComponentName adminComponent : new ComponentName[] {mComponent, mSecondComponent}) {
- mDevicePolicyManager.setPasswordMinimumLength(adminComponent, 0);
- mDevicePolicyManager.setPasswordMinimumUpperCase(adminComponent, 0);
- mDevicePolicyManager.setPasswordMinimumLowerCase(adminComponent, 0);
- mDevicePolicyManager.setPasswordMinimumLetters(adminComponent, 0);
- mDevicePolicyManager.setPasswordMinimumNumeric(adminComponent, 0);
- mDevicePolicyManager.setPasswordMinimumSymbols(adminComponent, 0);
- mDevicePolicyManager.setPasswordMinimumNonLetter(adminComponent, 0);
- }
- }
-
- private void assertPasswordFails(String password, String restriction) {
- try {
- boolean passwordResetResult = mDevicePolicyManager.resetPassword(password, /* flags= */0);
- assertFalse("Password '" + password + "' should have failed on " + restriction,
- passwordResetResult);
- } catch (IllegalArgumentException e) {
- // yesss, we have failed!
- }
- }
-
- private void assertPasswordSucceeds(String password, String restriction) {
- boolean passwordResetResult = mDevicePolicyManager.resetPassword(password, /* flags= */0);
- assertTrue("Password '" + password + "' failed on " + restriction, passwordResetResult);
- assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
- }
-
- public void testSetDelegatedCertInstaller_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetDelegatedCertInstaller_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.setCertInstallerPackage(mComponent, "com.test.package");
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testGetDelegatedCertInstaller_failIfNotProfileOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testGetDelegatedCertInstaller_failIfNotProfileOwner");
- return;
- }
- try {
- mDevicePolicyManager.getCertInstallerPackage(mComponent);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertProfileOwnerMessage(e.getMessage());
- }
- }
-
- public void testSetSystemUpdatePolicy_failIfNotDeviceOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetSystemUpdatePolicy_failIfNotDeviceOwner");
- return;
- }
- try {
- mDevicePolicyManager.setSystemUpdatePolicy(mComponent, null);
- fail("did not throw expected SecurityException");
- } catch (SecurityException e) {
- assertDeviceOwnerMessage(e.getMessage());
- }
- }
-
- private boolean isPackageInstalledOnSystemImage(String packagename) {
- try {
- ApplicationInfo info = mPackageManager.getApplicationInfo(packagename,
- 0 /* default flags */);
- return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- } catch (NameNotFoundException e) {
- return false;
- }
- }
-}
diff --git a/tests/tests/alarmclock/Android.mk b/tests/tests/alarmclock/Android.mk
index 6c30bc7..ee3e015 100644
--- a/tests/tests/alarmclock/Android.mk
+++ b/tests/tests/alarmclock/Android.mk
@@ -29,5 +29,10 @@
LOCAL_SDK_VERSION := current
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/alarmclock/AndroidTest.xml b/tests/tests/alarmclock/AndroidTest.xml
index aafdb61..525257e 100644
--- a/tests/tests/alarmclock/AndroidTest.xml
+++ b/tests/tests/alarmclock/AndroidTest.xml
@@ -1,3 +1,4 @@
+<?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");
@@ -12,10 +13,19 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Test module config for AlarmClock">
- <include name="common-config" />
- <option name="cts-apk-installer:test-file-name" value="CtsAlarmClockService.apk" />
- <option name="run-command:run-command"
- value="settings put secure voice_interaction_service android.alarmclock.service/.MainInteractionService" />
- <option name="cts-apk-installer:test-file-name" value="CtsAlarmClockTestCases.apk" />
-</configuration>
+<configuration description="Configuration for AlarmClock Tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAlarmClockService.apk" />
+ <option name="test-file-name" value="CtsAlarmClockTestCases.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command"
+ value="settings put secure voice_interaction_service android.alarmclock.service/.MainInteractionService" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="android.alarmclock.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/alarmclock/OldAndroidTest.xml b/tests/tests/alarmclock/OldAndroidTest.xml
new file mode 100644
index 0000000..aafdb61
--- /dev/null
+++ b/tests/tests/alarmclock/OldAndroidTest.xml
@@ -0,0 +1,21 @@
+<!-- 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.
+-->
+<configuration description="Test module config for AlarmClock">
+ <include name="common-config" />
+ <option name="cts-apk-installer:test-file-name" value="CtsAlarmClockService.apk" />
+ <option name="run-command:run-command"
+ value="settings put secure voice_interaction_service android.alarmclock.service/.MainInteractionService" />
+ <option name="cts-apk-installer:test-file-name" value="CtsAlarmClockTestCases.apk" />
+</configuration>
diff --git a/tests/tests/alarmclock/common/Android.mk b/tests/tests/alarmclock/common/Android.mk
index d460ade..d0b7be0 100644
--- a/tests/tests/alarmclock/common/Android.mk
+++ b/tests/tests/alarmclock/common/Android.mk
@@ -27,4 +27,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/alarmclock/service/Android.mk b/tests/tests/alarmclock/service/Android.mk
index 53dc564..3502582 100644
--- a/tests/tests/alarmclock/service/Android.mk
+++ b/tests/tests/alarmclock/service/Android.mk
@@ -29,4 +29,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/animation/Android.mk b/tests/tests/animation/Android.mk
index 3d8daf7..35b9312 100644
--- a/tests/tests/animation/Android.mk
+++ b/tests/tests/animation/Android.mk
@@ -28,6 +28,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/animation/AndroidManifest.xml b/tests/tests/animation/AndroidManifest.xml
index fdc5ad9..3744a2a 100644
--- a/tests/tests/animation/AndroidManifest.xml
+++ b/tests/tests/animation/AndroidManifest.xml
@@ -15,20 +15,22 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.animation">
+ package="android.animation.cts">
<uses-sdk android:minSdkVersion="11" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
<activity android:name="android.animation.cts.AnimationActivity"
- android:label="AnimationActivity"/>
+ android:label="AnimationActivity"/>
+ <activity android:name="android.animation.cts.ButtonViewActivity"
+ android:label="ButtonViewActivity"/>
<activity
android:name="android.animation.cts.LayoutAnimationActivity" />
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.animation"
+ android:targetPackage="android.animation.cts"
android:label="CTS tests for android.animation package">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/animation/AndroidTest.xml b/tests/tests/animation/AndroidTest.xml
new file mode 100644
index 0000000..b4a0ad5
--- /dev/null
+++ b/tests/tests/animation/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Animation test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAnimationTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.animation.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/object_animator.xml b/tests/tests/animation/res/animator/object_animator.xml
new file mode 100644
index 0000000..17fcd60
--- /dev/null
+++ b/tests/tests/animation/res/animator/object_animator.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:propertyName="x" android:valueFrom="0" android:valueTo="1">
+
+</objectAnimator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/object_animator_pvh1.xml b/tests/tests/animation/res/animator/object_animator_pvh1.xml
new file mode 100644
index 0000000..7e16bc8
--- /dev/null
+++ b/tests/tests/animation/res/animator/object_animator_pvh1.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android">
+ <propertyValuesHolder android:propertyName="x" android:valueFrom="0" android:valueTo="1"/>
+ <propertyValuesHolder android:propertyName="y" android:valueFrom="10" android:valueTo="11"/>
+</objectAnimator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/object_animator_pvh_kf1.xml b/tests/tests/animation/res/animator/object_animator_pvh_kf1.xml
new file mode 100644
index 0000000..b99b819
--- /dev/null
+++ b/tests/tests/animation/res/animator/object_animator_pvh_kf1.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android">
+ <propertyValuesHolder android:propertyName="x" android:valueFrom="0" android:valueTo="1"/>
+ <propertyValuesHolder android:propertyName="y" >
+ <keyframe android:fraction="0" android:value="10"/>
+ <keyframe android:fraction="1" android:value="11"/>
+ </propertyValuesHolder>
+</objectAnimator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator.xml b/tests/tests/animation/res/animator/value_animator.xml
new file mode 100644
index 0000000..4c1abfe
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:valueFrom="0" android:valueTo="1">
+
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh1.xml b/tests/tests/animation/res/animator/value_animator_pvh1.xml
new file mode 100644
index 0000000..30540ec
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh1.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+ <propertyValuesHolder android:valueFrom="0" android:valueTo="1"/>
+
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh2.xml b/tests/tests/animation/res/animator/value_animator_pvh2.xml
new file mode 100644
index 0000000..2c07b4e
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh2.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+ <propertyValuesHolder android:valueFrom="0" android:valueTo="1"></propertyValuesHolder>
+
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh_kf1.xml b/tests/tests/animation/res/animator/value_animator_pvh_kf1.xml
new file mode 100644
index 0000000..e8fb9cc
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh_kf1.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+ <propertyValuesHolder>
+ <keyframe android:fraction="0" android:value="0"/>
+ <keyframe android:fraction="1" android:value="1"/>
+ </propertyValuesHolder>
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh_kf2.xml b/tests/tests/animation/res/animator/value_animator_pvh_kf2.xml
new file mode 100644
index 0000000..be8184f
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh_kf2.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+ <propertyValuesHolder>
+ <keyframe android:fraction="0" android:value="0"></keyframe>
+ <keyframe android:fraction="1" android:value="1"/>
+ </propertyValuesHolder>
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh_kf3.xml b/tests/tests/animation/res/animator/value_animator_pvh_kf3.xml
new file mode 100644
index 0000000..5d6dd4b
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh_kf3.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+ <propertyValuesHolder>
+ <keyframe android:fraction="0" android:value="0"></keyframe>
+ <keyframe android:fraction=".4" android:value=".2"/>
+ <keyframe android:fraction=".6" android:value=".2"/>
+ <keyframe android:fraction="1" android:value="1"/>
+ </propertyValuesHolder>
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh_kf4.xml b/tests/tests/animation/res/animator/value_animator_pvh_kf4.xml
new file mode 100644
index 0000000..a59fb84
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh_kf4.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+ <propertyValuesHolder>
+ <keyframe android:value="0"></keyframe>
+ <keyframe android:value=".2"/>
+ <keyframe android:value=".2"/>
+ <keyframe android:value="1"/>
+ </propertyValuesHolder>
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/layout/button_view.xml b/tests/tests/animation/res/layout/button_view.xml
new file mode 100644
index 0000000..349fedf
--- /dev/null
+++ b/tests/tests/animation/res/layout/button_view.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/container">
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button"
+ android:id="@+id/button"/>
+ <View
+ android:layout_width="200dp"
+ android:layout_height="200dp"
+ android:background="#fff"
+ android:id="@+id/square"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/animation/res/values/strings.xml b/tests/tests/animation/res/values/strings.xml
index 8d167fd..587930b 100644
--- a/tests/tests/animation/res/values/strings.xml
+++ b/tests/tests/animation/res/values/strings.xml
@@ -15,4 +15,5 @@
-->
<resources>
<string name="add_button">Add Button</string>
+ <string name="button">Button</string>
</resources>
diff --git a/tests/tests/animation/src/android/animation/cts/AnimationActivity.java b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
index 225a97e..598048e 100644
--- a/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
+++ b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
@@ -39,7 +39,7 @@
import android.view.animation.AccelerateInterpolator;
import java.util.ArrayList;
-import com.android.cts.animation.R;
+import android.animation.cts.R;
public class AnimationActivity extends Activity {
private static final String BALL_HEIGHT = "ballwidth";
diff --git a/tests/tests/animation/src/android/animation/cts/ButtonViewActivity.java b/tests/tests/animation/src/android/animation/cts/ButtonViewActivity.java
new file mode 100644
index 0000000..fe66951
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/ButtonViewActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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.app.Activity;
+import android.os.Bundle;
+
+import android.animation.cts.R;
+
+public class ButtonViewActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.button_view);
+ }
+}
diff --git a/tests/tests/animation/src/android/animation/cts/CreationTest.java b/tests/tests/animation/src/android/animation/cts/CreationTest.java
new file mode 100644
index 0000000..f45f64b
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/CreationTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ */
+
+package android.animation.cts;
+
+import android.animation.AnimatorInflater;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.os.Debug;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+
+import android.animation.cts.R;
+
+public class CreationTest extends ActivityInstrumentationTestCase2<ButtonViewActivity> {
+
+ private ButtonViewActivity mActivity;
+
+ public CreationTest() {
+ super(ButtonViewActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ setActivityInitialTouchMode(false);
+ mActivity = getActivity();
+ }
+
+ @UiThreadTest
+ public void testValueAnimatorCreation() {
+ ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
+ verifyValues(animator, 0, 1);
+ }
+
+ @UiThreadTest
+ public void testValueAnimatorResourceCreation() {
+ ValueAnimator animator = (ValueAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator);
+ verifyValues(animator, 0, 1);
+ }
+
+ @UiThreadTest
+ public void testValueAnimatorPvh1() {
+ ValueAnimator animator = (ValueAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh1);
+ verifyValues(animator, 0, 1);
+ }
+
+ @UiThreadTest
+ public void testValueAnimatorPvh2() {
+ ValueAnimator animator = (ValueAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh2);
+ verifyValues(animator, 0, 1);
+ }
+
+ @UiThreadTest
+ public void testValueAnimatorPvhKf1() {
+ ValueAnimator animator = (ValueAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh_kf1);
+ verifyValues(animator, 0, 1);
+ }
+
+ @UiThreadTest
+ public void testValueAnimatorPvhKf2() {
+ ValueAnimator animator = (ValueAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh_kf2);
+ verifyValues(animator, 0, 1);
+ }
+
+ @UiThreadTest
+ public void testValueAnimatorPvhKf3() {
+ ValueAnimator animator = (ValueAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh_kf3);
+ verifyValues(animator, 0, .2f, 1);
+ }
+
+ @UiThreadTest
+ public void testValueAnimatorPvhKf4() {
+ ValueAnimator animator = (ValueAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh_kf4);
+ verifyValues(animator, 0, .2f, 1);
+ }
+
+ @UiThreadTest
+ public void testObjectAnimator() {
+ ObjectAnimator animator = (ObjectAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.object_animator);
+ animator.setTarget(new DummyAnimatorTarget());
+ verifyValues(animator, "x", 0, 1);
+ }
+
+ @UiThreadTest
+ public void testObjectAnimatorPvh1() {
+ ObjectAnimator animator = (ObjectAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.object_animator_pvh1);
+ animator.setTarget(new DummyAnimatorTarget());
+ verifyValues(animator, "x", 0, 1);
+ verifyValues(animator, "y", 10, 11);
+ }
+
+ @UiThreadTest
+ public void testObjectAnimatorPvhKf1() {
+ ObjectAnimator animator = (ObjectAnimator)
+ AnimatorInflater.loadAnimator(mActivity, R.animator.object_animator_pvh_kf1);
+ animator.setTarget(new DummyAnimatorTarget());
+ verifyValues(animator, "x", 0, 1);
+ verifyValues(animator, "y", 10, 11);
+ }
+
+ class DummyAnimatorTarget {
+ public float getX() {
+ return 0;
+ }
+
+ public void setX(float x) {
+ }
+
+ public float getY() {
+ return 0;
+ }
+
+ public void setY(float y) {
+ }
+ }
+
+ private void assertRoughlyEqual(float checkValue, float correctValue) {
+ // use epsilon for float compares
+ final float epsilon = .0001f;
+ assertTrue(checkValue > correctValue - epsilon && checkValue < correctValue + epsilon);
+ }
+
+ private void verifyValues(ValueAnimator animator, float... values) {
+ animator.setCurrentFraction(0);
+ assertRoughlyEqual((Float) animator.getAnimatedValue(), values[0]);
+ for (int i = 1; i < values.length - 1; ++i) {
+ animator.setCurrentFraction((float) i / (values.length - 1));
+ assertRoughlyEqual((Float) animator.getAnimatedValue(), values[i]);
+ }
+ animator.setCurrentFraction(1);
+ assertRoughlyEqual((Float) animator.getAnimatedValue(), values[values.length - 1]);
+ }
+
+ private void verifyValues(ObjectAnimator animator, String propertyName, float... values) {
+ animator.setCurrentFraction(0);
+ assertRoughlyEqual((Float) animator.getAnimatedValue(propertyName), values[0]);
+ for (int i = 1; i < values.length - 1; ++i) {
+ animator.setCurrentFraction((float) i / (values.length - 1));
+ assertRoughlyEqual((Float) animator.getAnimatedValue(propertyName), values[i]);
+ }
+ animator.setCurrentFraction(1);
+ assertRoughlyEqual((Float) animator.getAnimatedValue(propertyName),
+ values[values.length - 1]);
+ }
+}
diff --git a/tests/tests/animation/src/android/animation/cts/LayoutAnimationActivity.java b/tests/tests/animation/src/android/animation/cts/LayoutAnimationActivity.java
index 9b2eaff..fb5426e 100644
--- a/tests/tests/animation/src/android/animation/cts/LayoutAnimationActivity.java
+++ b/tests/tests/animation/src/android/animation/cts/LayoutAnimationActivity.java
@@ -15,7 +15,7 @@
*/
package android.animation.cts;
-import com.android.cts.animation.R;
+import android.animation.cts.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
diff --git a/tests/tests/animation/src/android/animation/cts/LayoutAnimationTest.java b/tests/tests/animation/src/android/animation/cts/LayoutAnimationTest.java
index f9918a8..f39fe505 100644
--- a/tests/tests/animation/src/android/animation/cts/LayoutAnimationTest.java
+++ b/tests/tests/animation/src/android/animation/cts/LayoutAnimationTest.java
@@ -19,7 +19,7 @@
import java.util.LinkedList;
import java.util.List;
-import com.android.cts.animation.R;
+import android.animation.cts.R;
import android.animation.Animator;
import android.animation.LayoutTransition;
@@ -28,7 +28,6 @@
import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.test.ActivityInstrumentationTestCase2;
-import android.test.TouchUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
@@ -41,6 +40,7 @@
private MyLayoutTransition mLayoutTransition;
private LinearLayout mView;
private Button mButton;
+
public LayoutAnimationTest() {
super(LayoutAnimationActivity.class);
}
@@ -65,14 +65,14 @@
assertEquals(listener, actualListener);
}
- public void testIsRunning() {
+ public void testIsRunning() throws Throwable {
setDefaultTransition();
assertFalse(mLayoutTransition.isRunning());
- TouchUtils.clickView(this, mButton);
+ clickButton();
assertTrue(mLayoutTransition.isRunning());
}
- public void testIsChangingLayout() {
+ public void testIsChangingLayout() throws Throwable {
long duration = 2000l;
mView.setLayoutTransition(mLayoutTransition);
mLayoutTransition.setDuration(duration);
@@ -80,7 +80,7 @@
new AccelerateInterpolator());
assertFalse(mLayoutTransition.isChangingLayout());
- TouchUtils.clickView(this, mButton);
+ clickButton();
assertTrue(mLayoutTransition.isChangingLayout());
}
@@ -138,7 +138,7 @@
mLayoutTransition.setAnimator(LayoutTransition.APPEARING, appearingAnimator);
List<Float> alphaList = new LinkedList<Float>();
- TouchUtils.clickView(this, mButton);
+ clickButton();
while(listener.mTransition) {
float alpha = mActivity.getLastButton().getAlpha();
alphaList.add(alpha);
@@ -177,6 +177,15 @@
new AccelerateInterpolator());
}
+ private void clickButton() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ mButton.callOnClick();
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ }
+
class MyTransitionListener implements LayoutTransition.TransitionListener {
ViewGroup mContainer;
View mView;
diff --git a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
index f0db168..6ff1cf9 100644
--- a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
@@ -21,6 +21,7 @@
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.test.ActivityInstrumentationTestCase2;
+import android.util.Property;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
@@ -246,6 +247,106 @@
Thread.sleep(100);
}
+ public void testSetStartEndValues() throws Throwable {
+ final float startValue = 100, endValue = 500;
+ final AnimTarget target = new AnimTarget();
+ final ObjectAnimator anim1 = ObjectAnimator.ofFloat(target, "testValue", 0);
+ target.setTestValue(startValue);
+ anim1.setupStartValues();
+ target.setTestValue(endValue);
+ anim1.setupEndValues();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim1.start();
+ assertEquals(startValue, (Float) anim1.getAnimatedValue());
+ anim1.setCurrentFraction(1);
+ assertEquals(endValue, (Float) anim1.getAnimatedValue());
+ anim1.cancel();
+ }
+ });
+
+ final Property property = AnimTarget.TEST_VALUE;
+ final ObjectAnimator anim2 = ObjectAnimator.ofFloat(target, AnimTarget.TEST_VALUE, 0);
+ target.setTestValue(startValue);
+ final float startValueExpected = (Float) property.get(target);
+ anim2.setupStartValues();
+ target.setTestValue(endValue);
+ final float endValueExpected = (Float) property.get(target);
+ anim2.setupEndValues();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim2.start();
+ assertEquals(startValueExpected, (Float) anim2.getAnimatedValue());
+ anim2.setCurrentFraction(1);
+ assertEquals(endValueExpected, (Float) anim2.getAnimatedValue());
+ anim2.cancel();
+ }
+ });
+
+ // This is a test that ensures that the values set on a Property-based animator
+ // are determined by the property, not by the setter/getter of the target object
+ final Property doubler = AnimTarget.TEST_DOUBLING_VALUE;
+ final ObjectAnimator anim3 = ObjectAnimator.ofFloat(target,
+ doubler, 0);
+ target.setTestValue(startValue);
+ final float startValueExpected3 = (Float) doubler.get(target);
+ anim3.setupStartValues();
+ target.setTestValue(endValue);
+ final float endValueExpected3 = (Float) doubler.get(target);
+ anim3.setupEndValues();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim3.start();
+ assertEquals(startValueExpected3, (Float) anim3.getAnimatedValue());
+ anim3.setCurrentFraction(1);
+ assertEquals(endValueExpected3, (Float) anim3.getAnimatedValue());
+ anim3.cancel();
+ }
+ });
+ }
+
+ static class AnimTarget {
+ private float mTestValue = 0;
+
+ public void setTestValue(float value) {
+ mTestValue = value;
+ }
+
+ public float getTestValue() {
+ return mTestValue;
+ }
+
+ public static final Property<AnimTarget, Float> TEST_VALUE =
+ new Property<AnimTarget, Float>(Float.class, "testValue") {
+ @Override
+ public void set(AnimTarget object, Float value) {
+ object.setTestValue(value);
+ }
+
+ @Override
+ public Float get(AnimTarget object) {
+ return object.getTestValue();
+ }
+ };
+ public static final Property<AnimTarget, Float> TEST_DOUBLING_VALUE =
+ new Property<AnimTarget, Float>(Float.class, "testValue") {
+ @Override
+ public void set(AnimTarget object, Float value) {
+ object.setTestValue(value);
+ }
+
+ @Override
+ public Float get(AnimTarget object) {
+ // purposely different from getTestValue, to verify that properties
+ // are independent of setters/getters
+ return object.getTestValue() * 2;
+ }
+ };
+ }
+
private void startAnimation(final ObjectAnimator mObjectAnimator) throws Throwable {
Thread mAnimationRunnable = new Thread() {
public void run() {
diff --git a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
index 5451472..7c85710 100644
--- a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
@@ -82,20 +82,138 @@
assertEquals(startDelay, mValueAnimator.getStartDelay());
}
- public void testCurrentPlayTime() throws Throwable {
+ public void testGetCurrentPlayTime() throws Throwable {
startAnimation(mValueAnimator);
Thread.sleep(100);
long currentPlayTime = mValueAnimator.getCurrentPlayTime();
assertTrue(currentPlayTime > 0);
}
+ /**
+ * Test for equality within some epsilon. This accounts for minor differences
+ * due to floating-point accuracy.
+ */
+ private void assertRoughlyEqual(float expected, float actual) {
+ final float epsilon = .001f;
+ assertTrue(actual > (expected - epsilon) && actual < (expected + epsilon));
+ }
+
+ public void testSetCurrentPlayTime() throws Throwable {
+ final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
+ final ValueAnimator delayedAnim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
+ delayedAnim.setStartDelay(mDuration);
+ final long proposedCurrentPlayTime = mDuration / 2;
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.setCurrentPlayTime(mDuration / 2);
+ long currentPlayTime = anim.getCurrentPlayTime();
+ float currentFraction = anim.getAnimatedFraction();
+ float currentValue = (Float) anim.getAnimatedValue();
+ assertEquals(proposedCurrentPlayTime, currentPlayTime);
+ assertRoughlyEqual(.5f, currentFraction);
+ assertRoughlyEqual(50, currentValue);
+
+ delayedAnim.setCurrentPlayTime(mDuration / 2);
+ currentPlayTime = delayedAnim.getCurrentPlayTime();
+ currentFraction = delayedAnim.getAnimatedFraction();
+ currentValue = (Float) delayedAnim.getAnimatedValue();
+ assertEquals(proposedCurrentPlayTime, currentPlayTime);
+ assertRoughlyEqual(.5f, currentFraction);
+ assertRoughlyEqual(50, currentValue);
+ }
+ });
+ // Now make sure that it's still true a little later, to test that we're
+ // getting a result based on the seek time, not the wall clock time
+ Thread.sleep(100);
+ long currentPlayTime = anim.getCurrentPlayTime();
+ float currentFraction = anim.getAnimatedFraction();
+ float currentValue = (Float) anim.getAnimatedValue();
+ assertEquals(proposedCurrentPlayTime, currentPlayTime);
+ assertRoughlyEqual(.5f, currentFraction);
+ assertRoughlyEqual(50, currentValue);
+
+ currentPlayTime = delayedAnim.getCurrentPlayTime();
+ currentFraction = delayedAnim.getAnimatedFraction();
+ currentValue = (Float) delayedAnim.getAnimatedValue();
+ assertEquals(proposedCurrentPlayTime, currentPlayTime);
+ assertRoughlyEqual(.5f, currentFraction);
+ assertRoughlyEqual(50, currentValue);
+
+ // Finally, start() the delayed animation and check that the play time was
+ // not affected by playing during the delay
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ delayedAnim.start();
+ long currentPlayTime = delayedAnim.getCurrentPlayTime();
+ float currentFraction = delayedAnim.getAnimatedFraction();
+ float currentValue = (Float) delayedAnim.getAnimatedValue();
+ assertEquals(proposedCurrentPlayTime, currentPlayTime);
+ assertRoughlyEqual(.5f, currentFraction);
+ assertRoughlyEqual(50, currentValue);
+ }
+ });
+
+ Thread.sleep(100);
+ currentPlayTime = delayedAnim.getCurrentPlayTime();
+ currentFraction = delayedAnim.getAnimatedFraction();
+ currentValue = (Float) delayedAnim.getAnimatedValue();
+ assertEquals(proposedCurrentPlayTime, currentPlayTime);
+ assertRoughlyEqual(.5f, currentFraction);
+ assertRoughlyEqual(50, currentValue);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ delayedAnim.cancel();
+ }
+ });
+ }
+
+ public void testSetCurrentFraction() throws Throwable {
+ final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
+ final long proposedCurrentPlayTime = mDuration / 2;
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.setCurrentFraction(.5f);
+ long currentPlayTime = anim.getCurrentPlayTime();
+ float currentFraction = anim.getAnimatedFraction();
+ float currentValue = (Float) anim.getAnimatedValue();
+ assertEquals(proposedCurrentPlayTime, currentPlayTime);
+ assertRoughlyEqual(.5f, currentFraction);
+ assertRoughlyEqual(50, currentValue);
+ }
+ });
+ // Now make sure that it's still true a little later, to test that we're
+ // getting a result based on the seek time, not the wall clock time
+ Thread.sleep(100);
+ long currentPlayTime = anim.getCurrentPlayTime();
+ float currentFraction = anim.getAnimatedFraction();
+ float currentValue = (Float) anim.getAnimatedValue();
+ assertEquals(proposedCurrentPlayTime, currentPlayTime);
+ assertRoughlyEqual(.5f, currentFraction);
+ assertRoughlyEqual(50, currentValue);
+ }
+
public void testGetFrameDelay() throws Throwable {
- long frameDelay = 10;
- mValueAnimator.setFrameDelay(frameDelay);
+ final long frameDelay = 10;
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mValueAnimator.setFrameDelay(frameDelay);
+ }
+ });
startAnimation(mValueAnimator);
Thread.sleep(100);
- long actualFrameDelay = mValueAnimator.getFrameDelay();
- assertEquals(frameDelay, actualFrameDelay);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ long actualFrameDelay = mValueAnimator.getFrameDelay();
+ assertEquals(frameDelay, actualFrameDelay);
+ }
+ });
}
public void testSetInterpolator() throws Throwable {
diff --git a/tests/tests/app.usage/Android.mk b/tests/tests/app.usage/Android.mk
index f245e5f..52118bc 100644
--- a/tests/tests/app.usage/Android.mk
+++ b/tests/tests/app.usage/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/app.usage/AndroidTest.xml b/tests/tests/app.usage/AndroidTest.xml
new file mode 100644
index 0000000..d4967f9
--- /dev/null
+++ b/tests/tests/app.usage/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Configuration for app.usage Tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsUsageStatsTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.app.usage.cts" />
+ <option name="runtime-hint" value="1m47s" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java
index 10ac4ea..2656bb2 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java
@@ -31,6 +31,7 @@
import android.view.View;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
/**
* A simple activity containing the start state for an Activity Transition
@@ -41,6 +42,10 @@
public static final String LAYOUT_ID = "layoutId";
public static final String TEST = "test";
public static final String RESULT_RECEIVER = "resultReceiver";
+ public static final String PAUSE_ON_RESTART = "pauseOnRestart";
+ public static final String QUICK_FINISH = "quickFinish";
+ public static final String ALLOW_OVERLAP = "allowOverlap";
+ public static final String NO_RETURN_TRANSITION = "noReturnTransition";
public static final int NO_TEST = 0;
public static final int TEST_ARRIVE = 1;
@@ -62,6 +67,13 @@
public int resultCode = 0;
public Bundle result = new Bundle();
+ public boolean mPauseOnRestart;
+ public boolean mQuickFinish;
+ public boolean mAllowOverlap;
+ public boolean mNoReturnTransition;
+
+ public CountDownLatch returnLatch = new CountDownLatch(1);
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -75,6 +87,10 @@
mLayoutId = icicle.getInt(LAYOUT_ID);
mTest = icicle.getInt(TEST);
mResultReceiver = icicle.getParcelable(RESULT_RECEIVER);
+ mPauseOnRestart = icicle.getBoolean(PAUSE_ON_RESTART);
+ mQuickFinish = icicle.getBoolean(QUICK_FINISH);
+ mAllowOverlap = icicle.getBoolean(ALLOW_OVERLAP, true);
+ mNoReturnTransition = icicle.getBoolean(NO_RETURN_TRANSITION);
}
if (mLayoutId == 0) {
@@ -82,9 +98,18 @@
mLayoutId = intent.getIntExtra(LAYOUT_ID, R.layout.start);
mTest = intent.getIntExtra(TEST, 0);
mResultReceiver = intent.getParcelableExtra(RESULT_RECEIVER);
+ mPauseOnRestart = intent.getBooleanExtra(PAUSE_ON_RESTART, false);
+ mQuickFinish = intent.getBooleanExtra(QUICK_FINISH, false);
+ mAllowOverlap = intent.getBooleanExtra(ALLOW_OVERLAP, true);
+ mNoReturnTransition = intent.getBooleanExtra(NO_RETURN_TRANSITION, false);
}
setContentView(mLayoutId);
+ getWindow().setAllowReturnTransitionOverlap(mAllowOverlap);
+ if (mNoReturnTransition) {
+ getWindow().setReturnTransition(null);
+ getWindow().setSharedElementReturnTransition(null);
+ }
startTest();
}
@@ -94,6 +119,7 @@
outState.putInt(LAYOUT_ID, mLayoutId);
outState.putInt(TEST, mTest);
outState.putParcelable(RESULT_RECEIVER, mResultReceiver);
+ outState.putBoolean(PAUSE_ON_RESTART, mPauseOnRestart);
}
private void startTest() {
@@ -129,44 +155,59 @@
}, SHARED_ELEMENT_READY_DELAY);
}
});
- getWindow().getEnterTransition().addListener(new TransitionListener() {
- @Override
- public void onTransitionStart(Transition transition) {
- }
-
- @Override
- public void onTransitionEnd(Transition transition) {
- mEntering = false;
- setResult(RESULT_OK);
- getWindow().getDecorView().post(new Runnable() {
- @Override
- public void run() {
- finishAfterTransition();
- }
- });
- }
-
- @Override
- public void onTransitionCancel(Transition transition) {
- }
-
- @Override
- public void onTransitionPause(Transition transition) {
- }
-
- @Override
- public void onTransitionResume(Transition transition) {
- }
- });
}
+ getWindow().getEnterTransition().addListener(new TransitionListener() {
+ @Override
+ public void onTransitionStart(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ mEntering = false;
+ setResult(RESULT_OK);
+ getWindow().getDecorView().post(new Runnable() {
+ @Override
+ public void run() {
+ finishAfterTransition();
+ if (mQuickFinish) {
+ finish();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionPause(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionResume(Transition transition) {
+ }
+ });
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- synchronized (this) {
- super.onActivityResult(requestCode, resultCode, data);
- this.resultCode = resultCode;
- this.notifyAll();
+ super.onActivityResult(requestCode, resultCode, data);
+ this.resultCode = resultCode;
+ returnLatch.countDown();
+ }
+
+ @Override
+ protected void onRestart() {
+ super.onRestart();
+ if (mPauseOnRestart) {
+ postponeEnterTransition();
+ getWindow().getDecorView().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ startPostponedEnterTransition();
+ }
+ }, 500);
}
}
}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java
index ef126fe..7417d3e 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java
@@ -24,9 +24,13 @@
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
+import android.transition.Transition;
+import android.transition.Transition.TransitionListener;
import android.view.View;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public class ActivityTransitionTest extends
ActivityInstrumentationTestCase2<ActivityTransitionActivity> {
@@ -94,16 +98,8 @@
}
});
- long endTime = SystemClock.uptimeMillis() + 1500;
- synchronized (mActivity) {
- while (mActivity.resultCode == 0) {
- long waitTime = endTime - SystemClock.uptimeMillis();
- if (waitTime <= 0) {
- fail("Activity didn't finish!");
- }
- mActivity.wait(waitTime);
- }
- }
+ assertTrue("Activity didn't finish!",
+ mActivity.returnLatch.await(1500, TimeUnit.MILLISECONDS));
assertNotNull(mReceiver.resultData);
assertEquals(2, mReceiver.resultData.getInt(
ActivityTransitionActivity.ARRIVE_COUNT, -1));
@@ -130,6 +126,154 @@
assertTrue(mReenterTime < mReenterTimeReady);
}
+ public void testFinishPostponed() throws Throwable {
+ getInstrumentation().waitForIdleSync();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.mPauseOnRestart = true;
+ Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
+ mActivity.findViewById(R.id.hello), "target").toBundle();
+ Intent intent = new Intent(mActivity, ActivityTransitionActivity.class);
+ intent.putExtra(ActivityTransitionActivity.LAYOUT_ID, R.layout.end);
+ intent.putExtra(ActivityTransitionActivity.QUICK_FINISH, true);
+ mActivity.startActivityForResult(intent, 0, options);
+ }
+ });
+ CountDownLatch latch = setReenterLatch();
+
+ assertTrue("Activity didn't finish!",
+ mActivity.returnLatch.await(2000, TimeUnit.MILLISECONDS));
+ assertTrue("Reenter transition didn't finish", latch.await(1000, TimeUnit.MILLISECONDS));
+ getInstrumentation().waitForIdleSync();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ final View greenSquare = mActivity.findViewById(R.id.greenSquare);
+ final View hello = mActivity.findViewById(R.id.hello);
+ assertEquals(View.VISIBLE, greenSquare.getVisibility());
+ assertEquals(View.VISIBLE, hello.getVisibility());
+ }
+ });
+ }
+
+ public void testFinishNoOverlap() throws Throwable {
+ getInstrumentation().waitForIdleSync();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
+ mActivity.findViewById(R.id.hello), "target").toBundle();
+ Intent intent = new Intent(mActivity, ActivityTransitionActivity.class);
+ intent.putExtra(ActivityTransitionActivity.LAYOUT_ID, R.layout.end);
+ intent.putExtra(ActivityTransitionActivity.QUICK_FINISH, true);
+ intent.putExtra(ActivityTransitionActivity.ALLOW_OVERLAP, false);
+ mActivity.startActivityForResult(intent, 0, options);
+ }
+ });
+
+ assertTrue("Activity didn't finish!",
+ mActivity.returnLatch.await(1500, TimeUnit.MILLISECONDS));
+ getInstrumentation().waitForIdleSync();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ final View greenSquare = mActivity.findViewById(R.id.greenSquare);
+ final View hello = mActivity.findViewById(R.id.hello);
+ assertEquals(View.VISIBLE, greenSquare.getVisibility());
+ assertEquals(View.VISIBLE, hello.getVisibility());
+ }
+ });
+ }
+
+ public void testFinishWithOverlap() throws Throwable {
+ getInstrumentation().waitForIdleSync();
+ CountDownLatch latch = setReenterLatch();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
+ mActivity.findViewById(R.id.hello), "target").toBundle();
+ Intent intent = new Intent(mActivity, ActivityTransitionActivity.class);
+ intent.putExtra(ActivityTransitionActivity.LAYOUT_ID, R.layout.end);
+ intent.putExtra(ActivityTransitionActivity.QUICK_FINISH, true);
+ intent.putExtra(ActivityTransitionActivity.ALLOW_OVERLAP, true);
+ mActivity.startActivityForResult(intent, 0, options);
+ }
+ });
+
+ assertTrue("Activity didn't finish!",
+ mActivity.returnLatch.await(1500, TimeUnit.MILLISECONDS));
+ assertTrue("Reenter transition didn't finish", latch.await(1000, TimeUnit.MILLISECONDS));
+ getInstrumentation().waitForIdleSync();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ final View greenSquare = mActivity.findViewById(R.id.greenSquare);
+ final View hello = mActivity.findViewById(R.id.hello);
+ assertEquals(View.VISIBLE, greenSquare.getVisibility());
+ assertEquals(View.VISIBLE, hello.getVisibility());
+ }
+ });
+ }
+
+ public void testFinishNoReturnTransition() throws Throwable {
+ getInstrumentation().waitForIdleSync();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
+ mActivity.findViewById(R.id.hello), "target").toBundle();
+ Intent intent = new Intent(mActivity, ActivityTransitionActivity.class);
+ intent.putExtra(ActivityTransitionActivity.LAYOUT_ID, R.layout.end);
+ intent.putExtra(ActivityTransitionActivity.QUICK_FINISH, true);
+ intent.putExtra(ActivityTransitionActivity.ALLOW_OVERLAP, true);
+ intent.putExtra(ActivityTransitionActivity.NO_RETURN_TRANSITION, true);
+ mActivity.startActivityForResult(intent, 0, options);
+ }
+ });
+
+ assertTrue("Activity didn't finish!",
+ mActivity.returnLatch.await(1500, TimeUnit.MILLISECONDS));
+ getInstrumentation().waitForIdleSync();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ final View greenSquare = mActivity.findViewById(R.id.greenSquare);
+ final View hello = mActivity.findViewById(R.id.hello);
+ assertEquals(View.VISIBLE, greenSquare.getVisibility());
+ assertEquals(View.VISIBLE, hello.getVisibility());
+ }
+ });
+ }
+
+ private CountDownLatch setReenterLatch() {
+ final CountDownLatch latch = new CountDownLatch(1);
+ TransitionListener listener = new TransitionListener() {
+ @Override
+ public void onTransitionStart(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ latch.countDown();
+ }
+
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionPause(Transition transition) {
+ }
+
+ @Override
+ public void onTransitionResume(Transition transition) {
+ }
+ };
+ mActivity.getWindow().getReenterTransition().addListener(listener);
+ return latch;
+ }
public static class PassInfo extends ResultReceiver {
public int resultCode;
public Bundle resultData;
diff --git a/tests/tests/app/Android.mk b/tests/tests/app/Android.mk
deleted file mode 100644
index 301f931..0000000
--- a/tests/tests/app/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common voip-common org.apache.http.legacy
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-
-LOCAL_PACKAGE_NAME := CtsAppTestCases
-
-LOCAL_INSTRUMENTATION_FOR := CtsAppTestStubs
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/app/AndroidManifest.xml b/tests/tests/app/AndroidManifest.xml
deleted file mode 100644
index d05648c..0000000
--- a/tests/tests/app/AndroidManifest.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.app">
-
- <uses-sdk android:minSdkVersion="11" />
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.BODY_SENSORS" />
- <application>
- <uses-library android:name="android.test.runner" />
- <uses-library android:name="org.apache.http.legacy" android:required="false" />
- </application>
-
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.app.stub"
- android:label="CTS tests of android.app">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
-
diff --git a/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java b/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java
deleted file mode 100644
index 1b0a401..0000000
--- a/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2011 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.backup.cts;
-
-import android.app.backup.BackupManager;
-import android.app.backup.RestoreObserver;
-import android.test.AndroidTestCase;
-
-public class BackupManagerTest extends AndroidTestCase {
-
- public void testBackupManager() throws Exception {
- // Check that these don't crash as if they were called in an app...
- BackupManager backupManager = new BackupManager(mContext);
- backupManager.dataChanged();
- BackupManager.dataChanged("com.android.cts.app.stub");
-
- // Backup isn't expected to work in this test but check for obvious bugs...
- int result = backupManager.requestRestore(new RestoreObserver() {});
- assertTrue(result != 0);
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/ActionBarTest.java b/tests/tests/app/src/android/app/cts/ActionBarTest.java
deleted file mode 100644
index 75e7807..0000000
--- a/tests/tests/app/src/android/app/cts/ActionBarTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2012 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.ActionBar;
-import android.app.ActionBar.Tab;
-import android.app.ActionBar.TabListener;
-import android.app.FragmentTransaction;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-
-public class ActionBarTest extends ActivityInstrumentationTestCase2<ActionBarActivity> {
-
- private ActionBarActivity mActivity;
- private ActionBar mBar;
-
- public ActionBarTest() {
- super(ActionBarActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mActivity = getActivity();
- mBar = mActivity.getActionBar();
- }
-
- @UiThreadTest
- public void testAddTab() {
- if (mBar == null) {
- return;
- }
- assertEquals(0, mBar.getTabCount());
-
- Tab t1 = createTab("Tab 1");
- mBar.addTab(t1);
- assertEquals(1, mBar.getTabCount());
- assertEquals(t1, mBar.getSelectedTab());
- assertEquals(t1, mBar.getTabAt(0));
-
- Tab t2 = createTab("Tab 2");
- mBar.addTab(t2);
- assertEquals(2, mBar.getTabCount());
- assertEquals(t1, mBar.getSelectedTab());
- assertEquals(t2, mBar.getTabAt(1));
-
- Tab t3 = createTab("Tab 3");
- mBar.addTab(t3, true);
- assertEquals(3, mBar.getTabCount());
- assertEquals(t3, mBar.getSelectedTab());
- assertEquals(t3, mBar.getTabAt(2));
-
- Tab t4 = createTab("Tab 2.5");
- mBar.addTab(t4, 2);
- assertEquals(4, mBar.getTabCount());
- assertEquals(t4, mBar.getTabAt(2));
- assertEquals(t3, mBar.getTabAt(3));
-
- Tab t5 = createTab("Tab 0.5");
- mBar.addTab(t5, 0, true);
- assertEquals(5, mBar.getTabCount());
- assertEquals(t5, mBar.getSelectedTab());
- assertEquals(t5, mBar.getTabAt(0));
- assertEquals(t1, mBar.getTabAt(1));
- assertEquals(t2, mBar.getTabAt(2));
- assertEquals(t4, mBar.getTabAt(3));
- assertEquals(t3, mBar.getTabAt(4));
- }
-
- private Tab createTab(String name) {
- return mBar.newTab().setText("Tab 1").setTabListener(new TestTabListener());
- }
-
- static class TestTabListener implements TabListener {
- @Override
- public void onTabSelected(Tab tab, FragmentTransaction ft) {
- }
-
- @Override
- public void onTabUnselected(Tab tab, FragmentTransaction ft) {
- }
-
- @Override
- public void onTabReselected(Tab tab, FragmentTransaction ft) {
- }
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/ActivityGroupTest.java b/tests/tests/app/src/android/app/cts/ActivityGroupTest.java
deleted file mode 100644
index f5fc0bd..0000000
--- a/tests/tests/app/src/android/app/cts/ActivityGroupTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.ActivityGroup;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.Bundle;
-
-public class ActivityGroupTest extends ActivityTestsBase {
- private Intent mTabIntent;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mTabIntent = new Intent(mContext, LaunchpadTabActivity.class);
- mTabIntent.putExtra("tab", new ComponentName(mContext, LaunchpadActivity.class));
- }
-
- public void testTabBasic() throws Exception {
- mIntent = mTabIntent;
- runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC);
- }
-
- public void testTabScreen() throws Exception {
- mIntent = mTabIntent;
- runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN);
- }
-
- public void testTabDialog() throws Exception {
- mIntent = mTabIntent;
- runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG);
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java b/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
deleted file mode 100644
index 639741d..0000000
--- a/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2011 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.Activity;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.WindowManager;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * {@link ActivityInstrumentationTestCase2} that tests {@link ActivityManager#getMemoryClass()}
- * by checking that the memory class matches the proper screen density and by launching an
- * application that attempts to allocate memory on the heap.
- */
-public class ActivityManagerMemoryClassTest
- extends ActivityInstrumentationTestCase2<ActivityManagerMemoryClassLaunchActivity> {
-
- public ActivityManagerMemoryClassTest() {
- super(ActivityManagerMemoryClassLaunchActivity.class);
- }
-
- public static class ExpectedMemorySizesClass {
- private static final Map<Integer, Integer> expectedMemorySizeForWatch
- = new HashMap<Integer, Integer>();
- private static final Map<Integer, Integer> expectedMemorySizeForSmallNormalScreen
- = new HashMap<Integer, Integer>();
- private static final Map<Integer, Integer> expectedMemorySizeForLargeScreen
- = new HashMap<Integer, Integer>();
- private static final Map<Integer, Integer> expectedMemorySizeForXLargeScreen
- = new HashMap<Integer, Integer>();
-
- static {
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_LOW, 32);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_MEDIUM, 32);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_TV, 32);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_HIGH, 36);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_280, 36);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XHIGH, 48);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_360, 48);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_400, 56);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_420, 64);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XXHIGH, 88);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_560, 112);
- expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XXXHIGH, 154);
- }
-
- static {
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_LOW, 32);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_MEDIUM, 32);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_TV, 48);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_HIGH, 48);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_280, 48);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XHIGH, 80);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_360, 80);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_400, 96);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_420, 112);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXHIGH, 128);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_560, 192);
- expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 256);
- }
-
- static {
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_LOW, 32);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_MEDIUM, 64);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_TV, 80);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_HIGH, 80);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_280, 96);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XHIGH, 128);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_360, 160);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_400, 192);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_420, 228);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 256);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_560, 384);
- expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 512);
- }
-
- static {
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_LOW, 48);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_MEDIUM, 80);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_TV, 96);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_HIGH, 96);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_280, 144);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XHIGH, 192);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_360, 240);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_400, 288);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_420, 336);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 384);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_560, 576);
- expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 768);
- }
-
- public static Integer getExpectedMemorySize(
- int screenSize,
- int screenDensity,
- boolean isWatch) {
-
- if (isWatch) {
- return expectedMemorySizeForWatch.get(screenDensity);
- }
-
- switch (screenSize) {
- case Configuration.SCREENLAYOUT_SIZE_SMALL:
- case Configuration.SCREENLAYOUT_SIZE_NORMAL:
- return expectedMemorySizeForSmallNormalScreen.get(screenDensity);
- case Configuration.SCREENLAYOUT_SIZE_LARGE:
- return expectedMemorySizeForLargeScreen.get(screenDensity);
- case Configuration.SCREENLAYOUT_SIZE_XLARGE:
- return expectedMemorySizeForXLargeScreen.get(screenDensity);
- default:
- throw new IllegalArgumentException("No memory requirement specified "
- + " for screen layout size " + screenSize);
- }
- }
- }
-
- public void testGetMemoryClass() throws Exception {
- int memoryClass = getMemoryClass();
- int screenDensity = getScreenDensity();
- int screenSize = getScreenSize();
- assertMemoryForScreenDensity(memoryClass, screenDensity, screenSize);
-
- runHeapTestApp(memoryClass);
- }
-
- private int getMemoryClass() {
- Context context = getInstrumentation().getTargetContext();
- ActivityManager activityManager =
- (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- return activityManager.getMemoryClass();
- }
-
- private int getScreenDensity() {
- Context context = getInstrumentation().getTargetContext();
- WindowManager windowManager =
- (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- Display display = windowManager.getDefaultDisplay();
- DisplayMetrics metrics = new DisplayMetrics();
- display.getMetrics(metrics);
- return metrics.densityDpi;
- }
-
- private int getScreenSize() {
- Context context = getInstrumentation().getTargetContext();
- Configuration config = context.getResources().getConfiguration();
- return config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
- }
-
- private void assertMemoryForScreenDensity(int memoryClass, int screenDensity, int screenSize) {
- Context context = getInstrumentation().getTargetContext();
- boolean isWatch =
- context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
- int expectedMinimumMemory =
- ExpectedMemorySizesClass.getExpectedMemorySize(screenSize, screenDensity, isWatch);
-
- assertTrue("Expected to have at least " + expectedMinimumMemory
- + "mb of memory for screen density " + screenDensity,
- memoryClass >= expectedMinimumMemory);
- }
-
- private void runHeapTestApp(int memoryClass) throws InterruptedException {
- Intent intent = new Intent();
- intent.putExtra(ActivityManagerMemoryClassLaunchActivity.MEMORY_CLASS_EXTRA,
- memoryClass);
- setActivityIntent(intent);
- ActivityManagerMemoryClassLaunchActivity activity = getActivity();
- assertEquals("The test application couldn't allocate memory close to the amount "
- + " specified by the memory class.", Activity.RESULT_OK, activity.getResult());
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
deleted file mode 100644
index 02d13ef..0000000
--- a/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * 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.
- */
-package android.app.cts;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.ActivityManager.RecentTaskInfo;
-import android.app.ActivityManager.RunningAppProcessInfo;
-import android.app.ActivityManager.RunningServiceInfo;
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityOptions;
-import android.app.Instrumentation;
-import android.app.Instrumentation.ActivityMonitor;
-import android.app.Instrumentation.ActivityResult;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ConfigurationInfo;
-import android.test.InstrumentationTestCase;
-
-public class ActivityManagerTest extends InstrumentationTestCase {
- private static final String STUB_PACKAGE_NAME = "com.android.cts.app.stub";
- private static final int WAITFOR_MSEC = 5000;
- private static final String SERVICE_NAME = "android.app.cts.MockService";
- private static final int WAIT_TIME = 2000;
- // A secondary test activity from another APK.
- private static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp";
- private static final String SIMPLE_ACTIVITY = ".SimpleActivity";
- private static final String SIMPLE_ACTIVITY_IMMEDIATE_EXIT = ".SimpleActivityImmediateExit";
- private static final String SIMPLE_ACTIVITY_CHAIN_EXIT = ".SimpleActivityChainExit";
- // The action sent back by the SIMPLE_APP after a restart.
- private static final String ACTIVITY_LAUNCHED_ACTION =
- "com.android.cts.launchertests.LauncherAppsTests.LAUNCHED_ACTION";
- // The action sent back by the SIMPLE_APP_IMMEDIATE_EXIT when it terminates.
- private static final String ACTIVITY_EXIT_ACTION =
- "com.android.cts.launchertests.LauncherAppsTests.EXIT_ACTION";
- // The action sent back by the SIMPLE_APP_CHAIN_EXIT when the task chain ends.
- private static final String ACTIVITY_CHAIN_EXIT_ACTION =
- "com.android.cts.launchertests.LauncherAppsTests.CHAIN_EXIT_ACTION";
- // The action sent to identify the time track info.
- private static final String ACTIVITY_TIME_TRACK_INFO = "com.android.cts.TIME_TRACK_INFO";
- // Return states of the ActivityReceiverFilter.
- public static final int RESULT_PASS = 1;
- public static final int RESULT_FAIL = 2;
- public static final int RESULT_TIMEOUT = 3;
-
- private Context mContext;
- private ActivityManager mActivityManager;
- private Intent mIntent;
- private List<Activity> mStartedActivityList;
- private int mErrorProcessID;
- private Instrumentation mInstrumentation;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mInstrumentation = getInstrumentation();
- mContext = mInstrumentation.getContext();
- mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- mStartedActivityList = new ArrayList<Activity>();
- mErrorProcessID = -1;
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- if (mIntent != null) {
- mInstrumentation.getContext().stopService(mIntent);
- }
- for (int i = 0; i < mStartedActivityList.size(); i++) {
- mStartedActivityList.get(i).finish();
- }
- if (mErrorProcessID != -1) {
- android.os.Process.killProcess(mErrorProcessID);
- }
- }
-
- public void testGetRecentTasks() throws Exception {
- int maxNum = 0;
- int flags = 0;
-
- List<RecentTaskInfo> recentTaskList;
- // Test parameter: maxNum is set to 0
- recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
- assertNotNull(recentTaskList);
- assertTrue(recentTaskList.size() == 0);
- // Test parameter: maxNum is set to 50
- maxNum = 50;
- recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
- assertNotNull(recentTaskList);
- // start recent1_activity.
- startSubActivity(ActivityManagerRecentOneActivity.class);
- Thread.sleep(WAIT_TIME);
- // start recent2_activity
- startSubActivity(ActivityManagerRecentTwoActivity.class);
- Thread.sleep(WAIT_TIME);
- /*
- * assert both recent1_activity and recent2_activity exist in the recent
- * tasks list. Moreover,the index of the recent2_activity is smaller
- * than the index of recent1_activity
- */
- recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
- int indexRecentOne = -1;
- int indexRecentTwo = -1;
- int i = 0;
- for (RecentTaskInfo rti : recentTaskList) {
- if (rti.baseIntent.getComponent().getClassName().equals(
- ActivityManagerRecentOneActivity.class.getName())) {
- indexRecentOne = i;
- } else if (rti.baseIntent.getComponent().getClassName().equals(
- ActivityManagerRecentTwoActivity.class.getName())) {
- indexRecentTwo = i;
- }
- i++;
- }
- assertTrue(indexRecentOne != -1 && indexRecentTwo != -1);
- assertTrue(indexRecentTwo < indexRecentOne);
-
- try {
- mActivityManager.getRecentTasks(-1, 0);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected exception
- }
- }
-
- public void testGetRecentTasksLimitedToCurrentAPK() throws Exception {
- int maxNum = 0;
- int flags = 0;
-
- // Check the number of tasks at this time.
- List<RecentTaskInfo> recentTaskList;
- recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
- int numberOfEntriesFirstRun = recentTaskList.size();
-
- // Start another activity from another APK.
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- ActivityReceiverFilter receiver = new ActivityReceiverFilter(ACTIVITY_LAUNCHED_ACTION);
- mContext.startActivity(intent);
-
- // Make sure the activity has really started.
- assertEquals(RESULT_PASS, receiver.waitForActivity());
- receiver.close();
-
- // There shouldn't be any more tasks in this list at this time.
- recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
- int numberOfEntriesSecondRun = recentTaskList.size();
- assertTrue(numberOfEntriesSecondRun == numberOfEntriesFirstRun);
- }
-
- // The receiver filter needs to be instantiated with the command to filter for before calling
- // startActivity.
- private class ActivityReceiverFilter extends BroadcastReceiver {
- // The activity we want to filter for.
- private String mActivityToFilter;
- private int result = RESULT_TIMEOUT;
- public long mTimeUsed = 0;
- private static final int TIMEOUT_IN_MS = 1000;
-
- // Create the filter with the intent to look for.
- public ActivityReceiverFilter(String activityToFilter) {
- mActivityToFilter = activityToFilter;
- IntentFilter filter = new IntentFilter();
- filter.addAction(mActivityToFilter);
- mInstrumentation.getTargetContext().registerReceiver(this, filter);
- }
-
- // Turn off the filter.
- public void close() {
- mInstrumentation.getTargetContext().unregisterReceiver(this);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(mActivityToFilter)) {
- synchronized(this) {
- result = RESULT_PASS;
- if (mActivityToFilter.equals(ACTIVITY_TIME_TRACK_INFO)) {
- mTimeUsed = intent.getExtras().getLong(
- ActivityOptions.EXTRA_USAGE_TIME_REPORT);
- }
- notifyAll();
- }
- }
- }
-
- public int waitForActivity() {
- synchronized(this) {
- try {
- wait(TIMEOUT_IN_MS);
- } catch (InterruptedException e) {
- }
- }
- return result;
- }
- }
-
- private final <T extends Activity> void startSubActivity(Class<T> activityClass) {
- final Instrumentation.ActivityResult result = new ActivityResult(0, new Intent());
- final ActivityMonitor monitor = new ActivityMonitor(activityClass.getName(), result, false);
- mInstrumentation.addMonitor(monitor);
- launchActivity(STUB_PACKAGE_NAME, activityClass, null);
- mStartedActivityList.add(monitor.waitForActivity());
- }
-
- public void testGetRunningTasks() {
- // Test illegal parameter
- List<RunningTaskInfo> runningTaskList;
- runningTaskList = mActivityManager.getRunningTasks(-1);
- assertTrue(runningTaskList.size() == 0);
-
- runningTaskList = mActivityManager.getRunningTasks(0);
- assertTrue(runningTaskList.size() == 0);
-
- runningTaskList = mActivityManager.getRunningTasks(20);
- int taskSize = runningTaskList.size();
- assertTrue(taskSize >= 0 && taskSize <= 20);
-
- // start recent1_activity.
- startSubActivity(ActivityManagerRecentOneActivity.class);
- // start recent2_activity
- startSubActivity(ActivityManagerRecentTwoActivity.class);
-
- /*
- * assert both recent1_activity and recent2_activity exist in the
- * running tasks list. Moreover,the index of the recent2_activity is
- * smaller than the index of recent1_activity
- */
- runningTaskList = mActivityManager.getRunningTasks(20);
- int indexRecentOne = -1;
- int indexRecentTwo = -1;
- int i = 0;
- for (RunningTaskInfo rti : runningTaskList) {
- if (rti.baseActivity.getClassName().equals(
- ActivityManagerRecentOneActivity.class.getName())) {
- indexRecentOne = i;
- } else if (rti.baseActivity.getClassName().equals(
- ActivityManagerRecentTwoActivity.class.getName())) {
- indexRecentTwo = i;
- }
- i++;
- }
- assertTrue(indexRecentOne != -1 && indexRecentTwo != -1);
- assertTrue(indexRecentTwo < indexRecentOne);
- }
-
- public void testGetRunningServices() throws Exception {
- // Test illegal parameter
- List<RunningServiceInfo> runningServiceInfo;
- runningServiceInfo = mActivityManager.getRunningServices(-1);
- assertTrue(runningServiceInfo.size() == 0);
-
- runningServiceInfo = mActivityManager.getRunningServices(0);
- assertTrue(runningServiceInfo.size() == 0);
-
- runningServiceInfo = mActivityManager.getRunningServices(5);
- assertTrue(runningServiceInfo.size() >= 0 && runningServiceInfo.size() <= 5);
-
- Intent intent = new Intent();
- intent.setClass(mInstrumentation.getTargetContext(), MockService.class);
- mInstrumentation.getTargetContext().startService(intent);
- Thread.sleep(WAIT_TIME);
-
- runningServiceInfo = mActivityManager.getRunningServices(Integer.MAX_VALUE);
- boolean foundService = false;
- for (RunningServiceInfo rs : runningServiceInfo) {
- if (rs.service.getClassName().equals(SERVICE_NAME)) {
- foundService = true;
- break;
- }
- }
- assertTrue(foundService);
- mContext.stopService(intent);
- Thread.sleep(WAIT_TIME);
- }
-
- public void testGetMemoryInfo() {
- ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
- mActivityManager.getMemoryInfo(outInfo);
- assertTrue(outInfo.lowMemory == (outInfo.availMem <= outInfo.threshold));
- }
-
- public void testGetRunningAppProcesses() throws Exception {
- List<RunningAppProcessInfo> list = mActivityManager.getRunningAppProcesses();
- assertNotNull(list);
- final String SYSTEM_PROCESS = "system";
- boolean hasSystemProcess = false;
- // The package name is also the default name for the application process
- final String TEST_PROCESS = STUB_PACKAGE_NAME;
- boolean hasTestProcess = false;
- for (RunningAppProcessInfo ra : list) {
- if (ra.processName.equals(SYSTEM_PROCESS)) {
- hasSystemProcess = true;
- } else if (ra.processName.equals(TEST_PROCESS)) {
- hasTestProcess = true;
- }
- }
- // For security reasons the system process is not exposed.
- assertTrue(!hasSystemProcess && hasTestProcess);
-
- for (RunningAppProcessInfo ra : list) {
- if (ra.processName.equals("com.android.cts.app.stub:remote")) {
- fail("should be no process named com.android.cts.app.stub:remote");
- }
- }
- // start a new process
- mIntent = new Intent("android.app.REMOTESERVICE");
- mIntent.setPackage("com.android.cts.app.stub");
- mInstrumentation.getTargetContext().startService(mIntent);
- Thread.sleep(WAITFOR_MSEC);
-
- List<RunningAppProcessInfo> listNew = mActivityManager.getRunningAppProcesses();
- assertTrue(list.size() <= listNew.size());
-
- for (RunningAppProcessInfo ra : listNew) {
- if (ra.processName.equals("com.android.cts.app.stub:remote")) {
- return;
- }
- }
- fail("com.android.cts.app.stub:remote process should be available");
- }
-
- public void testGetProcessInErrorState() throws Exception {
- List<ActivityManager.ProcessErrorStateInfo> errList = null;
- errList = mActivityManager.getProcessesInErrorState();
- }
-
- public void testRestartPackage() {
- }
-
- public void testGetDeviceConfigurationInfo() {
- ConfigurationInfo conInf = mActivityManager.getDeviceConfigurationInfo();
- assertNotNull(conInf);
- }
-
- /**
- * Simple test for {@link ActivityManager.isUserAMonkey()} - verifies its false.
- *
- * TODO: test positive case
- */
- public void testIsUserAMonkey() {
- assertFalse(ActivityManager.isUserAMonkey());
- }
-
- /**
- * Verify that {@link ActivityManager.isRunningInTestHarness()} is false.
- */
- public void testIsRunningInTestHarness() {
- assertFalse("isRunningInTestHarness must be false in production builds",
- ActivityManager.isRunningInTestHarness());
- }
-
- /**
- * Go back to the home screen since running applications can interfere with application
- * lifetime tests.
- */
- private void launchHome() throws Exception {
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_HOME);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- Thread.sleep(WAIT_TIME);
- }
-
- /**
- * Verify that the TimeTrackingAPI works properly when starting and ending an activity.
- */
- public void testTimeTrackingAPI_SimpleStartExit() throws Exception {
- launchHome();
- // Prepare to start an activity from another APK.
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName(SIMPLE_PACKAGE_NAME,
- SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_IMMEDIATE_EXIT);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- // Prepare the time receiver action.
- Context context = mInstrumentation.getTargetContext();
- ActivityOptions options = ActivityOptions.makeBasic();
- Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
- options.requestUsageTimeReport(PendingIntent.getBroadcast(context,
- 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
-
- // The application finished tracker.
- ActivityReceiverFilter appEndReceiver = new ActivityReceiverFilter(ACTIVITY_EXIT_ACTION);
-
- // The filter for the time event.
- ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
-
- // Run the activity.
- mContext.startActivity(intent, options.toBundle());
-
- // Wait until it finishes and end the reciever then.
- assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
- appEndReceiver.close();
-
- // At this time the timerReceiver should not fire, even though the activity has shut down,
- // because we are back to the home screen.
- assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
- assertTrue(timeReceiver.mTimeUsed == 0);
-
- // Issuing now another activity will trigger the timing information release.
- final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
- dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
-
- // Wait until it finishes and end the reciever then.
- assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
- timeReceiver.close();
- assertTrue(timeReceiver.mTimeUsed != 0);
- }
-
- /**
- * Verify that the TimeTrackingAPI works properly when switching away from the monitored task.
- */
- public void testTimeTrackingAPI_SwitchAwayTriggers() throws Exception {
- launchHome();
-
- // Prepare to start an activity from another APK.
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- // Prepare the time receiver action.
- Context context = mInstrumentation.getTargetContext();
- ActivityOptions options = ActivityOptions.makeBasic();
- Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
- options.requestUsageTimeReport(PendingIntent.getBroadcast(context,
- 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
-
- // The application started tracker.
- ActivityReceiverFilter appStartedReceiver = new ActivityReceiverFilter(
- ACTIVITY_LAUNCHED_ACTION);
-
- // The filter for the time event.
- ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
-
- // Run the activity.
- mContext.startActivity(intent, options.toBundle());
-
- // Wait until it finishes and end the reciever then.
- assertEquals(RESULT_PASS, appStartedReceiver.waitForActivity());
- appStartedReceiver.close();
-
- // At this time the timerReceiver should not fire since our app is running.
- assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
- assertTrue(timeReceiver.mTimeUsed == 0);
-
- // Starting now another activity will put ours into the back hence releasing the timing.
- final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
- dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
-
- // Wait until it finishes and end the reciever then.
- assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
- timeReceiver.close();
- assertTrue(timeReceiver.mTimeUsed != 0);
- }
-
- /**
- * Verify that the TimeTrackingAPI works properly when handling an activity chain gets started
- * and ended.
- */
- public void testTimeTrackingAPI_ChainedActivityExit() throws Exception {
- launchHome();
- // Prepare to start an activity from another APK.
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName(SIMPLE_PACKAGE_NAME,
- SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_CHAIN_EXIT);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- // Prepare the time receiver action.
- Context context = mInstrumentation.getTargetContext();
- ActivityOptions options = ActivityOptions.makeBasic();
- Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
- options.requestUsageTimeReport(PendingIntent.getBroadcast(context,
- 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
-
- // The application finished tracker.
- ActivityReceiverFilter appEndReceiver = new ActivityReceiverFilter(
- ACTIVITY_CHAIN_EXIT_ACTION);
-
- // The filter for the time event.
- ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
-
- // Run the activity.
- mContext.startActivity(intent, options.toBundle());
-
- // Wait until it finishes and end the reciever then.
- assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
- appEndReceiver.close();
-
- // At this time the timerReceiver should not fire, even though the activity has shut down.
- assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
- assertTrue(timeReceiver.mTimeUsed == 0);
-
- // Issue another activity so that the timing information gets released.
- final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
- dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
-
- // Wait until it finishes and end the reciever then.
- assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
- timeReceiver.close();
- assertTrue(timeReceiver.mTimeUsed != 0);
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/ActivityManager_RunningServiceInfoTest.java b/tests/tests/app/src/android/app/cts/ActivityManager_RunningServiceInfoTest.java
deleted file mode 100644
index a6a38ae..0000000
--- a/tests/tests/app/src/android/app/cts/ActivityManager_RunningServiceInfoTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.
- */
-package android.app.cts;
-
-import android.app.ActivityManager;
-import android.content.ComponentName;
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-
-public class ActivityManager_RunningServiceInfoTest extends AndroidTestCase {
- private ActivityManager.RunningServiceInfo mRunningServiceInfo;
- private ComponentName mService;
- private static final String PROCESS = "process";
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mRunningServiceInfo = new ActivityManager.RunningServiceInfo();
- mService = new ComponentName(getContext(), MockActivity.class);
-
- mRunningServiceInfo.service = mService;
- mRunningServiceInfo.pid = 1;
- mRunningServiceInfo.process = PROCESS;
- mRunningServiceInfo.foreground = true;
- mRunningServiceInfo.activeSince = 1l;
- mRunningServiceInfo.started = true;
- mRunningServiceInfo.clientCount = 2;
- mRunningServiceInfo.crashCount = 1;
- mRunningServiceInfo.lastActivityTime = 1l;
- mRunningServiceInfo.restarting = 1l;
- }
-
- public void testConstructor() {
- new ActivityManager.RunningServiceInfo();
- }
-
- public void testDescribeContents() {
- assertEquals(0, mRunningServiceInfo.describeContents());
- }
-
- public void testWriteToParcel() throws Exception {
-
- Parcel parcel = Parcel.obtain();
- mRunningServiceInfo.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- ActivityManager.RunningServiceInfo values =
- ActivityManager.RunningServiceInfo.CREATOR.createFromParcel(parcel);
- assertEquals(mService, values.service);
- assertEquals(1, values.pid);
- assertEquals(PROCESS, values.process);
- assertTrue(values.foreground);
- assertEquals(1l, values.activeSince);
- assertTrue(values.started);
- assertEquals(2, values.clientCount);
- assertEquals(1, values.crashCount);
- assertEquals(1l, values.lastActivityTime);
- assertEquals(1l, values.restarting);
- }
-
- public void testReadFromParcel() throws Exception {
-
- Parcel parcel = Parcel.obtain();
- mRunningServiceInfo.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- ActivityManager.RunningServiceInfo values =
- new ActivityManager.RunningServiceInfo();
- values.readFromParcel(parcel);
- assertEquals(mService, values.service);
- assertEquals(1, values.pid);
- assertEquals(PROCESS, values.process);
- assertTrue(values.foreground);
- assertEquals(1l, values.activeSince);
- assertTrue(values.started);
- assertEquals(2, values.clientCount);
- assertEquals(1, values.crashCount);
- assertEquals(1l, values.lastActivityTime);
- assertEquals(1l, values.restarting);
- }
-
-}
diff --git a/tests/tests/app/src/android/app/cts/AlarmManagerTest.java b/tests/tests/app/src/android/app/cts/AlarmManagerTest.java
deleted file mode 100644
index b85c616..0000000
--- a/tests/tests/app/src/android/app/cts/AlarmManagerTest.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.AlarmManager;
-import android.app.AlarmManager.AlarmClockInfo;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.cts.util.PollingCheck;
-import android.os.Build;
-import android.os.SystemClock;
-import android.test.AndroidTestCase;
-import android.util.Log;
-import android.test.MoreAsserts;
-
-public class AlarmManagerTest extends AndroidTestCase {
- public static final String MOCKACTION = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER";
- public static final String MOCKACTION2 = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER2";
-
- private AlarmManager mAm;
- private Intent mIntent;
- private PendingIntent mSender;
- private Intent mIntent2;
- private PendingIntent mSender2;
-
- /*
- * The default snooze delay: 5 seconds
- */
- private static final long SNOOZE_DELAY = 5 * 1000L;
- private long mWakeupTime;
- private MockAlarmReceiver mMockAlarmReceiver;
- private MockAlarmReceiver mMockAlarmReceiver2;
-
- private static final int TIME_DELTA = 1000;
- private static final int TIME_DELAY = 10000;
- private static final int REPEAT_PERIOD = 60000;
-
- // Receiver registration/unregistration between tests races with the system process, so
- // we add a little buffer time here to allow the system to process before we proceed.
- // This value is in milliseconds.
- private static final long REGISTER_PAUSE = 250;
-
- // Constants used for validating exact vs inexact alarm batching immunity. We run a few
- // trials of an exact alarm that is placed within an inexact alarm's window of opportunity,
- // and mandate that the average observed delivery skew between the two be statistically
- // significant -- i.e. that the two alarms are not being coalesced. We also place an
- // additional exact alarm only a short time after the inexact alarm's nominal trigger time.
- // If exact alarms are allowed to batch with inexact ones this will tend to have no effect,
- // but in the correct behavior -- inexact alarms not permitted to batch with exact ones --
- // this additional exact alarm will have the effect of guaranteeing that the inexact alarm
- // must fire no later than it -- i.e. a considerable time before the significant, later
- // exact alarm.
- //
- // The test essentially amounts to requiring that the inexact MOCKACTION alarm and
- // the much later exact MOCKACTION2 alarm fire far apart, always; with an implicit
- // insistence that alarm batches are delivered at the head of their window.
- private static final long TEST_WINDOW_LENGTH = 5 * 1000L;
- private static final long TEST_ALARM_FUTURITY = 6 * 1000L;
- private static final long FAIL_DELTA = 50;
- private static final long NUM_TRIALS = 5;
- private static final long MAX_NEAR_DELIVERIES = 2;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mAm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-
- mIntent = new Intent(MOCKACTION)
- .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mSender = PendingIntent.getBroadcast(mContext, 0, mIntent, 0);
- mMockAlarmReceiver = new MockAlarmReceiver(mIntent.getAction());
-
- mIntent2 = new Intent(MOCKACTION2)
- .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mSender2 = PendingIntent.getBroadcast(mContext, 0, mIntent2, 0);
- mMockAlarmReceiver2 = new MockAlarmReceiver(mIntent2.getAction());
-
- IntentFilter filter = new IntentFilter(mIntent.getAction());
- mContext.registerReceiver(mMockAlarmReceiver, filter);
-
- IntentFilter filter2 = new IntentFilter(mIntent2.getAction());
- mContext.registerReceiver(mMockAlarmReceiver2, filter2);
-
- Thread.sleep(REGISTER_PAUSE);
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- mContext.unregisterReceiver(mMockAlarmReceiver);
- mContext.unregisterReceiver(mMockAlarmReceiver2);
-
- Thread.sleep(REGISTER_PAUSE);
- }
-
- public void testSetTypes() throws Exception {
- // TODO: try to find a way to make device sleep then test whether
- // AlarmManager perform the expected way
-
- // test parameter type is RTC_WAKEUP
- mMockAlarmReceiver.setAlarmedFalse();
- mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
- mAm.setExact(AlarmManager.RTC_WAKEUP, mWakeupTime, mSender);
- new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver.alarmed;
- }
- }.run();
- assertEquals(mMockAlarmReceiver.rtcTime, mWakeupTime, TIME_DELTA);
-
- // test parameter type is RTC
- mMockAlarmReceiver.setAlarmedFalse();
- mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
- mAm.setExact(AlarmManager.RTC, mWakeupTime, mSender);
- new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver.alarmed;
- }
- }.run();
- assertEquals(mMockAlarmReceiver.rtcTime, mWakeupTime, TIME_DELTA);
-
- // test parameter type is ELAPSED_REALTIME
- mMockAlarmReceiver.setAlarmedFalse();
- mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
- mAm.setExact(AlarmManager.ELAPSED_REALTIME, mWakeupTime, mSender);
- new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver.alarmed;
- }
- }.run();
- assertEquals(mMockAlarmReceiver.elapsedTime, mWakeupTime, TIME_DELTA);
-
- // test parameter type is ELAPSED_REALTIME_WAKEUP
- mMockAlarmReceiver.setAlarmedFalse();
- mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
- mAm.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, mWakeupTime, mSender);
- new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver.alarmed;
- }
- }.run();
- assertEquals(mMockAlarmReceiver.elapsedTime, mWakeupTime, TIME_DELTA);
- }
-
- public void testAlarmTriggersImmediatelyIfSetTimeIsNegative() throws Exception {
- // An alarm with a negative wakeup time should be triggered immediately.
- // This exercises a workaround for a limitation of the /dev/alarm driver
- // that would instead cause such alarms to never be triggered.
- mMockAlarmReceiver.setAlarmedFalse();
- mWakeupTime = -1000;
- mAm.set(AlarmManager.RTC, mWakeupTime, mSender);
- new PollingCheck(TIME_DELAY) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver.alarmed;
- }
- }.run();
- }
-
- public void testExactAlarmBatching() throws Exception {
- int deliveriesTogether = 0;
- for (int i = 0; i < NUM_TRIALS; i++) {
- final long now = System.currentTimeMillis();
- final long windowStart = now + TEST_ALARM_FUTURITY;
- final long exactStart = windowStart + TEST_WINDOW_LENGTH - 1;
-
- mMockAlarmReceiver.setAlarmedFalse();
- mMockAlarmReceiver2.setAlarmedFalse();
- mAm.setWindow(AlarmManager.RTC_WAKEUP, windowStart, TEST_WINDOW_LENGTH, mSender);
- mAm.setExact(AlarmManager.RTC_WAKEUP, exactStart, mSender2);
-
- // Wait until a half-second beyond its target window, just to provide a
- // little safety slop.
- new PollingCheck(TEST_WINDOW_LENGTH + (windowStart - now) + 500) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver.alarmed;
- }
- }.run();
-
- // Now wait until 1 sec beyond the expected exact alarm fire time, or for at
- // least one second if we're already past the nominal exact alarm fire time
- long timeToExact = Math.max(exactStart - System.currentTimeMillis() + 1000, 1000);
- new PollingCheck(timeToExact) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver2.alarmed;
- }
- }.run();
-
- // Success when we observe that the exact and windowed alarm are not being often
- // delivered close together -- that is, when we can be confident that they are not
- // being coalesced.
- final long delta = Math.abs(mMockAlarmReceiver2.rtcTime - mMockAlarmReceiver.rtcTime);
- Log.i("TEST", "[" + i + "] delta = " + delta);
- if (delta < FAIL_DELTA) {
- deliveriesTogether++;
- assertTrue("Exact alarms appear to be coalescing with inexact alarms",
- deliveriesTogether <= MAX_NEAR_DELIVERIES);
- }
- }
- }
-
- public void testSetRepeating() throws Exception {
- mMockAlarmReceiver.setAlarmedFalse();
- mWakeupTime = System.currentTimeMillis() + TEST_ALARM_FUTURITY;
- mAm.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, REPEAT_PERIOD, mSender);
-
- // wait beyond the initial alarm's possible delivery window to verify that it fires the first time
- new PollingCheck(TEST_ALARM_FUTURITY + REPEAT_PERIOD) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver.alarmed;
- }
- }.run();
- assertTrue(mMockAlarmReceiver.alarmed);
-
- // Now reset the receiver and wait for the intended repeat alarm to fire as expected
- mMockAlarmReceiver.setAlarmedFalse();
- new PollingCheck(REPEAT_PERIOD*2) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver.alarmed;
- }
- }.run();
- assertTrue(mMockAlarmReceiver.alarmed);
-
- mAm.cancel(mSender);
- }
-
- public void testCancel() throws Exception {
- mMockAlarmReceiver.setAlarmedFalse();
- mMockAlarmReceiver2.setAlarmedFalse();
-
- // set two alarms
- final long when1 = System.currentTimeMillis() + TEST_ALARM_FUTURITY;
- mAm.setExact(AlarmManager.RTC_WAKEUP, when1, mSender);
- final long when2 = when1 + TIME_DELTA; // will fire after when1's target time
- mAm.setExact(AlarmManager.RTC_WAKEUP, when2, mSender2);
-
- // cancel the earlier one
- mAm.cancel(mSender);
-
- // and verify that only the later one fired
- new PollingCheck(TIME_DELAY) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver2.alarmed;
- }
- }.run();
-
- assertFalse(mMockAlarmReceiver.alarmed);
- assertTrue(mMockAlarmReceiver2.alarmed);
- }
-
- public void testSetInexactRepeating() throws Exception {
- mAm.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
- AlarmManager.INTERVAL_FIFTEEN_MINUTES, mSender);
- SystemClock.setCurrentTimeMillis(System.currentTimeMillis()
- + AlarmManager.INTERVAL_FIFTEEN_MINUTES);
- // currently there is no way to write Android system clock. When try to
- // write the system time, there will be log as
- // " Unable to open alarm driver: Permission denied". But still fail
- // after tried many permission.
- }
-
- public void testSetAlarmClock() throws Exception {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- mMockAlarmReceiver.setAlarmedFalse();
- mMockAlarmReceiver2.setAlarmedFalse();
-
- // Set first alarm clock.
- final long wakeupTimeFirst = System.currentTimeMillis()
- + 2 * TEST_ALARM_FUTURITY;
- mAm.setAlarmClock(new AlarmClockInfo(wakeupTimeFirst, null), mSender);
-
- // Verify getNextAlarmClock returns first alarm clock.
- AlarmClockInfo nextAlarmClock = mAm.getNextAlarmClock();
- assertEquals(wakeupTimeFirst, nextAlarmClock.getTriggerTime());
- assertNull(nextAlarmClock.getShowIntent());
-
- // Set second alarm clock, earlier than first.
- final long wakeupTimeSecond = System.currentTimeMillis()
- + TEST_ALARM_FUTURITY;
- PendingIntent showIntentSecond = PendingIntent.getBroadcast(getContext(), 0,
- new Intent(getContext(), AlarmManagerTest.class).setAction("SHOW_INTENT"), 0);
- mAm.setAlarmClock(new AlarmClockInfo(wakeupTimeSecond, showIntentSecond),
- mSender2);
-
- // Verify getNextAlarmClock returns second alarm clock now.
- nextAlarmClock = mAm.getNextAlarmClock();
- assertEquals(wakeupTimeSecond, nextAlarmClock.getTriggerTime());
- assertEquals(showIntentSecond, nextAlarmClock.getShowIntent());
-
- // Cancel second alarm.
- mAm.cancel(mSender2);
-
- // Verify getNextAlarmClock returns first alarm clock again.
- nextAlarmClock = mAm.getNextAlarmClock();
- assertEquals(wakeupTimeFirst, nextAlarmClock.getTriggerTime());
- assertNull(nextAlarmClock.getShowIntent());
-
- // Wait for first alarm to trigger.
- assertFalse(mMockAlarmReceiver.alarmed);
- new PollingCheck(2 * TEST_ALARM_FUTURITY + TIME_DELAY) {
- @Override
- protected boolean check() {
- return mMockAlarmReceiver.alarmed;
- }
- }.run();
-
- // Verify first alarm fired at the right time.
- assertEquals(mMockAlarmReceiver.rtcTime, wakeupTimeFirst, TIME_DELTA);
-
- // Verify second alarm didn't fire.
- assertFalse(mMockAlarmReceiver2.alarmed);
-
- // Verify the next alarm is not returning neither the first nor the second alarm.
- nextAlarmClock = mAm.getNextAlarmClock();
- MoreAsserts.assertNotEqual(wakeupTimeFirst, nextAlarmClock != null
- ? nextAlarmClock.getTriggerTime()
- : null);
- MoreAsserts.assertNotEqual(wakeupTimeSecond, nextAlarmClock != null
- ? nextAlarmClock.getTriggerTime()
- : null);
- }
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/AlertDialogTest.java b/tests/tests/app/src/android/app/cts/AlertDialogTest.java
deleted file mode 100644
index 3e9f3b2..0000000
--- a/tests/tests/app/src/android/app/cts/AlertDialogTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.AlertDialog;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnClickListener;
-import android.cts.util.PollingCheck;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Message;
-import android.test.ActivityInstrumentationTestCase2;
-import android.view.KeyEvent;
-import android.view.View;
-import android.widget.Button;
-
-/*
- * Test AlertDialog
- */
-public class AlertDialogTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
- private static final String ALERTDIALOG_CUSTOM_TITLE = "Hello, World!";
-
- private Instrumentation mInstrumentation;
- private DialogStubActivity mActivity;
- private Button mPositiveButton;
- private Button mNegativeButton;
- private Button mNeutralButton;
-
- public AlertDialogTest() {
- super("com.android.cts.app.stub", DialogStubActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mInstrumentation = getInstrumentation();
- }
-
- protected void startDialogActivity(int dialogNumber) {
- mActivity = DialogStubActivity.startDialogActivity(this, dialogNumber);
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mActivity.getDialog().isShowing();
- }
- }.run();
- }
-
- public void testAlertDialog() throws Throwable {
- doTestAlertDialog(DialogStubActivity.TEST_ALERTDIALOG);
- }
-
- private void doTestAlertDialog(int index) throws Throwable {
- startDialogActivity(index);
- assertTrue(mActivity.getDialog().isShowing());
-
- mPositiveButton = ((AlertDialog) (mActivity.getDialog())).getButton(
- DialogInterface.BUTTON_POSITIVE);
- assertNotNull(mPositiveButton);
- assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_positive),
- mPositiveButton.getText());
- mNeutralButton = ((AlertDialog) (mActivity.getDialog())).getButton(
- DialogInterface.BUTTON_NEUTRAL);
- assertNotNull(mNeutralButton);
- assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_neutral),
- mNeutralButton.getText());
- mNegativeButton = ((AlertDialog) (mActivity.getDialog())).getButton(
- DialogInterface.BUTTON_NEGATIVE);
- assertNotNull(mNegativeButton);
- assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_negative),
- mNegativeButton.getText());
-
- assertFalse(mActivity.isPositiveButtonClicked);
- performClick(mPositiveButton);
- assertTrue(mActivity.isPositiveButtonClicked);
-
- assertFalse(mActivity.isNegativeButtonClicked);
- performClick(mNegativeButton);
- assertTrue(mActivity.isNegativeButtonClicked);
-
- assertFalse(mActivity.isNeutralButtonClicked);
- performClick(mNeutralButton);
- assertTrue(mActivity.isNeutralButtonClicked);
- }
-
- public void testAlertDialogDeprecatedAPI() throws Throwable {
- doTestAlertDialog(DialogStubActivity.TEST_ALERTDIALOG_DEPRECATED);
- }
-
- public void testAlertDialogDeprecatedAPIWithMessage() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE);
- assertTrue(mActivity.getDialog().isShowing());
-
- mPositiveButton = ((AlertDialog) (mActivity.getDialog())).getButton(
- DialogInterface.BUTTON_POSITIVE);
- assertNotNull(mPositiveButton);
- assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_positive),
- mPositiveButton.getText());
- mNegativeButton = ((AlertDialog) (mActivity.getDialog())).getButton(
- DialogInterface.BUTTON_NEGATIVE);
- assertNotNull(mNegativeButton);
- assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_negative),
- mNegativeButton.getText());
- mNeutralButton = ((AlertDialog) (mActivity.getDialog())).getButton(
- DialogInterface.BUTTON_NEUTRAL);
- assertNotNull(mNeutralButton);
- assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_neutral),
- mNeutralButton.getText());
-
- DialogStubActivity.buttonIndex = 0;
- performClick(mPositiveButton);
- assertEquals(DialogInterface.BUTTON_POSITIVE, DialogStubActivity.buttonIndex);
-
- DialogStubActivity.buttonIndex = 0;
- performClick(mNeutralButton);
- assertEquals(DialogInterface.BUTTON_NEUTRAL, DialogStubActivity.buttonIndex);
-
- DialogStubActivity.buttonIndex = 0;
- performClick(mNegativeButton);
- assertEquals(DialogInterface.BUTTON_NEGATIVE, DialogStubActivity.buttonIndex);
- }
-
- private void performClick(final Button button) throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- button.performClick();
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testCustomAlertDialog() {
- startDialogActivity(DialogStubActivity.TEST_CUSTOM_ALERTDIALOG);
- assertTrue(mActivity.getDialog().isShowing());
- }
-
- public void testCustomAlertDialogView() {
- startDialogActivity(DialogStubActivity.TEST_CUSTOM_ALERTDIALOG_VIEW);
- assertTrue(mActivity.getDialog().isShowing());
- }
-
-
- public void testCallback() {
- startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_CALLBACK);
- assertTrue(mActivity.onCreateCalled);
-
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
- assertTrue(mActivity.onKeyDownCalled);
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
- assertTrue(mActivity.onKeyUpCalled);
- }
-
- public void testAlertDialogTheme() throws Exception {
- startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_THEME);
- assertTrue(mActivity.getDialog().isShowing());
- }
-
- public void testAlertDialogCancelable() throws Exception {
- startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_CANCELABLE);
- assertTrue(mActivity.getDialog().isShowing());
- assertFalse(mActivity.onCancelCalled);
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.onCancelCalled);
- }
-
- public void testAlertDialogNotCancelable() throws Exception {
- startDialogActivity(DialogStubActivity.TEST_ALERTDIALOG_NOT_CANCELABLE);
- assertTrue(mActivity.getDialog().isShowing());
- assertFalse(mActivity.onCancelCalled);
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- assertFalse(mActivity.onCancelCalled);
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java b/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
deleted file mode 100644
index 58e69b8..0000000
--- a/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import java.util.ArrayList;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Instrumentation;
-import android.app.AlertDialog.Builder;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnClickListener;
-import android.content.DialogInterface.OnKeyListener;
-import android.content.DialogInterface.OnMultiChoiceClickListener;
-import android.cts.util.PollingCheck;
-import android.database.Cursor;
-import android.database.CursorWrapper;
-import android.graphics.drawable.Drawable;
-import android.provider.Contacts.People;
-import android.test.ActivityInstrumentationTestCase2;
-import android.view.KeyEvent;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.AdapterView.OnItemSelectedListener;
-
-
-public class AlertDialog_BuilderTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
- private Builder mBuilder;
- private Context mContext;
- private Instrumentation mInstrumentation;
- private final CharSequence mTitle = "title";
- private Drawable mDrawable;
- private AlertDialog mDialog;
- private Button mButton;
- private boolean mResult;
- private boolean mItemSelected;
- private CharSequence mSelectedItem;
- private final String[] mPROJECTION = new String[] {
- People._ID, People.NAME
- };
-
- private View mView;
- private ListView mListView;
- private ArrayList<Integer> mSelectedItems;
- private FrameLayout mFrameLayout;
-
- private OnClickListener mOnClickListener = new OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- mResult = true;
- }
- };
-
- private OnCancelListener mOnCancelListener = new OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- mResult = true;
- }
- };
-
- private OnKeyListener mOnKeyListener = new OnKeyListener() {
- public boolean onKey(DialogInterface dialog, int key, KeyEvent envnt) {
- mResult = true;
- return true;
- }
- };
-
- private OnItemSelectedListener mOnItemSelectedListener = new OnItemSelectedListener() {
- public void onItemSelected(AdapterView parent, View v, int position, long id) {
- mItemSelected = true;
- }
-
- public void onNothingSelected(AdapterView parent) {
- }
-
- };
-
- private OnMultiChoiceClickListener mOnMultiChoiceClickListener =
- new OnMultiChoiceClickListener() {
- public void onClick(DialogInterface dialog, int which, boolean isChecked) {
- mSelectedItems.add(which);
- mResult = true;
- }
- };
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mBuilder = null;
- mInstrumentation = getInstrumentation();
- mContext = getActivity();
- final Activity activity = getActivity();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return activity.hasWindowFocus();
- }
- }.run();
- mButton = null;
- mView = null;
- mListView = null;
- mDialog = null;
- mItemSelected = false;
- mSelectedItem = null;
- mSelectedItems = new ArrayList<Integer>();
- }
-
- public AlertDialog_BuilderTest() {
- super("com.android.cts.app.stub", DialogStubActivity.class);
- }
-
- public void testConstructor() {
- new AlertDialog.Builder(mContext);
- }
-
- public void testSetIconWithParamInt() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mDrawable = mContext.getResources().getDrawable(android.R.drawable.btn_default);
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setIcon(android.R.drawable.btn_default);
- mDialog = mBuilder.show();
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testSetIconWithParamDrawable() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mDrawable = mContext.getResources().getDrawable(android.R.drawable.btn_default);
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setIcon(mDrawable);
- mDialog = mBuilder.show();
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testSetPositiveButtonWithParamInt() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setPositiveButton(android.R.string.yes, mOnClickListener);
- mDialog = mBuilder.show();
- mButton = mDialog.getButton(DialogInterface.BUTTON_POSITIVE);
- mButton.performClick();
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertEquals(mContext.getText(android.R.string.yes), mButton.getText());
- assertTrue(mResult);
- }
-
- public void testSetPositiveButtonWithParamCharSequence() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setPositiveButton(android.R.string.yes, mOnClickListener);
- mDialog = mBuilder.show();
- mButton = mDialog.getButton(DialogInterface.BUTTON_POSITIVE);
- mButton.performClick();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(mContext.getText(android.R.string.yes), mButton.getText());
- assertTrue(mResult);
- }
-
- public void testSetNegativeButtonWithParamCharSequence() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setNegativeButton(mTitle, mOnClickListener);
- mDialog = mBuilder.show();
- mButton = mDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
- mButton.performClick();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(mTitle, mButton.getText());
- assertTrue(mResult);
- }
-
- public void testSetNegativeButtonWithParamInt() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setNegativeButton(com.android.cts.app.stub.R.string.notify, mOnClickListener);
- mDialog = mBuilder.show();
- mButton = mDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
- mButton.performClick();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(mContext.getText(com.android.cts.app.stub.R.string.notify), mButton.getText());
- assertTrue(mResult);
- }
-
- public void testSetNeutralButtonWithParamInt() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setNeutralButton(com.android.cts.app.stub.R.string.notify, mOnClickListener);
- mDialog = mBuilder.show();
- mButton = mDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
- mButton.performClick();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(mContext.getText(com.android.cts.app.stub.R.string.notify), mButton.getText());
- assertTrue(mResult);
- }
-
- public void testSetNeutralButtonWithParamCharSequence() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setNeutralButton(mTitle, mOnClickListener);
- mDialog = mBuilder.show();
- mButton = mDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
- mButton.performClick();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(mTitle, mButton.getText());
- assertTrue(mResult);
- }
-
- private void testCancelable(final boolean cancelable) throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setCancelable(cancelable);
- mDialog = mBuilder.show();
- }
- });
- mInstrumentation.waitForIdleSync();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mDialog.isShowing();
- }
- }.run();
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- mInstrumentation.waitForIdleSync();
- new PollingCheck() {
- @Override
- protected boolean check() {
- boolean showing = mDialog.isShowing();
- if (cancelable) {
- // if the dialog is cancelable, then pressing back
- // should cancel it. Thus it should not be showing
- return !showing;
- } else {
- // if the dialog is not cancelable, pressing back
- // should so nothing and it should still be showing
- return showing;
- }
- }
- }.run();
- }
-
- public void testSetCancelable() throws Throwable {
- testCancelable(true);
- }
-
- public void testDisableCancelable() throws Throwable {
- testCancelable(false);
- }
-
- public void testSetOnCancelListener() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setOnCancelListener(mOnCancelListener);
- mDialog = mBuilder.show();
- mDialog.cancel();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertTrue(mResult);
- }
-
- public void testSetOnKeyListener() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setOnKeyListener(mOnKeyListener);
- mDialog = mBuilder.show();
- }
- });
- mInstrumentation.waitForIdleSync();
- sendKeys(KeyEvent.ACTION_DOWN, KeyEvent.ACTION_DOWN);
- assertTrue(mResult);
- }
-
- public void testSetItemsWithParamInt() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setItems(com.android.cts.app.stub.R.array.difficultyLevel, mOnClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- }
- });
- mInstrumentation.waitForIdleSync();
-
- final CharSequence[] levels = mContext.getResources().getTextArray(
- com.android.cts.app.stub.R.array.difficultyLevel);
- assertEquals(levels[0], mListView.getItemAtPosition(0));
- }
-
- public void testSetItemsWithParamCharSequence() throws Throwable {
- final CharSequence[] expect = mContext.getResources().getTextArray(
- com.android.cts.app.stub.R.array.difficultyLevel);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setItems(expect, mOnClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(expect[0], mListView.getItemAtPosition(0));
- }
-
- public void testSetAdapter() throws Throwable {
- final ListAdapter adapter = new AdapterTest();
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setAdapter(adapter, mOnClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(adapter, mListView.getAdapter());
- }
-
- public void testSetCursor() throws Throwable {
- preparePeople();
- final Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, mPROJECTION, null,
- null, null);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setCursor(c, mOnClickListener, People.NAME);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- mListView.performItemClick(null, 0, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- final CursorWrapper selected = (CursorWrapper)mListView.getSelectedItem();
- assertEquals(c.getString(1), selected.getString(1));
- assertTrue(mResult);
- }
-
- public void testSetMultiChoiceItemsWithParamInt() throws Throwable {
-
- final CharSequence[] items = mContext.getResources().getTextArray(
- com.android.cts.app.stub.R.array.difficultyLevel);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setMultiChoiceItems(com.android.cts.app.stub.R.array.difficultyLevel, null,
- mOnMultiChoiceClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- mSelectedItem = (CharSequence)mListView.getSelectedItem();
- mListView.performItemClick(null, 0, 0);
- mListView.performItemClick(null, 1, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(items[0], mSelectedItem);
- assertEquals(2, mSelectedItems.size());
- assertEquals(items[0], mListView.getItemAtPosition(0));
- assertTrue(mResult);
- }
-
- public void testSetMultiChoiceItemsWithParamCharSequence() throws Throwable {
- final CharSequence[] items = mContext.getResources().getTextArray(
- com.android.cts.app.stub.R.array.difficultyLevel);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setMultiChoiceItems(items, null, mOnMultiChoiceClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- mSelectedItem = (CharSequence)mListView.getSelectedItem();
- mListView.performItemClick(null, 0, 0);
- mListView.performItemClick(null, 1, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(items[0], mSelectedItem);
- assertEquals(2, mSelectedItems.size());
- assertEquals(items[0], mListView.getItemAtPosition(0));
- assertTrue(mResult);
- }
-
- public void testSetMultiChoiceItemsWithParamCursor() throws Throwable {
- preparePeople();
- final Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, mPROJECTION, null,
- null, null);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setMultiChoiceItems(c, People.NAME, People.NAME,
- mOnMultiChoiceClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- mListView.performItemClick(null, 0, 0);
- mListView.performItemClick(null, 1, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- final CursorWrapper selected = (CursorWrapper)mListView.getSelectedItem();
- assertEquals(c.getString(1), selected.getString(1));
- assertEquals(2, mSelectedItems.size());
- assertTrue(mResult);
- }
-
- public void testSetSingleChoiceItemsWithParamInt() throws Throwable {
- final CharSequence[] items = mContext.getResources().getTextArray(
- com.android.cts.app.stub.R.array.difficultyLevel);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setSingleChoiceItems(com.android.cts.app.stub.R.array.difficultyLevel, 0,
- mOnClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- mSelectedItem = (CharSequence)mListView.getSelectedItem();
- mListView.performItemClick(null, 0, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(items[0], mSelectedItem);
- assertEquals(items[0], mListView.getItemAtPosition(0));
- assertTrue(mResult);
- }
-
- private void preparePeople() {
- final ContentResolver mResolver = mContext.getContentResolver();
- mResolver.delete(People.CONTENT_URI, null, null);
- final ContentValues valuse = new ContentValues();
- valuse.put(People._ID, "1");
- valuse.put(People.NAME, "name");
- mResolver.insert(People.CONTENT_URI, valuse);
- }
-
- public void testSetSingleChoiceItemsWithParamCursor() throws Throwable {
- final String[] PROJECTION = new String[] {
- People._ID, People.NAME
- };
- preparePeople();
- final Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, PROJECTION, null,
- null, null);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setSingleChoiceItems(c, 0, People.NAME, mOnClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- mListView.performItemClick(null, 0, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- final CursorWrapper selected = (CursorWrapper)mListView.getSelectedItem();
- assertEquals(c.getString(1), selected.getString(1));
- assertTrue(mResult);
- }
-
- public void testSetSingleChoiceItemsWithParamCharSequence() throws Throwable {
- final CharSequence[] items = mContext.getResources().getTextArray(
- com.android.cts.app.stub.R.array.difficultyLevel);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setSingleChoiceItems(items, 0, mOnClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- mSelectedItem = (CharSequence)mListView.getSelectedItem();
- mListView.performItemClick(null, 0, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(items[0], mSelectedItem);
- assertEquals(items[0], mListView.getItemAtPosition(0));
- assertTrue(mResult);
- }
-
- public void testSetSingleChoiceItems() throws Throwable {
- final CharSequence[] items = mContext.getResources().getTextArray(
- com.android.cts.app.stub.R.array.difficultyLevel);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setSingleChoiceItems(new ArrayAdapter<CharSequence>(mContext,
- android.R.layout.select_dialog_singlechoice, android.R.id.text1, items), 0,
- mOnClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- mSelectedItem = (CharSequence)mListView.getSelectedItem();
- mListView.performItemClick(null, 0, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(items[0], mSelectedItem);
- assertEquals(items[0], mListView.getItemAtPosition(0));
- assertTrue(mResult);
- }
-
- public void testSetOnItemSelectedListener() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setOnItemSelectedListener(mOnItemSelectedListener);
- mBuilder.setItems(com.android.cts.app.stub.R.array.difficultyLevel, mOnClickListener);
- mDialog = mBuilder.show();
- mListView = mDialog.getListView();
- mListView.pointToPosition(0, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertTrue(mItemSelected);
- }
-
- public void testSetView() throws Throwable {
- final View view = new View(mContext);
- view.setId(100);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setView(view);
- mDialog = mBuilder.show();
- mView = mDialog.getWindow().findViewById(100);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertEquals(view, mView);
- }
-
- public void testSetInverseBackgroundForced() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mBuilder.setInverseBackgroundForced(true);
- mDialog = mBuilder.create();
- mDialog.show();
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testCreate() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mDialog = mBuilder.create();
- mDialog.show();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertNotNull(mDialog);
- assertTrue(mDialog.isShowing());
- }
-
- public void testShow() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- mBuilder = new AlertDialog.Builder(mContext);
- mDialog = mBuilder.show();
- }
- });
- mInstrumentation.waitForIdleSync();
- assertTrue(mDialog.isShowing());
- }
-
- private static class AdapterTest implements android.widget.ListAdapter {
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- public boolean isEnabled(int position) {
- return false;
- }
-
- public int getCount() {
- return 0;
- }
-
- public Object getItem(int position) {
- return null;
- }
-
- public long getItemId(int position) {
- return 0;
- }
-
- public int getItemViewType(int position) {
- return 0;
- }
-
- public android.view.View getView( int position,
- android.view.View convertView,
- android.view.ViewGroup parent){
- return null;
- }
-
- public int getViewTypeCount() {
- return 1;
- }
-
- public boolean hasStableIds() {
- return false;
- }
-
- public boolean isEmpty() {
- return true;
- }
-
- public void registerDataSetObserver(
- android.database.DataSetObserver observer) {
- }
-
- public void unregisterDataSetObserver(
- android.database.DataSetObserver observer) {
- }
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/AliasActivityTest.java b/tests/tests/app/src/android/app/cts/AliasActivityTest.java
deleted file mode 100644
index d44050f..0000000
--- a/tests/tests/app/src/android/app/cts/AliasActivityTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.AliasActivity;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.Intent;
-import android.test.InstrumentationTestCase;
-
-public class AliasActivityTest extends InstrumentationTestCase {
-
- private static final long SLEEP_TIME = 1000;
-
- public void testAliasActivity() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- new AliasActivity();
- }
- });
- getInstrumentation().waitForIdleSync();
- Context context = getInstrumentation().getTargetContext();
-
- Intent intent = new Intent();
- intent.setClass(context, AliasActivityStub.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- assertFalse(ChildActivity.isStarted);
- assertFalse(AliasActivityStub.isOnCreateCalled);
- context.startActivity(intent);
- Thread.sleep(SLEEP_TIME);
- assertTrue(AliasActivityStub.isOnCreateCalled);
- assertTrue(ChildActivity.isStarted);
- assertTrue(AliasActivityStub.isFinished);
- }
-
-}
diff --git a/tests/tests/app/src/android/app/cts/ApplicationTest.java b/tests/tests/app/src/android/app/cts/ApplicationTest.java
deleted file mode 100644
index 99cc8ba..0000000
--- a/tests/tests/app/src/android/app/cts/ApplicationTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.Activity;
-import android.app.Application;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.test.InstrumentationTestCase;
-
-/**
- * Test {@link Application}.
- */
-public class ApplicationTest extends InstrumentationTestCase {
-
- public void testApplication() throws Throwable {
- final Instrumentation instrumentation = getInstrumentation();
- final Context targetContext = instrumentation.getTargetContext();
-
- final Intent intent = new Intent(targetContext, MockApplicationActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- final Activity activity = instrumentation.startActivitySync(intent);
- final MockApplication mockApp = (MockApplication) activity.getApplication();
- assertTrue(mockApp.isConstructorCalled);
- assertTrue(mockApp.isOnCreateCalled);
-
- //skip if the device doesn't support both of portrait and landscape orientation screens.
- final PackageManager pm = targetContext.getPackageManager();
- if(!(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
- && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT))){
- return;
- }
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- OrientationTestUtils.toggleOrientation(activity);
- }
- });
- instrumentation.waitForIdleSync();
- assertTrue(mockApp.isOnConfigurationChangedCalled);
- }
-
-}
diff --git a/tests/tests/app/src/android/app/cts/DialogTest.java b/tests/tests/app/src/android/app/cts/DialogTest.java
deleted file mode 100755
index 4e8d588..0000000
--- a/tests/tests/app/src/android/app/cts/DialogTest.java
+++ /dev/null
@@ -1,937 +0,0 @@
-/*
- * 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.
- */
-package android.app.cts;
-
-import com.android.cts.app.stub.R;
-
-import android.app.Dialog;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnDismissListener;
-import android.content.DialogInterface.OnKeyListener;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.cts.util.PollingCheck;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.LinearLayout;
-
-import java.lang.ref.WeakReference;
-
-public class DialogTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
-
- protected static final long SLEEP_TIME = 200;
- private static final String STUB_ACTIVITY_PACKAGE = "com.android.cts.app.stub";
- private static final long TEST_TIMEOUT = 1000L;
-
- /**
- * please refer to Dialog
- */
- private static final int DISMISS = 0x43;
- private static final int CANCEL = 0x44;
-
- private boolean mCalledCallback;
- private boolean mIsKey0Listened;
- private boolean mIsKey1Listened;
- private boolean mOnCancelListenerCalled;
-
- private Instrumentation mInstrumentation;
- private Context mContext;
- private DialogStubActivity mActivity;
-
-
- public DialogTest() {
- super(STUB_ACTIVITY_PACKAGE, DialogStubActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mInstrumentation = getInstrumentation();
- mContext = mInstrumentation.getContext();
- }
-
- private void startDialogActivity(int dialogNumber) {
- mActivity = DialogStubActivity.startDialogActivity(this, dialogNumber);
- }
-
- @UiThreadTest
- public void testConstructor() {
- new Dialog(mContext);
- Dialog d = new Dialog(mContext, 0);
- // According to javadoc of constructors, it will set theme to system default theme,
- // when we set no theme id or set it theme id to 0.
- // But CTS can no assert dialog theme equals system internal theme.
-
- d = new Dialog(mContext, R.style.TextAppearance);
- TypedArray ta =
- d.getContext().getTheme().obtainStyledAttributes(R.styleable.TextAppearance);
- assertTextAppearanceStyle(ta);
-
- final Window w = d.getWindow();
- ta = w.getContext().getTheme().obtainStyledAttributes(R.styleable.TextAppearance);
- assertTextAppearanceStyle(ta);
- }
-
- public void testConstructor_protectedCancellable() {
- startDialogActivity(DialogStubActivity.TEST_PROTECTED_CANCELABLE);
- mActivity.onCancelListenerCalled = false;
- sendKeys(KeyEvent.KEYCODE_BACK);
- assertTrue(mActivity.onCancelListenerCalled);
- }
-
- public void testConstructor_protectedNotCancellable() {
- startDialogActivity(DialogStubActivity.TEST_PROTECTED_NOT_CANCELABLE);
- mActivity.onCancelListenerCalled = false;
- sendKeys(KeyEvent.KEYCODE_BACK);
- assertFalse(mActivity.onCancelListenerCalled);
- }
-
- private void assertTextAppearanceStyle(TypedArray ta) {
- final int defValue = -1;
- // get Theme and assert
- final Resources.Theme expected = mContext.getResources().newTheme();
- expected.setTo(mContext.getTheme());
- expected.applyStyle(R.style.TextAppearance, true);
- TypedArray expectedTa = expected.obtainStyledAttributes(R.styleable.TextAppearance);
- assertEquals(expectedTa.getIndexCount(), ta.getIndexCount());
- assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColor, defValue),
- ta.getColor(R.styleable.TextAppearance_textColor, defValue));
- assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColorHint, defValue),
- ta.getColor(R.styleable.TextAppearance_textColorHint, defValue));
- assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColorLink, defValue),
- ta.getColor(R.styleable.TextAppearance_textColorLink, defValue));
- assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColorHighlight, defValue),
- ta.getColor(R.styleable.TextAppearance_textColorHighlight, defValue));
- assertEquals(expectedTa.getDimension(R.styleable.TextAppearance_textSize, defValue),
- ta.getDimension(R.styleable.TextAppearance_textSize, defValue));
- assertEquals(expectedTa.getInt(R.styleable.TextAppearance_textStyle, defValue),
- ta.getInt(R.styleable.TextAppearance_textStyle, defValue));
- }
-
- public void testOnStartCreateStop(){
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
-
- assertTrue(d.isOnStartCalled);
- assertTrue(d.isOnCreateCalled);
-
- assertFalse(d.isOnStopCalled);
- sendKeys(KeyEvent.KEYCODE_BACK);
- assertTrue(d.isOnStopCalled);
- }
-
- public void testAccessOwnerActivity() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- Dialog d = mActivity.getDialog();
- assertNotNull(d);
- assertSame(mActivity, d.getOwnerActivity());
- d.setVolumeControlStream(d.getVolumeControlStream() + 1);
- assertEquals(d.getOwnerActivity().getVolumeControlStream() + 1, d.getVolumeControlStream());
-
- try {
- d.setOwnerActivity(null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
- }
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- Dialog dialog = new Dialog(mContext);
- assertNull(dialog.getOwnerActivity());
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testShow() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
- final View decor = d.getWindow().getDecorView();
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.hide();
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertEquals(View.GONE, decor.getVisibility());
- assertTrue(d.isShowing());
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.show();
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertEquals(View.VISIBLE, decor.getVisibility());
- assertTrue(d.isShowing());
- dialogDismiss(d);
- assertFalse(d.isShowing());
- }
-
- public void testOnSaveInstanceState() {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
-
- assertFalse(d.isOnSaveInstanceStateCalled);
- assertFalse(TestDialog.isOnRestoreInstanceStateCalled);
-
- //skip if the device doesn't support both of portrait and landscape orientation screens.
- final PackageManager pm = mContext.getPackageManager();
- if(!(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
- && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT))){
- return;
- }
-
- OrientationTestUtils.toggleOrientationSync(mActivity, mInstrumentation);
-
- assertTrue(d.isOnSaveInstanceStateCalled);
- assertTrue(TestDialog.isOnRestoreInstanceStateCalled);
- }
-
- public void testGetCurrentFocus() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
- assertNull(d.getCurrentFocus());
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.takeKeyEvents(true);
- d.setContentView(R.layout.alert_dialog_text_entry);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- sendKeys(KeyEvent.KEYCODE_0);
- // When mWindow is not null getCUrrentFocus is the view in dialog
- assertEquals(d.getWindow().getCurrentFocus(), d.getCurrentFocus());
- }
-
- public void testSetContentView() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
- assertNotNull(d);
-
- // set content view to a four elements layout
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.setContentView(R.layout.alert_dialog_text_entry);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- // check if four elements are right there
- assertNotNull(d.findViewById(R.id.username_view));
- assertNotNull(d.findViewById(R.id.username_edit));
- assertNotNull(d.findViewById(R.id.password_view));
- assertNotNull(d.findViewById(R.id.password_edit));
-
- final LayoutInflater inflate1 = d.getLayoutInflater();
-
- // set content view to a two elements layout
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.setContentView(inflate1.inflate(R.layout.alert_dialog_text_entry_2, null));
- }
- });
- mInstrumentation.waitForIdleSync();
-
- // check if only two elements are right there
- assertNotNull(d.findViewById(R.id.username_view));
- assertNotNull(d.findViewById(R.id.username_edit));
- assertNull(d.findViewById(R.id.password_view));
- assertNull(d.findViewById(R.id.password_edit));
-
- final WindowManager.LayoutParams lp = d.getWindow().getAttributes();
- final LayoutInflater inflate2 = mActivity.getLayoutInflater();
-
- // set content view to a four elements layout
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.setContentView(inflate2.inflate(R.layout.alert_dialog_text_entry, null), lp);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- // check if four elements are right there
- assertNotNull(d.findViewById(R.id.username_view));
- assertNotNull(d.findViewById(R.id.username_edit));
- assertNotNull(d.findViewById(R.id.password_view));
- assertNotNull(d.findViewById(R.id.password_edit));
-
- final WindowManager.LayoutParams lp2 = d.getWindow().getAttributes();
- final LayoutInflater inflate3 = mActivity.getLayoutInflater();
- lp2.height = ViewGroup.LayoutParams.WRAP_CONTENT;
- lp2.width = ViewGroup.LayoutParams.WRAP_CONTENT;
-
- // add a check box view
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.addContentView(inflate3.inflate(R.layout.checkbox_layout, null), lp2);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- // check if four elements are right there, and new add view there.
- assertNotNull(d.findViewById(R.id.check_box));
- assertNotNull(d.findViewById(R.id.username_view));
- assertNotNull(d.findViewById(R.id.username_edit));
- assertNotNull(d.findViewById(R.id.password_view));
- assertNotNull(d.findViewById(R.id.password_edit));
- }
-
- public void testSetTitle() {
- final String expectedTitle = "Test Dialog Without theme";
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
-
- assertNotNull(mActivity.getDialog());
- mActivity.setUpTitle(expectedTitle);
- mInstrumentation.waitForIdleSync();
-
- final Dialog d = mActivity.getDialog();
- assertEquals(expectedTitle, (String) d.getWindow().getAttributes().getTitle());
-
- mActivity.setUpTitle(R.string.hello_android);
- mInstrumentation.waitForIdleSync();
- assertEquals(mActivity.getResources().getString(R.string.hello_android),
- (String) d.getWindow().getAttributes().getTitle());
- }
-
- public void testOnKeyDownKeyUp() {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
- assertFalse(d.isOnKeyDownCalled);
- assertFalse(d.isOnKeyUpCalled);
-
- // send key 0 down and up events, onKeyDown return false
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
- assertTrue(d.isOnKeyDownCalled);
- assertTrue(d.isOnKeyUpCalled);
- assertEquals(KeyEvent.KEYCODE_0, d.keyDownCode);
- assertFalse(d.onKeyDownReturn);
-
- // send key back down and up events, onKeyDown return true
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- assertEquals(KeyEvent.KEYCODE_BACK, d.keyDownCode);
- assertTrue(d.onKeyDownReturn);
- }
-
- public void testOnKeyMultiple() {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
-
- assertNull(d.keyMultipleEvent);
- d.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_UNKNOWN));
- assertTrue(d.isOnKeyMultipleCalled);
- assertFalse(d.onKeyMultipleReturn);
- assertEquals(KeyEvent.KEYCODE_UNKNOWN, d.keyMultipleEvent.getKeyCode());
- assertEquals(KeyEvent.ACTION_MULTIPLE, d.keyMultipleEvent.getAction());
- }
-
- public void testTouchEvent() {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
-
- assertNull(d.onTouchEvent);
- assertNull(d.touchEvent);
- assertFalse(d.isOnTouchEventCalled);
-
- // Send a touch event outside the activity. The event will be ignored
- // because closeOnTouchOutside is false.
- d.setCanceledOnTouchOutside(false);
-
- long now = SystemClock.uptimeMillis();
- MotionEvent touchMotionEvent = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
- 1, getStatusBarHeight(), 0);
- mInstrumentation.sendPointerSync(touchMotionEvent);
-
- new PollingCheck(TEST_TIMEOUT) {
- protected boolean check() {
- return !d.dispatchTouchEventResult;
- }
- }.run();
-
- assertMotionEventEquals(touchMotionEvent, d.touchEvent);
-
- assertTrue(d.isOnTouchEventCalled);
- assertMotionEventEquals(touchMotionEvent, d.onTouchEvent);
- d.isOnTouchEventCalled = false;
- assertTrue(d.isShowing());
-
- // Watch activities cover the entire screen, so there is no way to touch outside.
- if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
- // Send a touch event outside the activity. This time the dialog will be dismissed
- // because closeOnTouchOutside is true.
- d.setCanceledOnTouchOutside(true);
-
- touchMotionEvent = MotionEvent.obtain(now, now + 1, MotionEvent.ACTION_DOWN,
- 1, getStatusBarHeight(), 0);
- mInstrumentation.sendPointerSync(touchMotionEvent);
-
- new PollingCheck(TEST_TIMEOUT) {
- protected boolean check() {
- return d.dispatchTouchEventResult;
- }
- }.run();
-
- assertMotionEventEquals(touchMotionEvent, d.touchEvent);
-
- assertTrue(d.isOnTouchEventCalled);
- assertMotionEventEquals(touchMotionEvent, d.onTouchEvent);
- assertFalse(d.isShowing());
- }
- }
-
- private int getStatusBarHeight() {
- final Rect rect = new Rect();
- Window window = mActivity.getWindow();
- window.getDecorView().getWindowVisibleDisplayFrame(rect);
- return rect.top;
- }
-
- public void testTrackballEvent() {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
- long eventTime = SystemClock.uptimeMillis();
- final MotionEvent trackBallEvent = MotionEvent.obtain(eventTime, eventTime,
- MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0);
-
- assertNull(d.trackballEvent);
- assertNull(d.onTrackballEvent);
-
- assertFalse(d.isOnTrackballEventCalled);
- mInstrumentation.sendTrackballEventSync(trackBallEvent);
- assertTrue(d.isOnTrackballEventCalled);
- assertMotionEventEquals(trackBallEvent, d.trackballEvent);
- assertMotionEventEquals(trackBallEvent, d.onTrackballEvent);
-
- }
-
- private void assertMotionEventEquals(final MotionEvent expected, final MotionEvent actual) {
- assertEquals(expected.getDownTime(), actual.getDownTime());
- assertEquals(expected.getEventTime(), actual.getEventTime());
- assertEquals(expected.getAction(), actual.getAction());
- assertEquals(expected.getMetaState(), actual.getMetaState());
- assertEquals(expected.getSize(), actual.getSize());
- // As MotionEvent doc says the value of X and Y coordinate may have
- // a fraction for input devices that are sub-pixel precise,
- // so we won't assert them here.
- }
-
- public void testOnWindowAttributesChanged() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
-
- assertTrue(d.isOnWindowAttributesChangedCalled);
- d.isOnWindowAttributesChangedCalled = false;
-
- final WindowManager.LayoutParams lp = d.getWindow().getAttributes();
- lp.setTitle("test OnWindowAttributesChanged");
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.getWindow().setAttributes(lp);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertTrue(d.isOnWindowAttributesChangedCalled);
- assertSame(lp, d.getWindow().getAttributes());
- }
-
- public void testOnContentChanged() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
- assertNotNull(d);
-
- assertFalse(d.isOnContentChangedCalled);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.setContentView(R.layout.alert_dialog_text_entry);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertTrue(d.isOnContentChangedCalled);
- }
-
- public void testOnWindowFocusChanged() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
- assertTrue(d.isOnWindowFocusChangedCalled);
- d.isOnWindowFocusChangedCalled = false;
-
- // show a new dialog, the new dialog get focus
- runTestOnUiThread(new Runnable() {
- public void run() {
- mActivity.showDialog(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- // Wait until TestDialog#OnWindowFocusChanged() is called
- new PollingCheck(TEST_TIMEOUT) {
- protected boolean check() {
- return d.isOnWindowFocusChangedCalled;
- }
- }.run();
- }
-
- public void testDispatchKeyEvent() {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
-
- sendKeys(KeyEvent.KEYCODE_0);
- assertFalse(d.dispatchKeyEventResult);
- assertEquals(KeyEvent.KEYCODE_0, d.keyEvent.getKeyCode());
-
- d.setOnKeyListener(new OnKeyListener() {
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- if (KeyEvent.ACTION_DOWN == event.getAction()) {
- if (KeyEvent.KEYCODE_0 == keyCode) {
- mIsKey0Listened = true;
- return true;
- }
-
- if (KeyEvent.KEYCODE_1 == keyCode) {
- mIsKey1Listened = true;
- return true;
- }
- }
-
- return false;
- }
- });
-
- mIsKey1Listened = false;
- sendKeys(KeyEvent.KEYCODE_1);
- assertTrue(mIsKey1Listened);
-
- mIsKey0Listened = false;
- sendKeys(KeyEvent.KEYCODE_0);
- assertTrue(mIsKey0Listened);
- }
-
- /*
- * Test point
- * 1. registerForContextMenu() will OnCreateContextMenuListener on the view to this activity,
- * so onCreateContextMenu() will be called when it is time to show the context menu.
- * 2. Close context menu will make onPanelClosed to be called,
- * and onPanelClosed will calls through to the new onPanelClosed method.
- * 3. unregisterForContextMenu() will remove the OnCreateContextMenuListener on the view,
- * so onCreateContextMenu() will not be called when try to open context menu.
- * 4. Selected a item of context menu will make onMenuItemSelected() to be called,
- * and onMenuItemSelected will calls through to the new onContextItemSelected method.
- * 5. onContextMenuClosed is called whenever the context menu is being closed (either by
- * the user canceling the menu with the back/menu button, or when an item is selected).
- */
- public void testContextMenu() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
- final LinearLayout parent = new LinearLayout(mContext);
- final MockView v = new MockView(mContext);
- parent.addView(v);
- assertFalse(v.isShowContextMenuCalled);
- // Register for context menu and open it
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.addContentView(parent, new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- d.registerForContextMenu(v);
- d.openContextMenu(v);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertTrue(v.isShowContextMenuCalled);
- assertTrue(d.isOnCreateContextMenuCalled);
-
- assertFalse(d.isOnPanelClosedCalled);
- assertFalse(d.isOnContextMenuClosedCalled);
- // Closed context menu
- sendKeys(KeyEvent.KEYCODE_BACK);
- assertTrue(d.isOnPanelClosedCalled);
- // Here isOnContextMenuClosedCalled should be true, see bug 1716918.
- assertFalse(d.isOnContextMenuClosedCalled);
-
- v.isShowContextMenuCalled = false;
- d.isOnCreateContextMenuCalled = false;
- // Unregister for context menu, and try to open it
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.unregisterForContextMenu(v);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.openContextMenu(v);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertTrue(v.isShowContextMenuCalled);
- assertFalse(d.isOnCreateContextMenuCalled);
-
- // Register for context menu and open it again
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.registerForContextMenu(v);
- d.openContextMenu(v);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertFalse(d.isOnContextItemSelectedCalled);
- assertFalse(d.isOnMenuItemSelectedCalled);
- d.isOnPanelClosedCalled = false;
- assertFalse(d.isOnContextMenuClosedCalled);
- // select a context menu item
- sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
- assertTrue(d.isOnMenuItemSelectedCalled);
- // Here isOnContextItemSelectedCalled should be true, see bug 1716918.
- assertFalse(d.isOnContextItemSelectedCalled);
- assertTrue(d.isOnPanelClosedCalled);
- // Here isOnContextMenuClosedCalled should be true, see bug 1716918.
- assertFalse(d.isOnContextMenuClosedCalled);
- }
-
- public void testOnSearchRequested() {
- }
-
- public void testTakeKeyEvents() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
- final View v = d.getWindow().getDecorView();
- assertNull(d.getCurrentFocus());
- takeKeyEvents(d, true);
- assertTrue(v.isFocusable());
- sendKeys(KeyEvent.KEYCODE_0);
- assertEquals(KeyEvent.KEYCODE_0, d.keyEvent.getKeyCode());
- d.keyEvent = null;
-
- takeKeyEvents(d, false);
- assertNull(d.getCurrentFocus());
- assertFalse(v.isFocusable());
- sendKeys(KeyEvent.KEYCODE_0);
- // d.keyEvent should be null
- }
-
- private void takeKeyEvents(final Dialog d, final boolean get) throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.takeKeyEvents(get);
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testRequestWindowFeature() {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- // called requestWindowFeature at TestDialog onCreate method
- assertTrue(((TestDialog) mActivity.getDialog()).isRequestWindowFeature);
- }
-
- public void testSetFeatureDrawableResource() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mActivity.getDialog().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
- R.drawable.robot);
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testSetFeatureDrawableUri() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mActivity.getDialog().setFeatureDrawableUri(Window.FEATURE_LEFT_ICON,
- Uri.parse("http://www.google.com"));
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testSetFeatureDrawable() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mActivity.getDialog().setFeatureDrawable(Window.FEATURE_LEFT_ICON,
- new MockDrawable());
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testSetFeatureDrawableAlpha() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mActivity.getDialog().setFeatureDrawableAlpha(Window.FEATURE_LEFT_ICON, 0);
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- public void testGetLayoutInflater() {
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
- assertEquals(d.getWindow().getLayoutInflater(), d.getLayoutInflater());
- }
-
- public void testSetCancelable_true() {
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
-
- d.setCancelable(true);
- assertTrue(d.isShowing());
- sendKeys(KeyEvent.KEYCODE_BACK);
- assertFalse(d.isShowing());
- }
-
- public void testSetCancellable_false() {
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
-
- d.setCancelable(false);
- assertTrue(d.isShowing());
- sendKeys(KeyEvent.KEYCODE_BACK);
- assertTrue(d.isShowing());
- }
-
- /*
- * Test point
- * 1. Cancel the dialog.
- * 2. Set a listener to be invoked when the dialog is canceled.
- */
- public void testCancel_listener() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
-
- assertTrue(d.isShowing());
- mOnCancelListenerCalled = false;
- d.setOnCancelListener(new OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- mOnCancelListenerCalled = true;
- }
- });
- dialogCancel(d);
-
- assertFalse(d.isShowing());
- assertTrue(mOnCancelListenerCalled);
- }
-
- public void testCancel_noListener() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
-
- assertTrue(d.isShowing());
- mOnCancelListenerCalled = false;
- d.setOnCancelListener(null);
- dialogCancel(d);
-
- assertFalse(d.isShowing());
- assertFalse(mOnCancelListenerCalled);
- }
-
- public void testSetCancelMessage() throws Exception {
- mCalledCallback = false;
- startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
- final TestDialog d = (TestDialog) mActivity.getDialog();
- final HandlerThread ht = new HandlerThread("DialogTest");
- ht.start();
-
- d.setCancelMessage(new MockDismissCancelHandler(d, ht.getLooper()).obtainMessage(CANCEL,
- new OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- mCalledCallback = true;
- }
- }));
- assertTrue(d.isShowing());
- assertFalse(mCalledCallback);
- sendKeys(KeyEvent.KEYCODE_BACK);
- assertTrue(mCalledCallback);
- assertFalse(d.isShowing());
-
- ht.join(100);
- }
-
- /*
- * Test point
- * 1. Set a listener to be invoked when the dialog is dismissed.
- * 2. set onDismissListener to null, it will not changed flag after dialog dismissed.
- */
- public void testSetOnDismissListener_listener() throws Throwable {
- mCalledCallback = false;
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
-
- d.setOnDismissListener(new OnDismissListener() {
- public void onDismiss(DialogInterface dialog) {
- mCalledCallback = true;
- }
- });
-
- assertTrue(d.isShowing());
- assertFalse(mCalledCallback);
- dialogDismiss(d);
- assertTrue(mCalledCallback);
- assertFalse(d.isShowing());
- }
-
- public void testSetOnDismissListener_noListener() throws Throwable {
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
- assertTrue(d.isShowing());
- mCalledCallback = false;
- d.setOnDismissListener(null);
- dialogDismiss(d);
- assertFalse(mCalledCallback);
- assertFalse(d.isShowing());
- }
-
- public void testSetDismissMessage() throws Throwable {
- mCalledCallback = false;
- startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
- final Dialog d = mActivity.getDialog();
-
- final HandlerThread ht = new HandlerThread("DialogTest");
- ht.start();
-
- d.setDismissMessage(new MockDismissCancelHandler(d, ht.getLooper()).obtainMessage(DISMISS,
- new OnDismissListener() {
- public void onDismiss(DialogInterface dialog) {
- mCalledCallback = true;
- }
- }));
- assertTrue(d.isShowing());
- assertFalse(mCalledCallback);
- dialogDismiss(d);
- ht.join(100);
- assertTrue(mCalledCallback);
- assertFalse(d.isShowing());
- }
-
- private void dialogDismiss(final Dialog d) throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.dismiss();
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- private void dialogCancel(final Dialog d) throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.cancel();
- }
- });
- mInstrumentation.waitForIdleSync();
- }
-
- private static class MockDismissCancelHandler extends Handler {
- private WeakReference<DialogInterface> mDialog;
-
- public MockDismissCancelHandler(Dialog dialog, Looper looper) {
- super(looper);
-
- mDialog = new WeakReference<DialogInterface>(dialog);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case DISMISS:
- ((OnDismissListener) msg.obj).onDismiss(mDialog.get());
- break;
- case CANCEL:
- ((OnCancelListener) msg.obj).onCancel(mDialog.get());
- break;
- }
- }
- }
-
- private static class MockDrawable extends Drawable {
- @Override
- public void draw(Canvas canvas) {
- }
-
- @Override
- public int getOpacity() {
- return 0;
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- }
- }
-
- private static class MockView extends View {
- public boolean isShowContextMenuCalled;
- protected OnCreateContextMenuListener mOnCreateContextMenuListener;
-
- public MockView(Context context) {
- super(context);
- }
-
- public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
- super.setOnCreateContextMenuListener(l);
- mOnCreateContextMenuListener = l;
- }
-
- public OnCreateContextMenuListener getOnCreateContextMenuListener() {
- return mOnCreateContextMenuListener;
- }
-
- @Override
- public boolean showContextMenu() {
- isShowContextMenuCalled = true;
- return super.showContextMenu();
- }
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/ExpandableListActivityTest.java b/tests/tests/app/src/android/app/cts/ExpandableListActivityTest.java
deleted file mode 100644
index 9d97296..0000000
--- a/tests/tests/app/src/android/app/cts/ExpandableListActivityTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.ExpandableListActivity;
-import android.content.ComponentName;
-
-public class ExpandableListActivityTest extends ActivityTestsBase {
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mIntent.putExtra("component", new ComponentName(getContext(),
- ExpandableListTestActivity.class));
- }
-
- public void testSelect() {
- runLaunchpad(LaunchpadActivity.EXPANDLIST_SELECT);
- }
-
- public void testView() {
- runLaunchpad(LaunchpadActivity.EXPANDLIST_VIEW);
- }
-
- public void testCallback() {
- runLaunchpad(LaunchpadActivity.EXPANDLIST_CALLBACK);
- }
-}
\ No newline at end of file
diff --git a/tests/tests/app/src/android/app/cts/InstrumentationTest.java b/tests/tests/app/src/android/app/cts/InstrumentationTest.java
deleted file mode 100644
index 25403f3..0000000
--- a/tests/tests/app/src/android/app/cts/InstrumentationTest.java
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * 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.cts;
-
-import com.android.cts.app.stub.R;
-
-import android.app.Activity;
-import android.app.Application;
-import android.app.Instrumentation;
-import android.app.Instrumentation.ActivityMonitor;
-import android.app.Instrumentation.ActivityResult;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.graphics.Point;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Debug;
-import android.os.IBinder;
-import android.os.SystemClock;
-import android.test.InstrumentationTestCase;
-import android.test.UiThreadTest;
-import android.view.InputQueue;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.SurfaceHolder;
-import android.view.View;
-import android.view.Window;
-import android.view.ViewGroup.LayoutParams;
-
-import java.util.List;
-
-public class InstrumentationTest extends InstrumentationTestCase {
-
- private static final int WAIT_TIME = 1000;
- private Instrumentation mInstrumentation;
- private InstrumentationTestActivity mActivity;
- private Intent mIntent;
- private boolean mRunOnMainSyncResult;
- private Context mContext;
- private MockActivity mMockActivity;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mInstrumentation = getInstrumentation();
- mContext = mInstrumentation.getTargetContext();
- mIntent = new Intent(mContext, InstrumentationTestActivity.class);
- mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mActivity = (InstrumentationTestActivity) mInstrumentation.startActivitySync(mIntent);
- }
-
- protected void tearDown() throws Exception {
- mInstrumentation = null;
- mIntent = null;
- if (mActivity != null) {
- mActivity.finish();
- mActivity = null;
- }
- super.tearDown();
- }
-
- public void testConstructor() throws Exception {
- new Instrumentation();
- }
-
- public void testMonitor() throws Exception {
- if (mActivity != null)
- mActivity.finish();
- ActivityResult result = new ActivityResult(Activity.RESULT_OK, new Intent());
- ActivityMonitor monitor = new ActivityMonitor(
- InstrumentationTestActivity.class.getName(), result, false);
- mInstrumentation.addMonitor(monitor);
- Intent intent = new Intent(mContext, InstrumentationTestActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- Activity activity = mInstrumentation.waitForMonitorWithTimeout(monitor, WAIT_TIME);
- assertTrue(activity instanceof InstrumentationTestActivity);
- assertTrue(mInstrumentation.checkMonitorHit(monitor, 1));
- activity.finish();
-
- mInstrumentation.addMonitor(monitor);
- mInstrumentation.removeMonitor(monitor);
- Activity a = mInstrumentation.startActivitySync(intent);
- assertTrue(a instanceof InstrumentationTestActivity);
- activity = mInstrumentation.waitForMonitorWithTimeout(monitor, WAIT_TIME);
- assertNull(activity);
- a.finish();
-
- IntentFilter filter = new IntentFilter();
- ActivityMonitor am = mInstrumentation.addMonitor(filter, result, false);
- mContext.startActivity(intent);
- mInstrumentation.waitForIdleSync();
- activity = am.waitForActivity();
- assertTrue(activity instanceof InstrumentationTestActivity);
- activity.finish();
- mInstrumentation.removeMonitor(am);
- am = mInstrumentation
- .addMonitor(InstrumentationTestActivity.class.getName(), result, false);
- mContext.startActivity(intent);
- activity = am.waitForActivity();
- assertTrue(activity instanceof InstrumentationTestActivity);
- activity.finish();
- mInstrumentation.removeMonitor(am);
- }
-
- public void testCallActivityOnCreate() throws Throwable {
- mActivity.setOnCreateCalled(false);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mInstrumentation.callActivityOnCreate(mActivity, new Bundle());
- }
- });
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnCreateCalled());
- }
-
- public void testAllocCounting() throws Exception {
- mInstrumentation.startAllocCounting();
-
- Bundle b = mInstrumentation.getAllocCounts();
- assertTrue(b.size() > 0);
- b = mInstrumentation.getBinderCounts();
- assertTrue(b.size() > 0);
-
- int globeAllocCount = Debug.getGlobalAllocCount();
- int globeAllocSize = Debug.getGlobalAllocSize();
- int globeExternalAllCount = Debug.getGlobalExternalAllocCount();
- int globeExternalAllSize = Debug.getGlobalExternalAllocSize();
- int threadAllocCount = Debug.getThreadAllocCount();
-
- assertTrue(Debug.getGlobalAllocCount() >= globeAllocCount);
- assertTrue(Debug.getGlobalAllocSize() >= globeAllocSize);
- assertTrue(Debug.getGlobalExternalAllocCount() >= globeExternalAllCount);
- assertTrue(Debug.getGlobalExternalAllocSize() >= globeExternalAllSize);
- assertTrue(Debug.getThreadAllocCount() >= threadAllocCount);
-
- mInstrumentation.stopAllocCounting();
-
- globeAllocCount = Debug.getGlobalAllocCount();
- globeAllocSize = Debug.getGlobalAllocSize();
- globeExternalAllCount = Debug.getGlobalExternalAllocCount();
- globeExternalAllSize = Debug.getGlobalExternalAllocSize();
- threadAllocCount = Debug.getThreadAllocCount();
- assertEquals(globeAllocCount, Debug.getGlobalAllocCount());
- assertEquals(globeAllocSize, Debug.getGlobalAllocSize());
- assertEquals(globeExternalAllCount, Debug.getGlobalExternalAllocCount());
- assertEquals(globeExternalAllSize, Debug.getGlobalExternalAllocSize());
- assertEquals(threadAllocCount, Debug.getThreadAllocCount());
- }
-
- public void testSendTrackballEventSync() throws Exception {
- long now = SystemClock.uptimeMillis();
- MotionEvent orig = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
- 100, 100, 0);
- mInstrumentation.sendTrackballEventSync(orig);
- mInstrumentation.waitForIdleSync();
-
- MotionEvent motionEvent = mActivity.getMotionEvent();
- assertEquals(orig.getMetaState(), motionEvent.getMetaState());
- assertEquals(orig.getEventTime(), motionEvent.getEventTime());
- assertEquals(orig.getDownTime(), motionEvent.getDownTime());
- }
-
- public void testCallApplicationOnCreate() throws Exception {
- InstrumentationTestStub ca = new InstrumentationTestStub();
- mInstrumentation.callApplicationOnCreate(ca);
- assertTrue(ca.mIsOnCreateCalled);
- }
-
- public void testContext() throws Exception {
- Context c1 = mInstrumentation.getContext();
- Context c2 = mInstrumentation.getTargetContext();
- assertNotSame(c1.getPackageName(), c2.getPackageName());
- }
-
- public void testInvokeMenuActionSync() throws Exception {
- final int resId = R.id.goto_menu_id;
- if (mActivity.getWindow().hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
- mInstrumentation.invokeMenuActionSync(mActivity, resId, 0);
- mInstrumentation.waitForIdleSync();
-
- assertEquals(resId, mActivity.getMenuID());
- }
- }
-
- public void testCallActivityOnPostCreate() throws Throwable {
- mActivity.setOnPostCreate(false);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mInstrumentation.callActivityOnPostCreate(mActivity, new Bundle());
- }
- });
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnPostCreate());
- }
-
- public void testCallActivityOnNewIntent() throws Throwable {
- mActivity.setOnNewIntentCalled(false);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mInstrumentation.callActivityOnNewIntent(mActivity, null);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertTrue(mActivity.isOnNewIntentCalled());
- }
-
- public void testCallActivityOnResume() throws Throwable {
- mActivity.setOnResume(false);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mInstrumentation.callActivityOnResume(mActivity);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnResume());
- }
-
- public void testMisc() throws Exception {
- }
-
- public void testPerformanceSnapshot() throws Exception {
- mInstrumentation.setAutomaticPerformanceSnapshots();
- mInstrumentation.startPerformanceSnapshot();
- mInstrumentation.endPerformanceSnapshot();
- }
-
- public void testProfiling() throws Exception {
- // by default, profiling was disabled. but after set the handleProfiling attribute in the
- // manifest file for this Instrumentation to true, the profiling was also disabled.
- assertFalse(mInstrumentation.isProfiling());
-
- mInstrumentation.startProfiling();
- mInstrumentation.stopProfiling();
- }
-
- public void testInvokeContextMenuAction() throws Exception {
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mMockActivity = new MockActivity();
- }
- });
- mInstrumentation.waitForIdleSync();
- final int id = 1;
- final int flag = 2;
- mInstrumentation.invokeContextMenuAction(mMockActivity, id, flag);
- mInstrumentation.waitForIdleSync();
-
- assertEquals(id, mMockActivity.mWindow.mId);
- assertEquals(flag, mMockActivity.mWindow.mFlags);
- }
-
- public void testSendStringSync() {
- final String text = "abcd";
- mInstrumentation.sendStringSync(text);
- mInstrumentation.waitForIdleSync();
-
- List<KeyEvent> keyUpList = mActivity.getKeyUpList();
- List<KeyEvent> keyDownList = mActivity.getKeyDownList();
- assertEquals(text.length(), keyDownList.size());
- assertEquals(text.length(), keyUpList.size());
-
- KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
- KeyEvent[] keyEvents = kcm.getEvents(text.toCharArray());
-
- int i = 0;
- for (int j = 0; j < keyDownList.size(); j++) {
- assertEquals(keyEvents[i++].getKeyCode(), keyDownList.get(j).getKeyCode());
- assertEquals(keyEvents[i++].getKeyCode(), keyUpList.get(j).getKeyCode());
- }
- }
-
- public void testCallActivityOnSaveInstanceState() throws Throwable {
- final Bundle bundle = new Bundle();
- mActivity.setOnSaveInstanceState(false);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mInstrumentation.callActivityOnSaveInstanceState(mActivity, bundle);
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertTrue(mActivity.isOnSaveInstanceState());
- assertSame(bundle, mActivity.getBundle());
- }
-
- public void testSendPointerSync() throws Exception {
- mInstrumentation.waitForIdleSync();
- mInstrumentation.setInTouchMode(true);
-
- // Send a touch event to the middle of the activity.
- // We assume that the Activity is empty so there won't be anything in the middle
- // to handle the touch. Consequently the Activity should receive onTouchEvent
- // because nothing else handled it.
- Point size = new Point();
- mActivity.getWindowManager().getDefaultDisplay().getSize(size);
- final int x = size.x / 2;
- final int y = size.y / 2;
- long now = SystemClock.uptimeMillis();
- MotionEvent orig = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
- x, y, 0);
- mInstrumentation.sendPointerSync(orig);
-
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnTouchEventCalled());
- mActivity.setOnTouchEventCalled(false);
- }
-
- public void testGetComponentName() throws Exception {
- ComponentName com = getInstrumentation().getComponentName();
- assertNotNull(com.getPackageName());
- assertNotNull(com.getClassName());
- assertNotNull(com.getShortClassName());
- }
-
- public void testNewApplication() throws Exception {
- final String className = "android.app.cts.MockApplication";
- ClassLoader cl = getClass().getClassLoader();
-
- Application app = mInstrumentation.newApplication(cl, className, mContext);
- assertEquals(className, app.getClass().getName());
-
- app = Instrumentation.newApplication(MockApplication.class, mContext);
- assertEquals(className, app.getClass().getName());
- }
-
- public void testRunOnMainSync() throws Exception {
- mRunOnMainSyncResult = false;
- mInstrumentation.runOnMainSync(new Runnable() {
- public void run() {
- mRunOnMainSyncResult = true;
- }
- });
- mInstrumentation.waitForIdleSync();
- assertTrue(mRunOnMainSyncResult);
- }
-
- public void testCallActivityOnPause() throws Exception {
- mActivity.setOnPauseCalled(false);
- mInstrumentation.callActivityOnPause(mActivity);
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnPauseCalled());
- }
-
- public void testSendKeyDownUpSync() throws Exception {
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
- mInstrumentation.waitForIdleSync();
- assertEquals(1, mActivity.getKeyUpList().size());
- assertEquals(1, mActivity.getKeyDownList().size());
- assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyUpList().get(0).getKeyCode());
- assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyDownList().get(0).getKeyCode());
- }
-
- @UiThreadTest
- public void testNewActivity() throws Exception {
- Intent intent = new Intent();
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- ClassLoader cl = getClass().getClassLoader();
- Activity activity = mInstrumentation.newActivity(cl, InstrumentationTestActivity.class
- .getName(), intent);
- assertEquals(InstrumentationTestActivity.class.getName(), activity.getClass().getName());
- activity.finish();
- activity = null;
-
- intent = new Intent(mContext, InstrumentationTestActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- Activity father = new Activity();
- ActivityInfo info = new ActivityInfo();
-
- activity = mInstrumentation
- .newActivity(InstrumentationTestActivity.class, mContext, null, null, intent, info,
- InstrumentationTestActivity.class.getName(), father, null, null);
-
- assertEquals(father, activity.getParent());
- assertEquals(InstrumentationTestActivity.class.getName(), activity.getClass().getName());
- activity.finish();
- }
-
- public void testCallActivityOnStart() throws Exception {
- mActivity.setOnStart(false);
- mInstrumentation.callActivityOnStart(mActivity);
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnStart());
- }
-
- public void testWaitForIdle() throws Exception {
- MockRunnable mr = new MockRunnable();
- assertFalse(mr.isRunCalled());
- mInstrumentation.waitForIdle(mr);
- Thread.sleep(WAIT_TIME);
- assertTrue(mr.isRunCalled());
- }
-
- public void testSendCharacterSync() throws Exception {
- mInstrumentation.sendCharacterSync(KeyEvent.KEYCODE_0);
- mInstrumentation.waitForIdleSync();
- assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyDownCode());
- assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyUpCode());
- }
-
- public void testCallActivityOnRestart() throws Exception {
- mActivity.setOnRestart(false);
- mInstrumentation.callActivityOnRestart(mActivity);
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnRestart());
- }
-
- public void testCallActivityOnStop() throws Exception {
- mActivity.setOnStop(false);
- mInstrumentation.callActivityOnStop(mActivity);
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnStop());
- }
-
- public void testCallActivityOnUserLeaving() throws Exception {
- assertFalse(mActivity.isOnLeave());
- mInstrumentation.callActivityOnUserLeaving(mActivity);
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnLeave());
- }
-
- public void testCallActivityOnRestoreInstanceState() throws Exception {
- mActivity.setOnRestoreInstanceState(false);
- mInstrumentation.callActivityOnRestoreInstanceState(mActivity, new Bundle());
- mInstrumentation.waitForIdleSync();
- assertTrue(mActivity.isOnRestoreInstanceState());
- }
-
- public void testSendKeySync() throws Exception {
- KeyEvent key = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
- mInstrumentation.sendKeySync(key);
- mInstrumentation.waitForIdleSync();
- assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyDownCode());
- }
-
- private static class MockRunnable implements Runnable {
- private boolean mIsRunCalled ;
-
- public void run() {
- mIsRunCalled = true;
- }
-
- public boolean isRunCalled() {
- return mIsRunCalled;
- }
- }
-
- private class MockActivity extends Activity {
- MockWindow mWindow = new MockWindow(mContext);
-
- @Override
- public Window getWindow() {
- return mWindow;
- }
-
- private class MockWindow extends Window {
-
- public int mId;
- public int mFlags;
-
- public MockWindow(Context context) {
- super(context);
- }
-
- @Override
- public void addContentView(View view, LayoutParams params) {
- }
-
- @Override
- public void closeAllPanels() {
- }
-
- @Override
- public void closePanel(int featureId) {
- }
-
- @Override
- public View getCurrentFocus() {
- return null;
- }
-
- @Override
- public View getDecorView() {
- return null;
- }
-
- @Override
- public LayoutInflater getLayoutInflater() {
- return null;
- }
-
- @Override
- public int getVolumeControlStream() {
- return 0;
- }
-
- @Override
- public boolean isFloating() {
- return false;
- }
-
- @Override
- public boolean isShortcutKey(int keyCode, KeyEvent event) {
- return false;
- }
-
- @Override
- protected void onActive() {
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- }
-
- @Override
- public void openPanel(int featureId, KeyEvent event) {
- }
-
- public void alwaysReadCloseOnTouchAttr() {
- }
-
- @Override
- public View peekDecorView() {
- return null;
- }
-
- @Override
- public boolean performContextMenuIdentifierAction(int id, int flags) {
- mId = id;
- mFlags = flags;
- return false;
- }
-
- @Override
- public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
- return false;
- }
-
- @Override
- public boolean performPanelShortcut(int featureId, int keyCode,
- KeyEvent event, int flags) {
- return false;
- }
-
- @Override
- public void restoreHierarchyState(Bundle savedInstanceState) {
- }
-
- @Override
- public Bundle saveHierarchyState() {
- return null;
- }
-
- @Override
- public void setBackgroundDrawable(Drawable drawable) {
- }
-
- @Override
- public void setChildDrawable(int featureId, Drawable drawable) {
- }
-
- @Override
- public void setChildInt(int featureId, int value) {
- }
-
- @Override
- public void setContentView(int layoutResID) {
- }
-
- @Override
- public void setContentView(View view) {
- }
-
- @Override
- public void setContentView(View view, LayoutParams params) {
- }
-
- @Override
- public void setFeatureDrawable(int featureId, Drawable drawable) {
- }
-
- @Override
- public void setFeatureDrawableAlpha(int featureId, int alpha) {
- }
-
- @Override
- public void setFeatureDrawableResource(int featureId, int resId) {
- }
-
- @Override
- public void setFeatureDrawableUri(int featureId, Uri uri) {
- }
-
- @Override
- public void setFeatureInt(int featureId, int value) {
- }
-
- @Override
- public void setTitle(CharSequence title) {
- }
-
- @Override
- public void setTitleColor(int textColor) {
- }
-
- @Override
- public void setVolumeControlStream(int streamType) {
- }
-
- @Override
- public boolean superDispatchKeyEvent(KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean superDispatchTouchEvent(MotionEvent event) {
- return false;
- }
-
- @Override
- public boolean superDispatchTrackballEvent(MotionEvent event) {
- return false;
- }
-
- @Override
- public boolean superDispatchGenericMotionEvent(MotionEvent event) {
- return false;
- }
-
- @Override
- public void takeKeyEvents(boolean get) {
- }
-
- @Override
- public void togglePanel(int featureId, KeyEvent event) {
- }
-
- @Override
- public void invalidatePanelMenu(int featureId) {
- }
-
- @Override
- public void takeSurface(SurfaceHolder.Callback2 callback) {
- }
-
- @Override
- public void takeInputQueue(InputQueue.Callback queue) {
- }
-
- @Override
- public void setStatusBarColor(int color) {
- }
-
- @Override
- public int getStatusBarColor() {
- return 0;
- }
-
- @Override
- public void setNavigationBarColor(int color) {
- }
-
- @Override
- public int getNavigationBarColor() {
- return 0;
- }
- }
- }
-
- private static class InstrumentationTestStub extends Application {
- boolean mIsOnCreateCalled = false;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mIsOnCreateCalled = true;
- }
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java b/tests/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java
deleted file mode 100644
index 767142c..0000000
--- a/tests/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.cts;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.app.Instrumentation.ActivityMonitor;
-import android.app.Instrumentation.ActivityResult;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.test.InstrumentationTestCase;
-
-public class Instrumentation_ActivityMonitorTest extends InstrumentationTestCase {
-
- private static final long WAIT_TIMEOUT = 100;
-
- /**
- * check points:
- * 1 Constructor with blocking true and false
- * 2 waitForActivity with timeout and no timeout
- * 3 get info about ActivityMonitor
- */
- public void testActivityMonitor() throws Exception {
- ActivityResult result = new ActivityResult(Activity.RESULT_OK, new Intent());
- Instrumentation instrumentation = getInstrumentation();
- ActivityMonitor am = instrumentation.addMonitor(
- InstrumentationTestActivity.class.getName(), result, false);
- Context context = instrumentation.getTargetContext();
- Intent intent = new Intent(context, InstrumentationTestActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
- Activity lastActivity = am.getLastActivity();
- final long TIMEOUT_MSEC = 5000;
- long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
- while (lastActivity == null && System.currentTimeMillis() < timeout) {
- Thread.sleep(WAIT_TIMEOUT);
- lastActivity = am.getLastActivity();
- }
- Activity activity = am.waitForActivity();
- assertSame(activity, lastActivity);
- assertEquals(1, am.getHits());
- assertTrue(activity instanceof InstrumentationTestActivity);
- activity.finish();
- instrumentation.waitForIdleSync();
- context.startActivity(intent);
- timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
- activity = null;
- while (activity == null && System.currentTimeMillis() < timeout) {
- Thread.sleep(WAIT_TIMEOUT);
- activity = am.waitForActivityWithTimeout(WAIT_TIMEOUT);
- }
- assertNotNull(activity);
- activity.finish();
- instrumentation.removeMonitor(am);
-
- am = new ActivityMonitor(InstrumentationTestActivity.class.getName(), result, true);
- assertSame(result, am.getResult());
- assertTrue(am.isBlocking());
- IntentFilter which = new IntentFilter();
- am = new ActivityMonitor(which, result, false);
- assertSame(which, am.getFilter());
- assertFalse(am.isBlocking());
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/IntentServiceTest.java b/tests/tests/app/src/android/app/cts/IntentServiceTest.java
deleted file mode 100644
index 42c4730..0000000
--- a/tests/tests/app/src/android/app/cts/IntentServiceTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.cts;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.cts.util.PollingCheck;
-import android.os.IBinder;
-
-import java.util.concurrent.Callable;
-
-
-public class IntentServiceTest extends ActivityTestsBase {
-
- private Intent mIntent;
- private static final int TIMEOUT_MSEC = 30000;
- private boolean mConnected;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- IntentServiceStub.reset();
- mIntent = new Intent(mContext, IntentServiceStub.class);
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- mContext.stopService(mIntent);
- }
-
- public void testIntents() throws Throwable {
- final int value = 42;
- final int adds = 3;
-
- Intent addIntent = new Intent(mContext, IntentServiceStub.class);
-
- addIntent.setAction(IntentServiceStub.ISS_ADD);
- addIntent.putExtra(IntentServiceStub.ISS_VALUE, 42);
-
- for (int i = 0; i < adds; i++) {
- mContext.startService(addIntent);
- }
-
- PollingCheck.check("onHandleIntentCalled not called enough", TIMEOUT_MSEC,
- new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return IntentServiceStub.getOnHandleIntentCalledCount() == adds;
- }
- });
-
- PollingCheck.check("accumulator not correct", TIMEOUT_MSEC, new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return IntentServiceStub.getAccumulator() == adds * value;
- }
- });
-
- PollingCheck.check("onDestroyCalled not called", TIMEOUT_MSEC, new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return IntentServiceStub.isOnDestroyCalled();
- }
- });
- }
-
- public void testIntentServiceLifeCycle() throws Throwable {
- // start service
- mContext.startService(mIntent);
- new PollingCheck(TIMEOUT_MSEC) {
- protected boolean check() {
- return IntentServiceStub.getOnHandleIntentCalledCount() > 0;
- }
- }.run();
- assertTrue(IntentServiceStub.isOnCreateCalled());
- assertTrue(IntentServiceStub.isOnStartCalled());
-
- // bind service
- ServiceConnection conn = new TestConnection();
- mContext.bindService(mIntent, conn, Context.BIND_AUTO_CREATE);
- new PollingCheck(TIMEOUT_MSEC) {
- protected boolean check() {
- return mConnected;
- }
- }.run();
- assertTrue(IntentServiceStub.isOnBindCalled());
-
- // unbind service
- mContext.unbindService(conn);
- // stop service
- mContext.stopService(mIntent);
- IntentServiceStub.waitToFinish(TIMEOUT_MSEC);
- }
-
- private class TestConnection implements ServiceConnection {
-
- public void onServiceConnected(ComponentName name, IBinder service) {
- mConnected = true;
- }
-
- public void onServiceDisconnected(ComponentName name) {
- }
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/KeyguardManagerKeyguardLockTest.java b/tests/tests/app/src/android/app/cts/KeyguardManagerKeyguardLockTest.java
deleted file mode 100644
index 7a9f534..0000000
--- a/tests/tests/app/src/android/app/cts/KeyguardManagerKeyguardLockTest.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.KeyguardManager;
-import android.test.InstrumentationTestCase;
-
-public class KeyguardManagerKeyguardLockTest extends InstrumentationTestCase {
-
- public void testDisableKeyguard() {
- }
-
- public void testReenableKeyguard() {
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/KeyguardManagerTest.java b/tests/tests/app/src/android/app/cts/KeyguardManagerTest.java
deleted file mode 100644
index cb7cd4a..0000000
--- a/tests/tests/app/src/android/app/cts/KeyguardManagerTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.test.ActivityInstrumentationTestCase2;
-
-public class KeyguardManagerTest
- extends ActivityInstrumentationTestCase2<KeyguardManagerActivity> {
-
- private static final String TAG = "KeyguardManagerTest";
-
- public KeyguardManagerTest() {
- super("com.android.cts.app.stub", KeyguardManagerActivity.class);
- }
-
- public void testNewKeyguardLock() {
- final Context c = getInstrumentation().getContext();
- final KeyguardManager keyguardManager = (KeyguardManager) c.getSystemService(
- Context.KEYGUARD_SERVICE);
- final KeyguardManager.KeyguardLock keyLock = keyguardManager.newKeyguardLock(TAG);
- assertNotNull(keyLock);
- }
-
- public void testInKeyguardRestrictedInputMode() {
- }
-
- public void testExitKeyguardSecurely() {
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/LaunchTest.java b/tests/tests/app/src/android/app/cts/LaunchTest.java
deleted file mode 100644
index 26cdc20..0000000
--- a/tests/tests/app/src/android/app/cts/LaunchTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources.Theme;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.view.ContextMenu;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.WindowManager.LayoutParams;
-
-public class LaunchTest extends ActivityTestsBase {
-
- public void testClearTopWhilResumed() {
- mIntent.putExtra("component", new ComponentName(getContext(), ClearTop.class));
- mIntent.putExtra(ClearTop.WAIT_CLEAR_TASK, true);
- runLaunchpad(LaunchpadActivity.LAUNCH);
- }
-
- public void testClearTopInCreate() throws Exception {
- mIntent.putExtra("component", new ComponentName(getContext(), ClearTop.class));
- runLaunchpad(LaunchpadActivity.LAUNCH);
- }
-
- public void testForwardResult() {
- runLaunchpad(LaunchpadActivity.FORWARD_RESULT);
- }
-
- public void testLocalScreen() {
- mIntent.putExtra("component", new ComponentName(getContext(), LocalScreen.class));
- runLaunchpad(LaunchpadActivity.LAUNCH);
- }
-
- public void testColdScreen() {
- mIntent.putExtra("component", new ComponentName(getContext(), TestedScreen.class));
- runLaunchpad(LaunchpadActivity.LAUNCH);
- }
-
- public void testLocalActivity() {
- mIntent.putExtra("component", new ComponentName(getContext(), LocalActivity.class));
- runLaunchpad(LaunchpadActivity.LAUNCH);
- }
-
- public void testColdActivity() {
- mIntent.putExtra("component", new ComponentName(getContext(), TestedActivity.class));
- runLaunchpad(LaunchpadActivity.LAUNCH);
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/LauncherActivityTest.java b/tests/tests/app/src/android/app/cts/LauncherActivityTest.java
deleted file mode 100644
index 3eea0b7..0000000
--- a/tests/tests/app/src/android/app/cts/LauncherActivityTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.app.LauncherActivity;
-import android.app.LauncherActivity.ListItem;
-import android.content.Context;
-import android.content.Intent;
-import android.test.InstrumentationTestCase;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.view.KeyEvent;
-
-import java.util.List;
-
-public class LauncherActivityTest
- extends ActivityInstrumentationTestCase2<LauncherActivityStub> {
-
- private Instrumentation mInstrumentation;
- private LauncherActivityStub mActivity;
-
- public LauncherActivityTest() {
- super("com.android.cts.app.stub", LauncherActivityStub.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mInstrumentation = getInstrumentation();
- mActivity = getActivity();
- }
-
- public void testLaunchActivity() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- // Test getTargetIntent. LaunchActivity#getTargetIntent() just returns a Intent() instance
- // with no content, so we use LaunchActivityStub#getSuperIntent() to get the default Intent,
- // and create a new intent for other tests.
- assertNotNull(mActivity.getSuperIntent());
-
- // Test makeListItems. Make sure the size > 0. The sorted order is related to the sort
- // way, so it's mutable.
- final List<ListItem> list = mActivity.makeListItems();
- assertTrue(list.size() > 0);
-
- // There should be an activity(but with uncertain content) in position 0.
- assertNotNull(mActivity.intentForPosition(0));
- }
- });
- mInstrumentation.waitForIdleSync();
- // Test onListItemClick
- sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
- sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
- sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
- sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
- assertTrue(mActivity.isOnListItemClick);
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java b/tests/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java
deleted file mode 100644
index 2fdc8ec..0000000
--- a/tests/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.cts;
-
-import com.android.cts.app.stub.R;
-
-
-import android.app.LauncherActivity;
-import android.app.LauncherActivity.IconResizer;
-import android.graphics.drawable.Drawable;
-import android.test.ActivityInstrumentationTestCase2;
-
-public class LauncherActivity_IconResizerTest extends
- ActivityInstrumentationTestCase2<LauncherActivityStub> {
-
- private static final String PACKAGE = "com.android.cts.app.stub";
- private LauncherActivityStub mActivity;
-
- public LauncherActivity_IconResizerTest() {
- super(PACKAGE, LauncherActivityStub.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mActivity = getActivity();
- }
-
- public void testIconResizer() throws Throwable {
- final IconResizer ir = mActivity.new IconResizer();
- final Drawable d = mActivity.getResources().getDrawable(R.drawable.pass);
- assertNotNull(d);
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- Drawable thumbNail = ir.createIconThumbnail(d);
- assertNotNull(thumbNail);
- // The size of the thumbnail is defined by inner R resource file
- // whose details are not open.
- assertTrue(thumbNail.getIntrinsicHeight() > 0);
- assertTrue(thumbNail.getIntrinsicWidth() > 0);
- }
- });
- getInstrumentation().waitForIdleSync();
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/LauncherActivity_ListItemTest.java b/tests/tests/app/src/android/app/cts/LauncherActivity_ListItemTest.java
deleted file mode 100644
index 14ef831..0000000
--- a/tests/tests/app/src/android/app/cts/LauncherActivity_ListItemTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.cts;
-
-
-import android.app.LauncherActivity;
-import android.test.AndroidTestCase;
-
-public class LauncherActivity_ListItemTest extends AndroidTestCase {
- public void testConstructor() {
- // Test public constructor
- new LauncherActivity.ListItem();
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/LifecycleTest.java b/tests/tests/app/src/android/app/cts/LifecycleTest.java
deleted file mode 100644
index 5d2ded7..0000000
--- a/tests/tests/app/src/android/app/cts/LifecycleTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.
- */
-
-
-package android.app.cts;
-
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources.Theme;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.view.ContextMenu;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.WindowManager.LayoutParams;
-
-public class LifecycleTest extends ActivityTestsBase {
- private Intent mTopIntent;
- private Intent mTabIntent;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mTopIntent = mIntent;
- mTabIntent = new Intent(mContext, LaunchpadTabActivity.class);
- mTabIntent.putExtra("tab", new ComponentName(mContext, LaunchpadActivity.class));
- }
-
- public void testTabDialog() {
- mIntent = mTabIntent;
- runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG);
- }
-
- public void testDialog() {
- mIntent = mTopIntent;
- runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG);
- }
-
- public void testTabScreen() {
- mIntent = mTabIntent;
- runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN);
- }
-
- public void testScreen() {
- mIntent = mTopIntent;
- runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN);
- }
-
- public void testTabBasic() {
- mIntent = mTabIntent;
- runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC);
- }
-
- public void testBasic() {
- mIntent = mTopIntent;
- runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC);
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java b/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java
deleted file mode 100644
index db3baba..0000000
--- a/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.app.LocalActivityManager;
-import android.content.Intent;
-import android.cts.util.CTSResult;
-import android.test.InstrumentationTestCase;
-import android.test.UiThreadTest;
-
-public class LocalActivityManagerTest extends InstrumentationTestCase implements CTSResult {
-
- private Instrumentation mInstrumentation;
-
- private Sync mSync = new Sync();
- private static class Sync {
- public boolean mHasNotify;
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mInstrumentation = getInstrumentation();
- mSync = new Sync();
- }
-
- private void setupActivity(final String action) {
- final Intent intent = new Intent(mInstrumentation.getTargetContext(),
- LocalActivityManagerTestHelper.class);
- intent.setAction(action);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mInstrumentation.getTargetContext().startActivity(intent);
- }
-
- @UiThreadTest
- public void testConstructor() {
- new LocalActivityManager(new Activity(), true);
- new LocalActivityManager(new Activity(), false);
- new LocalActivityManager(null, false);
- new LocalActivityManager(null, true);
- }
-
- public void testDispatchResume() throws InterruptedException {
- LocalActivityManagerTestHelper.setResult(this);
- setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_RESUME);
- waitForResult();
- }
-
- private void waitForResult() throws InterruptedException {
- synchronized (mSync) {
- if (!mSync.mHasNotify) {
- mSync.wait();
- }
- }
- }
-
- public void testStartActivity() throws InterruptedException {
- LocalActivityManagerTestHelper.setResult(this);
- setupActivity(LocalActivityManagerTestHelper.ACTION_START_ACTIVITY);
- waitForResult();
- }
-
- public void testDispatchCreate() throws InterruptedException {
- LocalActivityManagerTestHelper.setResult(this);
- setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_CREATE);
- waitForResult();
- }
-
- public void testDispatchStop() throws InterruptedException {
- LocalActivityManagerTestHelper.setResult(this);
- setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_STOP);
- waitForResult();
- }
-
- public void testDispatchPauseTrue() throws InterruptedException {
- LocalActivityManagerTestHelper.setResult(this);
- setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_PAUSE_TRUE);
- waitForResult();
- }
-
- public void testDispatchPauseFalse() throws InterruptedException {
- LocalActivityManagerTestHelper.setResult(this);
- setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_PAUSE_FALSE);
- waitForResult();
- }
-
- public void testSaveInstanceState() throws InterruptedException {
- LocalActivityManagerTestHelper.setResult(this);
- setupActivity(LocalActivityManagerTestHelper.ACTION_SAVE_INSTANCE_STATE);
- waitForResult();
- }
-
- public void testDispatchDestroy() throws InterruptedException {
- LocalActivityManagerTestHelper.setResult(this);
- setupActivity(LocalActivityManagerTestHelper.ACTION_DISPATCH_DESTROY);
- waitForResult();
- }
-
- public void testRemoveAllActivities() throws InterruptedException {
- LocalActivityManagerTestHelper.setResult(this);
- setupActivity(LocalActivityManagerTestHelper.ACTION_REMOVE_ALL_ACTIVITY);
- waitForResult();
- }
-
- public void setResult(final int resultCode) {
- synchronized (mSync) {
- mSync.mHasNotify = true;
- mSync.notify();
- assertEquals(CTSResult.RESULT_OK, resultCode);
- }
- }
-
- public void setResult(Exception e) {
- setResult(CTSResult.RESULT_FAIL);
- }
-
-}
diff --git a/tests/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/tests/app/src/android/app/cts/NotificationManagerTest.java
deleted file mode 100644
index fbb3060..0000000
--- a/tests/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.Telephony.Threads;
-import android.service.notification.StatusBarNotification;
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-import com.android.cts.app.stub.R;
-
-
-public class NotificationManagerTest extends AndroidTestCase {
- final String TAG = NotificationManagerTest.class.getSimpleName();
- final boolean DEBUG = false;
-
- private NotificationManager mNotificationManager;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mNotificationManager = (NotificationManager) mContext.getSystemService(
- Context.NOTIFICATION_SERVICE);
- // clear the deck so that our getActiveNotifications results are predictable
- mNotificationManager.cancelAll();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- mNotificationManager.cancelAll();
- }
-
- public void testNotify() {
- mNotificationManager.cancelAll();
-
- final int id = 1;
- sendNotification(id, R.drawable.black);
- // test updating the same notification
- sendNotification(id, R.drawable.blue);
- sendNotification(id, R.drawable.yellow);
-
- // assume that sendNotification tested to make sure individual notifications were present
- StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
- for (StatusBarNotification sbn : sbns) {
- if (sbn.getId() != id) {
- fail("we got back other notifications besides the one we posted: "
- + sbn.getKey());
- }
- }
- }
-
- public void testCancel() {
- final int id = 9;
- sendNotification(id, R.drawable.black);
- mNotificationManager.cancel(id);
-
- if (!checkNotificationExistence(id, /*shouldExist=*/ false)) {
- fail("canceled notification was still alive, id=" + id);
- }
- }
-
- public void testCancelAll() {
- sendNotification(1, R.drawable.black);
- sendNotification(2, R.drawable.blue);
- sendNotification(3, R.drawable.yellow);
-
- if (DEBUG) {
- Log.d(TAG, "posted 3 notifications, here they are: ");
- StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
- for (StatusBarNotification sbn : sbns) {
- Log.d(TAG, " " + sbn);
- }
- Log.d(TAG, "about to cancel...");
- }
- mNotificationManager.cancelAll();
-
- StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
- assertTrue("notification list was not empty after cancelAll", sbns.length == 0);
- }
-
- private void sendNotification(final int id, final int icon) {
- final Intent intent = new Intent(Intent.ACTION_MAIN, Threads.CONTENT_URI);
-
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP
- | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- intent.setAction(Intent.ACTION_MAIN);
-
- final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
- final Notification notification = new Notification.Builder(mContext)
- .setSmallIcon(icon)
- .setWhen(System.currentTimeMillis())
- .setContentTitle("notify#" + id)
- .setContentText("This is #" + id + "notification ")
- .setContentIntent(pendingIntent)
- .build();
- mNotificationManager.notify(id, notification);
-
-
- if (!checkNotificationExistence(id, /*shouldExist=*/ true)) {
- fail("couldn't find posted notification id=" + id);
- }
- }
-
- private boolean checkNotificationExistence(int id, boolean shouldExist) {
- // notification is a bit asynchronous so it may take a few ms to appear in getActiveNotifications()
- // we will check for it for up to 200ms before giving up
- boolean found = false;
- for (int tries=3; tries-->0;) {
- final StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
- for (StatusBarNotification sbn : sbns) {
- if (sbn.getId() == id) {
- found = true;
- break;
- }
- }
- if (found == shouldExist) break;
- try {
- Thread.sleep(100);
- } catch (InterruptedException ex) {
- // pass
- }
- }
- return found == shouldExist;
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/NotificationTest.java b/tests/tests/app/src/android/app/cts/NotificationTest.java
deleted file mode 100644
index 6179922..0000000
--- a/tests/tests/app/src/android/app/cts/NotificationTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-import android.widget.RemoteViews;
-
-public class NotificationTest extends AndroidTestCase {
-
- private Notification mNotification;
- private Context mContext;
-
- private static final String TICKER_TEXT = "tickerText";
- private static final String CONTENT_TITLE = "contentTitle";
- private static final String CONTENT_TEXT = "contentText";
- private static final String URI_STRING = "uriString";
- private static final int TOLERANCE = 200;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mContext = getContext();
- mNotification = new Notification();
- }
-
- public void testConstructor() {
- mNotification = null;
- mNotification = new Notification();
- assertNotNull(mNotification);
- assertTrue(System.currentTimeMillis() - mNotification.when < TOLERANCE);
-
- mNotification = null;
- final int notificationTime = 200;
- mNotification = new Notification(0, TICKER_TEXT, notificationTime);
- assertEquals(notificationTime, mNotification.when);
- assertEquals(0, mNotification.icon);
- assertEquals(TICKER_TEXT, mNotification.tickerText);
- }
-
- public void testDescribeContents() {
- final int expected = 0;
- mNotification = new Notification();
- assertEquals(expected, mNotification.describeContents());
- }
-
- public void testWriteToParcel() {
- mNotification = new Notification();
- mNotification.icon = 0;
- mNotification.number = 1;
- final Intent intent = new Intent();
- final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
- mNotification.contentIntent = pendingIntent;
- final Intent deleteIntent = new Intent();
- final PendingIntent delPendingIntent = PendingIntent.getBroadcast(
- mContext, 0, deleteIntent, 0);
- mNotification.deleteIntent = delPendingIntent;
- mNotification.tickerText = TICKER_TEXT;
-
- final RemoteViews contentView = new RemoteViews(mContext.getPackageName(),
- android.R.layout.simple_list_item_1);
- mNotification.contentView = contentView;
- mNotification.defaults = 0;
- mNotification.flags = 0;
- final Uri uri = Uri.parse(URI_STRING);
- mNotification.sound = uri;
- mNotification.audioStreamType = 0;
- final long[] longArray = { 1l, 2l, 3l };
- mNotification.vibrate = longArray;
- mNotification.ledARGB = 0;
- mNotification.ledOnMS = 0;
- mNotification.ledOffMS = 0;
- mNotification.iconLevel = 0;
- Parcel parcel = Parcel.obtain();
- mNotification.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- // Test Notification(Parcel)
- Notification result = new Notification(parcel);
- assertEquals(mNotification.icon, result.icon);
- assertEquals(mNotification.when, result.when);
- assertEquals(mNotification.number, result.number);
- assertNotNull(result.contentIntent);
- assertNotNull(result.deleteIntent);
- assertEquals(mNotification.tickerText, result.tickerText);
- assertNotNull(result.contentView);
- assertEquals(mNotification.defaults, result.defaults);
- assertEquals(mNotification.flags, result.flags);
- assertNotNull(result.sound);
- assertEquals(mNotification.audioStreamType, result.audioStreamType);
- assertEquals(mNotification.vibrate[0], result.vibrate[0]);
- assertEquals(mNotification.vibrate[1], result.vibrate[1]);
- assertEquals(mNotification.vibrate[2], result.vibrate[2]);
- assertEquals(mNotification.ledARGB, result.ledARGB);
- assertEquals(mNotification.ledOnMS, result.ledOnMS);
- assertEquals(mNotification.ledOffMS, result.ledOffMS);
- assertEquals(mNotification.iconLevel, result.iconLevel);
-
- mNotification.contentIntent = null;
- parcel = Parcel.obtain();
- mNotification.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- result = new Notification(parcel);
- assertNull(result.contentIntent);
-
- mNotification.deleteIntent = null;
- parcel = Parcel.obtain();
- mNotification.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- result = new Notification(parcel);
- assertNull(result.deleteIntent);
-
- mNotification.tickerText = null;
- parcel = Parcel.obtain();
- mNotification.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- result = new Notification(parcel);
- assertNull(result.tickerText);
-
- mNotification.contentView = null;
- parcel = Parcel.obtain();
- mNotification.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- result = new Notification(parcel);
- assertNull(result.contentView);
-
- mNotification.sound = null;
- parcel = Parcel.obtain();
- mNotification.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- result = new Notification(parcel);
- assertNull(result.sound);
- }
-
- public void testBuilder() {
- final Intent intent = new Intent();
- final PendingIntent contentIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
- mNotification = new Notification.Builder(mContext)
- .setSmallIcon(1)
- .setContentTitle(CONTENT_TITLE)
- .setContentText(CONTENT_TEXT)
- .setContentIntent(contentIntent)
- .build();
- assertEquals(CONTENT_TEXT, mNotification.extras.getString(Notification.EXTRA_TEXT));
- assertEquals(CONTENT_TITLE, mNotification.extras.getString(Notification.EXTRA_TITLE));
- assertEquals(1, mNotification.icon);
- assertEquals(contentIntent, mNotification.contentIntent);
- assertNotNull(mNotification.contentView);
- }
-
- public void testToString() {
- mNotification = new Notification();
- assertNotNull(mNotification.toString());
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/PendingIntentTest.java b/tests/tests/app/src/android/app/cts/PendingIntentTest.java
deleted file mode 100644
index d2c1b31..0000000
--- a/tests/tests/app/src/android/app/cts/PendingIntentTest.java
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-
-public class PendingIntentTest extends AndroidTestCase {
-
- private static final int WAIT_TIME = 5000;
- private PendingIntent mPendingIntent;
- private Intent mIntent;
- private Context mContext;
- private boolean mFinishResult;
- private boolean mHandleResult;
- private String mResultAction;
- private PendingIntent.OnFinished mFinish;
- private boolean mLooperStart;
- private Looper mLooper;
- private Handler mHandler;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mContext = getContext();
- mFinish = new PendingIntent.OnFinished() {
- public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
- String resultData, Bundle resultExtras) {
- mFinishResult = true;
- if (intent != null) {
- mResultAction = intent.getAction();
- }
- }
- };
-
- new Thread() {
- @Override
- public void run() {
- Looper.prepare();
- mLooper = Looper.myLooper();
- mLooperStart = true;
- Looper.loop();
- }
- }.start();
- while (!mLooperStart) {
- Thread.sleep(50);
- }
- mHandler = new Handler(mLooper) {
- @Override
- public void dispatchMessage(Message msg) {
- mHandleResult = true;
- super.dispatchMessage(msg);
- }
-
- @Override
- public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
- mHandleResult = true;
- return super.sendMessageAtTime(msg, uptimeMillis);
- }
-
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- mHandleResult = true;
- }
- };
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- mLooper.quit();
- }
-
- public void testGetActivity() throws InterruptedException, CanceledException {
- PendingIntentStubActivity.status = PendingIntentStubActivity.INVALIDATE;
- mPendingIntent = null;
- mIntent = new Intent();
-
- mIntent.setClass(mContext, PendingIntentStubActivity.class);
- mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- assertEquals(mContext.getPackageName(), mPendingIntent.getTargetPackage());
-
- mPendingIntent.send();
-
- Thread.sleep(WAIT_TIME);
- assertNotNull(mPendingIntent);
- assertEquals(PendingIntentStubActivity.status, PendingIntentStubActivity.ON_CREATE);
-
- // test getActivity return null
- mPendingIntent.cancel();
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
- PendingIntent.FLAG_NO_CREATE);
- assertNull(mPendingIntent);
-
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
- PendingIntent.FLAG_ONE_SHOT);
-
- pendingIntentSendError(mPendingIntent);
- }
-
- private void pendingIntentSendError(PendingIntent pendingIntent) {
- try {
- // From the doc send function will throw CanceledException if the PendingIntent
- // is no longer allowing more intents to be sent through it. So here call it twice then
- // a CanceledException should be caught.
- mPendingIntent.send();
- mPendingIntent.send();
- fail("CanceledException expected, but not thrown");
- } catch (PendingIntent.CanceledException e) {
- // expected
- }
- }
-
- public void testGetBroadcast() throws InterruptedException, CanceledException {
- MockReceiver.sAction = null;
- mIntent = new Intent(MockReceiver.MOCKACTION);
- mIntent.setClass(mContext, MockReceiver.class);
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
-
- mPendingIntent.send();
-
- Thread.sleep(WAIT_TIME);
- assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
-
- // test getBroadcast return null
- mPendingIntent.cancel();
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
- PendingIntent.FLAG_NO_CREATE);
- assertNull(mPendingIntent);
-
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
- PendingIntent.FLAG_ONE_SHOT);
-
- pendingIntentSendError(mPendingIntent);
- }
-
- public void testGetService() throws InterruptedException, CanceledException {
- MockService.result = false;
- mIntent = new Intent();
- mIntent.setClass(mContext, MockService.class);
- mPendingIntent = PendingIntent.getService(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
-
- mPendingIntent.send();
-
- Thread.sleep(WAIT_TIME);
- assertTrue(MockService.result);
-
- // test getService return null
- mPendingIntent.cancel();
- mPendingIntent = PendingIntent.getService(mContext, 1, mIntent,
- PendingIntent.FLAG_NO_CREATE);
- assertNull(mPendingIntent);
-
- mPendingIntent = PendingIntent.getService(mContext, 1, mIntent,
- PendingIntent.FLAG_ONE_SHOT);
-
- pendingIntentSendError(mPendingIntent);
- }
-
- public void testCancel() throws CanceledException {
- mIntent = new Intent();
- mIntent.setClass(mContext, MockService.class);
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
-
- mPendingIntent.send();
-
- mPendingIntent.cancel();
- pendingIntentSendShouldFail(mPendingIntent);
- }
-
- private void pendingIntentSendShouldFail(PendingIntent pendingIntent) {
- try {
- pendingIntent.send();
- fail("CanceledException expected, but not thrown");
- } catch (CanceledException e) {
- // expected
- }
- }
-
- public void testSend() throws InterruptedException, CanceledException {
- MockReceiver.sAction = null;
- MockReceiver.sResultCode = -1;
- mIntent = new Intent();
- mIntent.setAction(MockReceiver.MOCKACTION);
- mIntent.setClass(mContext, MockReceiver.class);
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
-
- mPendingIntent.send();
-
- Thread.sleep(WAIT_TIME);
-
- // send function to send default code 0
- assertEquals(0, MockReceiver.sResultCode);
- assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
- mPendingIntent.cancel();
-
- pendingIntentSendShouldFail(mPendingIntent);
- }
-
- public void testSendWithParamInt() throws InterruptedException, CanceledException {
- mIntent = new Intent(MockReceiver.MOCKACTION);
- mIntent.setClass(mContext, MockReceiver.class);
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- MockReceiver.sResultCode = 0;
- MockReceiver.sAction = null;
- // send result code 1.
- mPendingIntent.send(1);
- Thread.sleep(WAIT_TIME);
- assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
-
- // assert the result code
- assertEquals(1, MockReceiver.sResultCode);
- assertEquals(mResultAction, null);
-
- mResultAction = null;
- MockReceiver.sResultCode = 0;
- // send result code 2
- mPendingIntent.send(2);
- Thread.sleep(WAIT_TIME);
-
- assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
-
- // assert the result code
- assertEquals(2, MockReceiver.sResultCode);
- assertEquals(MockReceiver.sAction, MockReceiver.MOCKACTION);
- assertNull(mResultAction);
- mPendingIntent.cancel();
- pendingIntentSendShouldFail(mPendingIntent);
- }
-
- public void testSendWithParamContextIntIntent() throws InterruptedException, CanceledException {
- mIntent = new Intent(MockReceiver.MOCKACTION);
- mIntent.setClass(mContext, MockReceiver.class);
-
- MockReceiver.sAction = null;
- MockReceiver.sResultCode = 0;
-
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
-
- mPendingIntent.send(mContext, 1, null);
- Thread.sleep(WAIT_TIME);
-
- assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
- assertEquals(1, MockReceiver.sResultCode);
- mPendingIntent.cancel();
-
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
- MockReceiver.sAction = null;
- MockReceiver.sResultCode = 0;
-
- mPendingIntent.send(mContext, 2, mIntent);
- Thread.sleep(WAIT_TIME);
- assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
- assertEquals(2, MockReceiver.sResultCode);
- mPendingIntent.cancel();
- }
-
- public void testSendWithParamIntOnFinishedHandler() throws InterruptedException,
- CanceledException {
- mIntent = new Intent(MockReceiver.MOCKACTION);
- mIntent.setClass(mContext, MockReceiver.class);
-
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
- mFinishResult = false;
- mHandleResult = false;
- MockReceiver.sAction = null;
- MockReceiver.sResultCode = 0;
-
- mPendingIntent.send(1, null, null);
- Thread.sleep(WAIT_TIME);
- assertFalse(mFinishResult);
- assertFalse(mHandleResult);
- assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
-
- // assert result code
- assertEquals(1, MockReceiver.sResultCode);
- mPendingIntent.cancel();
-
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
- mFinishResult = false;
- MockReceiver.sAction = null;
- MockReceiver.sResultCode = 0;
- mHandleResult = false;
-
- mPendingIntent.send(2, mFinish, null);
- Thread.sleep(WAIT_TIME);
- assertTrue(mFinishResult);
- assertFalse(mHandleResult);
- assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
-
- // assert result code
- assertEquals(2, MockReceiver.sResultCode);
- mPendingIntent.cancel();
-
- mHandleResult = false;
- mFinishResult = false;
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
- MockReceiver.sAction = null;
- mPendingIntent.send(3, mFinish, mHandler);
- Thread.sleep(WAIT_TIME);
- assertTrue(mHandleResult);
- assertTrue(mFinishResult);
- assertEquals(MockReceiver.MOCKACTION, MockReceiver.sAction);
-
- // assert result code
- assertEquals(3, MockReceiver.sResultCode);
- mPendingIntent.cancel();
- }
-
- public void testSendWithParamContextIntIntentOnFinishedHandler() throws InterruptedException,
- CanceledException {
- mIntent = new Intent(MockReceiver.MOCKACTION);
- mIntent.setAction(MockReceiver.MOCKACTION);
-
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
- mFinishResult = false;
- mResultAction = null;
- mHandleResult = false;
- mPendingIntent.send(mContext, 1, mIntent, null, null);
- Thread.sleep(WAIT_TIME);
- assertFalse(mFinishResult);
- assertFalse(mHandleResult);
- assertNull(mResultAction);
- mPendingIntent.cancel();
-
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
- mFinishResult = false;
- mResultAction = null;
- mHandleResult = false;
- mPendingIntent.send(mContext, 1, mIntent, mFinish, null);
- Thread.sleep(WAIT_TIME);
- assertTrue(mFinishResult);
- assertEquals(mResultAction, MockReceiver.MOCKACTION);
- assertFalse(mHandleResult);
- mPendingIntent.cancel();
-
- mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
- mFinishResult = false;
- mResultAction = null;
- mHandleResult = false;
- mPendingIntent.send(mContext, 1, mIntent, mFinish, mHandler);
- Thread.sleep(WAIT_TIME);
- assertTrue(mHandleResult);
- assertEquals(mResultAction, MockReceiver.MOCKACTION);
- assertTrue(mFinishResult);
- mPendingIntent.cancel();
- }
-
- public void testGetTargetPackage() {
- mIntent = new Intent();
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- assertEquals(mContext.getPackageName(), mPendingIntent.getTargetPackage());
- }
-
- public void testEquals() {
- mIntent = new Intent();
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
-
- PendingIntent target = PendingIntent.getActivity(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
-
- assertFalse(mPendingIntent.equals(target));
- assertFalse(mPendingIntent.hashCode() == target.hashCode());
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent, 1);
-
- target = PendingIntent.getActivity(mContext, 1, mIntent, 1);
- assertTrue(mPendingIntent.equals(target));
-
- mIntent = new Intent(MockReceiver.MOCKACTION);
- target = PendingIntent.getBroadcast(mContext, 1, mIntent, 1);
- assertFalse(mPendingIntent.equals(target));
- assertFalse(mPendingIntent.hashCode() == target.hashCode());
-
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent, 1);
- target = PendingIntent.getActivity(mContext, 1, mIntent, 1);
-
- assertTrue(mPendingIntent.equals(target));
- assertEquals(mPendingIntent.hashCode(), target.hashCode());
- }
-
- public void testDescribeContents() {
- mIntent = new Intent();
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- final int expected = 0;
- assertEquals(expected, mPendingIntent.describeContents());
- }
-
- public void testWriteToParcel() {
- mIntent = new Intent();
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- Parcel parcel = Parcel.obtain();
-
- mPendingIntent.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- PendingIntent pendingIntent = PendingIntent.CREATOR.createFromParcel(parcel);
- assertTrue(mPendingIntent.equals(pendingIntent));
- }
-
- public void testReadAndWritePendingIntentOrNullToParcel() {
- mIntent = new Intent();
- mPendingIntent = PendingIntent.getActivity(mContext, 1, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- assertNotNull(mPendingIntent.toString());
-
- Parcel parcel = Parcel.obtain();
- PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, parcel);
- parcel.setDataPosition(0);
- PendingIntent target = PendingIntent.readPendingIntentOrNullFromParcel(parcel);
- assertEquals(mPendingIntent, target);
- assertEquals(mPendingIntent.getTargetPackage(), target.getTargetPackage());
-
- mPendingIntent = null;
- parcel = Parcel.obtain();
- PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, parcel);
- target = PendingIntent.readPendingIntentOrNullFromParcel(parcel);
- assertNull(target);
- }
-
-}
diff --git a/tests/tests/app/src/android/app/cts/ProgressDialogTest.java b/tests/tests/app/src/android/app/cts/ProgressDialogTest.java
deleted file mode 100644
index b2037b6..0000000
--- a/tests/tests/app/src/android/app/cts/ProgressDialogTest.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.Instrumentation;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.view.KeyEvent;
-import android.view.Window;
-import android.widget.ProgressBar;
-
-/**
- * Test {@link ProgressDialog}.
- */
-public class ProgressDialogTest extends ActivityInstrumentationTestCase2<MockActivity> {
- private final CharSequence TITLE = "title";
- private final CharSequence MESSAGE = "message";
-
- private boolean mCanceled;
- private Drawable mDrawable;
- private Drawable mActualDrawableNull;
- private Drawable mActualDrawable;
- private ProgressBar mProgressBar;
- private int mProgress1;
- private int mProgress2;
-
- private Context mContext;
- private Instrumentation mInstrumentation;
- private MockActivity mActivity;
-
- public ProgressDialogTest() {
- super("com.android.cts.app.stub", MockActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mCanceled = false;
- mInstrumentation = getInstrumentation();
- mActivity = getActivity();
- mContext = mActivity;
- mDrawable = getActivity().getResources().getDrawable(
- com.android.cts.app.stub.R.drawable.yellow);
- }
-
- @UiThreadTest
- public void testProgressDialog1(){
- new ProgressDialog(mContext);
- }
-
- @UiThreadTest
- public void testProgressDialog2(){
- new ProgressDialog(mContext, com.android.cts.app.stub.R.style.Theme_AlertDialog);
- }
-
- @UiThreadTest
- public void testOnStartCreateStop() {
- MockProgressDialog pd = new MockProgressDialog(mContext);
-
- assertFalse(pd.mIsOnCreateCalled);
- assertFalse(pd.mIsOnStartCalled);
- pd.show();
- assertTrue(pd.mIsOnCreateCalled);
- assertTrue(pd.mIsOnStartCalled);
-
- assertFalse(pd.mIsOnStopCalled);
- pd.dismiss();
- assertTrue(pd.mIsOnStopCalled);
- }
-
- @UiThreadTest
- public void testShow1() {
- ProgressDialog.show(mContext, TITLE, MESSAGE);
- }
-
- @UiThreadTest
- public void testShow2() {
- ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, false);
-
- /*
- * note: the progress bar's style only supports indeterminate mode,
- * so can't change indeterminate
- */
- assertTrue(dialog.isIndeterminate());
-
- dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true);
- assertTrue(dialog.isIndeterminate());
- }
-
- public void testShow3() throws Throwable {
- final OnCancelListener cL = new OnCancelListener(){
- public void onCancel(DialogInterface dialog) {
- mCanceled = true;
- }
- };
-
- // cancelable is false
- runTestOnUiThread(new Runnable() {
- public void run() {
- ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, false);
-
- dialog.setOnCancelListener(cL);
- dialog.onBackPressed();
- dialog.dismiss();
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertFalse(mCanceled);
-
- // cancelable is true
- runTestOnUiThread(new Runnable() {
- public void run() {
- ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, true);
- assertFalse(mCanceled);
- dialog.setOnCancelListener(cL);
- dialog.onBackPressed();
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertTrue(mCanceled);
- }
-
- public void testShow4() throws Throwable {
- final OnCancelListener cL = new OnCancelListener(){
- public void onCancel(DialogInterface dialog) {
- mCanceled = true;
- }
- };
-
- // cancelable is false
- runTestOnUiThread(new Runnable() {
- public void run() {
- ProgressDialog dialog = ProgressDialog.show(
- mContext, TITLE, MESSAGE, true, false, cL);
-
- dialog.onBackPressed();
- dialog.dismiss();;
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertFalse(mCanceled);
-
- // cancelable is true
- runTestOnUiThread(new Runnable() {
- public void run() {
- ProgressDialog dialog = ProgressDialog.show(
- mContext, TITLE, MESSAGE, true, true, cL);
-
- assertFalse(mCanceled);
- dialog.onBackPressed();
- }
- });
- mInstrumentation.waitForIdleSync();
-
- assertTrue(mCanceled);
- }
-
- @UiThreadTest
- public void testAccessMax() {
- // progressDialog is null
- ProgressDialog progressDialog = buildDialog();
- progressDialog.setMax(2008);
- assertEquals(2008, progressDialog.getMax());
-
- // progressDialog is not null
- progressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
- progressDialog.setMax(2009);
- assertEquals(2009, progressDialog.getMax());
- }
-
- @UiThreadTest
- public void testAccessProgress() {
- // progressDialog is null
- ProgressDialog progressDialog = buildDialog();
- progressDialog.setProgress(11);
- assertEquals(11, progressDialog.getProgress());
-
- /* progressDialog is not null
- * note: the progress bar's style only supports indeterminate mode,
- * so can't change progress
- */
- progressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
- progressDialog.setProgress(12);
- assertEquals(0, progressDialog.getProgress());
- }
-
- @UiThreadTest
- public void testAccessSecondaryProgress() {
- // dialog is null
- ProgressDialog dialog = buildDialog();
- dialog.setSecondaryProgress(17);
- assertEquals(17, dialog.getSecondaryProgress());
-
- /* mProgress is not null
- * note: the progress bar's style only supports indeterminate mode,
- * so can't change secondary progress
- */
- dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
- dialog.setSecondaryProgress(18);
- assertEquals(0, dialog.getSecondaryProgress());
- }
-
- @UiThreadTest
- public void testSetIndeterminate() {
- // progress is null
- ProgressDialog dialog = buildDialog();
- dialog.setIndeterminate(true);
- assertTrue(dialog.isIndeterminate());
- dialog.setIndeterminate(false);
- assertFalse(dialog.isIndeterminate());
-
- /* mProgress is not null
- * note: the progress bar's style only supports indeterminate mode,
- * so can't change indeterminate
- */
- dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
- dialog.setIndeterminate(true);
- assertTrue(dialog.isIndeterminate());
- dialog.setIndeterminate(false);
- assertTrue(dialog.isIndeterminate());
- }
-
- @UiThreadTest
- public void testIncrementProgressBy() throws Throwable {
- ProgressDialog dialog = new ProgressDialog(mContext);
- dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- dialog.show();
- dialog.setProgress(10);
- mProgress1 = dialog.getProgress();
- dialog.incrementProgressBy(60);
- mProgress2 = dialog.getProgress();
- dialog.cancel();
-
- assertEquals(10, mProgress1);
- assertEquals(70, mProgress2);
- }
-
- @UiThreadTest
- public void testIncrementSecondaryProgressBy() throws Throwable {
- ProgressDialog dialog = new ProgressDialog(mContext);
- dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- dialog.show();
- dialog.setSecondaryProgress(10);
- mProgress1 = dialog.getSecondaryProgress();
- dialog.incrementSecondaryProgressBy(60);
- mProgress2 = dialog.getSecondaryProgress();
-
- assertEquals(10, mProgress1);
- assertEquals(70, mProgress2);
- }
-
- @UiThreadTest
- public void testSetProgressDrawable() throws Throwable {
- ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
- Window w = dialog.getWindow();
- ProgressBar progressBar = (ProgressBar) w.findViewById(android.R.id.progress);
-
- dialog.setProgressDrawable(mDrawable);
- mActualDrawable = progressBar.getProgressDrawable();
-
- dialog.setProgressDrawable(null);
- mActualDrawableNull = progressBar.getProgressDrawable();
- assertEquals(mDrawable, mActualDrawable);
- assertEquals(null, mActualDrawableNull);
- }
-
- @UiThreadTest
- public void testSetIndeterminateDrawable() throws Throwable {
- ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
- Window w = dialog.getWindow();
- mProgressBar = (ProgressBar) w.findViewById(android.R.id.progress);
-
- dialog.setIndeterminateDrawable(mDrawable);
- mActualDrawable = mProgressBar.getIndeterminateDrawable();
- assertEquals(mDrawable, mActualDrawable);
-
- dialog.setIndeterminateDrawable(null);
- mActualDrawableNull = mProgressBar.getIndeterminateDrawable();
- assertEquals(null, mActualDrawableNull);
- }
-
- @UiThreadTest
- public void testSetMessage() throws Throwable {
- ProgressDialog dialog = new ProgressDialog(mContext);
- dialog = new ProgressDialog(mContext);
- dialog.setMessage(MESSAGE);
- dialog.show();
- // dialog is not null
- dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
- dialog.setMessage("Chuck Norris");
- }
-
- @UiThreadTest
- public void testSetProgressStyle() throws Throwable {
- ProgressDialog dialog = new ProgressDialog(mContext);
- setProgressStyle(dialog, ProgressDialog.STYLE_HORIZONTAL);
- setProgressStyle(dialog, ProgressDialog.STYLE_SPINNER);
- setProgressStyle(dialog, 100);
- }
-
- private void setProgressStyle(ProgressDialog dialog, int style) {
- dialog.setProgressStyle(style);
- dialog.show();
- dialog.setProgress(10);
- dialog.setMax(100);
- }
-
- private static class MockProgressDialog extends ProgressDialog {
- public boolean mIsOnStopCalled;
- public boolean mIsOnStartCalled;
- public boolean mIsOnCreateCalled;
-
- public MockProgressDialog(Context context) {
- super(context);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mIsOnCreateCalled = true;
- }
-
- @Override
- public void onStart(){
- super.onStart();
- mIsOnStartCalled = true;
- }
-
- @Override
- public void onStop() {
- super.onStop();
- mIsOnStopCalled = true;
- }
- }
-
- private ProgressDialog buildDialog() {
- return new ProgressDialog(mContext);
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/SearchManagerTest.java b/tests/tests/app/src/android/app/cts/SearchManagerTest.java
deleted file mode 100644
index 1cece76..0000000
--- a/tests/tests/app/src/android/app/cts/SearchManagerTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.content.Intent;
-import android.cts.util.CTSResult;
-
-public class SearchManagerTest extends CTSActivityTestCaseBase {
-
- private void setupActivity(String action) {
- Intent intent = new Intent();
- intent.setAction(action);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setClass(getInstrumentation().getTargetContext(), SearchManagerStubActivity.class);
- getInstrumentation().getTargetContext().startActivity(intent);
- }
-
- public void testStopSearch() throws InterruptedException {
- SearchManagerStubActivity.setCTSResult(this);
- setupActivity(SearchManagerStubActivity.TEST_STOP_SEARCH);
- waitForResult();
- }
-
- public void testSetOnDismissListener() throws InterruptedException {
- SearchManagerStubActivity.setCTSResult(this);
- setupActivity(SearchManagerStubActivity.TEST_ON_DISMISSLISTENER);
- waitForResult();
- }
-
- public void testSetOnCancelListener() throws InterruptedException {
- SearchManagerStubActivity.setCTSResult(this);
- setupActivity(SearchManagerStubActivity.TEST_ON_CANCELLISTENER);
- waitForResult();
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/ServiceTest.java b/tests/tests/app/src/android/app/cts/ServiceTest.java
deleted file mode 100644
index 8ba1816..0000000
--- a/tests/tests/app/src/android/app/cts/ServiceTest.java
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.cts.util.IBinderParcelable;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.RemoteException;
-import android.test.suitebuilder.annotation.MediumTest;
-
-public class ServiceTest extends ActivityTestsBase {
- private static final int STATE_START_1 = 0;
- private static final int STATE_START_2 = 1;
- private static final int STATE_UNBIND = 2;
- private static final int STATE_DESTROY = 3;
- private static final int STATE_REBIND = 4;
- private static final int STATE_UNBIND_ONLY = 5;
- private static final int DELAY = 5000;
- private static final
- String EXIST_CONN_TO_RECEIVE_SERVICE = "existing connection to receive service";
- private static final String EXIST_CONN_TO_LOSE_SERVICE = "existing connection to lose service";
- private int mExpectedServiceState;
- private Context mContext;
- private Intent mLocalService;
- private Intent mLocalDeniedService;
- private Intent mLocalGrantedService;
- private Intent mLocalService_ApplicationHasPermission;
- private Intent mLocalService_ApplicationDoesNotHavePermission;
-
- private IBinder mStateReceiver;
-
- private static class EmptyConnection implements ServiceConnection {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- }
- }
-
- private class TestConnection implements ServiceConnection {
- private final boolean mExpectDisconnect;
- private final boolean mSetReporter;
- private boolean mMonitor;
- private int mCount;
-
- public TestConnection(boolean expectDisconnect, boolean setReporter) {
- mExpectDisconnect = expectDisconnect;
- mSetReporter = setReporter;
- mMonitor = !setReporter;
- }
-
- void setMonitor(boolean v) {
- mMonitor = v;
- }
-
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- if (mSetReporter) {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(LocalService.SERVICE_LOCAL);
- data.writeStrongBinder(mStateReceiver);
- try {
- service.transact(LocalService.SET_REPORTER_CODE, data, null, 0);
- } catch (RemoteException e) {
- finishBad("DeadObjectException when sending reporting object");
- }
- data.recycle();
- }
-
- if (mMonitor) {
- mCount++;
- if (mExpectedServiceState == STATE_START_1) {
- if (mCount == 1) {
- finishGood();
- } else {
- finishBad("onServiceConnected() again on an object when it "
- + "should have been the first time");
- }
- } else if (mExpectedServiceState == STATE_START_2) {
- if (mCount == 2) {
- finishGood();
- } else {
- finishBad("onServiceConnected() the first time on an object "
- + "when it should have been the second time");
- }
- } else {
- finishBad("onServiceConnected() called unexpectedly");
- }
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- if (mMonitor) {
- if (mExpectedServiceState == STATE_DESTROY) {
- if (mExpectDisconnect) {
- finishGood();
- } else {
- finishBad("onServiceDisconnected() when it shouldn't have been");
- }
- } else {
- finishBad("onServiceDisconnected() called unexpectedly");
- }
- }
- }
- }
-
- private void startExpectResult(Intent service) {
- startExpectResult(service, new Bundle());
- }
-
- private void startExpectResult(Intent service, Bundle bundle) {
- bundle.putParcelable(LocalService.REPORT_OBJ_NAME, new IBinderParcelable(mStateReceiver));
-
- boolean success = false;
- try {
- mExpectedServiceState = STATE_START_1;
- mContext.startService(new Intent(service).putExtras(bundle));
- waitForResultOrThrow(DELAY, "service to start first time");
- mExpectedServiceState = STATE_START_2;
- mContext.startService(new Intent(service).putExtras(bundle));
- waitForResultOrThrow(DELAY, "service to start second time");
- success = true;
- } finally {
- if (!success) {
- mContext.stopService(service);
- }
- }
- mExpectedServiceState = STATE_DESTROY;
- mContext.stopService(service);
- waitForResultOrThrow(DELAY, "service to be destroyed");
- }
-
- /**
- * test the service lifecycle, a service can be used in two ways:
- * 1 It can be started and allowed to run until someone stops it or it stops itself.
- * In this mode, it's started by calling Context.startService()
- * and stopped by calling Context.stopService().
- * It can stop itself by calling Service.stopSelf() or Service.stopSelfResult().
- * Only one stopService() call is needed to stop the service,
- * no matter how many times startService() was called.
- * 2 It can be operated programmatically using an interface that it defines and exports.
- * Clients establish a connection to the Service object
- * and use that connection to call into the service.
- * The connection is established by calling Context.bindService(),
- * and is closed by calling Context.unbindService().
- * Multiple clients can bind to the same service.
- * If the service has not already been launched, bindService() can optionally launch it.
- */
- private void bindExpectResult(Intent service) {
- TestConnection conn = new TestConnection(true, false);
- TestConnection conn2 = new TestConnection(false, false);
- boolean success = false;
- try {
- // Expect to see the TestConnection connected.
- mExpectedServiceState = STATE_START_1;
- mContext.bindService(service, conn, 0);
- mContext.startService(service);
- waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE);
-
- // Expect to see the second TestConnection connected.
- mContext.bindService(service, conn2, 0);
- waitForResultOrThrow(DELAY, "new connection to receive service");
-
- mContext.unbindService(conn2);
- success = true;
- } finally {
- if (!success) {
- mContext.unbindService(conn);
- mContext.unbindService(conn2);
- mContext.stopService(service);
- }
- }
-
- // Expect to see the TestConnection disconnected.
- mExpectedServiceState = STATE_DESTROY;
- mContext.stopService(service);
- waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE);
-
- mContext.unbindService(conn);
-
- conn = new TestConnection(true, true);
- success = false;
- try {
- // Expect to see the TestConnection connected.
- conn.setMonitor(true);
- mExpectedServiceState = STATE_START_1;
- mContext.bindService(service, conn, 0);
- mContext.startService(service);
- waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE);
-
- success = true;
- } finally {
- if (!success) {
- mContext.unbindService(conn);
- mContext.stopService(service);
- }
- }
-
- // Expect to see the service unbind and then destroyed.
- conn.setMonitor(false);
- mExpectedServiceState = STATE_UNBIND;
- mContext.stopService(service);
- waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE);
-
- mContext.unbindService(conn);
-
- conn = new TestConnection(true, true);
- success = false;
- try {
- // Expect to see the TestConnection connected.
- conn.setMonitor(true);
- mExpectedServiceState = STATE_START_1;
- mContext.bindService(service, conn, 0);
- mContext.startService(service);
- waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE);
-
- success = true;
- } finally {
- if (!success) {
- mContext.unbindService(conn);
- mContext.stopService(service);
- }
- }
-
- // Expect to see the service unbind but not destroyed.
- conn.setMonitor(false);
- mExpectedServiceState = STATE_UNBIND_ONLY;
- mContext.unbindService(conn);
- waitForResultOrThrow(DELAY, "existing connection to unbind service");
-
- // Expect to see the service rebound.
- mExpectedServiceState = STATE_REBIND;
- mContext.bindService(service, conn, 0);
- waitForResultOrThrow(DELAY, "existing connection to rebind service");
-
- // Expect to see the service unbind and then destroyed.
- mExpectedServiceState = STATE_UNBIND;
- mContext.stopService(service);
- waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE);
-
- mContext.unbindService(conn);
- }
-
- /**
- * test automatically create the service as long as the binding exists
- * and disconnect from an application service
- */
- private void bindAutoExpectResult(Intent service) {
- TestConnection conn = new TestConnection(false, true);
- boolean success = false;
- try {
- conn.setMonitor(true);
- mExpectedServiceState = STATE_START_1;
- mContext.bindService(
- service, conn, Context.BIND_AUTO_CREATE);
- waitForResultOrThrow(DELAY, "connection to start and receive service");
- success = true;
- } finally {
- if (!success) {
- mContext.unbindService(conn);
- }
- }
- mExpectedServiceState = STATE_UNBIND;
- mContext.unbindService(conn);
- waitForResultOrThrow(DELAY, "disconnecting from service");
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mContext = getContext();
- mLocalService = new Intent(mContext, LocalService.class);
- mLocalDeniedService = new Intent(mContext, LocalDeniedService.class);
- mLocalGrantedService = new Intent(mContext, LocalGrantedService.class);
- mLocalService_ApplicationHasPermission = new Intent(
- LocalService.SERVICE_LOCAL_GRANTED, null /*uri*/, mContext, LocalService.class);
- mLocalService_ApplicationDoesNotHavePermission = new Intent(
- LocalService.SERVICE_LOCAL_DENIED, null /*uri*/, mContext, LocalService.class);
- mStateReceiver = new MockBinder();
- }
-
- private class MockBinder extends Binder {
- @Override
- protected boolean onTransact(int code, Parcel data, Parcel reply,
- int flags) throws RemoteException {
- if (code == LocalService.STARTED_CODE) {
- data.enforceInterface(LocalService.SERVICE_LOCAL);
- int count = data.readInt();
- if (mExpectedServiceState == STATE_START_1) {
- if (count == 1) {
- finishGood();
- } else {
- finishBad("onStart() again on an object when it "
- + "should have been the first time");
- }
- } else if (mExpectedServiceState == STATE_START_2) {
- if (count == 2) {
- finishGood();
- } else {
- finishBad("onStart() the first time on an object when it "
- + "should have been the second time");
- }
- } else {
- finishBad("onStart() was called when not expected (state="
- + mExpectedServiceState + ")");
- }
- return true;
- } else if (code == LocalService.DESTROYED_CODE) {
- data.enforceInterface(LocalService.SERVICE_LOCAL);
- if (mExpectedServiceState == STATE_DESTROY) {
- finishGood();
- } else {
- finishBad("onDestroy() was called when not expected (state="
- + mExpectedServiceState + ")");
- }
- return true;
- } else if (code == LocalService.UNBIND_CODE) {
- data.enforceInterface(LocalService.SERVICE_LOCAL);
- if (mExpectedServiceState == STATE_UNBIND) {
- mExpectedServiceState = STATE_DESTROY;
- } else if (mExpectedServiceState == STATE_UNBIND_ONLY) {
- finishGood();
- } else {
- finishBad("onUnbind() was called when not expected (state="
- + mExpectedServiceState + ")");
- }
- return true;
- } else if (code == LocalService.REBIND_CODE) {
- data.enforceInterface(LocalService.SERVICE_LOCAL);
- if (mExpectedServiceState == STATE_REBIND) {
- finishGood();
- } else {
- finishBad("onRebind() was called when not expected (state="
- + mExpectedServiceState + ")");
- }
- return true;
- } else {
- return super.onTransact(code, data, reply, flags);
- }
- }
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- mContext.stopService(mLocalService);
- mContext.stopService(mLocalGrantedService);
- mContext.stopService(mLocalService_ApplicationHasPermission);
- }
-
- public void testLocalStartClass() throws Exception {
- startExpectResult(mLocalService);
- }
-
- public void testLocalStartAction() throws Exception {
- startExpectResult(new Intent(
- LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class));
- }
-
- public void testLocalBindClass() throws Exception {
- bindExpectResult(mLocalService);
- }
-
- @MediumTest
- public void testLocalBindAction() throws Exception {
- bindExpectResult(new Intent(
- LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class));
- }
-
- @MediumTest
- public void testLocalBindAutoClass() throws Exception {
- bindAutoExpectResult(mLocalService);
- }
-
- @MediumTest
- public void testLocalBindAutoAction() throws Exception {
- bindAutoExpectResult(new Intent(
- LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class));
- }
-
- @MediumTest
- public void testLocalStartClassPermissions() throws Exception {
- startExpectResult(mLocalGrantedService);
- startExpectResult(mLocalDeniedService);
- }
-
- @MediumTest
- public void testLocalStartActionPermissions() throws Exception {
- startExpectResult(mLocalService_ApplicationHasPermission);
- startExpectResult(mLocalService_ApplicationDoesNotHavePermission);
- }
-
- @MediumTest
- public void testLocalBindClassPermissions() throws Exception {
- bindExpectResult(mLocalGrantedService);
- bindExpectResult(mLocalDeniedService);
- }
-
- @MediumTest
- public void testLocalBindActionPermissions() throws Exception {
- bindExpectResult(mLocalService_ApplicationHasPermission);
- bindExpectResult(mLocalService_ApplicationDoesNotHavePermission);
- }
-
- @MediumTest
- public void testLocalBindAutoClassPermissionGranted() throws Exception {
- bindAutoExpectResult(mLocalGrantedService);
- }
-
- @MediumTest
- public void testLocalBindAutoActionPermissionGranted() throws Exception {
- bindAutoExpectResult(mLocalService_ApplicationHasPermission);
- }
-
- @MediumTest
- public void testLocalUnbindTwice() throws Exception {
- EmptyConnection conn = new EmptyConnection();
- mContext.bindService(
- mLocalService_ApplicationHasPermission, conn, 0);
- mContext.unbindService(conn);
- try {
- mContext.unbindService(conn);
- fail("No exception thrown on the second unbind");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- @MediumTest
- public void testImplicitIntentFailsOnApiLevel21() throws Exception {
- Intent intent = new Intent(LocalService.SERVICE_LOCAL);
- EmptyConnection conn = new EmptyConnection();
- try {
- mContext.bindService(intent, conn, 0);
- mContext.unbindService(conn);
- fail("Implicit intents should be disallowed for apps targeting API 21+");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java
deleted file mode 100644
index 4e57d31..0000000
--- a/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright (C) 2010 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.ActivityManager;
-import android.app.Instrumentation;
-import android.app.WallpaperManager;
-import android.bluetooth.BluetoothAdapter;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.hardware.Camera;
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-import android.hardware.Camera.CameraInfo;
-import android.hardware.Camera.Parameters;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata;
-import android.location.LocationManager;
-import android.net.sip.SipManager;
-import android.net.wifi.WifiManager;
-import android.nfc.NfcAdapter;
-import android.telephony.TelephonyManager;
-import android.test.InstrumentationTestCase;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Test for checking that the {@link PackageManager} is reporting the correct features.
- */
-public class SystemFeaturesTest extends InstrumentationTestCase {
-
- private Context mContext;
- private PackageManager mPackageManager;
- private HashSet<String> mAvailableFeatures;
-
- private ActivityManager mActivityManager;
- private LocationManager mLocationManager;
- private SensorManager mSensorManager;
- private TelephonyManager mTelephonyManager;
- private WifiManager mWifiManager;
- private CameraManager mCameraManager;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- Instrumentation instrumentation = getInstrumentation();
- mContext = instrumentation.getTargetContext();
- mPackageManager = mContext.getPackageManager();
- mAvailableFeatures = new HashSet<String>();
- if (mPackageManager.getSystemAvailableFeatures() != null) {
- for (FeatureInfo feature : mPackageManager.getSystemAvailableFeatures()) {
- mAvailableFeatures.add(feature.name);
- }
- }
- mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
- mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
- mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
- mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
- }
-
- /**
- * Check for features improperly prefixed with "android." that are not defined in
- * {@link PackageManager}.
- */
- public void testFeatureNamespaces() throws IllegalArgumentException, IllegalAccessException {
- Set<String> officialFeatures = getFeatureConstantsNames("FEATURE_");
- assertFalse(officialFeatures.isEmpty());
-
- Set<String> notOfficialFeatures = new HashSet<String>(mAvailableFeatures);
- notOfficialFeatures.removeAll(officialFeatures);
-
- for (String featureName : notOfficialFeatures) {
- if (featureName != null) {
- assertFalse("Use a different namespace than 'android' for " + featureName,
- featureName.startsWith("android"));
- }
- }
- }
-
- public void testBluetoothFeature() {
- if (BluetoothAdapter.getDefaultAdapter() != null) {
- assertAvailable(PackageManager.FEATURE_BLUETOOTH);
- } else {
- assertNotAvailable(PackageManager.FEATURE_BLUETOOTH);
- }
- }
-
- public void testCameraFeatures() throws Exception {
- int numCameras = Camera.getNumberOfCameras();
- if (numCameras == 0) {
- assertNotAvailable(PackageManager.FEATURE_CAMERA);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_FRONT);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_ANY);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_LEVEL_FULL);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_CAPABILITY_RAW);
-
- assertFalse("Devices supporting external cameras must have a representative camera " +
- "connected for testing",
- mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
- } else {
- assertAvailable(PackageManager.FEATURE_CAMERA_ANY);
- checkFrontCamera();
- checkRearCamera();
- checkCamera2Features();
- }
- }
-
- private void checkCamera2Features() throws Exception {
- String[] cameraIds = mCameraManager.getCameraIdList();
- boolean fullCamera = false;
- boolean manualSensor = false;
- boolean manualPostProcessing = false;
- boolean raw = false;
- CameraCharacteristics[] cameraChars = new CameraCharacteristics[cameraIds.length];
- for (String cameraId : cameraIds) {
- CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId);
- Integer hwLevel = chars.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
- int[] capabilities = chars.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
- if (hwLevel == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) {
- fullCamera = true;
- }
- for (int capability : capabilities) {
- switch (capability) {
- case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR:
- manualSensor = true;
- break;
- case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING:
- manualPostProcessing = true;
- break;
- case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW:
- raw = true;
- break;
- default:
- // Capabilities don't have a matching system feature
- break;
- }
- }
- }
- assertFeature(fullCamera, PackageManager.FEATURE_CAMERA_LEVEL_FULL);
- assertFeature(manualSensor, PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR);
- assertFeature(manualPostProcessing,
- PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING);
- assertFeature(raw, PackageManager.FEATURE_CAMERA_CAPABILITY_RAW);
- }
-
- private void checkFrontCamera() {
- CameraInfo info = new CameraInfo();
- int numCameras = Camera.getNumberOfCameras();
- int frontCameraId = -1;
- for (int i = 0; i < numCameras; i++) {
- Camera.getCameraInfo(i, info);
- if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
- frontCameraId = i;
- }
- }
-
- if (frontCameraId > -1) {
- assertTrue("Device has front-facing camera but does not report either " +
- "the FEATURE_CAMERA_FRONT or FEATURE_CAMERA_EXTERNAL feature",
- mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
- mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
- } else {
- assertFalse("Device does not have front-facing camera but reports either " +
- "the FEATURE_CAMERA_FRONT or FEATURE_CAMERA_EXTERNAL feature",
- mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
- mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
- }
- }
-
- private void checkRearCamera() {
- Camera camera = null;
- try {
- camera = Camera.open();
- if (camera != null) {
- assertAvailable(PackageManager.FEATURE_CAMERA);
-
- Camera.Parameters params = camera.getParameters();
- if (params.getSupportedFocusModes().contains(Parameters.FOCUS_MODE_AUTO)) {
- assertAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
- } else {
- assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
- }
-
- if (params.getFlashMode() != null) {
- assertAvailable(PackageManager.FEATURE_CAMERA_FLASH);
- } else {
- assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
- }
- } else {
- assertNotAvailable(PackageManager.FEATURE_CAMERA);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
- }
- } finally {
- if (camera != null) {
- camera.release();
- }
- }
- }
-
- public void testLiveWallpaperFeature() {
- try {
- Intent intent = new Intent(WallpaperManager.ACTION_LIVE_WALLPAPER_CHOOSER);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- assertAvailable(PackageManager.FEATURE_LIVE_WALLPAPER);
- } catch (ActivityNotFoundException e) {
- assertNotAvailable(PackageManager.FEATURE_LIVE_WALLPAPER);
- }
- }
-
- public void testLocationFeatures() {
- if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
- assertAvailable(PackageManager.FEATURE_LOCATION);
- assertAvailable(PackageManager.FEATURE_LOCATION_GPS);
- } else {
- assertNotAvailable(PackageManager.FEATURE_LOCATION_GPS);
- }
-
- if (mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
- assertAvailable(PackageManager.FEATURE_LOCATION);
- assertAvailable(PackageManager.FEATURE_LOCATION_NETWORK);
- } else {
- assertNotAvailable(PackageManager.FEATURE_LOCATION_NETWORK);
- }
- }
-
- public void testNfcFeatures() {
- if (NfcAdapter.getDefaultAdapter(mContext) != null) {
- assertAvailable(PackageManager.FEATURE_NFC);
- assertAvailable(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
- } else {
- assertNotAvailable(PackageManager.FEATURE_NFC);
- }
- }
-
- public void testScreenFeatures() {
- assertTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
- || mPackageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT));
- }
-
- /**
- * Check that the sensor features reported by the PackageManager correspond to the sensors
- * returned by {@link SensorManager#getSensorList(int)}.
- */
- public void testSensorFeatures() throws Exception {
- Set<String> featuresLeft = getFeatureConstantsNames("FEATURE_SENSOR_");
-
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_ACCELEROMETER,
- Sensor.TYPE_ACCELEROMETER);
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_BAROMETER,
- Sensor.TYPE_PRESSURE);
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_COMPASS,
- Sensor.TYPE_MAGNETIC_FIELD);
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_GYROSCOPE,
- Sensor.TYPE_GYROSCOPE);
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_LIGHT,
- Sensor.TYPE_LIGHT);
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_PROXIMITY,
- Sensor.TYPE_PROXIMITY);
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_STEP_COUNTER,
- Sensor.TYPE_STEP_COUNTER);
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_STEP_DETECTOR,
- Sensor.TYPE_STEP_DETECTOR);
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_AMBIENT_TEMPERATURE,
- Sensor.TYPE_AMBIENT_TEMPERATURE);
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_RELATIVE_HUMIDITY,
- Sensor.TYPE_RELATIVE_HUMIDITY);
-
-
- /*
- * We have three cases to test for :
- * Case 1: Device does not have an HRM
- * FEATURE_SENSOR_HEART_RATE false
- * FEATURE_SENSOR_HEART_RATE_ECG false
- * assertFeatureForSensor(TYPE_HEART_RATE) false
- *
- * Case 2: Device has a PPG HRM
- * FEATURE_SENSOR_HEART_RATE true
- * FEATURE_SENSOR_HEART_RATE_ECG false
- * assertFeatureForSensor(TYPE_HEART_RATE) true
- *
- * Case 3: Device has an ECG HRM
- * FEATURE_SENSOR_HEART_RATE false
- * FEATURE_SENSOR_HEART_RATE_ECG true
- * assertFeatureForSensor(TYPE_HEART_RATE) true
- */
-
- if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG)) {
- /* Case 3 for FEATURE_SENSOR_HEART_RATE_ECG true case */
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
- Sensor.TYPE_HEART_RATE);
-
- /* Remove HEART_RATE from featuresLeft, no way to test that one */
- assertTrue("Features left " + featuresLeft + " to check did not include "
- + PackageManager.FEATURE_SENSOR_HEART_RATE,
- featuresLeft.remove(PackageManager.FEATURE_SENSOR_HEART_RATE));
- } else if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE)) {
- /* Case 1 & 2 for FEATURE_SENSOR_HEART_RATE_ECG false case */
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
- Sensor.TYPE_HEART_RATE);
-
- /* Case 1 & 3 for FEATURE_SENSOR_HEART_RATE false case */
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE,
- Sensor.TYPE_HEART_RATE);
- } else {
- /* Case 2 for FEATURE_SENSOR_HEART_RATE true case */
- assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE,
- Sensor.TYPE_HEART_RATE);
-
- /* Remove HEART_RATE_ECG from featuresLeft, no way to test that one */
- assertTrue("Features left " + featuresLeft + " to check did not include "
- + PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
- featuresLeft.remove(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG));
- }
-
- assertTrue("Assertions need to be added to this test for " + featuresLeft,
- featuresLeft.isEmpty());
- }
-
- /** Get a list of feature constants in PackageManager matching a prefix. */
- private static Set<String> getFeatureConstantsNames(String prefix)
- throws IllegalArgumentException, IllegalAccessException {
- Set<String> features = new HashSet<String>();
- Field[] fields = PackageManager.class.getFields();
- for (Field field : fields) {
- if (field.getName().startsWith(prefix)) {
- String feature = (String) field.get(null);
- features.add(feature);
- }
- }
- return features;
- }
-
- public void testSipFeatures() {
- if (SipManager.newInstance(mContext) != null) {
- assertAvailable(PackageManager.FEATURE_SIP);
- } else {
- assertNotAvailable(PackageManager.FEATURE_SIP);
- assertNotAvailable(PackageManager.FEATURE_SIP_VOIP);
- }
-
- if (SipManager.isApiSupported(mContext)) {
- assertAvailable(PackageManager.FEATURE_SIP);
- } else {
- assertNotAvailable(PackageManager.FEATURE_SIP);
- assertNotAvailable(PackageManager.FEATURE_SIP_VOIP);
- }
-
- if (SipManager.isVoipSupported(mContext)) {
- assertAvailable(PackageManager.FEATURE_SIP);
- assertAvailable(PackageManager.FEATURE_SIP_VOIP);
- } else {
- assertNotAvailable(PackageManager.FEATURE_SIP_VOIP);
- }
- }
-
- /**
- * Check that if the PackageManager declares a sensor feature that the device has at least
- * one sensor that matches that feature. Also check that if a PackageManager does not declare
- * a sensor that the device also does not have such a sensor.
- *
- * @param featuresLeft to check in order to make sure the test covers all sensor features
- * @param expectedFeature that the PackageManager may report
- * @param expectedSensorType that that {@link SensorManager#getSensorList(int)} may have
- */
- private void assertFeatureForSensor(Set<String> featuresLeft, String expectedFeature,
- int expectedSensorType) {
- assertTrue("Features left " + featuresLeft + " to check did not include "
- + expectedFeature, featuresLeft.remove(expectedFeature));
-
- boolean hasSensorFeature = mPackageManager.hasSystemFeature(expectedFeature);
-
- List<Sensor> sensors = mSensorManager.getSensorList(expectedSensorType);
- List<String> sensorNames = new ArrayList<String>(sensors.size());
- for (Sensor sensor : sensors) {
- sensorNames.add(sensor.getName());
- }
- boolean hasSensorType = !sensors.isEmpty();
-
- String message = "PackageManager#hasSystemFeature(" + expectedFeature + ") returns "
- + hasSensorFeature
- + " but SensorManager#getSensorList(" + expectedSensorType + ") shows sensors "
- + sensorNames;
-
- assertEquals(message, hasSensorFeature, hasSensorType);
- }
-
- /**
- * Check that the {@link TelephonyManager#getPhoneType()} matches the reported features.
- */
- public void testTelephonyFeatures() {
- int phoneType = mTelephonyManager.getPhoneType();
- switch (phoneType) {
- case TelephonyManager.PHONE_TYPE_GSM:
- assertAvailable(PackageManager.FEATURE_TELEPHONY);
- assertAvailable(PackageManager.FEATURE_TELEPHONY_GSM);
- break;
-
- case TelephonyManager.PHONE_TYPE_CDMA:
- assertAvailable(PackageManager.FEATURE_TELEPHONY);
- assertAvailable(PackageManager.FEATURE_TELEPHONY_CDMA);
- break;
-
- case TelephonyManager.PHONE_TYPE_NONE:
- assertNotAvailable(PackageManager.FEATURE_TELEPHONY);
- assertNotAvailable(PackageManager.FEATURE_TELEPHONY_CDMA);
- assertNotAvailable(PackageManager.FEATURE_TELEPHONY_GSM);
- break;
-
- default:
- throw new IllegalArgumentException("Did you add a new phone type? " + phoneType);
- }
- }
-
- public void testTouchScreenFeatures() {
- ConfigurationInfo configInfo = mActivityManager.getDeviceConfigurationInfo();
- if (configInfo.reqTouchScreen != Configuration.TOUCHSCREEN_NOTOUCH) {
- assertAvailable(PackageManager.FEATURE_TOUCHSCREEN);
- assertAvailable(PackageManager.FEATURE_FAKETOUCH);
- } else {
- assertNotAvailable(PackageManager.FEATURE_TOUCHSCREEN);
- }
-
- // TODO: Add tests for the other touchscreen features.
- }
-
- public void testUsbAccessory() {
- assertAvailable(PackageManager.FEATURE_USB_ACCESSORY);
- }
-
- public void testWifiFeature() throws Exception {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
- // no WiFi, skip the test
- return;
- }
- boolean enabled = mWifiManager.isWifiEnabled();
- try {
- // WifiManager is hard-coded to return true,
- // the case without WiFi is already handled,
- // so this case MUST have WiFi.
- if (mWifiManager.setWifiEnabled(true)) {
- assertAvailable(PackageManager.FEATURE_WIFI);
- }
- } finally {
- if (!enabled) {
- mWifiManager.setWifiEnabled(false);
- }
- }
- }
-
- private void assertAvailable(String feature) {
- assertTrue("PackageManager#hasSystemFeature should return true for " + feature,
- mPackageManager.hasSystemFeature(feature));
- assertTrue("PackageManager#getSystemAvailableFeatures should have " + feature,
- mAvailableFeatures.contains(feature));
- }
-
- private void assertNotAvailable(String feature) {
- assertFalse("PackageManager#hasSystemFeature should NOT return true for " + feature,
- mPackageManager.hasSystemFeature(feature));
- assertFalse("PackageManager#getSystemAvailableFeatures should NOT have " + feature,
- mAvailableFeatures.contains(feature));
- }
-
- private void assertFeature(boolean exist, String feature) {
- if (exist) {
- assertAvailable(feature);
- } else {
- assertNotAvailable(feature);
- }
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/TabActivityTest.java b/tests/tests/app/src/android/app/cts/TabActivityTest.java
deleted file mode 100644
index 9c028a1..0000000
--- a/tests/tests/app/src/android/app/cts/TabActivityTest.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.app.TabActivity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.test.InstrumentationTestCase;
-import android.test.UiThreadTest;
-import android.widget.TabHost;
-
-public class TabActivityTest extends InstrumentationTestCase {
- private Instrumentation mInstrumentation;
- private MockTabActivity mActivity;
- private Activity mChildActivity;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mInstrumentation = super.getInstrumentation();
- }
-
- @Override
- protected void tearDown() throws Exception {
- if (mActivity != null) {
- if (!mActivity.isFinishing()) {
- mActivity.finish();
- } else if (mChildActivity != null) {
- if (!mChildActivity.isFinishing()) {
- mChildActivity.finish();
- }
- }
- }
- super.tearDown();
- }
-
- public void testTabActivity() throws Throwable {
- runTestOnUiThread(new Runnable() {
- public void run() {
- // Test constructor
- new TabActivity();
- }
- });
- mInstrumentation.waitForIdleSync();
- final String packageName = "com.android.cts.app.stub";
- final Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setClassName(packageName, MockTabActivity.class.getName());
- mActivity = (MockTabActivity) mInstrumentation.startActivitySync(intent);
- // Test onPostCreate, onContentChanged. These two methods are invoked in starting
- // activity. Default values of isOnContentChangedCalled, isOnPostCreateCalled are false.
- assertTrue(mActivity.isOnContentChangedCalled);
- assertTrue(mActivity.isOnPostCreateCalled);
-
- // Can't get default value.
- final int defaultIndex = 1;
- mActivity.setDefaultTab(defaultIndex);
- final String defaultTab = "DefaultTab";
- mActivity.setDefaultTab(defaultTab);
- // Test getTabHost, getTabWidget
- final TabHost tabHost = mActivity.getTabHost();
- assertNotNull(tabHost);
- assertNotNull(tabHost.getTabWidget());
- }
-
- @UiThreadTest
- public void testChildTitleCallback() throws Exception {
- final Context context = mInstrumentation.getTargetContext();
- final Intent intent = new Intent(context, MockTabActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- final MockTabActivity father = new MockTabActivity();
- final ComponentName componentName = new ComponentName(context, MockTabActivity.class);
- final ActivityInfo info = context.getPackageManager().getActivityInfo(componentName, 0);
- mChildActivity = mInstrumentation.newActivity(MockTabActivity.class, mInstrumentation
- .getTargetContext(), null, null, intent, info, MockTabActivity.class.getName(),
- father, null, null);
-
- assertNotNull(mChildActivity);
- final String newTitle = "New Title";
- mChildActivity.setTitle(newTitle);
- assertTrue(father.isOnChildTitleChangedCalled);
- }
-}
diff --git a/tests/tests/app/src/android/app/cts/TimePickerDialogTest.java b/tests/tests/app/src/android/app/cts/TimePickerDialogTest.java
deleted file mode 100644
index 79a91a1..0000000
--- a/tests/tests/app/src/android/app/cts/TimePickerDialogTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.
- */
-
-package android.app.cts;
-
-
-import android.app.TimePickerDialog;
-import android.app.TimePickerDialog.OnTimeSetListener;
-import android.content.Context;
-import android.os.Bundle;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.widget.TimePicker;
-
-/**
- * Test {@link TimePickerDialog}.
- */
-public class TimePickerDialogTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
- private static final String HOUR = "hour";
- private static final String MINUTE = "minute";
- private static final String IS_24_HOUR = "is24hour";
-
- private static final int TARGET_HOUR = 15;
- private static final int TARGET_MINUTE = 9;
-
- private int mCallbackHour;
- private int mCallbackMinute;
-
- private OnTimeSetListener mOnTimeSetListener;
-
- private Context mContext;
- private DialogStubActivity mActivity;
-
- public TimePickerDialogTest() {
- super("com.android.cts.app.stub", DialogStubActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mContext = getInstrumentation().getContext();
- mOnTimeSetListener = new OnTimeSetListener(){
- public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
- mCallbackHour = hourOfDay;
- mCallbackMinute = minute;
- }
- };
- }
-
- @UiThreadTest
- public void testSaveInstanceState() {
- TimePickerDialog tD = new TimePickerDialog(
- mContext, mOnTimeSetListener, TARGET_HOUR, TARGET_MINUTE, true);
-
- Bundle b = tD.onSaveInstanceState();
-
- assertEquals(TARGET_HOUR, b.getInt(HOUR));
- assertEquals(TARGET_MINUTE, b.getInt(MINUTE));
- assertTrue(b.getBoolean(IS_24_HOUR));
-
- int minute = 13;
- tD = new TimePickerDialog(
- mContext, com.android.cts.app.stub.R.style.Theme_AlertDialog,
- mOnTimeSetListener, TARGET_HOUR, minute, false);
-
- b = tD.onSaveInstanceState();
-
- assertEquals(TARGET_HOUR, b.getInt(HOUR));
- assertEquals(minute, b.getInt(MINUTE));
- assertFalse(b.getBoolean(IS_24_HOUR));
- }
-
- @UiThreadTest
- public void testOnClick() {
- TimePickerDialog timePickerDialog = buildDialog();
- timePickerDialog.onClick(null, TimePickerDialog.BUTTON_POSITIVE);
-
- assertEquals(TARGET_HOUR, mCallbackHour);
- assertEquals(TARGET_MINUTE, mCallbackMinute);
- }
-
- public void testOnTimeChanged() throws Throwable {
- final int minute = 34;
- startDialogActivity(DialogStubActivity.TEST_TIMEPICKERDIALOG);
- final TimePickerDialog d = (TimePickerDialog) mActivity.getDialog();
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- d.onTimeChanged(null, TARGET_HOUR, minute);
- }
- });
- getInstrumentation().waitForIdleSync();
-
- }
-
- @UiThreadTest
- public void testUpdateTime() {
- TimePickerDialog timePickerDialog = buildDialog();
- int minute = 18;
- timePickerDialog.updateTime(TARGET_HOUR, minute);
-
- // here call onSaveInstanceState is to check the data put by updateTime
- Bundle b = timePickerDialog.onSaveInstanceState();
-
- assertEquals(TARGET_HOUR, b.getInt(HOUR));
- assertEquals(minute, b.getInt(MINUTE));
- }
-
- @UiThreadTest
- public void testOnRestoreInstanceState() {
- int minute = 27;
- Bundle b1 = new Bundle();
- b1.putInt(HOUR, TARGET_HOUR);
- b1.putInt(MINUTE, minute);
- b1.putBoolean(IS_24_HOUR, false);
-
- TimePickerDialog timePickerDialog = buildDialog();
- timePickerDialog.onRestoreInstanceState(b1);
-
- //here call onSaveInstanceState is to check the data put by onRestoreInstanceState
- Bundle b2 = timePickerDialog.onSaveInstanceState();
-
- assertEquals(TARGET_HOUR, b2.getInt(HOUR));
- assertEquals(minute, b2.getInt(MINUTE));
- assertFalse(b2.getBoolean(IS_24_HOUR));
- }
-
- private void startDialogActivity(int dialogNumber) {
- mActivity = DialogStubActivity.startDialogActivity(this, dialogNumber);
- }
-
- private TimePickerDialog buildDialog() {
- return new TimePickerDialog(
- mContext, mOnTimeSetListener, TARGET_HOUR, TARGET_MINUTE, true);
- }
-}
diff --git a/tests/tests/appwidget/Android.mk b/tests/tests/appwidget/Android.mk
index 8641d53..28052d2 100644
--- a/tests/tests/appwidget/Android.mk
+++ b/tests/tests/appwidget/Android.mk
@@ -26,4 +26,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/appwidget/AndroidManifest.xml b/tests/tests/appwidget/AndroidManifest.xml
index 4d9b61d..6f7d053 100644
--- a/tests/tests/appwidget/AndroidManifest.xml
+++ b/tests/tests/appwidget/AndroidManifest.xml
@@ -17,7 +17,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.cts.appwidget">
+ package="android.appwidget.cts">
<application>
<uses-library android:name="android.test.runner"/>
@@ -45,7 +45,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.cts.appwidget"
+ android:targetPackage="android.appwidget.cts"
android:label="Tests for the app widget APIs.">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/appwidget/AndroidTest.xml b/tests/tests/appwidget/AndroidTest.xml
new file mode 100644
index 0000000..fcee457
--- /dev/null
+++ b/tests/tests/appwidget/AndroidTest.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS App Widget test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAppWidgetTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.appwidget.cts" />
+ <option name="runtime-hint" value="3m30s" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
index a385ebe..61b964d 100644
--- a/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
+++ b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
@@ -40,7 +40,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.cts.appwidget.R;
+import android.appwidget.cts.R;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
diff --git a/tests/tests/assist/Android.mk b/tests/tests/assist/Android.mk
index 89d2c49..428ff7b 100644
--- a/tests/tests/assist/Android.mk
+++ b/tests/tests/assist/Android.mk
@@ -21,6 +21,11 @@
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
LOCAL_STATIC_JAVA_LIBRARIES := CtsAssistCommon ctstestrunner ctsdeviceutil
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/assist/AndroidTest.xml b/tests/tests/assist/AndroidTest.xml
index 329692d..f1af0c4 100644
--- a/tests/tests/assist/AndroidTest.xml
+++ b/tests/tests/assist/AndroidTest.xml
@@ -13,11 +13,17 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Test module config for Assist">
- <include name="common-config" />
- <option name="cts-apk-installer:test-file-name" value="CtsAssistService.apk" />
- <option name="cts-apk-installer:test-file-name" value="CtsAssistApp.apk" />
- <option name="run-command:run-command"
- value="settings put secure voice_interaction_service android.assist.service/.MainInteractionService" />
- <option name="cts-apk-installer:test-file-name" value="CtsAssistTestCases.apk" />
-</configuration>
+<configuration description="Config for CTS Assist test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAssistService.apk" />
+ <option name="test-file-name" value="CtsAssistApp.apk" />
+ <option name="test-file-name" value="CtsAssistTestCases.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="settings put secure voice_interaction_service android.assist.service/.MainInteractionService" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.assist.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/assist/OldAndroidTest.xml b/tests/tests/assist/OldAndroidTest.xml
new file mode 100644
index 0000000..26db4cf
--- /dev/null
+++ b/tests/tests/assist/OldAndroidTest.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<configuration description="Test module config for Assist">
+ <include name="common-config" />
+ <option name="cts-apk-installer:test-file-name" value="CtsAssistService.apk" />
+ <option name="cts-apk-installer:test-file-name" value="CtsAssistApp.apk" />
+ <option name="run-command:run-command"
+ value="settings put secure voice_interaction_service android.assist.service/.MainInteractionService" />
+</configuration>
diff --git a/tests/tests/assist/service/Android.mk b/tests/tests/assist/service/Android.mk
index 07dc228..019b7d0 100644
--- a/tests/tests/assist/service/Android.mk
+++ b/tests/tests/assist/service/Android.mk
@@ -27,6 +27,9 @@
LOCAL_PACKAGE_NAME := CtsAssistService
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/assist/testapp/Android.mk b/tests/tests/assist/testapp/Android.mk
index 68297ef..6d066cba 100644
--- a/tests/tests/assist/testapp/Android.mk
+++ b/tests/tests/assist/testapp/Android.mk
@@ -27,6 +27,9 @@
LOCAL_PACKAGE_NAME := CtsAssistApp
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/automotive/Android.mk b/tests/tests/automotive/Android.mk
new file mode 100644
index 0000000..f4cef01
--- /dev/null
+++ b/tests/tests/automotive/Android.mk
@@ -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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsAutomotiveTestCases
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner car
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/automotive/AndroidManifest.xml b/tests/tests/automotive/AndroidManifest.xml
new file mode 100644
index 0000000..e0ee3e0
--- /dev/null
+++ b/tests/tests/automotive/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.support.car.cts">
+ <uses-feature android:name="android.hardware.type.automotive" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.support.car.cts"
+ android:label="CTS tests for Automotive">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+</manifest>
+
diff --git a/tests/tests/automotive/AndroidTest.xml b/tests/tests/automotive/AndroidTest.xml
new file mode 100644
index 0000000..b4af1f5
--- /dev/null
+++ b/tests/tests/automotive/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Automotive test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAutomotiveTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.support.car.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/automotive/src/android/support/car/cts/CarApiTestBase.java b/tests/tests/automotive/src/android/support/car/cts/CarApiTestBase.java
new file mode 100644
index 0000000..17482ea3
--- /dev/null
+++ b/tests/tests/automotive/src/android/support/car/cts/CarApiTestBase.java
@@ -0,0 +1,87 @@
+/*
+ * 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.support.car.cts;
+
+import android.content.ComponentName;
+import android.os.IBinder;
+import android.os.Looper;
+import android.support.car.Car;
+import android.support.car.ServiceConnectionListener;
+import android.test.AndroidTestCase;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class CarApiTestBase extends AndroidTestCase {
+ protected static final long DEFAULT_WAIT_TIMEOUT_MS = 1000;
+
+ private Car mCar;
+
+ private final DefaultServiceConnectionListener mConnectionListener =
+ new DefaultServiceConnectionListener();
+
+ protected void assertMainThread() {
+ assertTrue(Looper.getMainLooper().isCurrentThread());
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mCar = Car.createCar(getContext(), mConnectionListener, null);
+ mCar.connect();
+ mConnectionListener.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mCar.disconnect();
+ }
+
+ protected synchronized Car getCar() {
+ return mCar;
+ }
+
+ protected class DefaultServiceConnectionListener implements ServiceConnectionListener {
+ private final Semaphore mConnectionWait = new Semaphore(0);
+
+ public void waitForConnection(long timeoutMs) throws InterruptedException {
+ mConnectionWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public void onServiceSuspended(int cause) {
+ assertMainThread();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ assertMainThread();
+ }
+
+ @Override
+ public void onServiceConnectionFailed(int cause) {
+ assertMainThread();
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ assertMainThread();
+ mConnectionWait.release();
+ }
+ }
+}
diff --git a/tests/tests/automotive/src/android/support/car/cts/CarConnectionListenerTest.java b/tests/tests/automotive/src/android/support/car/cts/CarConnectionListenerTest.java
new file mode 100644
index 0000000..25c74f8
--- /dev/null
+++ b/tests/tests/automotive/src/android/support/car/cts/CarConnectionListenerTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.support.car.cts;
+
+import android.support.car.Car;
+import android.support.car.CarConnectionListener;
+import android.util.Log;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class CarConnectionListenerTest extends CarApiTestBase {
+ private static final String TAG = CarConnectionListenerTest.class.getSimpleName();
+
+ public void testRegisterUnregister() throws Exception {
+ CarConnectionListerImpl listener = new CarConnectionListerImpl();
+ getCar().registerCarConnectionListener(listener);
+ assertTrue(listener.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS));
+ getCar().unregisterCarConnectionListener(listener);
+ }
+
+ public void testMultiple() throws Exception {
+ CarConnectionListerImpl listener1 = new CarConnectionListerImpl();
+ getCar().registerCarConnectionListener(listener1);
+ assertTrue(listener1.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS));
+ CarConnectionListerImpl listener2 = new CarConnectionListerImpl();
+ getCar().registerCarConnectionListener(listener2);
+ assertTrue(listener2.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS));
+ assertFalse(listener1.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS));
+ getCar().unregisterCarConnectionListener(listener2);
+ getCar().unregisterCarConnectionListener(listener1);
+ }
+
+ private class CarConnectionListerImpl implements CarConnectionListener {
+ int mConnectionType;
+ boolean mIsConnected = false;
+ private Semaphore mWaitSemaphore = new Semaphore(0);
+
+ @Override
+ public void onConnected(int connectionType) {
+ Log.i(TAG, "onConnected " + connectionType);
+ mConnectionType = connectionType;
+ mIsConnected = true;
+ mWaitSemaphore.release();
+ }
+
+ @Override
+ public void onDisconnected() {
+ Log.i(TAG, "onDisconnected");
+ mIsConnected = false;
+ mWaitSemaphore.release();
+ }
+
+ public boolean waitForConnection(long timeoutMs) throws Exception {
+ if (!mWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
+ return false;
+ }
+ assertTrue(mIsConnected);
+ assertEquals(Car.CONNECTION_TYPE_EMBEDDED, mConnectionType);
+ return true;
+ }
+
+ public boolean waitForDisconnect(long timeoutMs) throws Exception {
+ if (!mWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
+ return false;
+ }
+ assertFalse(mIsConnected);
+ return true;
+ }
+ }
+}
diff --git a/tests/tests/bionic/Android.mk b/tests/tests/bionic/Android.mk
index 06b7920..db8c2a9 100644
--- a/tests/tests/bionic/Android.mk
+++ b/tests/tests/bionic/Android.mk
@@ -1,6 +1,6 @@
LOCAL_PATH := $(call my-dir)
-test_executable := bionic-unit-tests-cts
+test_executable := CtsBionicTestCases
list_executable := $(test_executable)_list
include $(CLEAR_VARS)
@@ -26,6 +26,9 @@
liblog \
libgtest \
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_CTS_TEST_PACKAGE := android.bionic
include $(BUILD_CTS_EXECUTABLE)
diff --git a/tests/tests/bionic/AndroidTest.xml b/tests/tests/bionic/AndroidTest.xml
new file mode 100644
index 0000000..97a9a0a
--- /dev/null
+++ b/tests/tests/bionic/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<configuration description="Config for CTS Bionic test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="CtsBionicTestCases->/data/local/tmp/CtsBionicTestCases" />
+ <option name="append-bitness" value="true" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="CtsBionicTestCases" />
+ <option name="runtime-hint" value="1m10s" />
+ </test>
+</configuration>
diff --git a/tests/tests/bluetooth/Android.mk b/tests/tests/bluetooth/Android.mk
index 4f837fc..12a461c 100644
--- a/tests/tests/bluetooth/Android.mk
+++ b/tests/tests/bluetooth/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/bluetooth/AndroidManifest.xml b/tests/tests/bluetooth/AndroidManifest.xml
index 12838f3..3c751d7 100644
--- a/tests/tests/bluetooth/AndroidManifest.xml
+++ b/tests/tests/bluetooth/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.bluetooth">
+ package="android.bluetooth.cts">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
@@ -28,7 +28,7 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.bluetooth"
+ android:targetPackage="android.bluetooth.cts"
android:label="CTS tests of bluetooth component">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/bluetooth/AndroidTest.xml b/tests/tests/bluetooth/AndroidTest.xml
new file mode 100644
index 0000000..fb4b205
--- /dev/null
+++ b/tests/tests/bluetooth/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Bluetooth test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsBluetoothTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.bluetooth.cts" />
+ <option name="runtime-hint" value="1m11s" />
+ </test>
+</configuration>
diff --git a/tests/tests/calendarcommon/Android.mk b/tests/tests/calendarcommon/Android.mk
index fa4b6c5..ef019fc 100644
--- a/tests/tests/calendarcommon/Android.mk
+++ b/tests/tests/calendarcommon/Android.mk
@@ -31,4 +31,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/calendarcommon/AndroidManifest.xml b/tests/tests/calendarcommon/AndroidManifest.xml
index 17520a3..4f21b18 100644
--- a/tests/tests/calendarcommon/AndroidManifest.xml
+++ b/tests/tests/calendarcommon/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.calendarcommon2">
+ package="android.calendarcommon2.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -24,7 +24,7 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.calendarcommon2"
+ android:targetPackage="android.calendarcommon2.cts"
android:label="CTS tests of calendarcommon">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/calendarcommon/AndroidTest.xml b/tests/tests/calendarcommon/AndroidTest.xml
new file mode 100644
index 0000000..65f2d7a
--- /dev/null
+++ b/tests/tests/calendarcommon/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Calendar test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsCalendarcommon2TestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.calendarcommon2.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/calllog/Android.mk b/tests/tests/calllog/Android.mk
index 6a7e96a..99e1781 100644
--- a/tests/tests/calllog/Android.mk
+++ b/tests/tests/calllog/Android.mk
@@ -32,4 +32,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/calllog/AndroidManifest.xml b/tests/tests/calllog/AndroidManifest.xml
index 50fe115..d66559f 100644
--- a/tests/tests/calllog/AndroidManifest.xml
+++ b/tests/tests/calllog/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.calllog">
+ package="android.calllog.cts">
<uses-sdk android:minSdkVersion="21" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
@@ -29,7 +29,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.calllog"
+ android:targetPackage="android.calllog.cts"
android:label="CTS tests for android.calllog package">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/calllog/AndroidTest.xml b/tests/tests/calllog/AndroidTest.xml
new file mode 100644
index 0000000..408aaac
--- /dev/null
+++ b/tests/tests/calllog/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Call Log test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsCallLogTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.calllog.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index 2c185d9..1c8fbfc 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -23,15 +23,21 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctsdeviceutil ctstestrunner
-# 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 \
+# Resource unit tests use various locales (including a private locale) and some densities
+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,fa_IR \
+ -c kok,kok_IN,kok_419,kok_419_VARIANT \
+ -c kok_Knda_419,kok_Knda_419_VARIANT,kok_VARIANT,kok_Knda \
+ -c tgl,tgl_PH,xx_YY
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CtsContentTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/content/AndroidManifest.xml b/tests/tests/content/AndroidManifest.xml
index bffb1f7..d88fdad 100644
--- a/tests/tests/content/AndroidManifest.xml
+++ b/tests/tests/content/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.content">
+ package="android.content.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<!-- content sync tests -->
@@ -35,7 +35,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<!-- Used for PackageManager test, don't delete this permission-tree -->
- <permission-tree android:name="com.android.cts.content.permission.TEST_DYNAMIC"
+ <permission-tree android:name="android.content.cts.permission.TEST_DYNAMIC"
android:label="Test Tree"/>
<!-- Used for PackageManager test, don't delete this permission-group -->
@@ -43,7 +43,7 @@
android:label="@string/permlab_costMoney"
android:description="@string/permdesc_costMoney"/>
- <permission android:name="com.android.cts.content.CALL_ABROAD_PERMISSION"
+ <permission android:name="android.content.cts.CALL_ABROAD_PERMISSION"
android:label="@string/permlab_callAbroad"
android:description="@string/permdesc_callAbroad"
android:protectionLevel="normal"
@@ -75,16 +75,16 @@
<meta-data android:name="android.app.intent.filter"
android:resource="@xml/intentfilter" />
<intent-filter>
- <action android:name="com.android.cts.content.action.TEST_ACTION" />
+ <action android:name="android.content.cts.action.TEST_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
- <category android:name="com.android.cts.content.category.TEST_CATEGORY" />
+ <category android:name="android.content.cts.category.TEST_CATEGORY" />
</intent-filter>
</activity>
<activity-alias android:name="android.content.cts.MockActivity2"
android:targetActivity="android.content.cts.MockActivity">
<intent-filter>
- <action android:name="com.android.cts.content.action.TEST_ACTION" />
+ <action android:name="android.content.cts.action.TEST_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity-alias>
@@ -170,6 +170,13 @@
<provider android:name="android.content.cts.MockRemoteContentProvider"
android:authorities="remotectstest"
android:process=":remoteprovider" android:multiprocess="false" />
+ <provider android:name="android.support.v4.content.FileProvider"
+ android:authorities="android.content.cts.fileprovider"
+ android:grantUriPermissions="true">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/file_paths" />
+ </provider>
<service android:name="android.content.cts.MockService" />
@@ -194,7 +201,7 @@
<activity android:name="android.content.cts.ClipboardManagerListenerActivity"/>
- <activity android:name="com.android.cts.content.ImageCaptureActivity"
+ <activity android:name="android.content.cts.ImageCaptureActivity"
android:exported="true">
<intent-filter>
<action android:name="android.media.action.IMAGE_CAPTURE" />
@@ -204,7 +211,7 @@
</intent-filter>
</activity>
- <activity android:name="com.android.cts.content.ReadableFileReceiverActivity"
+ <activity android:name="android.content.cts.ReadableFileReceiverActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
@@ -216,7 +223,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.content"
+ android:targetPackage="android.content.cts"
android:label="CTS tests of android.content">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
new file mode 100644
index 0000000..a8a8727
--- /dev/null
+++ b/tests/tests/content/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<configuration description="Config for CTS Content test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsContentTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.content.cts" />
+ <option name="runtime-hint" value="3m30s" />
+ </test>
+</configuration>
diff --git a/tests/tests/content/res/drawable-hdpi/density_test.xml b/tests/tests/content/res/drawable-hdpi/density_test.xml
new file mode 100644
index 0000000..e4a4b4a
--- /dev/null
+++ b/tests/tests/content/res/drawable-hdpi/density_test.xml
@@ -0,0 +1,24 @@
+<?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">
+ <solid
+ android:color="#0000ff" />
+ <size
+ android:width="100px"
+ android:height="100px"/>
+</shape>
diff --git a/tests/tests/content/res/drawable-ldpi/density_test.xml b/tests/tests/content/res/drawable-ldpi/density_test.xml
new file mode 100644
index 0000000..302987f
--- /dev/null
+++ b/tests/tests/content/res/drawable-ldpi/density_test.xml
@@ -0,0 +1,24 @@
+<?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">
+ <solid
+ android:color="#ff0000" />
+ <size
+ android:width="300px"
+ android:height="300px"/>
+</shape>
diff --git a/tests/tests/content/res/drawable-mdpi/density_test.xml b/tests/tests/content/res/drawable-mdpi/density_test.xml
new file mode 100644
index 0000000..60514c5
--- /dev/null
+++ b/tests/tests/content/res/drawable-mdpi/density_test.xml
@@ -0,0 +1,24 @@
+<?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">
+ <solid
+ android:color="#00ff00" />
+ <size
+ android:width="200px"
+ android:height="200px"/>
+</shape>
diff --git a/tests/tests/content/res/drawable/density_test.xml b/tests/tests/content/res/drawable/density_test.xml
new file mode 100644
index 0000000..2b70eb8
--- /dev/null
+++ b/tests/tests/content/res/drawable/density_test.xml
@@ -0,0 +1,24 @@
+<?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">
+ <solid
+ android:color="#ffffff" />
+ <size
+ android:width="1px"
+ android:height="1px"/>
+</shape>
diff --git a/tests/tests/content/res/values-fa-rIR/strings.xml b/tests/tests/content/res/values-fa-rIR/strings.xml
new file mode 100644
index 0000000..25fd20c
--- /dev/null
+++ b/tests/tests/content/res/values-fa-rIR/strings.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="am">صبØ</string>
+</resources>
diff --git a/tests/tests/content/res/values-hdpi/strings.xml b/tests/tests/content/res/values-hdpi/strings.xml
new file mode 100644
index 0000000..0ea4779
--- /dev/null
+++ b/tests/tests/content/res/values-hdpi/strings.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+ <string name="density_string">hdpi</string>
+</resources>
diff --git a/tests/tests/content/res/values-ldpi/strings.xml b/tests/tests/content/res/values-ldpi/strings.xml
new file mode 100644
index 0000000..8a49f34
--- /dev/null
+++ b/tests/tests/content/res/values-ldpi/strings.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+ <string name="density_string">ldpi</string>
+</resources>
diff --git a/tests/tests/content/res/values-mdpi/strings.xml b/tests/tests/content/res/values-mdpi/strings.xml
new file mode 100644
index 0000000..721481f
--- /dev/null
+++ b/tests/tests/content/res/values-mdpi/strings.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+ <string name="density_string">mdpi</string>
+</resources>
diff --git a/tests/tests/content/res/values-v24/strings.xml b/tests/tests/content/res/values-v24/strings.xml
new file mode 100644
index 0000000..b84c3a6
--- /dev/null
+++ b/tests/tests/content/res/values-v24/strings.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="version_cur">v24cur</string>
+</resources>
diff --git a/tests/tests/content/res/values/strings.xml b/tests/tests/content/res/values/strings.xml
index 8ffb477..0d72c9f 100644
--- a/tests/tests/content/res/values/strings.xml
+++ b/tests/tests/content/res/values/strings.xml
@@ -182,4 +182,5 @@
<string name="permlab_callAbroad">Call abroad</string>
<string name="permdesc_callAbroad">Make calls abroad</string>
+ <string name="density_string">default</string>
</resources>
diff --git a/tests/tests/content/res/xml/alias.xml b/tests/tests/content/res/xml/alias.xml
index c245ba8..624b029 100644
--- a/tests/tests/content/res/xml/alias.xml
+++ b/tests/tests/content/res/xml/alias.xml
@@ -19,7 +19,7 @@
<alias xmlns:android="http://schemas.android.com/apk/res/android">
<intent android:action="android.intent.action.MAIN"
- android:targetPackage="com.android.cts.content"
+ android:targetPackage="android.content.cts"
android:targetClass="android.content.cts.ChildActivity"
android:data="http://www.google.com/">
</intent>
diff --git a/tests/tests/content/res/xml/file_paths.xml b/tests/tests/content/res/xml/file_paths.xml
new file mode 100644
index 0000000..e8d2861
--- /dev/null
+++ b/tests/tests/content/res/xml/file_paths.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 Google Inc. All Rights Reserved. -->
+
+<!-- Specify the storage area and path used in file provider. -->
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+ <files-path name="debug" path="debug/"/>
+</paths>
\ No newline at end of file
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsActivity.java b/tests/tests/content/src/android/content/cts/AvailableIntentsActivity.java
index 773defc..acd615c 100644
--- a/tests/tests/content/src/android/content/cts/AvailableIntentsActivity.java
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsActivity.java
@@ -16,7 +16,7 @@
package android.content.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/content/src/android/content/cts/BroadcastReceiverTest.java b/tests/tests/content/src/android/content/cts/BroadcastReceiverTest.java
index 43d6cfe..588a915 100644
--- a/tests/tests/content/src/android/content/cts/BroadcastReceiverTest.java
+++ b/tests/tests/content/src/android/content/cts/BroadcastReceiverTest.java
@@ -49,15 +49,15 @@
private static final String ACTION_BROADCAST_DISABLED =
"android.content.cts.BroadcastReceiverTest.BROADCAST_DISABLED";
- private static final long SEND_BROADCAST_TIMEOUT = 5000;
+ private static final long SEND_BROADCAST_TIMEOUT = 15000;
private static final long START_SERVICE_TIMEOUT = 3000;
private static final ComponentName DISABLEABLE_RECEIVER =
- new ComponentName("com.android.cts.content",
+ new ComponentName("android.content.cts",
"android.content.cts.MockReceiverDisableable");
public BroadcastReceiverTest() {
- super("com.android.cts.content", MockActivity.class);
+ super("android.content.cts", MockActivity.class);
}
@Override
@@ -166,7 +166,8 @@
assertEquals(null, internalReceiver.getResultData());
assertEquals(null, internalReceiver.getResultExtras(false));
- activity.sendBroadcast(new Intent(ACTION_BROADCAST_INTERNAL));
+ activity.sendBroadcast(new Intent(ACTION_BROADCAST_INTERNAL)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND));
internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT);
activity.unregisterReceiver(internalReceiver);
@@ -181,7 +182,8 @@
map.putString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY,
MockReceiver.RESULT_EXTRAS_REMOVE_VALUE);
getInstrumentation().getContext().sendOrderedBroadcast(
- new Intent(ACTION_BROADCAST_MOCKTEST), null, internalOrderReceiver,
+ new Intent(ACTION_BROADCAST_MOCKTEST).addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
+ null, internalOrderReceiver,
null, RESULT_INITIAL_CODE, RESULT_INITIAL_DATA, map);
internalOrderReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT);
@@ -212,7 +214,8 @@
// MockReceiverFirst --> MockReceiverAbort --> MockReceiver --> internalOrderReceiver.
// And MockReceiver is the receiver which will be aborted.
getInstrumentation().getContext().sendOrderedBroadcast(
- new Intent(ACTION_BROADCAST_TESTABORT), null, internalOrderReceiver,
+ new Intent(ACTION_BROADCAST_TESTABORT).addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
+ null, internalOrderReceiver,
null, RESULT_INITIAL_CODE, RESULT_INITIAL_DATA, map);
internalOrderReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT);
@@ -242,7 +245,8 @@
PackageManager.DONT_KILL_APP);
context.sendOrderedBroadcast(
- new Intent(ACTION_BROADCAST_DISABLED), null, lastReceiver,
+ new Intent(ACTION_BROADCAST_DISABLED).addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
+ null, lastReceiver,
null, RESULT_INITIAL_CODE, RESULT_INITIAL_DATA, new Bundle());
lastReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT);
@@ -257,7 +261,8 @@
filter.addAction(ACTION_BROADCAST_INTERNAL);
activity.registerReceiver(internalReceiver, filter);
- activity.sendBroadcast(new Intent(ACTION_BROADCAST_INTERNAL));
+ activity.sendBroadcast(new Intent(ACTION_BROADCAST_INTERNAL)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND));
internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT);
assertNull(internalReceiver.getIBinder());
@@ -267,7 +272,8 @@
assertTrue(msc.waitForService(START_SERVICE_TIMEOUT));
internalReceiver.reset();
- activity.sendBroadcast(new Intent(ACTION_BROADCAST_INTERNAL));
+ activity.sendBroadcast(new Intent(ACTION_BROADCAST_INTERNAL)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND));
internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT);
assertNotNull(internalReceiver.getIBinder());
activity.unbindService(msc);
diff --git a/tests/tests/content/src/android/content/cts/ComponentNameTest.java b/tests/tests/content/src/android/content/cts/ComponentNameTest.java
index 6277bd6..23a2e00 100644
--- a/tests/tests/content/src/android/content/cts/ComponentNameTest.java
+++ b/tests/tests/content/src/android/content/cts/ComponentNameTest.java
@@ -85,14 +85,14 @@
}
public void testFlattenToString() {
- assertEquals("com.android.cts.content/android.content.cts.ComponentNameTest",
+ assertEquals("android.content.cts/android.content.cts.ComponentNameTest",
getComponentName().flattenToString());
}
public void testGetShortClassName() {
// set the expected value, test normal value
String actual = getComponentName().getShortClassName();
- assertEquals("android.content.cts.ComponentNameTest", actual);
+ assertEquals(".ComponentNameTest", actual);
// Test class name which can be abbreviated
ComponentName componentName = new ComponentName("com.android.view",
@@ -121,7 +121,7 @@
public void testGetPackageName() {
final String actual = getComponentName().getPackageName();
- assertEquals("com.android.cts.content", actual);
+ assertEquals("android.content.cts", actual);
}
public void testUnflattenFromString() {
@@ -135,7 +135,7 @@
public void testFlattenToShortString() {
// Test normal
String actual = getComponentName().flattenToShortString();
- assertEquals("com.android.cts.content/android.content.cts.ComponentNameTest", actual);
+ assertEquals("android.content.cts/.ComponentNameTest", actual);
// Test long class name
final ComponentName componentName = new ComponentName("com.android.view",
@@ -152,12 +152,12 @@
// new the ComponentName instances, both are the same.
final ComponentName componentName1 = getComponentName();
ComponentName componentName2 = new ComponentName(componentName1.getPackageName(),
- componentName1.getShortClassName());
+ componentName1.getClassName());
assertTrue(componentName1.equals(componentName2));
// new the ComponentName instances, are not the same.
componentName2 = new ComponentName(componentName1.getPackageName(),
- componentName1.getShortClassName() + "different name");
+ componentName1.getClassName() + "different name");
assertFalse(componentName1.equals(componentName2));
}
@@ -168,7 +168,7 @@
public void testToShortString() {
// Test normal string
final String shortString = getComponentName().toShortString();
- assertEquals("{com.android.cts.content/android.content.cts.ComponentNameTest}", shortString);
+ assertEquals("{android.content.cts/android.content.cts.ComponentNameTest}", shortString);
}
public void testGetClassName() {
@@ -196,7 +196,7 @@
ComponentName.writeToParcel(componentName, parcel);
parcel.setDataPosition(0);
assertFalse(0 == parcel.dataAvail());
- assertEquals("com.android.cts.content", parcel.readString());
+ assertEquals("android.content.cts", parcel.readString());
assertEquals("android.content.cts.ComponentNameTest", parcel.readString());
// Test null data
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderTest.java b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
index 5fee379..e7d8a05 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
@@ -27,7 +27,7 @@
import android.os.ParcelFileDescriptor;
import android.test.AndroidTestCase;
-import com.android.cts.content.R;
+import android.content.cts.R;
import java.io.File;
import java.io.FileNotFoundException;
@@ -37,7 +37,7 @@
* Test {@link ContentProvider}.
*/
public class ContentProviderTest extends AndroidTestCase {
- private static final String TEST_PACKAGE_NAME = "com.android.cts.content";
+ private static final String TEST_PACKAGE_NAME = "android.content.cts";
private static final String TEST_FILE_NAME = "testFile.tmp";
private static final String TEST_DB_NAME = "test.db";
diff --git a/tests/tests/content/src/android/content/cts/ContentResolverTest.java b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
index 628f956..ea1227c 100644
--- a/tests/tests/content/src/android/content/cts/ContentResolverTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
@@ -16,7 +16,7 @@
package android.content.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import android.accounts.Account;
@@ -80,7 +80,7 @@
private static final int VALUE2 = 2;
private static final int VALUE3 = 3;
- private static final String TEST_PACKAGE_NAME = "com.android.cts.content";
+ private static final String TEST_PACKAGE_NAME = "android.content.cts";
private Context mContext;
private ContentResolver mContentResolver;
diff --git a/tests/tests/content/src/android/content/cts/ContextTest.java b/tests/tests/content/src/android/content/cts/ContextTest.java
index d77c1b1..cf27bda 100644
--- a/tests/tests/content/src/android/content/cts/ContextTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextTest.java
@@ -16,7 +16,7 @@
package android.content.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/content/src/android/content/cts/ContextWrapperCtsActivity.java b/tests/tests/content/src/android/content/cts/ContextWrapperCtsActivity.java
index 9ff4df9..7ea2ab7 100644
--- a/tests/tests/content/src/android/content/cts/ContextWrapperCtsActivity.java
+++ b/tests/tests/content/src/android/content/cts/ContextWrapperCtsActivity.java
@@ -21,7 +21,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.content.R;
+import android.content.cts.R;
public class ContextWrapperCtsActivity extends Activity {
@Override
diff --git a/tests/tests/content/src/android/content/cts/ContextWrapperTest.java b/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
index edc9538..28e248e 100644
--- a/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
@@ -16,7 +16,7 @@
package android.content.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@@ -477,7 +477,7 @@
}
public void testGetPackageName() {
- assertEquals("com.android.cts.content", mContextWrapper.getPackageName());
+ assertEquals("android.content.cts", mContextWrapper.getPackageName());
}
public void testGetCacheDir() {
diff --git a/tests/tests/content/src/android/content/cts/ImageCaptureActivity.java b/tests/tests/content/src/android/content/cts/ImageCaptureActivity.java
index 71bf250..d8ba494 100644
--- a/tests/tests/content/src/android/content/cts/ImageCaptureActivity.java
+++ b/tests/tests/content/src/android/content/cts/ImageCaptureActivity.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.cts.content;
+package android.content.cts;
import android.app.Activity;
import android.content.ClipData;
@@ -30,7 +30,7 @@
import java.io.Writer;
public class ImageCaptureActivity extends Activity {
- public static final String ACTION_FILE_READY = "com.android.cts.content.action.file_ready";
+ public static final String ACTION_FILE_READY = "android.content.cts.action.file_ready";
private static final String TAG = ImageCaptureUriExtraToClipDataTest.TAG;
protected void onCreate(Bundle savedInstanceState) {
diff --git a/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java b/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java
index bb2a43d..b2a90f2 100644
--- a/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java
+++ b/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.cts.content;
+package android.content.cts;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -87,8 +87,8 @@
private void startActivityWithAction(String action) {
Intent intent = new Intent(action);
- intent.setComponent(new ComponentName("com.android.cts.content",
- "com.android.cts.content.ImageCaptureActivity"));
+ intent.setComponent(new ComponentName("android.content.cts",
+ "android.content.cts.ImageCaptureActivity"));
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTestFile));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
diff --git a/tests/tests/content/src/android/content/cts/IntentTest.java b/tests/tests/content/src/android/content/cts/IntentTest.java
index 677b31f..65da548 100644
--- a/tests/tests/content/src/android/content/cts/IntentTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentTest.java
@@ -720,33 +720,33 @@
}
public void testResolveActivitySingleMatch() {
- final Intent intent = new Intent("com.android.cts.content.action.TEST_ACTION");
- intent.addCategory("com.android.cts.content.category.TEST_CATEGORY");
+ final Intent intent = new Intent("android.content.cts.action.TEST_ACTION");
+ intent.addCategory("android.content.cts.category.TEST_CATEGORY");
// Should only have one activity responding to narrow category
final ComponentName target = intent.resolveActivity(mPm);
- assertEquals("com.android.cts.content", target.getPackageName());
+ assertEquals("android.content.cts", target.getPackageName());
assertEquals("android.content.cts.MockActivity", target.getClassName());
}
public void testResolveActivityShortcutMatch() {
- final Intent intent = new Intent("com.android.cts.content.action.TEST_ACTION");
+ final Intent intent = new Intent("android.content.cts.action.TEST_ACTION");
intent.setComponent(
- new ComponentName("com.android.cts.content", "android.content.cts.MockActivity2"));
+ new ComponentName("android.content.cts", "android.content.cts.MockActivity2"));
// Multiple activities match, but we asked for explicit component
final ComponentName target = intent.resolveActivity(mPm);
- assertEquals("com.android.cts.content", target.getPackageName());
+ assertEquals("android.content.cts", target.getPackageName());
assertEquals("android.content.cts.MockActivity2", target.getClassName());
}
public void testResolveActivityMultipleMatch() {
- final Intent intent = new Intent("com.android.cts.content.action.TEST_ACTION");
+ final Intent intent = new Intent("android.content.cts.action.TEST_ACTION");
// Should have multiple activities, resulting in resolver dialog
final ComponentName target = intent.resolveActivity(mPm);
final String pkgName = target.getPackageName();
- assertFalse("com.android.cts.content".equals(pkgName));
+ assertFalse("android.content.cts".equals(pkgName));
// Whoever they are must be able to set preferred activities
if (!"android".equals(pkgName)) {
diff --git a/tests/tests/content/src/android/content/cts/Intent_ShortcutIconResourceTest.java b/tests/tests/content/src/android/content/cts/Intent_ShortcutIconResourceTest.java
index 062ef90..ce45f1c 100644
--- a/tests/tests/content/src/android/content/cts/Intent_ShortcutIconResourceTest.java
+++ b/tests/tests/content/src/android/content/cts/Intent_ShortcutIconResourceTest.java
@@ -29,7 +29,7 @@
ShortcutIconResource mShortcutIconResource;
Context mContext;
- final int resourceId = com.android.cts.content.R.string.notify;
+ final int resourceId = android.content.cts.R.string.notify;
@Override
protected void setUp() throws Exception {
@@ -63,7 +63,7 @@
public void testWriteToParcel() {
mShortcutIconResource = ShortcutIconResource.fromContext(mContext,
- com.android.cts.content.R.string.notify);
+ android.content.cts.R.string.notify);
assertNotNull(mShortcutIconResource);
Parcel parce = Parcel.obtain();
mShortcutIconResource.writeToParcel(parce, 1);
diff --git a/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java b/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java
index bab516e..d5a8b72 100644
--- a/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java
+++ b/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.cts.content;
+package android.content.cts;
import android.app.Activity;
import android.content.ClipData;
@@ -32,7 +32,7 @@
public class ReadableFileReceiverActivity extends Activity {
public static final String ACTION_CONFIRM_READ_SUCCESS
- = "com.android.cts.content.action.CONFIRM_READ_SUCCESS";
+ = "android.content.cts.action.CONFIRM_READ_SUCCESS";
private static final String TAG = ReadableUriExtraToClipDataTest.TAG;
protected void onCreate(Bundle savedInstanceState) {
diff --git a/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java b/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java
index 129d964..8b89497 100644
--- a/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java
+++ b/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.cts.content;
+package android.content.cts;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
diff --git a/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java b/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java
index c271483..b4fcb31 100644
--- a/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java
+++ b/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java
@@ -18,8 +18,9 @@
import android.app.QueuedWork;
import android.content.Context;
-import android.content.ContextWrapper;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.test.AndroidTestCase;
@@ -39,7 +40,6 @@
private static final String TAG = "SharedPreferencesTest";
private Context mContext;
- private ContextWrapper mContextWrapper;
private File mPrefsFile;
@@ -47,15 +47,17 @@
protected void setUp() throws Exception {
super.setUp();
mContext = getContext();
- mContextWrapper = new ContextWrapper(mContext);
SharedPreferences prefs = getPrefs();
prefs.edit().clear().commit();
-
- // Duplicated from ContextImpl.java. Not ideal, but there wasn't a better
- // way to reach into Context{Wrapper,Impl} to ask where this file lives.
- mPrefsFile = new File("/data/data/com.android.cts.content/shared_prefs",
- "com.android.cts.content_preferences.xml");
+ try {
+ ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(
+ mContext.getPackageName(), 0);
+ mPrefsFile = new File(applicationInfo.dataDir,
+ "shared_prefs/android.content.cts_preferences.xml");
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
mPrefsFile.delete();
}
diff --git a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
index 1e9f5a2..6a06eb8 100644
--- a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
@@ -16,7 +16,7 @@
package android.content.pm.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import android.content.pm.ApplicationInfo;
diff --git a/tests/tests/content/src/android/content/pm/cts/ApplicationInfo_DisplayNameComparatorTest.java b/tests/tests/content/src/android/content/pm/cts/ApplicationInfo_DisplayNameComparatorTest.java
index 211a2ca..713c60b 100644
--- a/tests/tests/content/src/android/content/pm/cts/ApplicationInfo_DisplayNameComparatorTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ApplicationInfo_DisplayNameComparatorTest.java
@@ -26,7 +26,7 @@
* Test {@link DisplayNameComparator}.
*/
public class ApplicationInfo_DisplayNameComparatorTest extends AndroidTestCase {
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
DisplayNameComparator mDisplayNameComparator;
@Override
diff --git a/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java
index 14a42c01..e11beec 100644
--- a/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java
@@ -28,14 +28,14 @@
import android.util.Printer;
import android.util.StringBuilderPrinter;
-import com.android.cts.content.R;
+import android.content.cts.R;
/**
* Test {@link ComponentInfo}.
*/
public class ComponentInfoTest extends AndroidTestCase {
- private final String PACKAGE_NAME = "com.android.cts.content";
+ private final String PACKAGE_NAME = "android.content.cts";
private ComponentInfo mComponentInfo;
public void testConstructor() {
diff --git a/tests/tests/content/src/android/content/pm/cts/InstrumentationInfoTest.java b/tests/tests/content/src/android/content/pm/cts/InstrumentationInfoTest.java
index 5b7747d..ed9366b 100644
--- a/tests/tests/content/src/android/content/pm/cts/InstrumentationInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/InstrumentationInfoTest.java
@@ -25,7 +25,7 @@
import android.test.AndroidTestCase;
public class InstrumentationInfoTest extends AndroidTestCase {
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
private static final String INSTRUMENTATION_NAME =
"android.content.pm.cts.TestPmInstrumentation";
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java b/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
index 0540e0b..886b4f5 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
@@ -32,7 +32,7 @@
private PackageManager mPackageManager;
private PackageInfo mPackageInfo;
private PackageInfo mPackageInfoCmp;
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
@Override
protected void setUp() throws Exception {
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageItemInfoTest.java b/tests/tests/content/src/android/content/pm/cts/PackageItemInfoTest.java
index 53e69da..48db1b8 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageItemInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageItemInfoTest.java
@@ -16,7 +16,7 @@
package android.content.pm.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import android.content.ComponentName;
@@ -30,7 +30,7 @@
import android.util.Printer;
public class PackageItemInfoTest extends AndroidTestCase {
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
private static final String ACTIVITY_NAME = "android.content.pm.cts.TestPmActivity";
private static final String METADATA_NAME = "android.content.pm.cts.xmltest";
private PackageManager mPackageManager;
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageItemInfo_DisplayNameComparatorTest.java b/tests/tests/content/src/android/content/pm/cts/PackageItemInfo_DisplayNameComparatorTest.java
index 0cfd1dd..4624c85 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageItemInfo_DisplayNameComparatorTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageItemInfo_DisplayNameComparatorTest.java
@@ -26,7 +26,7 @@
import android.test.AndroidTestCase;
public class PackageItemInfo_DisplayNameComparatorTest extends AndroidTestCase {
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
private static final String ACTIVITY_NAME = "android.content.pm.cts.TestPmActivity";
private static final String CMPACTIVITY_NAME = "android.content.pm.cts.TestPmCompare";
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
index cb3de2a..490da35e 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
@@ -16,7 +16,7 @@
package android.content.pm.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import android.content.ComponentName;
@@ -44,8 +44,8 @@
*/
public class PackageManagerTest extends AndroidTestCase {
private PackageManager mPackageManager;
- private static final String PACKAGE_NAME = "com.android.cts.content";
- private static final String CONTENT_PKG_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
+ private static final String CONTENT_PKG_NAME = "android.content.cts";
private static final String ACTIVITY_ACTION_NAME = "android.intent.action.PMTEST";
private static final String MAIN_ACTION_NAME = "android.intent.action.MAIN";
private static final String SERVICE_ACTION_NAME =
@@ -110,7 +110,7 @@
String testPermissionsGroup = "android.permission-group.COST_MONEY";
List<PermissionInfo> permissions = mPackageManager.queryPermissionsByGroup(
testPermissionsGroup, PackageManager.GET_META_DATA);
- checkPermissionInfoName("com.android.cts.content.CALL_ABROAD_PERMISSION", permissions);
+ checkPermissionInfoName("android.content.cts.CALL_ABROAD_PERMISSION", permissions);
ApplicationInfo appInfo = mPackageManager.getApplicationInfo(PACKAGE_NAME, 0);
List<ProviderInfo> providers = mPackageManager.queryContentProviders(PACKAGE_NAME,
@@ -390,7 +390,7 @@
public void testOpPermission() {
PermissionInfo permissionInfo = new PermissionInfo();
- String permissionName = "com.android.cts.content.permission.TEST_DYNAMIC.ADD";
+ String permissionName = "android.content.cts.permission.TEST_DYNAMIC.ADD";
permissionInfo.name = permissionName;
permissionInfo.labelRes = R.string.permlab_testDynamic;
permissionInfo.nonLocalizedLabel = "Test Tree";
@@ -445,7 +445,7 @@
public void testGetResources() throws NameNotFoundException {
ComponentName componentName = new ComponentName(PACKAGE_NAME, ACTIVITY_NAME);
int resourceId = R.xml.pm_test;
- String xmlName = "com.android.cts.content:xml/pm_test";
+ String xmlName = "android.content.cts:xml/pm_test";
ApplicationInfo appInfo = mPackageManager.getApplicationInfo(PACKAGE_NAME, 0);
assertNotNull(mPackageManager.getXml(PACKAGE_NAME, resourceId, appInfo));
assertEquals(xmlName, mPackageManager.getResourcesForActivity(componentName)
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageStatsTest.java b/tests/tests/content/src/android/content/pm/cts/PackageStatsTest.java
index 6425209..722175b 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageStatsTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageStatsTest.java
@@ -22,7 +22,7 @@
import android.test.AndroidTestCase;
public class PackageStatsTest extends AndroidTestCase {
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
public void testPackageStats() {
// Set mock data to make sure the functionality of constructor
diff --git a/tests/tests/content/src/android/content/pm/cts/ProviderInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ProviderInfoTest.java
index 6256a69..4e07312 100644
--- a/tests/tests/content/src/android/content/pm/cts/ProviderInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ProviderInfoTest.java
@@ -21,14 +21,17 @@
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.XmlResourceParser;
import android.os.Parcel;
import android.test.AndroidTestCase;
+import libcore.io.IoUtils;
+
import java.util.Iterator;
import java.util.List;
public class ProviderInfoTest extends AndroidTestCase {
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
private static final String PROVIDER_NAME = "android.content.cts.MockContentProvider";
public void testProviderInfo() throws NameNotFoundException {
@@ -50,6 +53,19 @@
}
}
+ public void testProviderMetaData() {
+ final ProviderInfo info = getContext().getPackageManager()
+ .resolveContentProvider("android.content.cts.fileprovider",
+ PackageManager.GET_META_DATA);
+ final XmlResourceParser in = info.loadXmlMetaData(
+ getContext().getPackageManager(), "android.support.FILE_PROVIDER_PATHS");
+ try {
+ assertNotNull(in);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
private void checkProviderInfoMethods(ProviderInfo providerInfo, Parcel p) {
// Test toString, describeContents
assertNotNull(providerInfo.toString());
diff --git a/tests/tests/content/src/android/content/pm/cts/ResolveInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ResolveInfoTest.java
index af3f161..9b149f5 100644
--- a/tests/tests/content/src/android/content/pm/cts/ResolveInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ResolveInfoTest.java
@@ -26,7 +26,7 @@
import android.util.Printer;
public class ResolveInfoTest extends AndroidTestCase {
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
private static final String MAIN_ACTION_NAME = "android.intent.action.MAIN";
private static final String ACTIVITY_NAME = "android.content.pm.cts.TestPmActivity";
private static final String SERVICE_NAME = "android.content.pm.cts.activity.PMTEST_SERVICE";
diff --git a/tests/tests/content/src/android/content/pm/cts/ServiceInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ServiceInfoTest.java
index 297ab69..4298586 100644
--- a/tests/tests/content/src/android/content/pm/cts/ServiceInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ServiceInfoTest.java
@@ -25,7 +25,7 @@
import android.test.AndroidTestCase;
public class ServiceInfoTest extends AndroidTestCase {
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
private static final String SERVICE_NAME = "android.content.pm.cts.TestPmService";
public void testServiceInfo() throws NameNotFoundException {
diff --git a/tests/tests/content/src/android/content/res/cts/ArrayTest.java b/tests/tests/content/src/android/content/res/cts/ArrayTest.java
index 909fbf6..7ac1133 100644
--- a/tests/tests/content/src/android/content/res/cts/ArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ArrayTest.java
@@ -20,7 +20,7 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.cts.content.R;
+import android.content.cts.R;
public class ArrayTest extends AndroidTestCase {
private Resources mResources;
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 e8d363b..fe98b72 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
@@ -15,7 +15,7 @@
*/
package android.content.res.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -32,6 +32,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.HashSet;
public class AssetManagerTest extends AndroidTestCase{
@@ -115,6 +117,50 @@
}
+
+ 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.
+ final String KNOWN_LOCALES[] = {
+ "cs",
+ "fa-IR",
+ "fil",
+ "fil-PH",
+ "fr",
+ "fr-FR",
+ "kok",
+ "kok-419",
+ "kok-419-variant",
+ "kok-IN",
+ "kok-Knda",
+ "kok-Knda-419",
+ "kok-Knda-419-variant",
+ "kok-variant",
+ "tgl",
+ "tgl-PH",
+ "xx",
+ "xx-YY"
+ };
+
+ final HashSet<String> KNOWN_LOCALES_SET =
+ new HashSet<String>(Arrays.asList(KNOWN_LOCALES));
+
+ final String PSEUDO_OR_EMPTY_LOCALES[] = {
+ "",
+ "en-XA",
+ "ar-XB"
+ };
+
+ String locales[] = mAssets.getNonSystemLocales();
+ HashSet<String> localesSet = new HashSet<String>(Arrays.asList(locales));
+ for (String l : PSEUDO_OR_EMPTY_LOCALES) {
+ localesSet.remove(l);
+ }
+
+ assertEquals(KNOWN_LOCALES_SET, localesSet);
+ }
+
private void assertContextEquals(final String expect, final InputStream inputStream)
throws IOException {
final BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream));
diff --git a/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java b/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java
index 88f5798..2222ce4 100644
--- a/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java
@@ -27,7 +27,7 @@
import android.os.Parcel;
import android.test.AndroidTestCase;
-import com.android.cts.content.R;
+import android.content.cts.R;
public class ColorStateListTest extends AndroidTestCase {
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 0b94b6f..2390146 100644
--- a/tests/tests/content/src/android/content/res/cts/ConfigTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ConfigTest.java
@@ -31,7 +31,7 @@
import android.util.DisplayMetrics;
import android.util.Log;
-import com.android.cts.content.R;
+import android.content.cts.R;
public class ConfigTest extends AndroidTestCase {
enum Properties {
diff --git a/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java b/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java
index 30c78a8..c1ee6c4 100644
--- a/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java
@@ -22,6 +22,7 @@
import android.content.res.Configuration;
import android.os.Parcel;
import android.test.AndroidTestCase;
+import android.util.LocaleList;
import android.view.View;
public class ConfigurationTest extends AndroidTestCase {
@@ -40,7 +41,7 @@
mConfig = new Configuration();
mConfig.fontScale = 2;
mConfig.mcc = mConfig.mnc = 1;
- mConfig.locale = Locale.getDefault();
+ mConfig.setLocale(Locale.getDefault());
mConfig.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
mConfig.keyboard = Configuration.KEYBOARD_NOKEYS;
mConfig.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
@@ -93,6 +94,27 @@
cfg2.touchscreen = 2;
assertEquals(1, cfg1.compareTo(cfg2));
+ cfg1.setLocales(LocaleList.forLanguageTags("fr"));
+ cfg2.setLocales(LocaleList.forLanguageTags("fr,en"));
+ assertTrue(cfg1.compareTo(cfg2) < 0);
+ cfg1.setLocales(LocaleList.forLanguageTags("fr,en"));
+ cfg2.setLocales(LocaleList.forLanguageTags("fr"));
+ assertTrue(cfg1.compareTo(cfg2) > 0);
+
+ cfg1.setLocales(LocaleList.forLanguageTags("fr,en"));
+ cfg2.setLocales(LocaleList.forLanguageTags("fr,en-US"));
+ assertTrue(cfg1.compareTo(cfg2) < 0);
+ cfg1.setLocales(LocaleList.forLanguageTags("fr,en-US"));
+ cfg2.setLocales(LocaleList.forLanguageTags("fr,en"));
+ assertTrue(cfg1.compareTo(cfg2) > 0);
+
+ cfg1.locale = Locale.forLanguageTag("en");
+ cfg2.locale = Locale.forLanguageTag("en-Shaw");
+ assertTrue(cfg1.compareTo(cfg2) < 0);
+ cfg1.locale = Locale.forLanguageTag("en-Shaw");
+ cfg2.locale = Locale.forLanguageTag("en");
+ assertTrue(cfg1.compareTo(cfg2) > 0);
+
cfg1.locale = new Locale("", "", "2");
cfg2.locale = new Locale("", "", "3");
assertEquals(-1, cfg1.compareTo(cfg2));
@@ -114,6 +136,13 @@
cfg2.locale = new Locale("2", "", "");
assertEquals(1, cfg1.compareTo(cfg2));
+ cfg1.locale = new Locale("");
+ cfg2.locale = null;
+ assertTrue(cfg1.compareTo(cfg2) < 0);
+ cfg1.locale = null;
+ cfg2.locale = new Locale("");
+ assertTrue(cfg1.compareTo(cfg2) > 0);
+
cfg1.mnc = 2;
cfg2.mnc = 3;
assertEquals(-1, cfg1.compareTo(cfg2));
@@ -160,6 +189,11 @@
| ActivityInfo.CONFIG_MNC
| ActivityInfo.CONFIG_LOCALE
| ActivityInfo.CONFIG_LAYOUT_DIRECTION, mConfigDefault, config);
+ config.setLocales(LocaleList.forLanguageTags("fr,en"));
+ doConfigCompare(ActivityInfo.CONFIG_MCC
+ | ActivityInfo.CONFIG_MNC
+ | ActivityInfo.CONFIG_LOCALE
+ | ActivityInfo.CONFIG_LAYOUT_DIRECTION, mConfigDefault, config);
config.screenLayout = 1;
doConfigCompare(ActivityInfo.CONFIG_MCC
| ActivityInfo.CONFIG_MNC
@@ -282,6 +316,7 @@
assertFalse(temp.equals(mConfigDefault));
temp.setToDefaults();
assertTrue(temp.equals(mConfigDefault));
+ assertTrue(temp.getLocales().isEmpty());
}
public void testToString() {
@@ -289,47 +324,62 @@
}
public void testWriteToParcel() {
- assertWriteToParcel(createConfig(null), Parcel.obtain());
+ assertWriteToParcel(createConfig((Locale) null), Parcel.obtain());
+ assertWriteToParcel(createConfig(new Locale("")), Parcel.obtain());
assertWriteToParcel(createConfig(Locale.JAPAN), Parcel.obtain());
+ assertWriteToParcel(createConfig(Locale.forLanguageTag("en-Shaw")), Parcel.obtain());
+ assertWriteToParcel(createConfig(LocaleList.forLanguageTags("fr,en-US")), Parcel.obtain());
}
public void testSetLocale() {
Configuration config = new Configuration();
+ config.setLocale(null);
+ assertNull(config.locale);
+ assertTrue(config.getLocales().isEmpty());
+
config.setLocale(Locale.getDefault());
assertEquals(Locale.getDefault(), config.locale);
- assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+ assertEquals(new LocaleList(Locale.getDefault()), config.getLocales());
config.setLocale(Locale.ENGLISH);
assertEquals(Locale.ENGLISH, config.locale);
+ assertEquals(new LocaleList(Locale.ENGLISH), config.getLocales());
assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
config.setLocale(Locale.US);
assertEquals(Locale.US, config.locale);
+ assertEquals(new LocaleList(Locale.US), config.getLocales());
assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
final Locale arEGLocale = new Locale("ar", "EG");
config.setLocale(arEGLocale);
assertEquals(arEGLocale, config.locale);
+ assertEquals(new LocaleList(arEGLocale), config.getLocales());
assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
- final Locale faFALocale = new Locale("fa", "FA");
- config.setLocale(faFALocale);
- assertEquals(faFALocale, config.locale);
+ final Locale faIRLocale = new Locale("fa", "IR");
+ config.setLocale(faIRLocale);
+ assertEquals(faIRLocale, config.locale);
+ assertEquals(new LocaleList(faIRLocale), config.getLocales());
assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
final Locale iwILLocale = new Locale("iw", "IL");
config.setLocale(iwILLocale);
assertEquals(iwILLocale, config.locale);
+ assertEquals(new LocaleList(iwILLocale), config.getLocales());
+ assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+
+ final Locale urPKLocale = new Locale("ur", "PK");
+ config.setLocale(urPKLocale);
+ assertEquals(urPKLocale, config.locale);
+ assertEquals(new LocaleList(urPKLocale), config.getLocales());
assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
}
public void testSetGetLayoutDirection() {
Configuration config = new Configuration();
- config.setLayoutDirection(Locale.getDefault());
- assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
-
config.setLayoutDirection(Locale.ENGLISH);
assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
@@ -340,21 +390,240 @@
config.setLayoutDirection(arEGLocale);
assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
- final Locale faFALocale = new Locale("fa", "FA");
- config.setLayoutDirection(faFALocale);
+ final Locale faIRLocale = new Locale("fa", "IR");
+ config.setLayoutDirection(faIRLocale);
assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
final Locale iwILLocale = new Locale("iw", "IL");
config.setLayoutDirection(iwILLocale);
assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+
+ final Locale urPKLocale = new Locale("ur", "PK");
+ config.setLayoutDirection(urPKLocale);
+ assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+ }
+
+ public void testFixUpLocaleList() {
+ Configuration config = new Configuration();
+
+ config.setLocales(LocaleList.forLanguageTags("fr"));
+ config.locale = null;
+ assertEquals(LocaleList.getEmptyLocaleList(), config.getLocales());
+
+ config.setLocales(LocaleList.forLanguageTags("fr,en"));
+ config.locale = Locale.forLanguageTag("en");
+ assertEquals(LocaleList.forLanguageTags("en"), config.getLocales());
+
+ config.setLocales(LocaleList.forLanguageTags("fr,en"));
+ config.locale = Locale.forLanguageTag("fr");
+ assertEquals(LocaleList.forLanguageTags("fr,en"), config.getLocales());
+ }
+
+ public void testSetTo_nullLocale() {
+ Configuration config1 = new Configuration();
+ Configuration config2 = new Configuration();
+ assertEquals(null, config2.locale);
+
+ config1.setLocale(Locale.FRENCH);
+ config1.setTo(config2);
+ assertEquals(null, config1.locale);
+ }
+
+ public void testSetTo_localeFixUp() {
+ Configuration config1 = new Configuration();
+ Configuration config2 = new Configuration();
+ config2.locale = Locale.FRENCH;
+
+ config1.setTo(config2);
+ assertEquals(Locale.FRENCH, config1.locale);
+ assertEquals(new LocaleList(Locale.FRENCH), config1.getLocales());
+ assertEquals(new LocaleList(Locale.FRENCH), config2.getLocales());
+ }
+
+ public void testToString_localeFixUp() {
+ Configuration config1 = new Configuration();
+ Configuration config2 = new Configuration();
+ config1.setLocales(LocaleList.forLanguageTags("fr,en"));
+ config1.locale = Locale.forLanguageTag("en");
+ config2.setLocales(LocaleList.forLanguageTags("en"));
+
+ assertEquals(config1.toString(), config2.toString());
+ }
+
+ public void testUpdateFrom_localeFixUp() {
+ Configuration config1, config2;
+ int changed;
+
+ config1 = new Configuration();
+ config2 = new Configuration();
+ config1.locale = Locale.FRENCH;
+ changed = config1.updateFrom(config2);
+ assertEquals(0, changed);
+ assertEquals(Locale.FRENCH, config1.locale);
+ assertEquals(new LocaleList(Locale.FRENCH), config1.getLocales());
+
+ config1 = new Configuration();
+ config2 = new Configuration();
+ config2.locale = Locale.FRENCH;
+ changed = config1.updateFrom(config2);
+ assertEquals(ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_LAYOUT_DIRECTION, changed);
+ assertEquals(Locale.FRENCH, config1.locale);
+ assertEquals(new LocaleList(Locale.FRENCH), config1.getLocales());
+ assertEquals(new LocaleList(Locale.FRENCH), config2.getLocales());
+
+ config1 = new Configuration();
+ config2 = new Configuration();
+ config1.setLocales(LocaleList.forLanguageTags("en,fr"));
+ config1.locale = Locale.forLanguageTag("fr");
+ config2.setLocales(LocaleList.forLanguageTags("en,de"));
+ config2.locale = Locale.forLanguageTag("fr");
+ changed = config1.updateFrom(config2);
+ assertEquals(0, changed);
+ assertEquals(Locale.forLanguageTag("fr"), config1.locale);
+ assertEquals(LocaleList.forLanguageTags("fr"), config1.getLocales());
+ assertEquals(LocaleList.forLanguageTags("fr"), config2.getLocales());
+ }
+
+ public void testUpdateFrom_layoutDirection() {
+ Configuration config1, config2;
+ int changed;
+
+ config1 = new Configuration();
+ config2 = new Configuration();
+ config1.setLocales(LocaleList.forLanguageTags("fr,en"));
+ config2.setLocales(LocaleList.forLanguageTags("de,en"));
+ changed = config1.updateFrom(config2);
+ assertTrue((changed & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0);
+
+ config1 = new Configuration();
+ config2 = new Configuration();
+ config1.setLocales(LocaleList.forLanguageTags("fr,en"));
+ config2.setLocales(LocaleList.forLanguageTags("fr,de"));
+ changed = config1.updateFrom(config2);
+ assertEquals(0, changed & ActivityInfo.CONFIG_LAYOUT_DIRECTION);
+ }
+
+ public void testDiff_localeFixUp() {
+ Configuration config1 = new Configuration();
+ Configuration config2 = new Configuration();
+ config1.setLocales(LocaleList.forLanguageTags("en,fr"));
+ config1.locale = Locale.forLanguageTag("fr");
+ config2.setLocales(LocaleList.forLanguageTags("en,de"));
+ config2.locale = Locale.forLanguageTag("fr");
+
+ int diff = config1.diff(config2);
+ assertEquals(0, diff);
+ }
+
+ public void testCompareTo_localeFixUp() {
+ Configuration config1 = new Configuration();
+ Configuration config2 = new Configuration();
+ config1.setLocales(LocaleList.forLanguageTags("en,fr"));
+ config2.setLocales(LocaleList.forLanguageTags("en,fr"));
+ assertEquals(0, config1.compareTo(config2));
+ config1.locale = new Locale("2");
+ config2.locale = new Locale("3");
+ assertEquals(-1, config1.compareTo(config2));
+ }
+
+ public void testSetLocales_null() {
+ Configuration config = new Configuration();
+ config.setLocales(null);
+ assertNull(config.locale);
+ assertNotNull(config.getLocales());
+ assertTrue(config.getLocales().isEmpty());
+ assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+ }
+
+ public void testSetLocales_emptyList() {
+ Configuration config = new Configuration();
+ config.setLocales(LocaleList.getEmptyLocaleList());
+ assertNull(config.locale);
+ assertNotNull(config.getLocales());
+ assertTrue(config.getLocales().isEmpty());
+ assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+ }
+
+ public void testSetLocales_oneLtr() {
+ Configuration config = new Configuration();
+ Locale loc = Locale.forLanguageTag("en");
+ LocaleList ll = new LocaleList(loc);
+ config.setLocales(ll);
+ assertEquals(loc, config.locale);
+ assertEquals(ll, config.getLocales());
+ assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+ }
+
+ public void testSetLocales_oneRtl() {
+ Configuration config = new Configuration();
+ Locale loc = Locale.forLanguageTag("az-Arab");
+ LocaleList ll = new LocaleList(loc);
+ config.setLocales(ll);
+ assertEquals(loc, config.locale);
+ assertEquals(ll, config.getLocales());
+ assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+ }
+
+ public void testSetLocales_twoLocales() {
+ Configuration config = new Configuration();
+ Locale rtlLoc = Locale.forLanguageTag("az-Arab");
+ Locale ltrLoc = Locale.forLanguageTag("en");
+ LocaleList ll = LocaleList.forLanguageTags("az-Arab,en");
+ config.setLocales(ll);
+ assertEquals(rtlLoc, config.locale);
+ assertEquals(ll, config.getLocales());
+ assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+ }
+
+ public void testSetLocales_overridesLocale() {
+ Configuration config = new Configuration();
+ config.locale = Locale.forLanguageTag("en");
+ LocaleList ll = LocaleList.forLanguageTags("az-Arab,en");
+ config.setLocales(ll);
+
+ assertEquals(Locale.forLanguageTag("az-Arab"), config.locale);
+ assertEquals(ll, config.getLocales());
+ assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+ }
+
+ public void testSetLocales_overridesSetLocale() {
+ Configuration config = new Configuration();
+ config.setLocale(Locale.forLanguageTag("en"));
+ LocaleList ll = LocaleList.forLanguageTags("az-Arab,en");
+ config.setLocales(ll);
+
+ assertEquals(Locale.forLanguageTag("az-Arab"), config.locale);
+ assertEquals(ll, config.getLocales());
+ assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+ }
+
+ public void testSetLocale_overridesSetLocales() {
+ Configuration config = new Configuration();
+ config.setLocales(LocaleList.forLanguageTags("az-Arab,en"));
+ config.setLocale(Locale.ENGLISH);
+
+ assertEquals(Locale.ENGLISH, config.locale);
+ assertEquals(new LocaleList(Locale.ENGLISH), config.getLocales());
+ assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+ }
+
+ private Configuration createConfig(LocaleList list) {
+ Configuration config = createConfig();
+ config.setLocales(list);
+ return config;
}
private Configuration createConfig(Locale locale) {
+ Configuration config = createConfig();
+ config.locale = locale;
+ return config;
+ }
+
+ private Configuration createConfig() {
Configuration config = new Configuration();
config.fontScale = 13.37f;
config.mcc = 0;
config.mnc = 1;
- config.locale = locale;
config.touchscreen = Configuration.TOUCHSCREEN_STYLUS;
config.keyboard = Configuration.KEYBOARD_UNDEFINED;
config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
diff --git a/tests/tests/content/src/android/content/res/cts/FractionTest.java b/tests/tests/content/src/android/content/res/cts/FractionTest.java
index 2c3e797..6a65915 100644
--- a/tests/tests/content/src/android/content/res/cts/FractionTest.java
+++ b/tests/tests/content/src/android/content/res/cts/FractionTest.java
@@ -20,7 +20,7 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.TypedValue;
-import com.android.cts.content.R;
+import android.content.cts.R;
public class FractionTest extends AndroidTestCase {
diff --git a/tests/tests/content/src/android/content/res/cts/PluralResourcesTest.java b/tests/tests/content/src/android/content/res/cts/PluralResourcesTest.java
index 1fd204d..7c42c9e 100644
--- a/tests/tests/content/src/android/content/res/cts/PluralResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/PluralResourcesTest.java
@@ -25,7 +25,7 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
-import com.android.cts.content.R;
+import android.content.cts.R;
public class PluralResourcesTest extends AndroidTestCase {
public static boolean DEBUG = false;
@@ -42,7 +42,7 @@
private Resources resourcesForLanguage(final String lang) {
final Configuration config = new Configuration();
config.updateFrom(mResources.getConfiguration());
- config.locale = new Locale(lang);
+ config.setLocale(new Locale(lang));
return new Resources(mResources.getAssets(), mResources.getDisplayMetrics(), config);
}
diff --git a/tests/tests/content/src/android/content/res/cts/PrimitiveTest.java b/tests/tests/content/src/android/content/res/cts/PrimitiveTest.java
index 8eeb086..a612a15 100644
--- a/tests/tests/content/src/android/content/res/cts/PrimitiveTest.java
+++ b/tests/tests/content/src/android/content/res/cts/PrimitiveTest.java
@@ -21,7 +21,7 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.TypedValue;
-import com.android.cts.content.R;
+import android.content.cts.R;
public class PrimitiveTest extends AndroidTestCase {
private Resources mResources;
diff --git a/tests/tests/content/src/android/content/res/cts/RawResourceTest.java b/tests/tests/content/src/android/content/res/cts/RawResourceTest.java
index c92efc7..3ca0055 100644
--- a/tests/tests/content/src/android/content/res/cts/RawResourceTest.java
+++ b/tests/tests/content/src/android/content/res/cts/RawResourceTest.java
@@ -19,7 +19,7 @@
import android.content.res.Resources;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.cts.content.R;
+import android.content.cts.R;
import java.io.IOException;
import java.io.InputStream;
diff --git a/tests/tests/content/src/android/content/res/cts/ResourceNameTest.java b/tests/tests/content/src/android/content/res/cts/ResourceNameTest.java
index a7cc03b..dde2422 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourceNameTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourceNameTest.java
@@ -20,7 +20,7 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.cts.content.R;
+import android.content.cts.R;
public class ResourceNameTest extends AndroidTestCase {
@@ -29,10 +29,10 @@
final Resources res = mContext.getResources();
final String fullName = res.getResourceName(R.configVarying.simple);
- assertEquals("com.android.cts.content:configVarying/simple", fullName);
+ assertEquals("android.content.cts:configVarying/simple", fullName);
final String packageName = res.getResourcePackageName(R.configVarying.simple);
- assertEquals("com.android.cts.content", packageName);
+ assertEquals("android.content.cts", packageName);
final String typeName = res.getResourceTypeName(R.configVarying.simple);
assertEquals("configVarying", typeName);
@@ -45,16 +45,16 @@
public void testGetResourceIdentifier() {
final Resources res = mContext.getResources();
int resid = res.getIdentifier(
- "com.android.cts.content:configVarying/simple",
+ "android.content.cts:configVarying/simple",
null, null);
assertEquals(R.configVarying.simple, resid);
resid = res.getIdentifier("configVarying/simple", null,
- "com.android.cts.content");
+ "android.content.cts");
assertEquals(R.configVarying.simple, resid);
resid = res.getIdentifier("simple", "configVarying",
- "com.android.cts.content");
+ "android.content.cts");
assertEquals(R.configVarying.simple, resid);
}
}
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 4e2d60a..1304b26 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -16,7 +16,7 @@
package android.content.res.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -35,6 +35,7 @@
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.LocaleList;
import android.util.TypedValue;
import android.util.Xml;
import android.view.Display;
@@ -48,9 +49,9 @@
private static final String CONFIG_VARYING = "configVarying";
private static final String SIMPLE = "simple";
private static final String CONFIG_VARYING_SIMPLE = "configVarying/simple";
- private static final String PACKAGE_NAME = "com.android.cts.content";
+ private static final String PACKAGE_NAME = "android.content.cts";
private static final String COM_ANDROID_CTS_STUB_IDENTIFIER =
- "com.android.cts.content:configVarying/simple";
+ "android.content.cts:configVarying/simple";
private Resources mResources;
@Override
@@ -216,14 +217,120 @@
assertEquals(0xff00ff00, color);
}
+ public Resources createNewResources() {
+ final DisplayMetrics dm = new DisplayMetrics();
+ dm.setToDefaults();
+ final Configuration cfg = new Configuration();
+ cfg.setToDefaults();
+ return new Resources(new AssetManager(), dm, cfg);
+ }
+
public void testUpdateConfiguration() {
- final Configuration cfg = mResources.getConfiguration();
+ Resources res = createNewResources();
+ final Configuration cfg = new Configuration(res.getConfiguration());
assertTrue(cfg.fontScale != 5);
cfg.fontScale = 5;
- mResources.updateConfiguration(cfg, null);
- Configuration cfgNew = mResources.getConfiguration();
- assertEquals(5.0f, cfgNew.fontScale, 0.001f);
+ res.updateConfiguration(cfg, null);
+ assertEquals(5.0f, res.getConfiguration().fontScale, 0.001f);
+ }
+
+ public void testUpdateConfiguration_emptyLocaleIsOverridden() {
+ Resources res = createNewResources();
+ res.getConfiguration().setLocales(null);
+ assertTrue(res.getConfiguration().getLocales().isEmpty());
+
+ final Configuration cfg = new Configuration();
+ cfg.setToDefaults();
+ assertTrue(cfg.getLocales().isEmpty());
+
+ res.updateConfiguration(cfg, null);
+ assertEquals(LocaleList.getDefault(), res.getConfiguration().getLocales());
+ }
+
+ public void testUpdateConfiguration_copyLocales() {
+ Resources res = createNewResources();
+ final Configuration cfg = new Configuration(res.getConfiguration());
+
+ cfg.setLocales(LocaleList.forLanguageTags("az-Arab,ru"));
+
+ res.updateConfiguration(cfg, null);
+ assertEquals(LocaleList.forLanguageTags("az-Arab,ru"), res.getConfiguration().getLocales());
+ }
+
+ public void testUpdateConfiguration_emptyAfterUpdate() {
+ Resources res = createNewResources();
+ final Configuration cfg = new Configuration(res.getConfiguration());
+ cfg.setLocales(LocaleList.forLanguageTags("az-Arab"));
+
+ res.updateConfiguration(cfg, null);
+ assertEquals(LocaleList.forLanguageTags("az-Arab"), res.getConfiguration().getLocales());
+
+ res.getConfiguration().setLocales(null);
+ cfg.setLocales(null);
+ res.updateConfiguration(cfg, null);
+ assertEquals(LocaleList.getDefault(), res.getConfiguration().getLocales());
+ }
+
+ public void testUpdateConfiguration_ResolvedLocaleIsRecalculated() {
+ final DisplayMetrics dm = new DisplayMetrics();
+ dm.setToDefaults();
+ final Configuration cfg = new Configuration();
+ cfg.setToDefaults();
+
+ // Avestan has no assets, but Czech does
+ cfg.setLocales(LocaleList.forLanguageTags("ae"));
+ Resources res = new Resources(mResources.getAssets(), dm, cfg);
+ cfg.setLocales(LocaleList.forLanguageTags("ae,cs"));
+ res.updateConfiguration(cfg, null);
+ assertEquals("cs", res.getResolvedLocale().toLanguageTag());
+ }
+
+ public void testGetResolvedLocale_unsupportedLocale() {
+ final DisplayMetrics dm = new DisplayMetrics();
+ dm.setToDefaults();
+ final Configuration cfg = new Configuration();
+ cfg.setToDefaults();
+ cfg.setLocales(LocaleList.forLanguageTags("ae")); // Avestan has no assets
+
+ Resources res = new Resources(mResources.getAssets(), dm, cfg);
+ assertEquals("ae", res.getResolvedLocale().toLanguageTag());
+ }
+
+ public void testGetResolvedLocale_secondaryLocaleIsSupported() {
+ final DisplayMetrics dm = new DisplayMetrics();
+ dm.setToDefaults();
+ final Configuration cfg = new Configuration();
+ cfg.setToDefaults();
+ // Avestan has no assets, but Czech does
+ cfg.setLocales(LocaleList.forLanguageTags("ae,cs"));
+
+ Resources res = new Resources(mResources.getAssets(), dm, cfg);
+ assertEquals("cs", res.getResolvedLocale().toLanguageTag());
+ }
+
+ public void testGetResolvedLocale_secondaryLocaleIsPartiallySupported() {
+ final DisplayMetrics dm = new DisplayMetrics();
+ dm.setToDefaults();
+ final Configuration cfg = new Configuration();
+ cfg.setToDefaults();
+ // Avestan has no assets;
+ // Persian has assets for Iran, but not Afghanistan (partial match is accepted);
+ // Czech has assets (but we don't get to it)
+ cfg.setLocales(LocaleList.forLanguageTags("ae,fa-AF,cs"));
+
+ Resources res = new Resources(mResources.getAssets(), dm, cfg);
+ assertEquals("fa-AF", res.getResolvedLocale().toLanguageTag());
+ }
+
+ public void testGetResolvedLocale_SystemResourcesLocaleNonNull() {
+ Resources res = Resources.getSystem();
+ assertNotNull(res.getResolvedLocale());
+ }
+
+ public void testGetResolvedLocale_NonNull() {
+ Resources res = createNewResources();
+ assertNotNull(res.getResolvedLocale());
}
public void testGetDimensionPixelSize() {
@@ -256,6 +363,20 @@
assertEquals(142 * targetDensity / defaultDensity, draw.getIntrinsicHeight(), 1);
}
+ public void testGetDrawableForDensity() {
+ final Drawable ldpi = mResources.getDrawableForDensity(
+ R.drawable.density_test, DisplayMetrics.DENSITY_LOW);
+ assertEquals(300, ldpi.getIntrinsicWidth());
+
+ final Drawable mdpi = mResources.getDrawableForDensity(
+ R.drawable.density_test, DisplayMetrics.DENSITY_MEDIUM);
+ assertEquals(200, mdpi.getIntrinsicWidth());
+
+ final Drawable hdpi = mResources.getDrawableForDensity(
+ R.drawable.density_test, DisplayMetrics.DENSITY_HIGH);
+ assertEquals(100, hdpi.getIntrinsicWidth());
+ }
+
public void testGetAnimation() throws Exception {
try {
mResources.getAnimation(-1);
@@ -319,11 +440,27 @@
//expected
}
- mResources.getValue("com.android.cts.content:raw/text", tv, false);
+ mResources.getValue("android.content.cts:raw/text", tv, false);
assertNotNull(tv);
assertEquals("res/raw/text.txt", tv.coerceToString());
}
+ public void testGetValueForDensity() {
+ final TypedValue tv = new TypedValue();
+
+ mResources.getValueForDensity(R.string.density_string,
+ DisplayMetrics.DENSITY_LOW, tv, false);
+ assertEquals("ldpi", tv.coerceToString());
+
+ mResources.getValueForDensity(R.string.density_string,
+ DisplayMetrics.DENSITY_MEDIUM, tv, false);
+ assertEquals("mdpi", tv.coerceToString());
+
+ mResources.getValueForDensity(R.string.density_string,
+ DisplayMetrics.DENSITY_HIGH, tv, false);
+ assertEquals("hdpi", tv.coerceToString());
+ }
+
public void testGetAssets() {
final AssetManager aM = mResources.getAssets();
assertNotNull(aM);
@@ -456,7 +593,7 @@
private Resources resourcesForLanguage(final String lang) {
final Configuration config = new Configuration();
config.updateFrom(mResources.getConfiguration());
- config.locale = new Locale(lang);
+ config.setLocale(new Locale(lang));
return new Resources(mResources.getAssets(), mResources.getDisplayMetrics(), config);
}
diff --git a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
index 6d1c2e4..533b186 100644
--- a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
+++ b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
@@ -29,7 +29,7 @@
import android.util.Xml;
import android.view.View;
-import com.android.cts.content.R;
+import android.content.cts.R;
import java.util.Locale;
@@ -108,6 +108,8 @@
Resources res = getContext().getResources();
Configuration config = res.getConfiguration();
config.setLocale(Locale.ENGLISH);
+ res.updateConfiguration(config, null);
+
assertEquals("Theme will be created in LTR config",
View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
diff --git a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
index 346bb9b..2eb82a8 100644
--- a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
@@ -16,7 +16,7 @@
package android.content.res.cts;
-import com.android.cts.content.R;
+import android.content.cts.R;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/database/Android.mk b/tests/tests/database/Android.mk
index 8557c60..a554528 100644
--- a/tests/tests/database/Android.mk
+++ b/tests/tests/database/Android.mk
@@ -29,4 +29,7 @@
LOCAL_PACKAGE_NAME := CtsDatabaseTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/database/AndroidManifest.xml b/tests/tests/database/AndroidManifest.xml
index fefcc1f..f9043db 100644
--- a/tests/tests/database/AndroidManifest.xml
+++ b/tests/tests/database/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.database">
+ package="android.database.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -24,7 +24,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.database"
+ android:targetPackage="android.database.cts"
android:label="CTS tests of android.database">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/database/AndroidTest.xml b/tests/tests/database/AndroidTest.xml
new file mode 100644
index 0000000..046215d
--- /dev/null
+++ b/tests/tests/database/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS Database test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsDatabaseTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.database.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/display/Android.mk b/tests/tests/display/Android.mk
index f17f580..dc815c3 100644
--- a/tests/tests/display/Android.mk
+++ b/tests/tests/display/Android.mk
@@ -16,17 +16,26 @@
include $(CLEAR_VARS)
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsDisplayTestCases
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/display/AndroidManifest.xml b/tests/tests/display/AndroidManifest.xml
index bf84219..22cc824 100644
--- a/tests/tests/display/AndroidManifest.xml
+++ b/tests/tests/display/AndroidManifest.xml
@@ -16,9 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.display">
+ package="android.display.cts">
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<!-- For special presentation windows when testing mode switches. -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
@@ -26,12 +25,11 @@
<uses-library android:name="android.test.runner" />
</application>
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.display"
- android:label="CTS tests of android.view.display">
- <meta-data
- android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
+ <!-- self-instrumenting test package. -->
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.display.cts"
+ android:label="CTS tests of android.display">
</instrumentation>
</manifest>
diff --git a/tests/tests/display/AndroidTest.xml b/tests/tests/display/AndroidTest.xml
index dd42984..f346c22 100644
--- a/tests/tests/display/AndroidTest.xml
+++ b/tests/tests/display/AndroidTest.xml
@@ -13,9 +13,17 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Base config for CTS package preparer">
- <include name="common-config" />
- <!-- Use a non-standard pattern, must match values in tests/tests/display/.../DisplayTest.java -->
- <option name="run-command:run-command" value="settings put global overlay_display_devices '181x161/214|181x161/214'" />
- <option name="run-command:teardown-command" value="settings put global overlay_display_devices """ />
-</configuration>
+<configuration description="Config for CTS Acceleration test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsDisplayTestCases.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <!-- Use a non-standard pattern, must match values in tests/tests/display/.../DisplayTest.java -->
+ <option name="run-command" value="settings put global overlay_display_devices '181x161/214|181x161/214'" />
+ <option name="teardown-command" value="settings put global overlay_display_devices """ />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.display.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/display/OldAndroidTest.xml b/tests/tests/display/OldAndroidTest.xml
new file mode 100644
index 0000000..dd42984
--- /dev/null
+++ b/tests/tests/display/OldAndroidTest.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<configuration description="Base config for CTS package preparer">
+ <include name="common-config" />
+ <!-- Use a non-standard pattern, must match values in tests/tests/display/.../DisplayTest.java -->
+ <option name="run-command:run-command" value="settings put global overlay_display_devices '181x161/214|181x161/214'" />
+ <option name="run-command:teardown-command" value="settings put global overlay_display_devices """ />
+</configuration>
diff --git a/tests/tests/dpi/Android.mk b/tests/tests/dpi/Android.mk
index 4c05ecf..c961c4c 100644
--- a/tests/tests/dpi/Android.mk
+++ b/tests/tests/dpi/Android.mk
@@ -30,6 +30,9 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
# ============================================================
diff --git a/tests/tests/dpi/AndroidManifest.xml b/tests/tests/dpi/AndroidManifest.xml
index 0197056..118050e 100644
--- a/tests/tests/dpi/AndroidManifest.xml
+++ b/tests/tests/dpi/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.dpi">
+ package="android.dpi.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -27,7 +27,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.dpi"
+ android:targetPackage="android.dpi.cts"
android:label="CTS tests for DPI">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/dpi/AndroidTest.xml b/tests/tests/dpi/AndroidTest.xml
new file mode 100644
index 0000000..b8d941b
--- /dev/null
+++ b/tests/tests/dpi/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS DPI test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsDpiTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.dpi.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/dpi/src/android/dpi/cts/DefaultManifestAttributesSdkTest.java b/tests/tests/dpi/src/android/dpi/cts/DefaultManifestAttributesSdkTest.java
index 9253eca..d11f3ae 100644
--- a/tests/tests/dpi/src/android/dpi/cts/DefaultManifestAttributesSdkTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/DefaultManifestAttributesSdkTest.java
@@ -24,7 +24,7 @@
*/
public class DefaultManifestAttributesSdkTest extends DefaultManifestAttributesTest {
protected String getPackageName() {
- return "com.android.cts.dpi";
+ return "android.dpi.cts";
}
// This is a sanity test to make sure that we're instrumenting the proper package
diff --git a/tests/tests/dpi2/Android.mk b/tests/tests/dpi2/Android.mk
index 03a687d..af1207d 100644
--- a/tests/tests/dpi2/Android.mk
+++ b/tests/tests/dpi2/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/dpi2/AndroidManifest.xml b/tests/tests/dpi2/AndroidManifest.xml
index 6dbdc23..bb21910 100644
--- a/tests/tests/dpi2/AndroidManifest.xml
+++ b/tests/tests/dpi2/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.dpi2">
+ package="android.dpi2.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -28,7 +28,7 @@
<uses-sdk android:targetSdkVersion="3" />
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.dpi2"
+ android:targetPackage="android.dpi2.cts"
android:label="CTS tests for DPI">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/dpi2/AndroidTest.xml b/tests/tests/dpi2/AndroidTest.xml
new file mode 100644
index 0000000..dfb1730
--- /dev/null
+++ b/tests/tests/dpi2/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS DPI test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsDpiTestCases2.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.dpi2.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/dpi2/src/android/dpi2/cts/DefaultManifestAttributesCupcakeTest.java b/tests/tests/dpi2/src/android/dpi2/cts/DefaultManifestAttributesCupcakeTest.java
index 27a082b..04db412 100644
--- a/tests/tests/dpi2/src/android/dpi2/cts/DefaultManifestAttributesCupcakeTest.java
+++ b/tests/tests/dpi2/src/android/dpi2/cts/DefaultManifestAttributesCupcakeTest.java
@@ -29,7 +29,7 @@
*/
public class DefaultManifestAttributesCupcakeTest extends DefaultManifestAttributesTest {
protected String getPackageName() {
- return "com.android.cts.dpi2";
+ return "android.dpi2.cts";
}
// This is a sanity test to make sure that we're instrumenting the proper package
diff --git a/tests/tests/dreams/Android.mk b/tests/tests/dreams/Android.mk
index 87bd357..8a4c499 100644
--- a/tests/tests/dreams/Android.mk
+++ b/tests/tests/dreams/Android.mk
@@ -33,4 +33,7 @@
# Need access to ServiceManager - see b/13307221
#LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/dreams/AndroidManifest.xml b/tests/tests/dreams/AndroidManifest.xml
index b395a4f..8f1d75e 100644
--- a/tests/tests/dreams/AndroidManifest.xml
+++ b/tests/tests/dreams/AndroidManifest.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.dreams">
+ package="android.dreams.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -23,7 +23,7 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.dreams"
+ android:targetPackage="android.dreams.cts"
android:label="CTS tests for the android.service.dreams package">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/dreams/AndroidTest.xml b/tests/tests/dreams/AndroidTest.xml
new file mode 100644
index 0000000..b334ade
--- /dev/null
+++ b/tests/tests/dreams/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS Dreams test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsDreamsTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.dreams.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/drm/Android.mk b/tests/tests/drm/Android.mk
index 6272e9c..db6ec92 100644
--- a/tests/tests/drm/Android.mk
+++ b/tests/tests/drm/Android.mk
@@ -28,6 +28,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsDrmTestCases
LOCAL_JNI_SHARED_LIBRARIES := \
diff --git a/tests/tests/drm/AndroidManifest.xml b/tests/tests/drm/AndroidManifest.xml
index 527d498..c4ea03d 100644
--- a/tests/tests/drm/AndroidManifest.xml
+++ b/tests/tests/drm/AndroidManifest.xml
@@ -14,8 +14,7 @@
limitations under the License.
-->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.drm">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.drm.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -23,11 +22,10 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.drm"
+ android:targetPackage="android.drm.cts"
android:label="CTS tests of android.drm">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
-
diff --git a/tests/tests/drm/AndroidTest.xml b/tests/tests/drm/AndroidTest.xml
new file mode 100644
index 0000000..48287aa
--- /dev/null
+++ b/tests/tests/drm/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS DRM test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsDrmTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.drm.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/effect/Android.mk b/tests/tests/effect/Android.mk
index 6a9778e..aac0d73 100644
--- a/tests/tests/effect/Android.mk
+++ b/tests/tests/effect/Android.mk
@@ -28,6 +28,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/effect/AndroidManifest.xml b/tests/tests/effect/AndroidManifest.xml
index 481be14..81f3bbf 100644
--- a/tests/tests/effect/AndroidManifest.xml
+++ b/tests/tests/effect/AndroidManifest.xml
@@ -14,8 +14,7 @@
limitations under the License.
-->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.effect">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.effect.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -24,7 +23,7 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.effect"
+ android:targetPackage="android.effect.cts"
android:label="CTS tests of android.media.effect component">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/effect/AndroidTest.xml b/tests/tests/effect/AndroidTest.xml
new file mode 100644
index 0000000..abf2b22
--- /dev/null
+++ b/tests/tests/effect/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Effect test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsEffectTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.effect.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/gesture/Android.mk b/tests/tests/gesture/Android.mk
index 4a97931..0c4e023 100755
--- a/tests/tests/gesture/Android.mk
+++ b/tests/tests/gesture/Android.mk
@@ -16,15 +16,22 @@
include $(CLEAR_VARS)
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsGestureTestCases
LOCAL_SDK_VERSION := current
diff --git a/tests/tests/gesture/AndroidManifest.xml b/tests/tests/gesture/AndroidManifest.xml
index b288cd2..fb3ee51 100755
--- a/tests/tests/gesture/AndroidManifest.xml
+++ b/tests/tests/gesture/AndroidManifest.xml
@@ -16,19 +16,17 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.gesture">
+ package="android.gesture.cts">
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
<uses-library android:name="android.test.runner" />
</application>
<!-- self-instrumenting test package. -->
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.gesture"
- android:label="CTS tests of android.gesture">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.gesture.cts"
+ android:label="CTS tests of android.gesture">
</instrumentation>
</manifest>
diff --git a/tests/tests/gesture/AndroidTest.xml b/tests/tests/gesture/AndroidTest.xml
new file mode 100644
index 0000000..497cad1
--- /dev/null
+++ b/tests/tests/gesture/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Gesture test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsGestureTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.gesture.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index 773b47d..e722fa8 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -18,12 +18,15 @@
LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctsdeviceutil ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CtsGraphicsTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/graphics/AndroidManifest.xml b/tests/tests/graphics/AndroidManifest.xml
index 4249bb3..f14506f 100644
--- a/tests/tests/graphics/AndroidManifest.xml
+++ b/tests/tests/graphics/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.graphics">
+ package="android.graphics.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -54,7 +54,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.graphics"
+ android:targetPackage="android.graphics.cts"
android:label="CTS tests of android.graphics">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/graphics/AndroidTest.xml b/tests/tests/graphics/AndroidTest.xml
new file mode 100644
index 0000000..a9f746b
--- /dev/null
+++ b/tests/tests/graphics/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Graphics test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsGraphicsTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.graphics.cts" />
+ <option name="runtime-hint" value="5m" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/vector_icon_fill_state_list.xml b/tests/tests/graphics/res/color/vector_icon_fill_state_list.xml
new file mode 100644
index 0000000..f5b4632
--- /dev/null
+++ b/tests/tests/graphics/res/color/vector_icon_fill_state_list.xml
@@ -0,0 +1,22 @@
+<?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.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#00ff00" android:state_pressed="true" />
+ <item android:color="#0000ff" />
+</selector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/vector_icon_stroke_state_list.xml b/tests/tests/graphics/res/color/vector_icon_stroke_state_list.xml
new file mode 100644
index 0000000..bbc635e
--- /dev/null
+++ b/tests/tests/graphics/res/color/vector_icon_stroke_state_list.xml
@@ -0,0 +1,22 @@
+<?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.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#0000ff" android:state_pressed="true" />
+ <item android:color="#00ff00" />
+</selector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_arcto_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_arcto_golden.png
new file mode 100644
index 0000000..7ba0f17
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_arcto_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_implicit_lineto_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_implicit_lineto_golden.png
new file mode 100644
index 0000000..9d74952
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_implicit_lineto_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
index c60dfba..d24321c 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
index e7cc4d1..7e35798 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
index c7c049b..1427f4b 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_state_list_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_state_list_golden.png
new file mode 100644
index 0000000..3936c89
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_state_list_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_state_list_golden_pressed.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_state_list_golden_pressed.png
new file mode 100644
index 0000000..c5d06f6
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_state_list_golden_pressed.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/custom_drawable.xml b/tests/tests/graphics/res/drawable/custom_drawable.xml
new file mode 100644
index 0000000..cfb9bdb
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/custom_drawable.xml
@@ -0,0 +1,20 @@
+<?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.
+ -->
+
+<drawable xmlns:android="http://schemas.android.com/apk/res/android"
+ class="android.graphics.drawable.cts.CustomDrawableTest$CustomDrawable"
+ android:color="#ffff0000" />
diff --git a/tests/tests/graphics/res/drawable/gradient_drawable_density.xml b/tests/tests/graphics/res/drawable/gradient_drawable_density.xml
new file mode 100644
index 0000000..ad3a3be
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/gradient_drawable_density.xml
@@ -0,0 +1,43 @@
+<?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.
+ -->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="ring"
+ android:innerRadius="10dp"
+ android:thickness="4dp">
+ <gradient
+ android:gradientRadius="10dp" />
+ <corners
+ android:topLeftRadius="8dp"
+ android:topRightRadius="9dp"
+ android:bottomLeftRadius="10dp"
+ android:bottomRightRadius="11dp" />
+ <padding
+ android:left="11dp"
+ android:top="12dp"
+ android:right="13dp"
+ android:bottom="14dp" />
+ <stroke
+ android:color="@android:color/black"
+ android:dashGap="4dp"
+ android:dashWidth="4dp"
+ android:width="2dp" />
+ <size
+ android:width="200dp"
+ android:height="200dp" />
+</shape>
diff --git a/tests/tests/graphics/res/drawable/grayscale_jpg.jpg b/tests/tests/graphics/res/drawable/grayscale_jpg.jpg
new file mode 100644
index 0000000..6c6ae32
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/grayscale_jpg.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/grayscale_png.png b/tests/tests/graphics/res/drawable/grayscale_png.png
new file mode 100644
index 0000000..9f1beac
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/grayscale_png.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/inset_color.xml b/tests/tests/graphics/res/drawable/inset_color.xml
new file mode 100644
index 0000000..55cdf22
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/inset_color.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@android:color/white"
+ android:inset="10dp" />
+
diff --git a/tests/tests/graphics/res/drawable/inset_density.xml b/tests/tests/graphics/res/drawable/inset_density.xml
new file mode 100644
index 0000000..7e0823e
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/inset_density.xml
@@ -0,0 +1,20 @@
+<?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.
+ -->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/inset_testimage"
+ android:insetLeft="16dp" />
diff --git a/tests/tests/graphics/res/drawable/inset_mutate.xml b/tests/tests/graphics/res/drawable/inset_mutate.xml
index ba613e9..feeeda1 100644
--- a/tests/tests/graphics/res/drawable/inset_mutate.xml
+++ b/tests/tests/graphics/res/drawable/inset_mutate.xml
@@ -16,4 +16,4 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/inset_mutate_testimage" />
+ android:drawable="@drawable/inset_testimage" />
diff --git a/tests/tests/graphics/res/drawable/inset_mutate_testimage.jpg b/tests/tests/graphics/res/drawable/inset_testimage.jpg
similarity index 100%
rename from tests/tests/graphics/res/drawable/inset_mutate_testimage.jpg
rename to tests/tests/graphics/res/drawable/inset_testimage.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/layer_drawable_density.xml b/tests/tests/graphics/res/drawable/layer_drawable_density.xml
new file mode 100644
index 0000000..3012539
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/layer_drawable_density.xml
@@ -0,0 +1,35 @@
+<?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.
+ -->
+
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:paddingMode="nest">
+ <item
+ android:left="16dp"
+ android:right="16dp"
+ android:top="16dp"
+ android:bottom="16dp"
+ android:width="32dp"
+ android:height="32dp">
+ <color
+ android:color="@android:color/black" />
+ </item>
+</layer-list>
diff --git a/tests/tests/graphics/res/drawable/layer_drawable_intrinsic.xml b/tests/tests/graphics/res/drawable/layer_drawable_intrinsic.xml
new file mode 100644
index 0000000..0a8cd98
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/layer_drawable_intrinsic.xml
@@ -0,0 +1,24 @@
+<?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.
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:left="5dp"
+ android:right="5dp"
+ android:top="5dp"
+ android:bottom="5dp"
+ android:drawable="@android:color/black" />
+</layer-list>
diff --git a/tests/tests/graphics/res/drawable/layer_drawable_intrinsic_mixed.xml b/tests/tests/graphics/res/drawable/layer_drawable_intrinsic_mixed.xml
new file mode 100644
index 0000000..a590f90
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/layer_drawable_intrinsic_mixed.xml
@@ -0,0 +1,29 @@
+<?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.
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:left="2dp"
+ android:right="2dp"
+ android:top="2dp"
+ android:bottom="2dp"
+ android:drawable="@drawable/size_48x48" />
+ <item android:left="100dp"
+ android:right="100dp"
+ android:top="100dp"
+ android:bottom="100dp"
+ android:drawable="@android:color/black" />
+</layer-list>
diff --git a/tests/tests/graphics/res/drawable/rotatedrawable_abs.xml b/tests/tests/graphics/res/drawable/rotatedrawable_abs.xml
new file mode 100644
index 0000000..8f5f619
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/rotatedrawable_abs.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.
+ -->
+
+<rotate xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pivotX="0.3"
+ android:pivotY="0.3"
+ android:fromDegrees="180"
+ android:toDegrees="-180"
+ android:drawable="@drawable/testimage" />
diff --git a/tests/tests/graphics/res/drawable/rotatedrawable_rel.xml b/tests/tests/graphics/res/drawable/rotatedrawable_rel.xml
new file mode 100644
index 0000000..c5b5de3
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/rotatedrawable_rel.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.
+ -->
+
+<rotate xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pivotX="10%"
+ android:pivotY="20%"
+ android:fromDegrees="360"
+ android:toDegrees="360"
+ android:drawable="@drawable/testimage" />
diff --git a/tests/tests/graphics/res/drawable/state_list_density.xml b/tests/tests/graphics/res/drawable/state_list_density.xml
new file mode 100644
index 0000000..9a17384
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/state_list_density.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:drawable="@drawable/state_list_density_1" />
+ <item android:drawable="@drawable/state_list_density_2" />
+</selector>
+
diff --git a/tests/tests/graphics/res/drawable/inset_mutate_testimage.jpg b/tests/tests/graphics/res/drawable/state_list_density_1.jpg
similarity index 100%
copy from tests/tests/graphics/res/drawable/inset_mutate_testimage.jpg
copy to tests/tests/graphics/res/drawable/state_list_density_1.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/state_list_density_2.jpg b/tests/tests/graphics/res/drawable/state_list_density_2.jpg
new file mode 100644
index 0000000..f963c86
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/state_list_density_2.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/state_list_density_constant_size.xml b/tests/tests/graphics/res/drawable/state_list_density_constant_size.xml
new file mode 100644
index 0000000..4e183f3
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/state_list_density_constant_size.xml
@@ -0,0 +1,23 @@
+<?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.
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:constantSize="true">
+ <item android:state_focused="true" android:drawable="@drawable/state_list_density_1" />
+ <item android:drawable="@drawable/state_list_density_2" />
+</selector>
+
diff --git a/tests/tests/graphics/res/drawable/vector_density.xml b/tests/tests/graphics/res/drawable/vector_density.xml
new file mode 100644
index 0000000..c3ca1981
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_density.xml
@@ -0,0 +1,29 @@
+<?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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="64dp"
+ android:width="64dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24" >
+
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_arcto.xml b/tests/tests/graphics/res/drawable/vector_icon_arcto.xml
new file mode 100644
index 0000000..6038d2b
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_arcto.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="20dp"
+ android:height="50dp"
+ android:viewportWidth="20.0"
+ android:viewportHeight="50.0">
+ <path
+ android:pathData="M14.285706,47.362198A50.71429,62.14286 0,0 0,1.0630035 5.5146027"
+ android:fillColor="#ff55ff"/>
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_implicit_lineto.xml b/tests/tests/graphics/res/drawable/vector_icon_implicit_lineto.xml
new file mode 100644
index 0000000..d7b133b
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_implicit_lineto.xml
@@ -0,0 +1,29 @@
+<?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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="64dp"
+ android:width="64dp"
+ android:viewportHeight="64"
+ android:viewportWidth="64" >
+
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="m0,0 32,0 0,32 -32,0 0,-32z" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_state_list.xml b/tests/tests/graphics/res/drawable/vector_icon_state_list.xml
new file mode 100644
index 0000000..65aa967
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_state_list.xml
@@ -0,0 +1,31 @@
+<?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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="64dp"
+ android:width="64dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24" >
+
+ <path
+ android:fillColor="@color/vector_icon_fill_state_list"
+ android:strokeColor="@color/vector_icon_stroke_state_list"
+ android:strokeWidth="3"
+ android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z"/>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/xml/scaledrawable_level.xml b/tests/tests/graphics/res/xml/scaledrawable_level.xml
new file mode 100644
index 0000000..6a7ec74
--- /dev/null
+++ b/tests/tests/graphics/res/xml/scaledrawable_level.xml
@@ -0,0 +1,28 @@
+<?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.
+ -->
+
+<alias xmlns:android="http://schemas.android.com/apk/res/android">
+ <scale_allattrs>
+ <scale xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fromXScale="1.0"
+ android:toXScale="1.4"
+ android:fromYScale="1.0"
+ android:toYScale="0.6"
+ android:drawable="@drawable/testimage"
+ android:level="5000" />
+ </scale_allattrs>
+</alias>
\ No newline at end of file
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
index 2314ffb..a93fd27 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
@@ -16,7 +16,7 @@
package android.graphics.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import android.content.res.Resources;
@@ -64,12 +64,10 @@
private static int HEIGHTS[] = new int[] { 960, 480, 240, 240, 480 };
// Configurations for BitmapFactory.Options
- private static Config[] COLOR_CONFIGS = new Config[] {Config.ARGB_8888, Config.RGB_565,
- Config.ARGB_4444};
+ private static Config[] COLOR_CONFIGS = new Config[] {Config.ARGB_8888, Config.RGB_565};
private static int[] COLOR_TOLS = new int[] {16, 49, 576};
- private static Config[] COLOR_CONFIGS_RGBA = new Config[] {Config.ARGB_8888,
- Config.ARGB_4444};
+ private static Config[] COLOR_CONFIGS_RGBA = new Config[] {Config.ARGB_8888};
private static int[] COLOR_TOLS_RGBA = new int[] {72, 124};
private static int[] RAW_COLORS = new int[] {
@@ -573,6 +571,116 @@
verifyScaled(BitmapFactory.decodeStream(obtainInputStream(), null, scaledOpt));
}
+ public void testConfigs() {
+ // The output Config of a BitmapFactory decode depends on the request from the
+ // client and the properties of the image to be decoded.
+ //
+ // Options.inPreferredConfig = Config.ARGB_8888
+ // This is the default value of inPreferredConfig. In this case, the image
+ // will always be decoded to Config.ARGB_8888.
+ // Options.inPreferredConfig = Config.RGB_565
+ // If the encoded image is opaque, we will decode to Config.RGB_565,
+ // otherwise we will decode to whichever color type is the most natural match
+ // for the encoded data.
+ // Options.inPreferredConfig = Config.ARGB_4444
+ // This is deprecated and will always decode to Config.ARGB_8888.
+ // Options.inPreferredConfig = Config.ALPHA_8
+ // If the encoded image is gray, we will decode to 8-bit grayscale values
+ // and indicate that the output bitmap is Config.ALPHA_8. This is somewhat
+ // misleading because the image is really opaque and grayscale, but we are
+ // labeling each pixel as if it is a translucency (alpha) value. If the
+ // encoded image is not gray, we will decode to whichever color type is the
+ // most natural match for the encoded data.
+ // Options.inPreferredConfig = null
+ // We will decode to whichever Config is the most natural match with the
+ // encoded data. This could be 8-bit indices into a color table (call this
+ // INDEX_8), ALPHA_8 (gray), or ARGB_8888.
+ //
+ // This test ensures that images are decoded to the intended Config and that the
+ // decodes match regardless of the Config.
+ decodeConfigs(R.drawable.alpha, 31, 31, true, false, false);
+ decodeConfigs(R.drawable.baseline_jpeg, 1280, 960, false, false, false);
+ decodeConfigs(R.drawable.bmp_test, 320, 240, false, false, false);
+ decodeConfigs(R.drawable.scaled2, 6, 8, false, false, true);
+ decodeConfigs(R.drawable.grayscale_jpg, 128, 128, false, true, false);
+ decodeConfigs(R.drawable.grayscale_png, 128, 128, false, true, false);
+ }
+
+ private void decodeConfigs(int id, int width, int height, boolean hasAlpha, boolean isGray,
+ boolean hasColorTable) {
+ Options opts = new BitmapFactory.Options();
+ opts.inScaled = false;
+ assertEquals(Config.ARGB_8888, opts.inPreferredConfig);
+ Bitmap reference = BitmapFactory.decodeResource(mRes, id, opts);
+ assertNotNull(reference);
+ assertEquals(width, reference.getWidth());
+ assertEquals(height, reference.getHeight());
+ assertEquals(Config.ARGB_8888, reference.getConfig());
+
+ opts.inPreferredConfig = Config.ARGB_4444;
+ Bitmap argb4444 = BitmapFactory.decodeResource(mRes, id, opts);
+ assertNotNull(argb4444);
+ assertEquals(width, argb4444.getWidth());
+ assertEquals(height, argb4444.getHeight());
+ // ARGB_4444 is deprecated and we should decode to ARGB_8888.
+ assertEquals(Config.ARGB_8888, argb4444.getConfig());
+ compareBitmaps(reference, argb4444, 0, true, true);
+
+ opts.inPreferredConfig = Config.RGB_565;
+ Bitmap rgb565 = BitmapFactory.decodeResource(mRes, id, opts);
+ assertNotNull(rgb565);
+ assertEquals(width, rgb565.getWidth());
+ assertEquals(height, rgb565.getHeight());
+ if (!hasAlpha) {
+ assertEquals(Config.RGB_565, rgb565.getConfig());
+ // Convert the RGB_565 bitmap to ARGB_8888 and test that it is similar to
+ // the reference. We lose information when decoding to 565, so there must
+ // be some tolerance. The tolerance is intentionally loose to allow us some
+ // flexibility regarding if we dither and how we color convert.
+ compareBitmaps(reference, rgb565.copy(Config.ARGB_8888, false), 30, true, true);
+ }
+
+ opts.inPreferredConfig = Config.ALPHA_8;
+ Bitmap alpha8 = BitmapFactory.decodeResource(mRes, id, opts);
+ assertNotNull(alpha8);
+ assertEquals(width, reference.getWidth());
+ assertEquals(height, reference.getHeight());
+ if (isGray) {
+ assertEquals(Config.ALPHA_8, alpha8.getConfig());
+ // Convert the ALPHA_8 bitmap to ARGB_8888 and test that it is identical to
+ // the reference. We must do this manually because we are abusing ALPHA_8
+ // in order to represent grayscale.
+ compareBitmaps(reference, grayToARGB(alpha8), 0, true, true);
+ }
+
+ // Setting inPreferredConfig to null selects the most natural color type for
+ // the encoded data. If the image has a color table, this should be INDEX_8.
+ // If we decode to INDEX_8, the output bitmap will report that the Config is
+ // null.
+ opts.inPreferredConfig = null;
+ Bitmap index8 = BitmapFactory.decodeResource(mRes, id, opts);
+ assertNotNull(index8);
+ assertEquals(width, index8.getWidth());
+ assertEquals(height, index8.getHeight());
+ if (hasColorTable) {
+ assertEquals(null, index8.getConfig());
+ // Convert the INDEX_8 bitmap to ARGB_8888 and test that it is identical to
+ // the reference.
+ compareBitmaps(reference, index8.copy(Config.ARGB_8888, false), 0, true, true);
+ }
+ }
+
+ private Bitmap grayToARGB(Bitmap gray) {
+ Bitmap argb = Bitmap.createBitmap(gray.getWidth(), gray.getHeight(), Config.ARGB_8888);
+ for (int y = 0; y < argb.getHeight(); y++) {
+ for (int x = 0; x < argb.getWidth(); x++) {
+ int grayByte = Color.alpha(gray.getPixel(x, y));
+ argb.setPixel(x, y, Color.rgb(grayByte, grayByte, grayByte));
+ }
+ }
+ return argb;
+ }
+
private byte[] obtainArray() {
ByteArrayOutputStream stm = new ByteArrayOutputStream();
Options opt = new BitmapFactory.Options();
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
index adce1c4..328d9ed 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
@@ -29,7 +29,7 @@
import android.test.InstrumentationTestCase;
import android.util.Log;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import java.io.ByteArrayOutputStream;
@@ -304,6 +304,83 @@
}
}
+ // The documentation for BitmapRegionDecoder guarantees that, when reusing a
+ // bitmap, "the provided Bitmap's width, height, and Bitmap.Config will not
+ // be changed". If the inBitmap is too small, decoded content will be
+ // clipped into inBitmap. Here we test that:
+ // (1) If inBitmap is specified, it is always used.
+ // (2) The width, height, and Config of inBitmap are never changed.
+ // (3) All of the pixels decoded into inBitmap exactly match the pixels
+ // of a decode where inBitmap is NULL.
+ public void testInBitmapReuse() throws IOException {
+ Options defaultOpts = new BitmapFactory.Options();
+ Options reuseOpts = new BitmapFactory.Options();
+ Rect subset = new Rect(0, 0, TILE_SIZE, TILE_SIZE);
+
+ for (int i = 0; i < NUM_TEST_IMAGES; i++) {
+ InputStream is = obtainInputStream(RES_IDS[i]);
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
+ for (int j = 0; j < SAMPLESIZES.length; j++) {
+ int sampleSize = SAMPLESIZES[j];
+ defaultOpts.inSampleSize = sampleSize;
+ reuseOpts.inSampleSize = sampleSize;
+
+ // We don't need to worry about rounding here because sampleSize
+ // divides evenly into TILE_SIZE.
+ assertEquals(0, TILE_SIZE % sampleSize);
+ int scaledDim = TILE_SIZE / sampleSize;
+ int chunkSize = scaledDim / 2;
+ for (int k = 0; k < COLOR_CONFIGS.length; k++) {
+ Config config = COLOR_CONFIGS[k];
+ defaultOpts.inPreferredConfig = config;
+ reuseOpts.inPreferredConfig = config;
+
+ // For both the width and the height of inBitmap, we test three
+ // interesting cases:
+ // (1) inBitmap dimension is smaller than scaledDim. The decoded
+ // pixels that fit inside inBitmap should exactly match the
+ // corresponding decoded pixels from the same region decode,
+ // performed without an inBitmap. The pixels that do not fit
+ // inside inBitmap should be clipped.
+ // (2) inBitmap dimension matches scaledDim. After the decode,
+ // the pixels and dimensions of inBitmap should exactly match
+ // those of the result bitmap of the same region decode,
+ // performed without an inBitmap.
+ // (3) inBitmap dimension is larger than scaledDim. After the
+ // decode, inBitmap should contain decoded pixels for the
+ // entire region, exactly matching the decoded pixels
+ // produced when inBitmap is not specified. The additional
+ // pixels in inBitmap are left the same as before the decode.
+ for (int w = chunkSize; w <= 3 * chunkSize; w += chunkSize) {
+ for (int h = chunkSize; h <= 3 * chunkSize; h += chunkSize) {
+ // Decode reusing inBitmap.
+ reuseOpts.inBitmap = Bitmap.createBitmap(w, h, config);
+ Bitmap reuseResult = decoder.decodeRegion(subset, reuseOpts);
+ assertSame(reuseOpts.inBitmap, reuseResult);
+ assertEquals(reuseResult.getWidth(), w);
+ assertEquals(reuseResult.getHeight(), h);
+ assertEquals(reuseResult.getConfig(), config);
+
+ // Decode into a new bitmap.
+ Bitmap defaultResult = decoder.decodeRegion(subset, defaultOpts);
+ assertEquals(defaultResult.getWidth(), scaledDim);
+ assertEquals(defaultResult.getHeight(), scaledDim);
+
+ // Ensure that the decoded pixels of reuseResult and defaultResult
+ // are identical.
+ int cropWidth = Math.min(w, scaledDim);
+ int cropHeight = Math.min(h, scaledDim);
+ Rect crop = new Rect(0 ,0, cropWidth, cropHeight);
+ Bitmap reuseCropped = cropBitmap(reuseResult, crop);
+ Bitmap defaultCropped = cropBitmap(defaultResult, crop);
+ compareBitmaps(reuseCropped, defaultCropped, 0, true);
+ }
+ }
+ }
+ }
+ }
+ }
+
private void compareRegionByRegion(BitmapRegionDecoder decoder,
Options opts, int mseMargin, Bitmap wholeImage) {
int width = decoder.getWidth();
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
index 07e65d2..f820771 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
@@ -15,7 +15,7 @@
*/
package android.graphics.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import android.content.res.Resources;
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index 1dd6777..dee217b 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -41,7 +41,7 @@
import android.text.SpannableStringBuilder;
import android.text.SpannedString;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import java.util.Vector;
@@ -348,6 +348,117 @@
verifySaveFlagsSequence(flags);
}
+ // This test exercises the saveLayer flag that preserves the clip
+ // state across the matching restore call boundary. This is a vanilla
+ // test and doesn't exercise any interaction between the clip stack
+ // and SkCanvas' deferred save/restore system.
+ public void testSaveFlags9() {
+ Rect clip0 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip0));
+
+ mCanvas.save(Canvas.MATRIX_SAVE_FLAG);
+
+ // All clip elements should be preserved after restore
+ mCanvas.clipRect(0, 0, BITMAP_WIDTH / 2, BITMAP_HEIGHT);
+ Path path = new Path();
+ path.addOval(0.25f * BITMAP_WIDTH, 0.25f * BITMAP_HEIGHT,
+ 0.75f * BITMAP_WIDTH, 0.75f * BITMAP_HEIGHT,
+ Path.Direction.CW);
+ mCanvas.clipPath(path);
+ mCanvas.clipRect(0, 0, BITMAP_WIDTH, BITMAP_HEIGHT / 2);
+
+ Rect clip1 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip1));
+ assertTrue(clip1 != clip0);
+ assertTrue(clip0.contains(clip1));
+
+ mCanvas.restore();
+
+ Rect clip2 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip2));
+ assertEquals(clip2, clip1);
+ }
+
+ // This test exercises the saveLayer MATRIX_SAVE_FLAG flag and its
+ // interaction with the clip stack and SkCanvas deferred save/restore
+ // system.
+ public void testSaveFlags10() {
+ RectF rect1 = new RectF(0, 0, BITMAP_WIDTH / 2, BITMAP_HEIGHT);
+ RectF rect2 = new RectF(0, 0, BITMAP_WIDTH, BITMAP_HEIGHT / 2);
+ Path path = new Path();
+ path.addOval(0.25f * BITMAP_WIDTH, 0.25f * BITMAP_HEIGHT,
+ 0.75f * BITMAP_WIDTH, 0.75f * BITMAP_HEIGHT,
+ Path.Direction.CW);
+
+ Rect clip0 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip0));
+
+ // Exercise various Canvas lazy-save interactions.
+ mCanvas.save();
+ mCanvas.save();
+ mCanvas.clipRect(rect1);
+ mCanvas.clipPath(path);
+
+ Rect clip1 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip1));
+ assertTrue(clip1 != clip0);
+
+ mCanvas.save(Canvas.MATRIX_SAVE_FLAG);
+ mCanvas.save(Canvas.MATRIX_SAVE_FLAG);
+ mCanvas.clipRect(rect2);
+ mCanvas.clipPath(path);
+
+ Rect clip2 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip2));
+ assertTrue(clip2 != clip1);
+ assertTrue(clip2 != clip0);
+
+ mCanvas.save();
+ mCanvas.translate(10, 5);
+ mCanvas.save(Canvas.MATRIX_SAVE_FLAG);
+ // An uncommitted save/restore frame: exercises
+ // the partial save emulation, ensuring there
+ // are no side effects.
+ Rect clip3 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip3));
+ clip3.offset(10, 5); // adjust for local offset
+ assertEquals(clip3, clip2);
+ mCanvas.restore();
+
+ Rect clip4 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip4));
+ clip4.offset(10, 5); // adjust for local offset
+ assertEquals(clip4, clip2);
+ mCanvas.restore();
+
+ Rect clip5 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip5));
+ assertEquals(clip5, clip2);
+ mCanvas.restore();
+
+ // clip2 survives the preceding restore
+ Rect clip6 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip6));
+ assertEquals(clip6, clip2);
+ mCanvas.restore();
+
+ // clip2 also survives the preceding restore
+ Rect clip7 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip7));
+ assertEquals(clip7, clip2);
+ mCanvas.restore();
+
+ // clip1 does _not_ survive the preceding restore
+ Rect clip8 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip8));
+ assertEquals(clip8, clip0);
+ mCanvas.restore();
+
+ Rect clip9 = new Rect();
+ assertTrue(mCanvas.getClipBounds(clip9));
+ assertEquals(clip9, clip0);
+ }
+
public void testSaveLayer1() {
final Paint p = new Paint();
final RectF rF = new RectF(0, 10, 31, 0);
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageViewCtsActivity.java b/tests/tests/graphics/src/android/graphics/cts/ImageViewCtsActivity.java
index b9887b7..9d6de44 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageViewCtsActivity.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.graphics.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
index b18b800..c1e7ead 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
@@ -32,10 +32,10 @@
public class MovieTest extends ActivityInstrumentationTestCase2<MockActivity> {
private Movie mMovie;
- private final int MOVIE = com.android.cts.graphics.R.drawable.animated;
+ private final int MOVIE = android.graphics.cts.R.drawable.animated;
public MovieTest() {
- super("com.android.cts.graphics", MockActivity.class);
+ super("android.graphics.cts", MockActivity.class);
}
@Override
diff --git a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
index d37ec90..8b73380 100644
--- a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
@@ -16,7 +16,7 @@
package android.graphics.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import android.content.res.Resources;
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 80e0253..c813bdb 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -36,6 +36,7 @@
import android.os.Build;
import android.test.AndroidTestCase;
import android.text.SpannedString;
+import android.util.LocaleList;
import android.util.Log;
import java.util.Locale;
@@ -600,30 +601,73 @@
// Check default
assertEquals(defaultLocale, p.getTextLocale());
- // Check setter / getter
+ // Check setter / getters
p.setTextLocale(Locale.US);
assertEquals(Locale.US, p.getTextLocale());
+ assertEquals(new LocaleList(Locale.US), p.getTextLocales());
p.setTextLocale(Locale.CHINESE);
assertEquals(Locale.CHINESE, p.getTextLocale());
+ assertEquals(new LocaleList(Locale.CHINESE), p.getTextLocales());
p.setTextLocale(Locale.JAPANESE);
assertEquals(Locale.JAPANESE, p.getTextLocale());
+ assertEquals(new LocaleList(Locale.JAPANESE), p.getTextLocales());
p.setTextLocale(Locale.KOREAN);
assertEquals(Locale.KOREAN, p.getTextLocale());
+ assertEquals(new LocaleList(Locale.KOREAN), p.getTextLocales());
// Check reverting back to default
p.setTextLocale(defaultLocale);
assertEquals(defaultLocale, p.getTextLocale());
+ assertEquals(new LocaleList(defaultLocale), p.getTextLocales());
// Check that we cannot pass a null locale
try {
p.setTextLocale(null);
- assertFalse(true);
+ fail("Setting the text locale to null should throw");
+ } catch (Throwable e) {
+ assertEquals(IllegalArgumentException.class, e.getClass());
}
- catch (IllegalArgumentException iae) {
- // OK !!
+ }
+
+ public void testAccessTextLocales() {
+ Paint p = new Paint();
+
+ final LocaleList defaultLocales = LocaleList.getDefault();
+
+ // Check default
+ assertEquals(defaultLocales, p.getTextLocales());
+
+ // Check setter / getters for a one-member locale list
+ p.setTextLocales(new LocaleList(Locale.CHINESE));
+ assertEquals(Locale.CHINESE, p.getTextLocale());
+ assertEquals(new LocaleList(Locale.CHINESE), p.getTextLocales());
+
+ // Check setter / getters for a two-member locale list
+ p.setTextLocales(LocaleList.forLanguageTags("fr,de"));
+ assertEquals(Locale.forLanguageTag("fr"), p.getTextLocale());
+ assertEquals(LocaleList.forLanguageTags("fr,de"), p.getTextLocales());
+
+ // Check reverting back to default
+ p.setTextLocales(defaultLocales);
+ assertEquals(defaultLocales, p.getTextLocales());
+
+ // Check that we cannot pass a null locale list
+ try {
+ p.setTextLocales(null);
+ fail("Setting the text locale list to null should throw");
+ } catch (Throwable e) {
+ assertEquals(IllegalArgumentException.class, e.getClass());
+ }
+
+ // Check that we cannot pass an empty locale list
+ try {
+ p.setTextLocales(new LocaleList());
+ fail("Setting the text locale list to an empty list should throw");
+ } catch (Throwable e) {
+ assertEquals(IllegalArgumentException.class, e.getClass());
}
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java b/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
index 02b3afa..a2038b4 100644
--- a/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
@@ -33,7 +33,7 @@
import android.test.AndroidTestCase;
import android.util.Log;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
public class YuvImageTest extends AndroidTestCase {
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 769e110..2368d08 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -28,7 +28,7 @@
import android.util.Log;
import android.util.Xml;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java
index 28a3c6b..60da3ad 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java
@@ -16,7 +16,7 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -50,7 +50,7 @@
private Resources mResources;
public AnimationDrawableTest() {
- super("com.android.cts.graphics", ImageViewCtsActivity.class);
+ super("android.graphics.cts", ImageViewCtsActivity.class);
}
@Override
@@ -275,6 +275,23 @@
pollingCheckDrawable(THIRD_FRAME_INDEX, SECOND_FRAME_DURATION);
// do not repeat
assertStoppedAnimation(THIRD_FRAME_INDEX, THIRD_FRAME_DURATION);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ // Set visible to false and restart to false
+ mAnimationDrawable.setVisible(false, false);
+ }
+ });
+ // Check that animation drawable stays on the same frame
+ assertStoppedAnimation(THIRD_FRAME_INDEX, THIRD_FRAME_DURATION);
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ // Set visible to true and restart to false
+ mAnimationDrawable.setVisible(true, false);
+ }
+ });
+ // Check that animation drawable stays on the same frame
+ assertStoppedAnimation(THIRD_FRAME_INDEX, THIRD_FRAME_DURATION);
}
public void testInflateCorrect() throws XmlPullParserException, IOException {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
index 88e7acb..9b11cf7 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
@@ -16,7 +16,7 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParserException;
@@ -316,29 +316,48 @@
InputStream source = mContext.getResources().openRawResource(R.drawable.size_48x48);
bitmapDrawable = new BitmapDrawable(source);
- bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics().densityDpi);
+ bitmapDrawable.setTargetDensity(bitmapDrawable.getBitmap().getDensity());
assertEquals(48, bitmapDrawable.getIntrinsicWidth());
assertEquals(48, bitmapDrawable.getIntrinsicHeight());
}
@SuppressWarnings("deprecation")
public void testSetTargetDensity() {
- BitmapDrawable bitmapDrawable = new BitmapDrawable();
+ int sourceWidth, targetWidth;
+ int sourceHeight, targetHeight;
+ int sourceDensity, targetDensity;
+ BitmapDrawable bitmapDrawable;
+ Bitmap bitmap;
- Bitmap bitmap = Bitmap.createBitmap(200, 300, Config.RGB_565);
+ sourceWidth = 200;
+ sourceHeight = 300;
+ bitmap = Bitmap.createBitmap(sourceWidth, sourceHeight, Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
bitmapDrawable = new BitmapDrawable(bitmap);
- bitmapDrawable.setTargetDensity(canvas.getDensity());
- assertEquals(200, bitmapDrawable.getIntrinsicWidth());
- assertEquals(300, bitmapDrawable.getIntrinsicHeight());
+ sourceDensity = bitmap.getDensity();
+ targetDensity = canvas.getDensity();
+ bitmapDrawable.setTargetDensity(targetDensity);
+ targetWidth = DrawableTestUtils.scaleBitmapFromDensity(
+ sourceWidth, sourceDensity, targetDensity);
+ targetHeight = DrawableTestUtils.scaleBitmapFromDensity(
+ sourceHeight, sourceDensity, targetDensity);
+ assertEquals(targetWidth, bitmapDrawable.getIntrinsicWidth());
+ assertEquals(targetHeight, bitmapDrawable.getIntrinsicHeight());
- DisplayMetrics disMetrics = new DisplayMetrics();
- disMetrics = getInstrumentation().getTargetContext().getResources().getDisplayMetrics();
+ sourceWidth = 48;
+ sourceHeight = 48;
InputStream source = mContext.getResources().openRawResource(R.drawable.size_48x48);
bitmapDrawable = new BitmapDrawable(source);
- bitmapDrawable.setTargetDensity(disMetrics.densityDpi);
- assertEquals(48, bitmapDrawable.getIntrinsicWidth());
- assertEquals(48, bitmapDrawable.getIntrinsicHeight());
+ bitmap = bitmapDrawable.getBitmap();
+ sourceDensity = bitmap.getDensity();
+ targetDensity = sourceDensity * 2;
+ bitmapDrawable.setTargetDensity(targetDensity);
+ targetWidth = DrawableTestUtils.scaleBitmapFromDensity(
+ sourceWidth, sourceDensity, targetDensity);
+ targetHeight = DrawableTestUtils.scaleBitmapFromDensity(
+ sourceHeight, sourceDensity, targetDensity);
+ assertEquals(targetWidth, bitmapDrawable.getIntrinsicWidth());
+ assertEquals(targetHeight, bitmapDrawable.getIntrinsicHeight());
}
@SuppressWarnings("deprecation")
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java
index e727350..074cbd9 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java
@@ -16,7 +16,7 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ColorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ColorDrawableTest.java
index 465a476..c092f3c 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ColorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ColorDrawableTest.java
@@ -26,7 +26,7 @@
import android.util.AttributeSet;
import android.util.Xml;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/CustomDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/CustomDrawableTest.java
new file mode 100644
index 0000000..7dff729
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/CustomDrawableTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+package android.graphics.drawable.cts;
+
+import android.graphics.cts.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+
+import java.io.IOException;
+
+public class CustomDrawableTest extends AndroidTestCase {
+
+ public void testInflation() {
+ Drawable dr = getContext().getDrawable(R.drawable.custom_drawable);
+ assertTrue(dr instanceof CustomDrawable);
+ assertEquals(Color.RED, ((CustomDrawable) dr).getColor());
+ }
+
+ public static class CustomDrawable extends Drawable {
+ private static final int[] ATTRS = new int[] { android.R.attr.color };
+
+ private int mColor;
+
+ @Override
+ public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
+ throws XmlPullParserException, IOException {
+ super.inflate(r, parser, attrs, theme);
+
+ final TypedArray ta;
+ if (theme != null) {
+ ta = theme.obtainStyledAttributes(attrs, ATTRS, 0, 0);
+ } else {
+ ta = r.obtainAttributes(attrs, ATTRS);
+ }
+
+ mColor = ta.getColor(0, Color.BLACK);
+ }
+
+ public int getColor() {
+ return mColor;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.OPAQUE;
+ }
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
index 79d2a1d..1a1e870 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
@@ -69,6 +69,9 @@
}
public void testGetChangingConfigurations() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
assertConstantStateNotSet();
try {
@@ -84,7 +87,7 @@
MockDrawable dr1 = new MockDrawable();
dr1.setChangingConfigurations(0x010);
mDrawableContainerState.addChild(dr1);
- mDrawableContainer.selectDrawable(0);
+ dr.selectDrawable(0);
assertSame(dr0, mDrawableContainer.getCurrent());
// can not set mDrawableContainerState's ChangingConfigurations
@@ -94,6 +97,9 @@
}
public void testGetPadding() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
assertConstantStateNotSet();
assertNull(mDrawableContainer.getCurrent());
@@ -111,7 +117,7 @@
MockDrawable dr1 = new MockDrawable();
dr1.setPadding(new Rect(0, 0, 3, 4));
mDrawableContainerState.addChild(dr1);
- mDrawableContainer.selectDrawable(0);
+ dr.selectDrawable(0);
assertSame(dr0, mDrawableContainer.getCurrent());
// use the current drawable's padding
@@ -127,7 +133,7 @@
assertEquals(mDrawableContainerState.getConstantPadding(), result);
// use default padding
- mDrawableContainer.selectDrawable(-1);
+ dr.selectDrawable(-1);
assertNull(mDrawableContainer.getCurrent());
mDrawableContainerState.setVariablePadding(true);
assertNull(mDrawableContainerState.getConstantPadding());
@@ -142,24 +148,27 @@
}
public void testSetAlpha() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
assertConstantStateNotSet();
assertNull(mDrawableContainer.getCurrent());
- mDrawableContainer.setAlpha(0);
+ dr.setAlpha(0);
mDrawableContainer.setConstantState(mDrawableContainerState);
- MockDrawable dr = new MockDrawable();
- addAndSelectDrawable(dr);
+ MockDrawable mockDrawable = new MockDrawable();
+ addAndSelectDrawable(mockDrawable);
// call current drawable's setAlpha if alpha is changed.
- dr.reset();
- mDrawableContainer.setAlpha(1);
- assertTrue(dr.hasSetAlphaCalled());
+ mockDrawable.reset();
+ dr.setAlpha(1);
+ assertTrue(mockDrawable.hasSetAlphaCalled());
// does not call it if alpha is not changed.
- dr.reset();
- mDrawableContainer.setAlpha(1);
- assertFalse(dr.hasSetAlphaCalled());
+ mockDrawable.reset();
+ dr.setAlpha(1);
+ assertFalse(mockDrawable.hasSetAlphaCalled());
}
public void testSetDither() {
@@ -223,25 +232,28 @@
}
public void testSetColorFilter() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
assertConstantStateNotSet();
assertNull(mDrawableContainer.getCurrent());
mDrawableContainer.setConstantState(mDrawableContainerState);
- mDrawableContainer.setColorFilter(null);
- mDrawableContainer.setColorFilter(new ColorFilter());
+ dr.setColorFilter(null);
+ dr.setColorFilter(new ColorFilter());
- MockDrawable dr = new MockDrawable();
- addAndSelectDrawable(dr);
+ MockDrawable mockDrawable = new MockDrawable();
+ addAndSelectDrawable(mockDrawable);
// call current drawable's setColorFilter if filter is changed.
- dr.reset();
- mDrawableContainer.setColorFilter(null);
- assertTrue(dr.hasSetColorFilterCalled());
+ mockDrawable.reset();
+ dr.setColorFilter(null);
+ assertTrue(mockDrawable.hasSetColorFilterCalled());
// does not call it if filter is not changed.
- dr.reset();
- mDrawableContainer.setColorFilter(new ColorFilter());
- assertTrue(dr.hasSetColorFilterCalled());
+ mockDrawable.reset();
+ dr.setColorFilter(new ColorFilter());
+ assertTrue(mockDrawable.hasSetColorFilterCalled());
}
public void testSetTint() {
@@ -519,51 +531,57 @@
}
public void testInvalidateDrawable() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
assertConstantStateNotSet();
assertNull(mDrawableContainer.getCurrent());
mDrawableContainer.setCallback(null);
- mDrawableContainer.invalidateDrawable(mDrawableContainer);
- mDrawableContainer.invalidateDrawable(null);
+ dr.invalidateDrawable(mDrawableContainer);
+ dr.invalidateDrawable(null);
MockCallBack callback = new MockCallBack();
mDrawableContainer.setCallback(callback);
callback.reset();
- mDrawableContainer.invalidateDrawable(mDrawableContainer);
+ dr.invalidateDrawable(mDrawableContainer);
assertFalse(callback.hasInvalidateDrawableCalled());
// the callback method can be called if the drawable passed in and the
// current drawble are both null
callback.reset();
- mDrawableContainer.invalidateDrawable(null);
+ dr.invalidateDrawable(null);
assertTrue(callback.hasInvalidateDrawableCalled());
mDrawableContainer.setConstantState(mDrawableContainerState);
- MockDrawable dr = new MockDrawable();
- addAndSelectDrawable(dr);
+ MockDrawable mockDrawable = new MockDrawable();
+ addAndSelectDrawable(mockDrawable);
callback.reset();
- mDrawableContainer.invalidateDrawable(mDrawableContainer);
+ dr.invalidateDrawable(mDrawableContainer);
assertFalse(callback.hasInvalidateDrawableCalled());
callback.reset();
- mDrawableContainer.invalidateDrawable(null);
+ dr.invalidateDrawable(null);
assertFalse(callback.hasInvalidateDrawableCalled());
// Call the callback method if the drawable is selected.
callback.reset();
- mDrawableContainer.invalidateDrawable(dr);
+ dr.invalidateDrawable(mockDrawable);
assertTrue(callback.hasInvalidateDrawableCalled());
}
public void testScheduleDrawable() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
assertConstantStateNotSet();
assertNull(mDrawableContainer.getCurrent());
mDrawableContainer.setCallback(null);
- mDrawableContainer.scheduleDrawable(mDrawableContainer, null, 0);
- mDrawableContainer.scheduleDrawable(null, new Runnable() {
+ dr.scheduleDrawable(mDrawableContainer, null, 0);
+ dr.scheduleDrawable(null, new Runnable() {
public void run() {
}
}, 0);
@@ -572,28 +590,28 @@
mDrawableContainer.setCallback(callback);
callback.reset();
- mDrawableContainer.scheduleDrawable(mDrawableContainer, null, 0);
+ dr.scheduleDrawable(mDrawableContainer, null, 0);
assertFalse(callback.hasScheduleDrawableCalled());
// the callback method can be called if the drawable passed in and the
// current drawble are both null
callback.reset();
- mDrawableContainer.scheduleDrawable(null, new Runnable() {
+ dr.scheduleDrawable(null, new Runnable() {
public void run() {
}
}, 0);
assertTrue(callback.hasScheduleDrawableCalled());
mDrawableContainer.setConstantState(mDrawableContainerState);
- MockDrawable dr = new MockDrawable();
- addAndSelectDrawable(dr);
+ MockDrawable mockDrawable = new MockDrawable();
+ addAndSelectDrawable(mockDrawable);
callback.reset();
- mDrawableContainer.scheduleDrawable(mDrawableContainer, null, 0);
+ dr.scheduleDrawable(mDrawableContainer, null, 0);
assertFalse(callback.hasScheduleDrawableCalled());
callback.reset();
- mDrawableContainer.scheduleDrawable(null, new Runnable() {
+ dr.scheduleDrawable(null, new Runnable() {
public void run() {
}
}, 0);
@@ -601,17 +619,20 @@
// Call the callback method if the drawable is selected.
callback.reset();
- mDrawableContainer.scheduleDrawable(dr, null, 0);
+ dr.scheduleDrawable(mockDrawable, null, 0);
assertTrue(callback.hasScheduleDrawableCalled());
}
public void testUnscheduleDrawable() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
assertConstantStateNotSet();
assertNull(mDrawableContainer.getCurrent());
mDrawableContainer.setCallback(null);
- mDrawableContainer.unscheduleDrawable(mDrawableContainer, null);
- mDrawableContainer.unscheduleDrawable(null, new Runnable() {
+ dr.unscheduleDrawable(mDrawableContainer, null);
+ dr.unscheduleDrawable(null, new Runnable() {
public void run() {
}
});
@@ -620,28 +641,28 @@
mDrawableContainer.setCallback(callback);
callback.reset();
- mDrawableContainer.unscheduleDrawable(mDrawableContainer, null);
+ dr.unscheduleDrawable(mDrawableContainer, null);
assertFalse(callback.hasUnscheduleDrawableCalled());
// the callback method can be called if the drawable passed in and the
// current drawble are both null
callback.reset();
- mDrawableContainer.unscheduleDrawable(null, new Runnable() {
+ dr.unscheduleDrawable(null, new Runnable() {
public void run() {
}
});
assertTrue(callback.hasUnscheduleDrawableCalled());
mDrawableContainer.setConstantState(mDrawableContainerState);
- MockDrawable dr = new MockDrawable();
- addAndSelectDrawable(dr);
+ MockDrawable mockDrawable = new MockDrawable();
+ addAndSelectDrawable(mockDrawable);
callback.reset();
- mDrawableContainer.unscheduleDrawable(mDrawableContainer, null);
+ dr.unscheduleDrawable(mDrawableContainer, null);
assertFalse(callback.hasUnscheduleDrawableCalled());
callback.reset();
- mDrawableContainer.unscheduleDrawable(null, new Runnable() {
+ dr.unscheduleDrawable(null, new Runnable() {
public void run() {
}
});
@@ -649,7 +670,7 @@
// Call the callback method if the drawable is selected.
callback.reset();
- mDrawableContainer.unscheduleDrawable(dr, null);
+ dr.unscheduleDrawable(mockDrawable, null);
assertTrue(callback.hasUnscheduleDrawableCalled());
}
@@ -676,37 +697,43 @@
}
public void testGetOpacity() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
assertConstantStateNotSet();
// there is no child, so the container is transparent
- assertEquals(PixelFormat.TRANSPARENT, mDrawableContainer.getOpacity());
+ assertEquals(PixelFormat.TRANSPARENT, dr.getOpacity());
mDrawableContainer.setConstantState(mDrawableContainerState);
MockDrawable dr0 = new MockDrawable();
dr0.setOpacity(PixelFormat.OPAQUE);
mDrawableContainerState.addChild(dr0);
// no child selected yet
- assertEquals(PixelFormat.TRANSPARENT, mDrawableContainer.getOpacity());
+ assertEquals(PixelFormat.TRANSPARENT, dr.getOpacity());
- mDrawableContainer.selectDrawable(0);
- assertEquals(mDrawableContainerState.getOpacity(), mDrawableContainer.getOpacity());
+ dr.selectDrawable(0);
+ assertEquals(mDrawableContainerState.getOpacity(), dr.getOpacity());
assertEquals(PixelFormat.OPAQUE, mDrawableContainer.getOpacity());
MockDrawable dr1 = new MockDrawable();
dr1.setOpacity(PixelFormat.TRANSLUCENT);
mDrawableContainerState.addChild(dr1);
- mDrawableContainer.selectDrawable(1);
- assertEquals(mDrawableContainerState.getOpacity(), mDrawableContainer.getOpacity());
- assertEquals(PixelFormat.TRANSLUCENT, mDrawableContainer.getOpacity());
+ dr.selectDrawable(1);
+ assertEquals(mDrawableContainerState.getOpacity(), dr.getOpacity());
+ assertEquals(PixelFormat.TRANSLUCENT, dr.getOpacity());
}
public void testAccessCurrentDrawable() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
assertConstantStateNotSet();
assertNull(mDrawableContainer.getCurrent());
try {
- mDrawableContainer.selectDrawable(0);
+ dr.selectDrawable(0);
fail("Should throw NullPointerException if the constant state is not set.");
} catch (NullPointerException e) {
}
@@ -721,25 +748,25 @@
assertFalse(dr1.isVisible());
mDrawableContainerState.addChild(dr1);
- assertTrue(mDrawableContainer.selectDrawable(0));
+ assertTrue(dr.selectDrawable(0));
assertSame(dr0, mDrawableContainer.getCurrent());
assertTrue(dr0.isVisible());
- assertFalse(mDrawableContainer.selectDrawable(0));
+ assertFalse(dr.selectDrawable(0));
- assertTrue(mDrawableContainer.selectDrawable(1));
+ assertTrue(dr.selectDrawable(1));
assertSame(dr1, mDrawableContainer.getCurrent());
assertTrue(dr1.isVisible());
assertFalse(dr0.isVisible());
- assertFalse(mDrawableContainer.selectDrawable(1));
+ assertFalse(dr.selectDrawable(1));
- assertTrue(mDrawableContainer.selectDrawable(-1));
+ assertTrue(dr.selectDrawable(-1));
assertNull(mDrawableContainer.getCurrent());
assertFalse(dr0.isVisible());
assertFalse(dr1.isVisible());
- assertTrue(mDrawableContainer.selectDrawable(2));
+ assertTrue(dr.selectDrawable(2));
assertNull(mDrawableContainer.getCurrent());
assertFalse(dr0.isVisible());
assertFalse(dr1.isVisible());
@@ -774,10 +801,13 @@
assertTrue(dr0.hasMutateCalled());
}
- private void addAndSelectDrawable(MockDrawable dr) {
- int pos = mDrawableContainerState.addChild(dr);
- mDrawableContainer.selectDrawable(pos);
- assertSame(dr, mDrawableContainer.getCurrent());
+ private void addAndSelectDrawable(MockDrawable mockDrawable) {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ DrawableContainer dr = mDrawableContainer;
+
+ int pos = mDrawableContainerState.addChild(mockDrawable);
+ dr.selectDrawable(pos);
+ assertSame(mockDrawable, dr.getCurrent());
}
private void assertConstantStateNotSet() {
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 a91353f..0858c6b 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
@@ -17,7 +17,7 @@
package android.graphics.drawable.cts;
import android.view.View;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestUtils.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestUtils.java
index a0fa634..ae28eca 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestUtils.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestUtils.java
@@ -16,15 +16,17 @@
package android.graphics.drawable.cts;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
import android.util.Xml;
import java.io.IOException;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
/**
* The useful methods for graphics.drawable test.
*/
@@ -85,4 +87,41 @@
}
return attrs;
}
+
+ public static XmlResourceParser getResourceParser(Resources res, int resId)
+ throws XmlPullParserException, IOException {
+ final XmlResourceParser parser = res.getXml(resId);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Empty loop
+ }
+ return parser;
+ }
+
+ public static void setResourcesDensity(Resources res, int densityDpi) {
+ final Configuration config = new Configuration();
+ config.setTo(res.getConfiguration());
+ config.densityDpi = densityDpi;
+ res.updateConfiguration(config, null);
+ }
+
+ /**
+ * Implements scaling as used by the Bitmap class. Resulting values are
+ * rounded up (as distinct from resource scaling, which truncates or rounds
+ * to the nearest pixel).
+ *
+ * @param size the pixel size to scale
+ * @param sdensity the source density that corresponds to the size
+ * @param tdensity the target density
+ * @return the pixel size scaled for the target density
+ */
+ public static int scaleBitmapFromDensity(int size, int sdensity, int tdensity) {
+ if (sdensity == 0 || tdensity == 0 || sdensity == tdensity) {
+ return size;
+ }
+
+ // Scale by tdensity / sdensity, rounding up.
+ return ((size * tdensity) + (sdensity >> 1)) / sdensity;
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableWrapperTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableWrapperTest.java
index 40680c1..9037e6a 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableWrapperTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableWrapperTest.java
@@ -17,7 +17,7 @@
package android.graphics.drawable.cts;
import android.graphics.drawable.DrawableWrapper;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import java.util.Arrays;
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 eeda22c..c80ae4b 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
@@ -16,7 +16,9 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.content.res.Resources.Theme;
+import android.content.res.XmlResourceParser;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -320,4 +322,70 @@
assertEquals(50, d3.getIntrinsicHeight());
assertEquals(40, d3.getIntrinsicWidth());
}
+
+ public void testPreloadDensity() throws XmlPullParserException, IOException {
+ final Resources res = getContext().getResources();
+ final int densityDpi = res.getConfiguration().densityDpi;
+ final Rect tempPadding = new Rect();
+
+ // Capture initial state at default density.
+ final XmlResourceParser parser = DrawableTestUtils.getResourceParser(
+ res, R.drawable.gradient_drawable_density);
+ final GradientDrawable preloadedDrawable = new GradientDrawable();
+ preloadedDrawable.inflate(res, parser, Xml.asAttributeSet(parser));
+ final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
+ final int origWidth = preloadedDrawable.getIntrinsicWidth();
+ final int origHeight = preloadedDrawable.getIntrinsicHeight();
+ final Rect origPadding = new Rect();
+ preloadedDrawable.getPadding(origPadding);
+
+ // Set density to half of original. Unlike offsets, which are
+ // truncated, dimensions are rounded to the nearest pixel.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
+ final GradientDrawable halfDrawable =
+ (GradientDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(Math.round(origWidth / 2f), halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(origHeight / 2f), halfDrawable.getIntrinsicHeight());
+ assertTrue(halfDrawable.getPadding(tempPadding));
+ assertEquals((int) (origPadding.left / 2f), tempPadding.left);
+
+ // Set density to double original.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
+ final GradientDrawable doubleDrawable =
+ (GradientDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(origWidth * 2, doubleDrawable.getIntrinsicWidth());
+ assertEquals(origHeight * 2, doubleDrawable.getIntrinsicHeight());
+ assertTrue(doubleDrawable.getPadding(tempPadding));
+ assertEquals(origPadding.left * 2, tempPadding.left);
+
+ // Restore original density.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi);
+ final GradientDrawable origDrawable =
+ (GradientDrawable) preloadedConstantState.newDrawable();
+ assertEquals(origWidth, origDrawable.getIntrinsicWidth());
+ assertEquals(origHeight, origDrawable.getIntrinsicHeight());
+ assertTrue(origDrawable.getPadding(tempPadding));
+ assertEquals(origPadding, tempPadding);
+
+ // Some precision is lost when scaling the half-density
+ // drawable back up to the original density.
+ final Rect sloppyOrigPadding = new Rect();
+ sloppyOrigPadding.left = 2 * Math.round(origPadding.left / 2f);
+ sloppyOrigPadding.top = 2 * Math.round(origPadding.top / 2f);
+ sloppyOrigPadding.right = 2 * Math.round(origPadding.right / 2f);
+ sloppyOrigPadding.bottom = 2 * Math.round(origPadding.bottom / 2f);
+
+ // Ensure theme density is applied correctly.
+ final Theme t = res.newTheme();
+ halfDrawable.applyTheme(t);
+ assertEquals(2 * Math.round(origWidth / 2f), halfDrawable.getIntrinsicWidth());
+ assertEquals(2 * Math.round(origHeight / 2f), halfDrawable.getIntrinsicHeight());
+ assertTrue(halfDrawable.getPadding(tempPadding));
+ assertEquals(sloppyOrigPadding, tempPadding);
+ doubleDrawable.applyTheme(t);
+ assertEquals(origWidth, doubleDrawable.getIntrinsicWidth());
+ assertEquals(origHeight, doubleDrawable.getIntrinsicHeight());
+ assertTrue(doubleDrawable.getPadding(tempPadding));
+ assertEquals(origPadding, tempPadding);
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/IconTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/IconTest.java
index d89ce7c..299eaf0 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/IconTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/IconTest.java
@@ -16,7 +16,7 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import android.app.Activity;
import android.app.Instrumentation;
@@ -50,7 +50,7 @@
MockRunner mRunner;
public IconTest() {
- super("com.android.cts.graphics", ImageViewCtsActivity.class);
+ super("android.graphics.cts", ImageViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
index 9c5f063..fb10db6 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
@@ -16,23 +16,25 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.XmlResourceParser;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.cts.R;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.Drawable.ConstantState;
+import android.graphics.drawable.InsetDrawable;
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.StateSet;
import android.util.Xml;
+import android.view.InflateException;
import java.io.IOException;
import java.util.Arrays;
@@ -57,23 +59,25 @@
try {
insetDrawable.inflate(r, parser, attrs);
- fail("There should be a XmlPullParserException thrown out.");
- } catch (XmlPullParserException e) {
+ fail("There should be an InflateException thrown out.");
+ } catch (InflateException e) {
// expected, test success
} catch (IOException e) {
fail("There should not be an IOException thrown out.");
+ } catch (XmlPullParserException e) {
+ fail("There should not be a XmlPullParserException thrown out.");
}
// input null as params
try {
insetDrawable.inflate(null, null, null);
fail("There should be a NullPointerException thrown out.");
- } catch (XmlPullParserException e) {
- fail("There should not be a XmlPullParserException thrown out.");
- } catch (IOException e) {
- fail("There should not be an IOException thrown out.");
} catch (NullPointerException e) {
// expected, test success
+ } catch (IOException e) {
+ fail("There should not be an IOException thrown out.");
+ } catch (XmlPullParserException e) {
+ fail("There should not be a XmlPullParserException thrown out.");
}
}
@@ -283,28 +287,48 @@
Drawable d = mContext.getDrawable(R.drawable.pass);
InsetDrawable insetDrawable = new InsetDrawable(d, 0);
- int expected = d.getIntrinsicWidth(); /* 31 */
+ int expected = d.getIntrinsicWidth();
assertEquals(expected, insetDrawable.getIntrinsicWidth());
d = mContext.getDrawable(R.drawable.scenery);
insetDrawable = new InsetDrawable(d, 0);
- expected = d.getIntrinsicWidth(); /* 170 */
+ expected = d.getIntrinsicWidth();
assertEquals(expected, insetDrawable.getIntrinsicWidth());
+
+ d = mContext.getDrawable(R.drawable.scenery);
+ insetDrawable = new InsetDrawable(d, 20);
+
+ expected = d.getIntrinsicWidth() + 40;
+ assertEquals(expected, insetDrawable.getIntrinsicWidth());
+
+ d = mContext.getDrawable(R.drawable.inset_color);
+ expected = -1;
+ assertEquals(expected, d.getIntrinsicWidth());
}
public void testGetIntrinsicHeight() {
Drawable d = mContext.getDrawable(R.drawable.pass);
InsetDrawable insetDrawable = new InsetDrawable(d, 0);
- int expected = d.getIntrinsicHeight(); /* 31 */
+ int expected = d.getIntrinsicHeight();
assertEquals(expected, insetDrawable.getIntrinsicHeight());
d = mContext.getDrawable(R.drawable.scenery);
insetDrawable = new InsetDrawable(d, 0);
- expected = d.getIntrinsicHeight(); /* 107 */
+ expected = d.getIntrinsicHeight();
assertEquals(expected, insetDrawable.getIntrinsicHeight());
+
+ d = mContext.getDrawable(R.drawable.scenery);
+ insetDrawable = new InsetDrawable(d, 20);
+
+ expected = d.getIntrinsicHeight() + 40;
+ assertEquals(expected, insetDrawable.getIntrinsicHeight());
+
+ d = mContext.getDrawable(R.drawable.inset_color);
+ expected = -1;
+ assertEquals(expected, d.getIntrinsicHeight());
}
public void testGetConstantState() {
@@ -333,6 +357,51 @@
assertEquals("Did not modify post-mutate() instance", 255, post.getDrawable().getAlpha());
}
+ public void testPreloadDensity() throws XmlPullParserException, IOException {
+ final Resources res = getContext().getResources();
+ final int densityDpi = res.getConfiguration().densityDpi;
+
+ // Capture initial state at default density.
+ final XmlResourceParser parser = DrawableTestUtils.getResourceParser(
+ res, R.drawable.inset_density);
+ final InsetDrawable preloadedDrawable = new InsetDrawable(null, 0);
+ preloadedDrawable.inflate(res, parser, Xml.asAttributeSet(parser));
+ final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
+ final int origInsetHoriz = preloadedDrawable.getIntrinsicWidth()
+ - preloadedDrawable.getDrawable().getIntrinsicWidth();
+
+ // Set density to half of original. Unlike offsets, which are
+ // truncated, dimensions are rounded to the nearest pixel.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
+ final InsetDrawable halfDrawable =
+ (InsetDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(Math.round(origInsetHoriz / 2f), halfDrawable.getIntrinsicWidth()
+ - halfDrawable.getDrawable().getIntrinsicWidth());
+
+ // Set density to double original.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
+ final InsetDrawable doubleDrawable =
+ (InsetDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(origInsetHoriz * 2, doubleDrawable.getIntrinsicWidth()
+ - doubleDrawable.getDrawable().getIntrinsicWidth());
+
+ // Restore original density.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi);
+ final InsetDrawable origDrawable =
+ (InsetDrawable) preloadedConstantState.newDrawable();
+ assertEquals(origInsetHoriz, origDrawable.getIntrinsicWidth()
+ - origDrawable.getDrawable().getIntrinsicWidth());
+
+ // Ensure theme density is applied correctly.
+ final Theme t = res.newTheme();
+ halfDrawable.applyTheme(t);
+ assertEquals(origInsetHoriz, halfDrawable.getIntrinsicWidth()
+ - halfDrawable.getDrawable().getIntrinsicWidth());
+ doubleDrawable.applyTheme(t);
+ assertEquals(origInsetHoriz, doubleDrawable.getIntrinsicWidth()
+ - doubleDrawable.getDrawable().getIntrinsicWidth());
+ }
+
private class MockInsetDrawable extends InsetDrawable {
public MockInsetDrawable(Drawable drawable, int inset) {
super(drawable, inset);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
index a2f9ddf..4b17587 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
@@ -16,19 +16,18 @@
package android.graphics.drawable.cts;
-import android.view.Gravity;
-import com.android.cts.graphics.R;
-
+import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import java.io.IOException;
-
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
import android.content.res.XmlResourceParser;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.cts.R;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -41,8 +40,12 @@
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.StateSet;
+import android.util.Xml;
+import android.view.Gravity;
import android.view.View;
+import java.io.IOException;
+
public class LayerDrawableTest extends AndroidTestCase {
@SuppressWarnings("deprecation")
@@ -258,7 +261,12 @@
@SuppressWarnings("deprecation")
public void testSetLayerInset() {
- Drawable[] array = new Drawable[] { new BitmapDrawable(), new ColorDrawable(Color.BLUE) };
+ MockDrawable firstLayer = new MockDrawable();
+ firstLayer.setIntrinsicSize(10, 10);
+ MockDrawable secondLayer = new MockDrawable();
+ secondLayer.setIntrinsicSize(-1, -1);
+
+ Drawable[] array = new Drawable[] { firstLayer, secondLayer };
LayerDrawable layerDrawable = new LayerDrawable(array);
// set inset for layer 0
@@ -272,15 +280,12 @@
assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
layerDrawable.getIntrinsicHeight());
- // set bigger inset for layer 1
- left += 10;
- top += 10;
- right += 10;
- bottom += 10;
- layerDrawable.setLayerInset(1, left, top, right, bottom);
- assertEquals(layerDrawable.getDrawable(1).getIntrinsicWidth() + left + right,
+ // The drawable at index 0 has no intrinsic width or height, so it
+ // won't be counted for the overall intrinsic width or height.
+ layerDrawable.setLayerInset(1, 10, 10, 10, 10);
+ assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + left + right,
layerDrawable.getIntrinsicWidth());
- assertEquals(layerDrawable.getDrawable(1).getIntrinsicHeight() + top + bottom,
+ assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
layerDrawable.getIntrinsicHeight());
try {
@@ -640,6 +645,21 @@
assertTrue(mockDrawable2.hasCalledOnBoundsChange());
}
+ public void testJumpToCurrentState() {
+ MockDrawable mockDrawable1 = new MockDrawable();
+ MockDrawable mockDrawable2 = new MockDrawable();
+ Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+ LayerDrawable layerDrawable = new LayerDrawable(array);
+
+ assertFalse(mockDrawable1.hasCalledJumpToCurrentState());
+ assertFalse(mockDrawable2.hasCalledJumpToCurrentState());
+
+ layerDrawable.jumpToCurrentState();
+
+ assertTrue(mockDrawable1.hasCalledJumpToCurrentState());
+ assertTrue(mockDrawable2.hasCalledJumpToCurrentState());
+ }
+
public void testSetLevel() {
MockDrawable mockDrawable1 = new MockDrawable();
MockDrawable mockDrawable2 = new MockDrawable();
@@ -720,11 +740,13 @@
}
public void testGetIntrinsicWidth() {
- MockDrawable mockDrawable1 = new MockDrawable();
- MockDrawable mockDrawable2 = new MockDrawable();
- Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+ MockDrawable largeMockDrawable = new MockDrawable();
+ largeMockDrawable.setIntrinsicSize(10, 10);
+ MockDrawable smallMockDrawable = new MockDrawable();
+ smallMockDrawable.setIntrinsicSize(1, 1);
+ Drawable[] array = new Drawable[] { largeMockDrawable, smallMockDrawable };
LayerDrawable layerDrawable = new LayerDrawable(array);
- assertEquals(mockDrawable1.getIntrinsicWidth(), layerDrawable.getIntrinsicWidth());
+ assertEquals(largeMockDrawable.getIntrinsicWidth(), layerDrawable.getIntrinsicWidth());
Rect inset1 = new Rect(1, 2, 3, 4);
Rect inset2 = new Rect(2, 4, 6, 7);
@@ -732,26 +754,28 @@
Rect padding2 = new Rect(21, 32, 43, 54);
layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
layerDrawable.setLayerInset(1, inset2.left, inset2.top, inset2.right, inset2.bottom);
- mockDrawable1.setPadding(padding1);
- mockDrawable2.setPadding(padding2);
+ largeMockDrawable.setPadding(padding1);
+ smallMockDrawable.setPadding(padding2);
layerDrawable.getPadding(new Rect());
- assertEquals(mockDrawable2.getIntrinsicWidth() + inset2.left
+ assertEquals(smallMockDrawable.getIntrinsicWidth() + inset2.left
+ inset2.right + padding1.left + padding1.right,
layerDrawable.getIntrinsicWidth());
inset1 = new Rect(inset2.left + padding1.left + 1, inset2.top + padding1.top + 1,
inset2.right + padding1.right + 1, inset2.bottom + padding1.bottom + 1);
layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
- assertEquals(mockDrawable1.getIntrinsicWidth() + inset1.left + inset1.right,
+ assertEquals(largeMockDrawable.getIntrinsicWidth() + inset1.left + inset1.right,
layerDrawable.getIntrinsicWidth());
}
public void testGetIntrinsicHeight() {
- MockDrawable mockDrawable1 = new MockDrawable();
- MockDrawable mockDrawable2 = new MockDrawable();
- Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
+ MockDrawable largeMockDrawable = new MockDrawable();
+ largeMockDrawable.setIntrinsicSize(10, 10);
+ MockDrawable smallMockDrawable = new MockDrawable();
+ smallMockDrawable.setIntrinsicSize(1, 1);
+ Drawable[] array = new Drawable[] { largeMockDrawable, smallMockDrawable };
LayerDrawable layerDrawable = new LayerDrawable(array);
- assertEquals(mockDrawable1.getIntrinsicHeight(), layerDrawable.getIntrinsicHeight());
+ assertEquals(largeMockDrawable.getIntrinsicHeight(), layerDrawable.getIntrinsicHeight());
Rect inset1 = new Rect(1, 2, 3, 4);
Rect inset2 = new Rect(2, 4, 6, 7);
@@ -759,17 +783,17 @@
Rect padding2 = new Rect(21, 32, 43, 54);
layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
layerDrawable.setLayerInset(1, inset2.left, inset2.top, inset2.right, inset2.bottom);
- mockDrawable1.setPadding(padding1);
- mockDrawable2.setPadding(padding2);
+ largeMockDrawable.setPadding(padding1);
+ smallMockDrawable.setPadding(padding2);
layerDrawable.getPadding(new Rect());
- assertEquals(mockDrawable2.getIntrinsicHeight() + inset2.top
+ assertEquals(smallMockDrawable.getIntrinsicHeight() + inset2.top
+ inset2.bottom + padding1.top + padding1.bottom,
layerDrawable.getIntrinsicHeight());
inset1 = new Rect(inset2.left + padding1.left + 1, inset2.top + padding1.top + 1,
inset2.right + padding1.right + 1, inset2.bottom + padding1.bottom + 1);
layerDrawable.setLayerInset(0, inset1.left, inset1.top, inset1.right, inset1.bottom);
- assertEquals(mockDrawable1.getIntrinsicHeight() + inset1.top + inset1.bottom,
+ assertEquals(largeMockDrawable.getIntrinsicHeight() + inset1.top + inset1.bottom,
layerDrawable.getIntrinsicHeight());
}
@@ -1056,10 +1080,14 @@
@SuppressWarnings("deprecation")
public void testSetLayerInsetRelative() {
- Drawable[] array = new Drawable[] { new BitmapDrawable(), new ColorDrawable(Color.BLUE) };
+ MockDrawable firstLayer = new MockDrawable();
+ firstLayer.setIntrinsicSize(10, 10);
+ MockDrawable secondLayer = new MockDrawable();
+ secondLayer.setIntrinsicSize(-1, -1);
+
+ Drawable[] array = new Drawable[] { firstLayer, secondLayer };
LayerDrawable layerDrawable = new LayerDrawable(array);
- // set inset for layer 0
int start = 10;
int top = 20;
int end = 30;
@@ -1069,25 +1097,21 @@
layerDrawable.getIntrinsicWidth());
assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
layerDrawable.getIntrinsicHeight());
- assertEquals(10, layerDrawable.getLayerInsetStart(0));
- assertEquals(20, layerDrawable.getLayerInsetTop(0));
- assertEquals(30, layerDrawable.getLayerInsetEnd(0));
- assertEquals(40, layerDrawable.getLayerInsetBottom(0));
+ assertEquals(start, layerDrawable.getLayerInsetStart(0));
+ assertEquals(top, layerDrawable.getLayerInsetTop(0));
+ assertEquals(end, layerDrawable.getLayerInsetEnd(0));
+ assertEquals(bottom, layerDrawable.getLayerInsetBottom(0));
assertEquals(0, layerDrawable.getLayerInsetLeft(0));
assertEquals(0, layerDrawable.getLayerInsetRight(0));
- // set bigger inset for layer 1
- start += 10;
- top += 10;
- end += 10;
- bottom += 10;
- layerDrawable.setLayerInsetRelative(1, start, top, end, bottom);
- assertEquals(layerDrawable.getDrawable(1).getIntrinsicWidth() + start + end,
+ // The drawable at index 1 has no intrinsic width or height, so it
+ // won't be counted for the overall intrinsic width or height.
+ layerDrawable.setLayerInsetRelative(1, 10, 10, 10, 10);
+ assertEquals(layerDrawable.getDrawable(0).getIntrinsicWidth() + start + end,
layerDrawable.getIntrinsicWidth());
- assertEquals(layerDrawable.getDrawable(1).getIntrinsicHeight() + top + bottom,
+ assertEquals(layerDrawable.getDrawable(0).getIntrinsicHeight() + top + bottom,
layerDrawable.getIntrinsicHeight());
-
try {
layerDrawable.setLayerInsetRelative(-1, start, top, end, bottom);
fail("Should throw IndexOutOfBoundsException");
@@ -1390,7 +1414,29 @@
}
}
+ public void testChildIntrinsicSize() {
+ LayerDrawable dr;
+ // Ensure that a child with no intrinsic size correctly reports bounds.
+ dr = (LayerDrawable) getContext().getDrawable(R.drawable.layer_drawable_intrinsic);
+ assertEquals(-1, dr.getIntrinsicWidth());
+ assertEquals(-1, dr.getIntrinsicHeight());
+
+ // Check when creating the drawble from code.
+ dr = new LayerDrawable(new Drawable[] { new ColorDrawable(Color.RED) });
+ dr.setLayerInset(0, 10, 10, 10, 10);
+ assertEquals(-1, dr.getIntrinsicWidth());
+ assertEquals(-1, dr.getIntrinsicHeight());
+
+ // Ensure mixed children report bounds correctly as well.
+ dr = (LayerDrawable) getContext().getDrawable(R.drawable.layer_drawable_intrinsic_mixed);
+ int width = dr.getLayerInsetLeft(0) + dr.getLayerInsetRight(0)
+ + dr.getDrawable(0).getIntrinsicWidth();
+ int height = dr.getLayerInsetTop(0) + dr.getLayerInsetBottom(0)
+ + dr.getDrawable(0).getIntrinsicHeight();
+ assertEquals(width, dr.getIntrinsicWidth());
+ assertEquals(height, dr.getIntrinsicHeight());
+ }
private static class MockDrawable extends Drawable {
private boolean mCalledSetDither = false;
@@ -1400,7 +1446,7 @@
private boolean mCalledSetState = false;
private boolean mCalledOnLevelChange = false;
private boolean mCalledOnBoundsChange = false;
-
+ private boolean mCalledJumpToCurrentState = false;
private boolean mCalledDraw = false;
@@ -1408,6 +1454,9 @@
private int mOpacity = PixelFormat.OPAQUE;
+ private int mIntrinsicWidth = -1;
+ private int mIntrinsicHeight = -1;
+
private boolean mDither = false;
Rect mPadding = null;
@@ -1454,6 +1503,21 @@
mCalledSetDither = true;
}
+ public void setIntrinsicSize(int width, int height) {
+ mIntrinsicWidth = width;
+ mIntrinsicHeight = height;
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mIntrinsicWidth;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mIntrinsicHeight;
+ }
+
public boolean hasCalledSetDither() {
return mCalledSetDither;
}
@@ -1474,11 +1538,23 @@
mCalledSetState = false;
mCalledOnLevelChange = false;
mCalledOnBoundsChange = false;
+ mCalledJumpToCurrentState = false;
mCalledDraw = false;
}
@Override
+ public void jumpToCurrentState() {
+ super.jumpToCurrentState();
+
+ mCalledJumpToCurrentState = true;
+ }
+
+ public boolean hasCalledJumpToCurrentState() {
+ return mCalledJumpToCurrentState;
+ }
+
+ @Override
protected boolean onStateChange(int[] state) {
increasePadding();
return mIsStateful;
@@ -1583,4 +1659,103 @@
assertEquals(50, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
assertEquals(50, ((BitmapDrawable) d3.getDrawable(0)).getPaint().getAlpha());
}
+
+ public void testPreloadDensity() throws XmlPullParserException, IOException {
+ final Resources res = getContext().getResources();
+ final int densityDpi = res.getConfiguration().densityDpi;
+
+ // Capture initial state at default density.
+ final XmlResourceParser parser = DrawableTestUtils.getResourceParser(
+ res, R.drawable.layer_drawable_density);
+ final LayerDrawable preloadedDrawable = new LayerDrawable(new Drawable[0]);
+ preloadedDrawable.inflate(res, parser, Xml.asAttributeSet(parser));
+ final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
+ final int initialWidth = preloadedDrawable.getIntrinsicWidth();
+ final int initialLeftPadding = preloadedDrawable.getLeftPadding();
+ final int initialRightPadding = preloadedDrawable.getRightPadding();
+ final int initialBottomPadding = preloadedDrawable.getBottomPadding();
+ final int initialTopPadding = preloadedDrawable.getTopPadding();
+ final int initialLayerInsetLeft = preloadedDrawable.getLayerInsetLeft(0);
+ final int initialLayerInsetRight = preloadedDrawable.getLayerInsetRight(0);
+ final int initialLayerInsetTop = preloadedDrawable.getLayerInsetTop(0);
+ final int initialLayerInsetBottom = preloadedDrawable.getLayerInsetBottom(0);
+ final int initialLayerWidth = preloadedDrawable.getLayerWidth(0);
+ final int initialLayerHeight = preloadedDrawable.getLayerHeight(0);
+
+ // Set density to half of original. Unlike offsets, which are
+ // truncated, dimensions are rounded to the nearest pixel.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
+ final LayerDrawable halfDrawable =
+ (LayerDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(Math.round(initialWidth / 2f), halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(initialLeftPadding / 2f), halfDrawable.getLeftPadding());
+ assertEquals(Math.round(initialRightPadding / 2f), halfDrawable.getRightPadding());
+ assertEquals(Math.round(initialBottomPadding / 2f), halfDrawable.getBottomPadding());
+ assertEquals(Math.round(initialTopPadding / 2f), halfDrawable.getTopPadding());
+ assertEquals(Math.round(initialLayerInsetLeft / 2f),halfDrawable.getLayerInsetLeft(0));
+ assertEquals(Math.round(initialLayerInsetRight / 2f), halfDrawable.getLayerInsetRight(0));
+ assertEquals(Math.round(initialLayerInsetTop / 2f), halfDrawable.getLayerInsetTop(0));
+ assertEquals(Math.round(initialLayerInsetBottom / 2f), halfDrawable.getLayerInsetBottom(0));
+ assertEquals(Math.round(initialLayerWidth / 2f), halfDrawable.getLayerWidth(0));
+ assertEquals(Math.round(initialLayerHeight / 2f), halfDrawable.getLayerHeight(0));
+
+ // Set density to double original.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
+ final LayerDrawable doubleDrawable =
+ (LayerDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(initialWidth * 2, doubleDrawable.getIntrinsicWidth());
+ assertEquals(initialLeftPadding * 2, doubleDrawable.getLeftPadding());
+ assertEquals(initialRightPadding * 2, doubleDrawable.getRightPadding());
+ assertEquals(initialBottomPadding * 2, doubleDrawable.getBottomPadding());
+ assertEquals(initialTopPadding * 2, doubleDrawable.getTopPadding());
+ assertEquals(initialLayerInsetLeft * 2, doubleDrawable.getLayerInsetLeft(0));
+ assertEquals(initialLayerInsetRight * 2, doubleDrawable.getLayerInsetRight(0));
+ assertEquals(initialLayerInsetTop * 2, doubleDrawable.getLayerInsetTop(0));
+ assertEquals(initialLayerInsetBottom * 2, doubleDrawable.getLayerInsetBottom(0));
+ assertEquals(initialLayerWidth * 2, doubleDrawable.getLayerWidth(0));
+ assertEquals(initialLayerHeight * 2, doubleDrawable.getLayerHeight(0));
+
+ // Restore original configuration and metrics.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi);
+ final LayerDrawable origDrawable =
+ (LayerDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(initialWidth, origDrawable.getIntrinsicWidth());
+ assertEquals(initialLeftPadding, origDrawable.getLeftPadding());
+ assertEquals(initialRightPadding, origDrawable.getRightPadding());
+ assertEquals(initialBottomPadding, origDrawable.getBottomPadding());
+ assertEquals(initialTopPadding, origDrawable.getTopPadding());
+ assertEquals(initialLayerInsetLeft, origDrawable.getLayerInsetLeft(0));
+ assertEquals(initialLayerInsetRight, origDrawable.getLayerInsetRight(0));
+ assertEquals(initialLayerInsetTop, origDrawable.getLayerInsetTop(0));
+ assertEquals(initialLayerInsetBottom, origDrawable.getLayerInsetBottom(0));
+ assertEquals(initialLayerWidth, origDrawable.getLayerWidth(0));
+ assertEquals(initialLayerHeight, origDrawable.getLayerHeight(0));
+
+ // Ensure theme density is applied correctly.
+ final Theme t = res.newTheme();
+ halfDrawable.applyTheme(t);
+ assertEquals(initialWidth, halfDrawable.getIntrinsicWidth());
+ assertEquals(initialLeftPadding, halfDrawable.getLeftPadding());
+ assertEquals(initialRightPadding, halfDrawable.getRightPadding());
+ assertEquals(initialBottomPadding, halfDrawable.getBottomPadding());
+ assertEquals(initialTopPadding, halfDrawable.getTopPadding());
+ assertEquals(initialLayerInsetLeft, halfDrawable.getLayerInsetLeft(0));
+ assertEquals(initialLayerInsetRight, halfDrawable.getLayerInsetRight(0));
+ assertEquals(initialLayerInsetTop, halfDrawable.getLayerInsetTop(0));
+ assertEquals(initialLayerInsetBottom, halfDrawable.getLayerInsetBottom(0));
+ assertEquals(initialLayerWidth, halfDrawable.getLayerWidth(0));
+ assertEquals(initialLayerHeight, halfDrawable.getLayerHeight(0));
+ doubleDrawable.applyTheme(t);
+ assertEquals(initialWidth, doubleDrawable.getIntrinsicWidth());
+ assertEquals(initialLeftPadding, doubleDrawable.getLeftPadding());
+ assertEquals(initialRightPadding, doubleDrawable.getRightPadding());
+ assertEquals(initialBottomPadding, doubleDrawable.getBottomPadding());
+ assertEquals(initialTopPadding, doubleDrawable.getTopPadding());
+ assertEquals(initialLayerInsetLeft, doubleDrawable.getLayerInsetLeft(0));
+ assertEquals(initialLayerInsetRight, doubleDrawable.getLayerInsetRight(0));
+ assertEquals(initialLayerInsetTop, doubleDrawable.getLayerInsetTop(0));
+ assertEquals(initialLayerInsetBottom, doubleDrawable.getLayerInsetBottom(0));
+ assertEquals(initialLayerWidth, doubleDrawable.getLayerWidth(0));
+ assertEquals(initialLayerHeight, doubleDrawable.getLayerHeight(0));
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/LevelListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/LevelListDrawableTest.java
index 11186b0..4ef49c0 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/LevelListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LevelListDrawableTest.java
@@ -31,7 +31,7 @@
import android.test.InstrumentationTestCase;
import android.util.Xml;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
public class LevelListDrawableTest extends InstrumentationTestCase {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java
index 720397c..ba54b0c 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java
@@ -16,7 +16,7 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -311,15 +311,23 @@
}
public void testInflate() throws XmlPullParserException, IOException {
- final int width = 80;
- final int height = 120;
- final int[] COLOR = new int[width * height];
- Bitmap bitmap = Bitmap.createBitmap(COLOR, width, height, Bitmap.Config.RGB_565);
- NinePatchDrawable ninePatchDrawable =
- new NinePatchDrawable(mResources, bitmap, new byte[1000], null, "TESTNAME");
+ int sourceWidth = 80;
+ int sourceHeight = 120;
+ int[] colors = new int[sourceWidth * sourceHeight];
+ Bitmap bitmap = Bitmap.createBitmap(
+ colors, sourceWidth, sourceHeight, Bitmap.Config.RGB_565);
+ NinePatchDrawable ninePatchDrawable = new NinePatchDrawable(
+ mResources, bitmap, new byte[1000], null, "TESTNAME");
- assertEquals(height, ninePatchDrawable.getIntrinsicHeight());
- assertEquals(width, ninePatchDrawable.getIntrinsicWidth());
+ int sourceDensity = bitmap.getDensity();
+ int targetDensity = mResources.getDisplayMetrics().densityDpi;
+ int targetWidth = DrawableTestUtils.scaleBitmapFromDensity(
+ sourceWidth, sourceDensity, targetDensity);
+ int targetHeight = DrawableTestUtils.scaleBitmapFromDensity(
+ sourceHeight, sourceDensity, targetDensity);
+ assertEquals(targetWidth, ninePatchDrawable.getIntrinsicWidth());
+ assertEquals(targetHeight, ninePatchDrawable.getIntrinsicHeight());
+
XmlResourceParser parser = mResources.getXml(R.drawable.ninepatchdrawable);
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -329,8 +337,8 @@
ninePatchDrawable.inflate(mResources, parser, attrs);
assertTrue(ninePatchDrawable.getPaint().isDither());
- assertTrue(height != ninePatchDrawable.getIntrinsicHeight());
- assertTrue(width != ninePatchDrawable.getIntrinsicWidth());
+ assertTrue(sourceHeight != ninePatchDrawable.getIntrinsicHeight());
+ assertTrue(sourceWidth != ninePatchDrawable.getIntrinsicWidth());
}
public void testMutate() {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java
index a440dab..fdb8f2f 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java
@@ -16,7 +16,7 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/RippleDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/RippleDrawableTest.java
index b04433c..4031bc6 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/RippleDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/RippleDrawableTest.java
@@ -16,12 +16,23 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import static org.mockito.Mockito.*;
+
+import org.xmlpull.v1.XmlPullParserException;
import android.content.res.ColorStateList;
-import android.graphics.drawable.RippleDrawable;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.XmlResourceParser;
import android.graphics.Color;
+import android.graphics.cts.R;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.graphics.drawable.RippleDrawable;
import android.test.AndroidTestCase;
+import android.util.Xml;
+
+import java.io.IOException;
public class RippleDrawableTest extends AndroidTestCase {
public void testConstructor() {
@@ -41,4 +52,53 @@
(RippleDrawable) getContext().getDrawable(R.drawable.rippledrawable_radius);
assertEquals(10, drawable.getRadius());
}
+
+ public void testPreloadDensity() throws XmlPullParserException, IOException {
+ final Resources res = getContext().getResources();
+ final int densityDpi = res.getConfiguration().densityDpi;
+
+ // Capture initial state at default density.
+ final XmlResourceParser parser = DrawableTestUtils.getResourceParser(
+ res, R.drawable.rippledrawable_radius);
+ final RippleDrawable preloadedDrawable = new RippleDrawable(
+ ColorStateList.valueOf(Color.BLACK), null, null);
+ preloadedDrawable.inflate(res, parser, Xml.asAttributeSet(parser));
+ final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
+ final int initialRadius = preloadedDrawable.getRadius();
+
+ // Set density to half of original. Unlike offsets, which are
+ // truncated, dimensions are rounded to the nearest pixel.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
+ final RippleDrawable halfDrawable =
+ (RippleDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(Math.round(initialRadius / 2f), halfDrawable.getRadius());
+
+ // Set density to double original.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
+ final RippleDrawable doubleDrawable =
+ (RippleDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(initialRadius * 2, doubleDrawable.getRadius());
+
+ // Restore original density.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi);
+ final RippleDrawable origDrawable =
+ (RippleDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(initialRadius, origDrawable.getRadius());
+
+ // Ensure theme density is applied correctly.
+ final Theme t = res.newTheme();
+ halfDrawable.applyTheme(t);
+ assertEquals(initialRadius, halfDrawable.getRadius());
+ doubleDrawable.applyTheme(t);
+ assertEquals(initialRadius, doubleDrawable.getRadius());
+ }
+
+ public void testSetColor() {
+ Drawable.Callback cb = mock(Drawable.Callback.class);
+ RippleDrawable dr = new RippleDrawable(ColorStateList.valueOf(Color.RED), null, null);
+ dr.setCallback(cb);
+
+ dr.setColor(ColorStateList.valueOf(Color.BLACK));
+ verify(cb, times(1)).invalidateDrawable(dr);
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
index cf25857..b6912a0 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
@@ -16,7 +16,7 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -57,6 +57,58 @@
mRotateDrawable.draw(canvas);
}
+ public void testInflate() {
+ RotateDrawable d;
+
+ d = (RotateDrawable) mContext.getResources().getDrawable(R.drawable.rotatedrawable_rel);
+ assertEquals(0.1f, d.getPivotX(), 0.01f);
+ assertEquals(0.2f, d.getPivotY(), 0.01f);
+ assertEquals(360.0f, d.getFromDegrees(), 0.01f);
+ assertEquals(360.0f, d.getToDegrees(), 0.01f);
+ assertEquals(true, d.isPivotXRelative());
+ assertEquals(true, d.isPivotYRelative());
+
+ d = (RotateDrawable) mContext.getResources().getDrawable(R.drawable.rotatedrawable_abs);
+ assertEquals(0.3f, d.getPivotX(), 0.01f);
+ assertEquals(0.3f, d.getPivotY(), 0.01f);
+ assertEquals(180.0f, d.getFromDegrees(), 0.01f);
+ assertEquals(-180.0f, d.getToDegrees(), 0.01f);
+ assertEquals(false, d.isPivotXRelative());
+ assertEquals(false, d.isPivotYRelative());
+ }
+
+ public void testSetPivot() {
+ RotateDrawable d = new RotateDrawable();
+ assertEquals(0.5f, d.getPivotX(), 0.01f);
+ assertEquals(0.5f, d.getPivotY(), 0.01f);
+ assertEquals(true, d.isPivotXRelative());
+ assertEquals(true, d.isPivotYRelative());
+
+ d.setPivotX(10.0f);
+ assertEquals(10.0f, d.getPivotX(), 0.01f);
+
+ d.setPivotY(10.0f);
+ assertEquals(10.0f, d.getPivotY(), 0.01f);
+
+ d.setPivotXRelative(false);
+ assertEquals(false, d.isPivotXRelative());
+
+ d.setPivotYRelative(false);
+ assertEquals(false, d.isPivotYRelative());
+ }
+
+ public void testSetDegrees() {
+ RotateDrawable d = new RotateDrawable();
+ assertEquals(0.0f, d.getFromDegrees(), 0.01f);
+ assertEquals(0.0f, d.getFromDegrees(), 0.01f);
+
+ d.setFromDegrees(-10.0f);
+ assertEquals(-10.0f, d.getFromDegrees(), 0.01f);
+
+ d.setToDegrees(10.0f);
+ assertEquals(10.0f, d.getFromDegrees(), 0.01f);
+ }
+
public void testGetChangingConfigurations() {
assertEquals(0, mRotateDrawable.getChangingConfigurations());
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
index b58e40f..e1f37b3 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
@@ -16,7 +16,7 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParserException;
@@ -33,6 +33,7 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.drawable.ScaleDrawable;
+import android.os.Debug;
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -296,6 +297,29 @@
// expected, no Exception thrown out, test success
}
+ public void testInitialLevel() throws XmlPullParserException, IOException {
+ ScaleDrawable dr = new ScaleDrawable(null, Gravity.CENTER, 1, 1);
+ Resources res = mContext.getResources();
+ XmlResourceParser parser = res.getXml(R.xml.scaledrawable_level);
+ AttributeSet attrs = DrawableTestUtils.getAttributeSet(parser, "scale_allattrs");
+
+ // Ensure that initial level is loaded from XML.
+ dr.inflate(res, parser, attrs);
+ assertEquals(5000, dr.getLevel());
+
+ dr.setLevel(0);
+ assertEquals(0, dr.getLevel());
+
+ // Ensure that initial level is propagated to constant state clones.
+ ScaleDrawable clone = (ScaleDrawable) dr.getConstantState().newDrawable(res);
+ assertEquals(5000, clone.getLevel());
+
+ // Ensure that current level is not tied to constant state.
+ dr.setLevel(1000);
+ assertEquals(1000, dr.getLevel());
+ assertEquals(5000, clone.getLevel());
+ }
+
public void testOnLevelChange() {
MockDrawable mockDrawable = new MockDrawable();
MockScaleDrawable mockScaleDrawable = new MockScaleDrawable(
@@ -411,8 +435,7 @@
XmlResourceParser parser = res.getXml(R.xml.scaledrawable);
AttributeSet attrs = DrawableTestUtils.getAttributeSet(parser, "scale_allattrs");
scaleDrawable.inflate(res, parser, attrs);
- int bitmapSize = (int) Math.ceil(48.0 *
- res.getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
+ final int bitmapSize = Math.round(48f * res.getDisplayMetrics().density);
assertEquals(bitmapSize, scaleDrawable.getIntrinsicWidth());
assertEquals(bitmapSize, scaleDrawable.getIntrinsicHeight());
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
index 5b3234e..042fb1b 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
@@ -34,7 +34,7 @@
import android.util.AttributeSet;
import android.util.Xml;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
index d55b91d..9f6a771 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
@@ -22,23 +22,27 @@
import org.xmlpull.v1.XmlPullParserException;
import android.R.attr;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.drawable.StateListDrawable;
import android.graphics.drawable.DrawableContainer.DrawableContainerState;
import android.test.InstrumentationTestCase;
+import android.util.DisplayMetrics;
import android.util.StateSet;
import android.util.Xml;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
public class StateListDrawableTest extends InstrumentationTestCase {
- private MockStateListDrawable mStateListDrawable;
+ private MockStateListDrawable mMockDrawable;
+ private StateListDrawable mDrawable;
private Resources mResources;
@@ -47,8 +51,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mStateListDrawable = new MockStateListDrawable();
- mDrawableContainerState = (DrawableContainerState) mStateListDrawable.getConstantState();
+ mDrawable = mMockDrawable = new MockStateListDrawable();
+ mDrawableContainerState = (DrawableContainerState) mMockDrawable.getConstantState();
mResources = getInstrumentation().getTargetContext().getResources();
}
@@ -60,32 +64,34 @@
}
public void testAddState() {
+ // Workaround for CTS coverage not recognizing calls on subclasses.
+ StateListDrawable dr = mMockDrawable;
+
assertEquals(0, mDrawableContainerState.getChildCount());
// nothing happens if drawable is null
- mStateListDrawable.reset();
- mStateListDrawable.addState(StateSet.WILD_CARD, null);
+ mMockDrawable.reset();
+ dr.addState(StateSet.WILD_CARD, null);
assertEquals(0, mDrawableContainerState.getChildCount());
- assertFalse(mStateListDrawable.hasCalledOnStateChanged());
+ assertFalse(mMockDrawable.hasCalledOnStateChanged());
// call onLevelChanged to assure that the correct drawable is selected.
- mStateListDrawable.reset();
- mStateListDrawable.addState(StateSet.WILD_CARD, new MockDrawable());
+ mMockDrawable.reset();
+ dr.addState(StateSet.WILD_CARD, new MockDrawable());
assertEquals(1, mDrawableContainerState.getChildCount());
- assertTrue(mStateListDrawable.hasCalledOnStateChanged());
+ assertTrue(mMockDrawable.hasCalledOnStateChanged());
- mStateListDrawable.reset();
- mStateListDrawable.addState(new int[] { attr.state_focused, - attr.state_selected },
- new MockDrawable());
+ mMockDrawable.reset();
+ dr.addState(new int[] { attr.state_focused, - attr.state_selected }, new MockDrawable());
assertEquals(2, mDrawableContainerState.getChildCount());
- assertTrue(mStateListDrawable.hasCalledOnStateChanged());
+ assertTrue(mMockDrawable.hasCalledOnStateChanged());
// call onLevelChanged will not throw NPE here because the first drawable with wild card
// state is matched first. There is no chance that other drawables will be matched.
- mStateListDrawable.reset();
- mStateListDrawable.addState(null, new MockDrawable());
+ mMockDrawable.reset();
+ dr.addState(null, new MockDrawable());
assertEquals(3, mDrawableContainerState.getChildCount());
- assertTrue(mStateListDrawable.hasCalledOnStateChanged());
+ assertTrue(mMockDrawable.hasCalledOnStateChanged());
}
public void testIsStateful() {
@@ -93,110 +99,189 @@
}
public void testOnStateChange() {
- mStateListDrawable.addState(new int[] { attr.state_focused, - attr.state_selected },
+ mMockDrawable.addState(new int[] { attr.state_focused, - attr.state_selected },
new MockDrawable());
- mStateListDrawable.addState(StateSet.WILD_CARD, new MockDrawable());
- mStateListDrawable.addState(StateSet.WILD_CARD, new MockDrawable());
+ mMockDrawable.addState(StateSet.WILD_CARD, new MockDrawable());
+ mMockDrawable.addState(StateSet.WILD_CARD, new MockDrawable());
// the method is not called if same state is set
- mStateListDrawable.reset();
- mStateListDrawable.setState(mStateListDrawable.getState());
- assertFalse(mStateListDrawable.hasCalledOnStateChanged());
+ mMockDrawable.reset();
+ mMockDrawable.setState(mMockDrawable.getState());
+ assertFalse(mMockDrawable.hasCalledOnStateChanged());
// the method is called if different state is set
- mStateListDrawable.reset();
- mStateListDrawable.setState(new int[] { attr.state_focused, - attr.state_selected });
- assertTrue(mStateListDrawable.hasCalledOnStateChanged());
+ mMockDrawable.reset();
+ mMockDrawable.setState(new int[] { attr.state_focused, - attr.state_selected });
+ assertTrue(mMockDrawable.hasCalledOnStateChanged());
- mStateListDrawable.reset();
- mStateListDrawable.setState(null);
- assertTrue(mStateListDrawable.hasCalledOnStateChanged());
+ mMockDrawable.reset();
+ mMockDrawable.setState(null);
+ assertTrue(mMockDrawable.hasCalledOnStateChanged());
// check that correct drawable is selected.
- mStateListDrawable.onStateChange(new int[] { attr.state_focused, - attr.state_selected });
- assertSame(mStateListDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
+ mMockDrawable.onStateChange(new int[] { attr.state_focused, - attr.state_selected });
+ assertSame(mMockDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
- assertFalse(mStateListDrawable.onStateChange(new int[] { attr.state_focused }));
- assertSame(mStateListDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
+ assertFalse(mMockDrawable.onStateChange(new int[] { attr.state_focused }));
+ assertSame(mMockDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
- assertTrue(mStateListDrawable.onStateChange(StateSet.WILD_CARD));
- assertSame(mStateListDrawable.getCurrent(), mDrawableContainerState.getChildren()[1]);
+ assertTrue(mMockDrawable.onStateChange(StateSet.WILD_CARD));
+ assertSame(mMockDrawable.getCurrent(), mDrawableContainerState.getChildren()[1]);
// null state will match the wild card
- assertFalse(mStateListDrawable.onStateChange(null));
- assertSame(mStateListDrawable.getCurrent(), mDrawableContainerState.getChildren()[1]);
+ assertFalse(mMockDrawable.onStateChange(null));
+ assertSame(mMockDrawable.getCurrent(), mDrawableContainerState.getChildren()[1]);
}
public void testOnStateChangeWithWildCardAtFirst() {
- mStateListDrawable.addState(StateSet.WILD_CARD, new MockDrawable());
- mStateListDrawable.addState(new int[] { attr.state_focused, - attr.state_selected },
+ mMockDrawable.addState(StateSet.WILD_CARD, new MockDrawable());
+ mMockDrawable.addState(new int[] { attr.state_focused, - attr.state_selected },
new MockDrawable());
// matches the first wild card although the second one is more accurate
- mStateListDrawable.onStateChange(new int[] { attr.state_focused, - attr.state_selected });
- assertSame(mStateListDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
+ mMockDrawable.onStateChange(new int[] { attr.state_focused, - attr.state_selected });
+ assertSame(mMockDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
}
public void testOnStateChangeWithNullStateSet() {
assertEquals(0, mDrawableContainerState.getChildCount());
try {
- mStateListDrawable.addState(null, new MockDrawable());
+ mMockDrawable.addState(null, new MockDrawable());
fail("Should throw NullPointerException.");
} catch (NullPointerException e) {
}
assertEquals(1, mDrawableContainerState.getChildCount());
try {
- mStateListDrawable.onStateChange(StateSet.WILD_CARD);
+ mMockDrawable.onStateChange(StateSet.WILD_CARD);
fail("Should throw NullPointerException.");
} catch (NullPointerException e) {
}
}
+ public void testPreloadDensity() throws XmlPullParserException, IOException {
+ runPreloadDensityTestForDrawable(R.drawable.state_list_density, false);
+ }
+
+ public void testPreloadDensityConstantSize() throws XmlPullParserException, IOException {
+ runPreloadDensityTestForDrawable(R.drawable.state_list_density_constant_size, true);
+ }
+
+ private void runPreloadDensityTestForDrawable(int drawableResId, boolean isConstantSize)
+ throws XmlPullParserException, IOException {
+ final Configuration origConfig = new Configuration();
+ origConfig.setTo(mResources.getConfiguration());
+ final DisplayMetrics origMetrics = new DisplayMetrics();
+ origMetrics.setTo(mResources.getDisplayMetrics());
+
+ final Configuration halfConfig = new Configuration();
+ halfConfig.setTo(origConfig);
+ final DisplayMetrics halfMetrics = new DisplayMetrics();
+ halfMetrics.setTo(origMetrics);
+ halfConfig.densityDpi /= 2;
+ halfMetrics.densityDpi /= 2;
+ halfMetrics.density *= 2;
+
+ final Configuration doubleConfig = new Configuration();
+ doubleConfig.setTo(origConfig);
+ final DisplayMetrics doubleMetrics = new DisplayMetrics();
+ doubleMetrics.setTo(origMetrics);
+ doubleConfig.densityDpi *= 2;
+ doubleMetrics.densityDpi *= 2;
+ doubleMetrics.density /= 2;
+
+ final XmlResourceParser parser = getResourceParser(drawableResId);
+ final StateListDrawable preloadedDrawable = new StateListDrawable();
+ preloadedDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+ final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
+ preloadedDrawable.selectDrawable(0);
+ final int tempWidth0 = preloadedDrawable.getIntrinsicWidth();
+ preloadedDrawable.selectDrawable(1);
+ final int tempWidth1 = preloadedDrawable.getIntrinsicWidth();
+
+ // Pick comparison widths based on constant size.
+ final int origWidth0;
+ final int origWidth1;
+ if (isConstantSize) {
+ origWidth0 = Math.max(tempWidth0, tempWidth1);
+ origWidth1 = origWidth0;
+ } else {
+ origWidth0 = tempWidth0;
+ origWidth1 = tempWidth1;
+ }
+
+ // Set density to half of original.
+ mResources.updateConfiguration(halfConfig, halfMetrics);
+ final StateListDrawable halfDrawable =
+ (StateListDrawable) preloadedConstantState.newDrawable(mResources);
+ halfDrawable.selectDrawable(0);
+ assertEquals(origWidth0 / 2, halfDrawable.getIntrinsicWidth());
+ halfDrawable.selectDrawable(1);
+ assertEquals(origWidth1 / 2, halfDrawable.getIntrinsicWidth());
+
+ // Restore original configuration and metrics.
+ mResources.updateConfiguration(origConfig, origMetrics);
+ final StateListDrawable origDrawable =
+ (StateListDrawable) preloadedConstantState.newDrawable(mResources);
+ origDrawable.selectDrawable(0);
+ assertEquals(origWidth0, origDrawable.getIntrinsicWidth());
+ origDrawable.selectDrawable(1);
+ assertEquals(origWidth1, origDrawable.getIntrinsicWidth());
+
+ // Set density to double original.
+ mResources.updateConfiguration(doubleConfig, doubleMetrics);
+ final StateListDrawable doubleDrawable =
+ (StateListDrawable) preloadedConstantState.newDrawable(mResources);
+ doubleDrawable.selectDrawable(0);
+ assertEquals(origWidth0 * 2, doubleDrawable.getIntrinsicWidth());
+ doubleDrawable.selectDrawable(1);
+ assertEquals(origWidth1 * 2, doubleDrawable.getIntrinsicWidth());
+ }
+
public void testInflate() throws XmlPullParserException, IOException {
XmlResourceParser parser = getResourceParser(R.xml.selector_correct);
- mStateListDrawable.reset();
- mStateListDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+ mMockDrawable.reset();
+ mMockDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
// android:visible="false"
- assertFalse(mStateListDrawable.isVisible());
+ assertFalse(mMockDrawable.isVisible());
// android:constantSize="true"
assertTrue(mDrawableContainerState.isConstantSize());
// android:variablePadding="true"
assertNull(mDrawableContainerState.getConstantPadding());
- assertTrue(mStateListDrawable.hasCalledOnStateChanged());
+ assertTrue(mMockDrawable.hasCalledOnStateChanged());
assertEquals(2, mDrawableContainerState.getChildCount());
// check the android:state_* by calling setState
- mStateListDrawable.setState(new int[]{ attr.state_focused, - attr.state_pressed });
- assertSame(mStateListDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
- mStateListDrawable.setState(StateSet.WILD_CARD);
- assertSame(mStateListDrawable.getCurrent(), mDrawableContainerState.getChildren()[1]);
+ mMockDrawable.setState(new int[]{ attr.state_focused, - attr.state_pressed });
+ assertSame(mMockDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
+ mMockDrawable.setState(StateSet.WILD_CARD);
+ assertSame(mMockDrawable.getCurrent(), mDrawableContainerState.getChildren()[1]);
- mStateListDrawable = new MockStateListDrawable();
- mDrawableContainerState = (DrawableContainerState) mStateListDrawable.getConstantState();
- assertNull(mStateListDrawable.getCurrent());
- mStateListDrawable.reset();
- assertTrue(mStateListDrawable.isVisible());
+ mMockDrawable = new MockStateListDrawable();
+ mDrawableContainerState = (DrawableContainerState) mMockDrawable.getConstantState();
+ assertNull(mMockDrawable.getCurrent());
+ mMockDrawable.reset();
+ assertTrue(mMockDrawable.isVisible());
parser = getResourceParser(R.xml.selector_missing_selector_attrs);
- mStateListDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+ mMockDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
// use current the visibility
- assertTrue(mStateListDrawable.isVisible());
+ assertTrue(mMockDrawable.isVisible());
// default value of android:constantSize is false
assertFalse(mDrawableContainerState.isConstantSize());
// default value of android:variablePadding is false
// TODO: behavior of mDrawableContainerState.getConstantPadding() when variablePadding is
// false is undefined
//assertNotNull(mDrawableContainerState.getConstantPadding());
- assertTrue(mStateListDrawable.hasCalledOnStateChanged());
+ assertTrue(mMockDrawable.hasCalledOnStateChanged());
assertEquals(1, mDrawableContainerState.getChildCount());
- mStateListDrawable.setState(new int[]{ - attr.state_pressed, attr.state_focused });
- assertSame(mStateListDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
- mStateListDrawable.setState(StateSet.WILD_CARD);
- assertNull(mStateListDrawable.getCurrent());
+ mMockDrawable.setState(new int[]{ - attr.state_pressed, attr.state_focused });
+ assertSame(mMockDrawable.getCurrent(), mDrawableContainerState.getChildren()[0]);
+ mMockDrawable.setState(StateSet.WILD_CARD);
+ assertNull(mMockDrawable.getCurrent());
parser = getResourceParser(R.xml.selector_missing_item_drawable);
try {
- mStateListDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+ mMockDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
fail("Should throw XmlPullParserException if drawable of item is missing");
} catch (XmlPullParserException e) {
}
@@ -205,19 +290,19 @@
public void testInflateWithNullParameters() throws XmlPullParserException, IOException{
XmlResourceParser parser = getResourceParser(R.xml.level_list_correct);
try {
- mStateListDrawable.inflate(null, parser, Xml.asAttributeSet(parser));
+ mMockDrawable.inflate(null, parser, Xml.asAttributeSet(parser));
fail("Should throw XmlPullParserException if resource is null");
} catch (NullPointerException e) {
}
try {
- mStateListDrawable.inflate(mResources, null, Xml.asAttributeSet(parser));
+ mMockDrawable.inflate(mResources, null, Xml.asAttributeSet(parser));
fail("Should throw XmlPullParserException if parser is null");
} catch (NullPointerException e) {
}
try {
- mStateListDrawable.inflate(mResources, parser, null);
+ mMockDrawable.inflate(mResources, parser, null);
fail("Should throw XmlPullParserException if AttributeSet is null");
} catch (NullPointerException e) {
}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java
index d7becc6..52bef55 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java
@@ -32,7 +32,7 @@
import android.test.AndroidTestCase;
import android.view.Gravity;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
@TargetApi(21)
public class ThemedDrawableTest extends AndroidTestCase {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java
index f2a22a2..c0ef1be 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java
@@ -16,7 +16,7 @@
package android.graphics.drawable.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import android.content.res.Resources;
import android.graphics.Bitmap;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
index fdc7b7a..8944d63 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
@@ -16,33 +16,34 @@
package android.graphics.drawable.cts;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.ColorFilter;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.VectorDrawable;
+import android.graphics.cts.R;
import android.graphics.drawable.Drawable.ConstantState;
+import android.graphics.drawable.VectorDrawable;
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
-import com.android.cts.graphics.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class VectorDrawableTest extends AndroidTestCase {
- private static final String LOGTAG = VectorDrawableTest.class.getSimpleName();
- private int[] mIconResIds = new int[] {
+ private static final String LOGTAG = "VectorDrawableTest";
+
+ private static final int[] ICON_RES_IDS = new int[] {
R.drawable.vector_icon_create,
R.drawable.vector_icon_delete,
R.drawable.vector_icon_heart,
@@ -68,9 +69,11 @@
R.drawable.vector_icon_stroke_3,
R.drawable.vector_icon_scale_1,
R.drawable.vector_icon_scale_2,
+ R.drawable.vector_icon_implicit_lineto,
+ R.drawable.vector_icon_arcto,
};
- private int[] mGoldenImages = new int[] {
+ private static final int[] GOLDEN_IMAGES = new int[] {
R.drawable.vector_icon_create_golden,
R.drawable.vector_icon_delete_golden,
R.drawable.vector_icon_heart_golden,
@@ -96,6 +99,22 @@
R.drawable.vector_icon_stroke_3_golden,
R.drawable.vector_icon_scale_1_golden,
R.drawable.vector_icon_scale_2_golden,
+ R.drawable.vector_icon_implicit_lineto_golden,
+ R.drawable.vector_icon_arcto_golden,
+ };
+
+ private static final int[] STATEFUL_RES_IDS = new int[] {
+ R.drawable.vector_icon_state_list
+ };
+
+ private static final int[][] STATEFUL_GOLDEN_IMAGES = new int[][] {
+ { R.drawable.vector_icon_state_list_golden },
+ { R.drawable.vector_icon_state_list_golden_pressed }
+ };
+
+ private static final int[][] STATEFUL_STATE_SETS = new int[][] {
+ {},
+ { android.R.attr.state_pressed }
};
private static final int IMAGE_WIDTH = 64;
@@ -104,7 +123,7 @@
// exactly with the golden image.
// We can increase the threshold if the Skia is drawing with some variance
// on different devices. So far, the tests show they are matching correctly.
- private static final float PIXEL_ERROR_THRESHOLD = 0.02f;
+ private static final float PIXEL_ERROR_THRESHOLD = 0.03f;
private static final float PIXEL_ERROR_COUNT_THRESHOLD = 0.005f;
private static final boolean DBG_DUMP_PNG = false;
@@ -128,19 +147,27 @@
mResources = mContext.getResources();
}
- public void testSimpleVectorDrawables() throws Exception {
- verifyVectorDrawables(mIconResIds, mGoldenImages, 0);
+ public void testSimpleVectorDrawables() throws XmlPullParserException, IOException {
+ verifyVectorDrawables(ICON_RES_IDS, GOLDEN_IMAGES, null);
}
- private void verifyVectorDrawables(int[] resIds, int[] goldenImages, float fraction) throws Exception {
+ public void testColorStateList() throws XmlPullParserException, IOException {
+ for (int i = 0; i < STATEFUL_STATE_SETS.length; i++) {
+ verifyVectorDrawables(
+ STATEFUL_RES_IDS, STATEFUL_GOLDEN_IMAGES[i], STATEFUL_STATE_SETS[i]);
+ }
+ }
+
+ private void verifyVectorDrawables(int[] resIds, int[] goldenImages, int[] stateSet)
+ throws XmlPullParserException, IOException {
for (int i = 0; i < resIds.length; i++) {
// Setup VectorDrawable from xml file and draw into the bitmap.
XmlPullParser parser = mResources.getXml(resIds[i]);
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
- while ((type=parser.next()) != XmlPullParser.START_TAG &&
- type != XmlPullParser.END_DOCUMENT) {
+ while ((type=parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
// Empty loop
}
@@ -150,11 +177,15 @@
mVectorDrawable.inflate(mResources, parser, attrs);
+ if (stateSet != null) {
+ mVectorDrawable.setState(stateSet);
+ }
+
mBitmap.eraseColor(0);
mVectorDrawable.draw(mCanvas);
if (DBG_DUMP_PNG) {
- saveVectorDrawableIntoPNG(mBitmap, resIds, i);
+ saveVectorDrawableIntoPNG(mBitmap, resIds, i, stateSet);
} else {
// Start to compare
Bitmap golden = BitmapFactory.decodeResource(mResources, goldenImages[i]);
@@ -164,7 +195,8 @@
}
// This is only for debugging or golden image (re)generation purpose.
- private void saveVectorDrawableIntoPNG(Bitmap bitmap, int[] resIds, int index) throws IOException {
+ private void saveVectorDrawableIntoPNG(Bitmap bitmap, int[] resIds, int index, int[] stateSet)
+ throws IOException {
// Save the image to the disk.
FileOutputStream out = null;
try {
@@ -177,7 +209,8 @@
File originalFile = new File(originalFilePath);
String fileFullName = originalFile.getName();
String fileTitle = fileFullName.substring(0, fileFullName.lastIndexOf("."));
- String outputFilename = outputFolder + fileTitle + "_golden.png";
+ String stateSetTitle = getTitleForStateSet(stateSet);
+ String outputFilename = outputFolder + fileTitle + "_golden" + stateSetTitle + ".png";
File outputFile = new File(outputFilename);
if (!outputFile.exists()) {
outputFile.createNewFile();
@@ -195,6 +228,38 @@
}
}
+ /**
+ * Generates an underline-delimited list of states in a given state set.
+ * <p>
+ * For example, the array {@code {R.attr.state_pressed}} would return
+ * {@code "_pressed"}.
+ *
+ * @param stateSet a state set
+ * @return a string representing the state set, or the empty string if the
+ * state set is empty or {@code null}
+ */
+ private String getTitleForStateSet(int[] stateSet) {
+ if (stateSet == null || stateSet.length == 0) {
+ return "";
+ }
+
+ final Resources res = getContext().getResources();
+ final StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < stateSet.length; i++) {
+ builder.append('_');
+
+ final String state = res.getResourceName(stateSet[i]);
+ final int stateIndex = state.indexOf("state_");
+ if (stateIndex >= 0) {
+ builder.append(state.substring(stateIndex + 6));
+ } else {
+ builder.append(stateSet[i]);
+ }
+ }
+
+ return builder.toString();
+ }
+
private void compareImages(Bitmap ideal, Bitmap given, String filename) {
int idealWidth = ideal.getWidth();
int idealHeight = ideal.getHeight();
@@ -299,4 +364,43 @@
assertEquals(filter, vectorDrawable.getColorFilter());
}
+
+ public void testPreloadDensity() throws XmlPullParserException, IOException {
+ final Resources res = mResources;
+ final int densityDpi = res.getConfiguration().densityDpi;
+
+ // Capture initial state at default density.
+ final XmlResourceParser parser = DrawableTestUtils.getResourceParser(
+ res, R.drawable.vector_density);
+ final VectorDrawable preloadedDrawable = new VectorDrawable();
+ preloadedDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+ final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
+ final int origWidth = preloadedDrawable.getIntrinsicWidth();
+
+ // Set density to half of original. Unlike offsets, which are
+ // truncated, dimensions are rounded to the nearest pixel.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
+ final VectorDrawable halfDrawable =
+ (VectorDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(Math.round(origWidth / 2f), halfDrawable.getIntrinsicWidth());
+
+ // Set density to double original.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
+ final VectorDrawable doubleDrawable =
+ (VectorDrawable) preloadedConstantState.newDrawable(res);
+ assertEquals(origWidth * 2, doubleDrawable.getIntrinsicWidth());
+
+ // Restore original density.
+ DrawableTestUtils.setResourcesDensity(res, densityDpi);
+ final VectorDrawable origDrawable =
+ (VectorDrawable) preloadedConstantState.newDrawable();
+ assertEquals(origWidth, origDrawable.getIntrinsicWidth());
+
+ // Ensure theme density is applied correctly.
+ final Theme t = res.newTheme();
+ halfDrawable.applyTheme(t);
+ assertEquals(origWidth, halfDrawable.getIntrinsicWidth());
+ doubleDrawable.applyTheme(t);
+ assertEquals(origWidth, doubleDrawable.getIntrinsicWidth());
+ }
}
diff --git a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureCtsActivity.java b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureCtsActivity.java
index 533508a..bade5a8 100644
--- a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureCtsActivity.java
+++ b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureCtsActivity.java
@@ -15,7 +15,7 @@
*/
package android.opengl.cts;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import android.app.Activity;
import android.content.Intent;
diff --git a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureLoader.java b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureLoader.java
index 1524f99..3a2e00f 100644
--- a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureLoader.java
+++ b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureLoader.java
@@ -21,7 +21,7 @@
import java.nio.ByteOrder;
import java.util.HashMap;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import android.app.Activity;
import android.content.res.AssetFileDescriptor;
diff --git a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureSurfaceView.java b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureSurfaceView.java
index 84aae10..9437c58 100644
--- a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureSurfaceView.java
+++ b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureSurfaceView.java
@@ -27,7 +27,7 @@
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
-import com.android.cts.graphics.R;
+import android.graphics.cts.R;
import android.content.Context;
import android.content.res.Resources;
diff --git a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureTest.java b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureTest.java
index c153712..09902df 100644
--- a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureTest.java
@@ -24,13 +24,13 @@
public class CompressedTextureTest extends ActivityInstrumentationTestCase2<CompressedTextureCtsActivity> {
public CompressedTextureTest() {
- super("com.android.cts.graphics", CompressedTextureCtsActivity.class);
+ super("android.graphics.cts", CompressedTextureCtsActivity.class);
}
private void launchTest(String format) throws Exception {
Bundle extras = new Bundle();
extras.putString("TextureFormat", format);
- CompressedTextureCtsActivity activity = launchActivity("com.android.cts.graphics",
+ CompressedTextureCtsActivity activity = launchActivity("android.graphics.cts",
CompressedTextureCtsActivity.class, extras);
activity.finish();
assertTrue(activity.getPassed());
diff --git a/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java b/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java
index 14c8e10..33e82043 100644
--- a/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java
@@ -37,7 +37,7 @@
private Instrumentation mInstrumentation;
public EglConfigTest() {
- super("com.android.cts.graphics", EglConfigCtsActivity.class);
+ super("android.graphics.cts", EglConfigCtsActivity.class);
}
@Override
@@ -60,7 +60,7 @@
Bundle extras = new Bundle();
extras.putInt(EglConfigCtsActivity.CONFIG_ID_EXTRA, configId);
extras.putInt(EglConfigCtsActivity.CONTEXT_CLIENT_VERSION_EXTRA, contextClientVersion);
- EglConfigCtsActivity activity = launchActivity("com.android.cts.graphics",
+ EglConfigCtsActivity activity = launchActivity("android.graphics.cts",
EglConfigCtsActivity.class, extras);
activity.waitToFinishDrawing();
activity.finish();
diff --git a/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewTest.java b/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewTest.java
index 87995fb..f603419 100644
--- a/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewTest.java
@@ -41,7 +41,7 @@
private GLSurfaceViewCtsActivity mActivity;
public GLSurfaceViewTest() {
- super("com.android.cts.graphics", GLSurfaceViewCtsActivity.class);
+ super("android.graphics.cts", GLSurfaceViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
index 28ac5c0..c991b6f 100644
--- a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
@@ -48,7 +48,7 @@
private OpenGlEsVersionCtsActivity mActivity;
public OpenGlEsVersionTest() {
- super("com.android.cts.graphics", OpenGlEsVersionCtsActivity.class);
+ super("android.graphics.cts", OpenGlEsVersionCtsActivity.class);
}
@Override
diff --git a/tests/tests/graphics2/Android.mk b/tests/tests/graphics2/Android.mk
index a3cdafa..566b6a32b 100644
--- a/tests/tests/graphics2/Android.mk
+++ b/tests/tests/graphics2/Android.mk
@@ -27,6 +27,9 @@
LOCAL_PACKAGE_NAME := CtsGraphics2TestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_INSTRUMENTATION_FOR :=
LOCAL_SDK_VERSION := current
diff --git a/tests/tests/graphics2/AndroidManifest.xml b/tests/tests/graphics2/AndroidManifest.xml
index 67557ad..be7a985 100644
--- a/tests/tests/graphics2/AndroidManifest.xml
+++ b/tests/tests/graphics2/AndroidManifest.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.graphics2"
+ package="android.graphics2.cts"
android:versionCode="1"
android:versionName="1.0" >
@@ -23,7 +23,7 @@
<uses-feature android:name="android.hardware.camera" />
<instrumentation
- android:targetPackage="com.android.cts.graphics2"
+ android:targetPackage="android.graphics2.cts"
android:name="android.support.test.runner.AndroidJUnitRunner" >
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/graphics2/AndroidTest.xml b/tests/tests/graphics2/AndroidTest.xml
new file mode 100644
index 0000000..2f9961b
--- /dev/null
+++ b/tests/tests/graphics2/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Graphics test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsGraphics2TestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.graphics2.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index 07d5de9..df493d6 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -22,7 +22,9 @@
LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util
LOCAL_SDK_VERSION := current
@@ -36,8 +38,6 @@
src/android/hardware/cts/SensorTest.java \
src/android/hardware/cts/SensorManagerStaticTest.java
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil
-
include $(BUILD_STATIC_JAVA_LIBRARY)
@@ -47,16 +47,21 @@
LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner mockito-target android-ex-camera2
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner mockito-target android-ex-camera2
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
LOCAL_PACKAGE_NAME := CtsHardwareTestCases
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
LOCAL_SDK_VERSION := current
LOCAL_JAVA_LIBRARIES := android.test.runner
-cts_runtime_hint := 120
-
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/hardware/AndroidManifest.xml b/tests/tests/hardware/AndroidManifest.xml
index 031b19e..1e4cedf 100644
--- a/tests/tests/hardware/AndroidManifest.xml
+++ b/tests/tests/hardware/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.hardware">
+ package="android.hardware.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.CAMERA" />
@@ -72,6 +72,9 @@
android:process=":camera2ActivityProcess">
</activity>
+ <activity android:name="android.hardware.input.cts.InputCtsActivity"
+ android:label="InputCtsActivity" />
+
<activity android:name="android.hardware.cts.FingerprintTestActivity"
android:label="FingerprintTestActivity">
</activity>
@@ -79,8 +82,8 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.hardware"
- android:label="CTS tests of android.hardware">
+ android:targetPackage="android.hardware.cts"
+ android:label="CTS hardware tests">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/tests/hardware/AndroidTest.xml b/tests/tests/hardware/AndroidTest.xml
index 4ddf28c..14027dd 100644
--- a/tests/tests/hardware/AndroidTest.xml
+++ b/tests/tests/hardware/AndroidTest.xml
@@ -1,4 +1,3 @@
-<?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");
@@ -13,10 +12,20 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Base config for Sensor CTS tests. Put SensorService in restricted mode">
- <include name="common-config" />
+<configuration description="Config for CTS Hardware test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsHardwareTestCases.apk" />
+ </target_preparer>
<!-- Put SensorService in restricted mode so that only CTS tests will be able to get access to
sensors -->
- <option name="run-command:run-command" value="dumpsys sensorservice restrict .cts." />
- <option name="run-command:teardown-command" value="dumpsys sensorservice enable" />
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="dumpsys sensorservice restrict .cts." />
+ <option name="teardown-command" value="dumpsys sensorservice enable" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.hardware.cts" />
+ </test>
+
</configuration>
diff --git a/tests/tests/hardware/OldAndroidTest.xml b/tests/tests/hardware/OldAndroidTest.xml
new file mode 100644
index 0000000..4ddf28c
--- /dev/null
+++ b/tests/tests/hardware/OldAndroidTest.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<configuration description="Base config for Sensor CTS tests. Put SensorService in restricted mode">
+ <include name="common-config" />
+ <!-- Put SensorService in restricted mode so that only CTS tests will be able to get access to
+ sensors -->
+ <option name="run-command:run-command" value="dumpsys sensorservice restrict .cts." />
+ <option name="run-command:teardown-command" value="dumpsys sensorservice enable" />
+</configuration>
diff --git a/tests/tests/hardware/res/raw/gamepad_press_a.json b/tests/tests/hardware/res/raw/gamepad_press_a.json
new file mode 100644
index 0000000..ff3ca4f
--- /dev/null
+++ b/tests/tests/hardware/res/raw/gamepad_press_a.json
@@ -0,0 +1,39 @@
+{
+ "id": 1,
+ "command": "register",
+ "name": "Odie (Test)",
+ "vid": 0x18d1,
+ "pid": 0x2c40,
+ "descriptor": [0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x05, 0x09, 0x0a, 0x01, 0x00,
+ 0x0a, 0x02, 0x00, 0x0a, 0x04, 0x00, 0x0a, 0x05, 0x00, 0x0a, 0x07, 0x00, 0x0a, 0x08, 0x00,
+ 0x0a, 0x0e, 0x00, 0x0a, 0x0f, 0x00, 0x0a, 0x0d, 0x00, 0x05, 0x0c, 0x0a, 0x24, 0x02, 0x0a,
+ 0x23, 0x02, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0b, 0x81, 0x02, 0x75, 0x01, 0x95,
+ 0x01, 0x81, 0x03, 0x05, 0x01, 0x75, 0x04, 0x95, 0x01, 0x25, 0x07, 0x46, 0x3b, 0x01, 0x66,
+ 0x14, 0x00, 0x09, 0x39, 0x81, 0x42, 0x66, 0x00, 0x00, 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30,
+ 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x05, 0x02, 0x09, 0xc5, 0x09, 0xc4, 0x15, 0x00, 0x26,
+ 0xff, 0x00, 0x35, 0x00, 0x46, 0xff, 0x00, 0x75, 0x08, 0x95, 0x06, 0x81, 0x02, 0xc0, 0x85,
+ 0x02, 0x05, 0x08, 0x0a, 0x01, 0x00, 0x0a, 0x02, 0x00, 0x0a, 0x03, 0x00, 0x0a, 0x04, 0x00,
+ 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x04, 0x91, 0x02, 0x75, 0x04, 0x95, 0x01, 0x91,
+ 0x03, 0xc0, 0x05, 0x0c, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x03, 0x05, 0x01, 0x09, 0x06, 0xa1,
+ 0x02, 0x05, 0x06, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x81,
+ 0x02, 0x06, 0xbc, 0xff, 0x0a, 0xad, 0xbd, 0x75, 0x08, 0x95, 0x06, 0x81, 0x02, 0xc0, 0xc0],
+ "report": [0x01, 0x00, 0x80, 0x90, 0x80, 0x7f, 0x73, 0x00, 0x00]
+}
+
+{
+ "id": 1,
+ "command": "report",
+ "report": [0x01, 0x01, 0x80, 0x90, 0x80, 0x7f, 0x73, 0x00, 0x00]
+}
+
+{
+ "id": 1,
+ "command": "delay",
+ "duration": 10
+}
+
+{
+ "id": 1,
+ "command": "report",
+ "report": [0x01, 0x00, 0x80, 0x90, 0x80, 0x7f, 0x73, 0x00, 0x00]
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java
index 4d4f3d3..2a4c720 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java
@@ -39,7 +39,7 @@
* <p>To execute these test cases, the following command can be used:</p>
* <pre>
* adb shell am instrument -e class android.hardware.cts.SensorBatchingTests \
- * -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * -w android.hardware.cts/android.test.AndroidJUnitRunner
* </pre>
*/
public class SensorBatchingTests extends SensorTestCase {
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
index 9bf1fd6..302ce72 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
@@ -34,7 +34,7 @@
*
* To execute these test cases, the following command can be used:
* $ adb shell am instrument -e class android.hardware.cts.SensorIntegrationTests \
- * -w com.android.cts.hardware/android.test.InstrumentationCtsTestRunner
+ * -w android.hardware.cts/android.test.InstrumentationCtsTestRunner
*/
public class SensorIntegrationTests extends SensorTestCase {
private static final String TAG = "SensorIntegrationTests";
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java
index 22f092a..997565e 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java
@@ -30,7 +30,7 @@
* <p>To execute these test cases, the following command can be used:</p>
* <pre>
* adb shell am instrument -e class android.hardware.cts.SensorParameterRangeTest \
- * -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * -w android.hardware.cts/android.test.AndroidJUnitRunner
* </pre>
*/
public class SensorParameterRangeTest extends SensorTestCase {
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java
index 2f25c8d..185eb07 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java
@@ -30,7 +30,7 @@
* <p>To execute these test cases, the following command can be used:</p>
* <pre>
* adb shell am instrument -e class android.hardware.cts.SensorSupportTest \
- * -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * -w android.hardware.cts/android.test.AndroidJUnitRunner
* </pre>
*/
public class SensorSupportTest extends AndroidTestCase {
diff --git a/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
index 73d61a5..e2a69e9d 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
@@ -36,7 +36,7 @@
* To execute these test cases, the following command can be used:
* </p><pre>
* adb shell am instrument -e class android.hardware.cts.SingleSensorTests \
- * -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * -w android.hardware.cts/android.test.AndroidJUnitRunner
* </pre><p>
* For each sensor that reports continuously, it takes a set of samples. The test suite verifies
* that the event ordering, frequency, and jitter pass for the collected sensor events. It
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
index 9d36f37..694c61f 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
@@ -27,8 +27,6 @@
import android.hardware.cts.helpers.TestSensorEvent;
import android.util.SparseIntArray;
-import com.android.cts.util.StatisticsUtils;
-
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/InputCallback.java b/tests/tests/hardware/src/android/hardware/input/cts/InputCallback.java
new file mode 100644
index 0000000..accdcaf
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/input/cts/InputCallback.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.input.cts;
+
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+public interface InputCallback {
+ public void onKeyEvent(KeyEvent ev);
+ public void onMotionEvent(MotionEvent ev);
+}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/InputCtsActivity.java b/tests/tests/hardware/src/android/hardware/input/cts/InputCtsActivity.java
new file mode 100644
index 0000000..b16cadb
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/input/cts/InputCtsActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.input.cts;
+
+import android.app.Activity;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class InputCtsActivity extends Activity {
+ private InputCallback mInputCallback;
+
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
+ if (mInputCallback != null) {
+ mInputCallback.onMotionEvent(ev);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (mInputCallback != null) {
+ mInputCallback.onMotionEvent(ev);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean dispatchTrackballEvent(MotionEvent ev) {
+ if (mInputCallback != null) {
+ mInputCallback.onMotionEvent(ev);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent ev) {
+ if (mInputCallback != null) {
+ mInputCallback.onKeyEvent(ev);
+ }
+ return true;
+ }
+
+ public void setInputCallback(InputCallback callback) {
+ mInputCallback = callback;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/GamepadTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/GamepadTestCase.java
new file mode 100644
index 0000000..2a772ae
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/GamepadTestCase.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.input.cts.tests;
+
+import android.util.Log;
+import android.view.KeyEvent;
+
+import java.io.Writer;
+import java.util.List;
+
+import android.hardware.cts.R;
+
+public class GamepadTestCase extends InputTestCase {
+ private static final String TAG = "GamepadTests";
+
+ public void testButtonA() throws Exception {
+ sendHidCommands(R.raw.gamepad_press_a);
+ assertReceivedKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BUTTON_A);
+ assertReceivedKeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BUTTON_A);
+ assertNoMoreEvents();
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java
new file mode 100644
index 0000000..fba5f51
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.input.cts.tests;
+
+import android.app.UiAutomation;
+import android.hardware.input.cts.InputCtsActivity;
+import android.hardware.input.cts.InputCallback;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.List;
+import java.util.UUID;
+
+public class InputTestCase extends ActivityInstrumentationTestCase2<InputCtsActivity> {
+ private static final String TAG = "InputTestCase";
+ private static final String HID_EXECUTABLE = "hid";
+ private static final int SHELL_UID = 2000;
+ private static final String[] KEY_ACTIONS = {"DOWN", "UP", "MULTIPLE"};
+
+ private File mFifo;
+ private Writer mWriter;
+
+ private BlockingQueue<KeyEvent> mKeys;
+ private BlockingQueue<MotionEvent> mMotions;
+ private InputListener mInputListener;
+
+ public InputTestCase() {
+ super(InputCtsActivity.class);
+ mKeys = new LinkedBlockingQueue<KeyEvent>();
+ mMotions = new LinkedBlockingQueue<MotionEvent>();
+ mInputListener = new InputListener();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mFifo = setupFifo();
+ clearKeys();
+ clearMotions();
+ getActivity().setInputCallback(mInputListener);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (mFifo != null) {
+ mFifo.delete();
+ mFifo = null;
+ }
+ closeQuietly(mWriter);
+ mWriter = null;
+ super.tearDown();
+ }
+
+ /**
+ * Sends the HID commands designated by the given resource id.
+ * The commands must be in the format expected by the `hid` shell command.
+ *
+ * @param id The resource id from which to load the HID commands. This must be a "raw"
+ * resource.
+ */
+ public void sendHidCommands(int id) {
+ try {
+ Writer w = getWriter();
+ w.write(getEvents(id));
+ w.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Asserts that the application received a {@link android.view.KeyEvent} with the given action
+ * and keycode.
+ *
+ * If other KeyEvents are received by the application prior to the expected KeyEvent, or no
+ * KeyEvents are received within a reasonable amount of time, then this will throw an
+ * AssertionFailedError.
+ *
+ * @param action The action to expect on the next KeyEvent
+ * (e.g. {@link android.view.KeyEvent#ACTION_DOWN}).
+ * @param keyCode The expected key code of the next KeyEvent.
+ */
+ public void assertReceivedKeyEvent(int action, int keyCode) {
+ KeyEvent k = waitForKey();
+ if (k == null) {
+ fail("Timed out waiting for " + KeyEvent.keyCodeToString(keyCode)
+ + " with action " + KEY_ACTIONS[action]);
+ return;
+ }
+ assertEquals(action, k.getAction());
+ assertEquals(keyCode, k.getKeyCode());
+ }
+
+ /**
+ * Asserts that no more events have been received by the application.
+ *
+ * If any more events have been received by the application, this throws an
+ * AssertionFailedError.
+ */
+ public void assertNoMoreEvents() {
+ KeyEvent key;
+ MotionEvent motion;
+ if ((key = mKeys.poll()) != null) {
+ fail("Extraneous key events generated: " + key);
+ }
+ if ((motion = mMotions.poll()) != null) {
+ fail("Extraneous motion events generated: " + motion);
+ }
+ }
+
+ private KeyEvent waitForKey() {
+ try {
+ return mKeys.poll(1, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ return null;
+ }
+ }
+
+ private void clearKeys() {
+ mKeys.clear();
+ }
+
+ private void clearMotions() {
+ mMotions.clear();
+ }
+
+ private File setupFifo() throws ErrnoException {
+ File dir = getActivity().getCacheDir();
+ String filename = dir.getAbsolutePath() + File.separator + UUID.randomUUID().toString();
+ Os.mkfifo(filename, 0666);
+ File f = new File(filename);
+ return f;
+ }
+
+ private Writer getWriter() throws IOException {
+ if (mWriter == null) {
+ UiAutomation ui = getInstrumentation().getUiAutomation();
+ ui.executeShellCommand("hid " + mFifo.getAbsolutePath());
+ mWriter = new FileWriter(mFifo);
+ }
+ return mWriter;
+ }
+
+ private String getEvents(int id) throws IOException {
+ InputStream is =
+ getInstrumentation().getTargetContext().getResources().openRawResource(id);
+ return readFully(is);
+ }
+
+
+ private static void closeQuietly(AutoCloseable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (RuntimeException rethrown) {
+ throw rethrown;
+ } catch (Exception ignored) { }
+ }
+ }
+
+ private static String readFully(InputStream is) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int read = 0;
+ byte[] buffer = new byte[1024];
+ while ((read = is.read(buffer)) >= 0) {
+ baos.write(buffer, 0, read);
+ }
+ return baos.toString();
+ }
+
+ private class InputListener implements InputCallback {
+ public void onKeyEvent(KeyEvent ev) {
+ boolean done = false;
+ do {
+ try {
+ mKeys.put(new KeyEvent(ev));
+ done = true;
+ } catch (InterruptedException ignore) { }
+ } while (!done);
+ }
+
+ public void onMotionEvent(MotionEvent ev) {
+ boolean done = false;
+ do {
+ try {
+ mMotions.put(MotionEvent.obtain(ev));
+ done = true;
+ } catch (InterruptedException ignore) { }
+ } while (!done);
+ }
+ }
+}
diff --git a/tests/tests/icu/Android.mk b/tests/tests/icu/Android.mk
new file mode 100644
index 0000000..12cd7b0
--- /dev/null
+++ b/tests/tests/icu/Android.mk
@@ -0,0 +1,66 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# The aim of this package is to run tests against the default packaging of ICU as a standalone
+# java library, and not as the implementation in use by the current android system. For this
+# reason, all the required ICU resources are included into the APK by the following rules.
+# icu4j contains ICU's implementation classes, icu4j-tests contains the test classes,
+# and icudata/icutzdata contain data files and timezone data files respectively.
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test icu4j icu4j-tests \
+ icu4j-icudata icu4j-icutzdata icu4j-testdata
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsIcuTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
+
+# The CTS framework has it's own logic for generating XML files based on scanning the source
+# for test methods and classes. Since the classes that we are testing are not actually in this
+# package we must provide an alternative. Here we define a specially crafted XML file which
+# conforms to what CTS and particularly, the cts-tradefed tool understands. This file contains
+# lists of classes in ICU4J that we know are used in libcore and should be tested as part of CTS.
+# The following rule uses the Android CoPy (ACP) tool to copy this file to where it is expected.
+
+ifeq ($(TARGET_ARCH),arm64)
+ LOCAL_ARCH := arm
+else ifeq ($(TARGET_ARCH),mips64)
+ LOCAL_ARCH := mips
+else ifeq ($(TARGET_ARCH),x86_64)
+ LOCAL_ARCH := x86
+else
+ LOCAL_ARCH := $(TARGET_ARCH)
+endif
+
+cts_package_xml := $(CTS_TESTCASES_OUT)/CtsIcuTestCases.xml
+$(cts_package_xml): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk | $(ACP)
+ $(ACP) -fp cts/tests/tests/icu/CtsIcuTestCases_$(LOCAL_ARCH).xml $@
diff --git a/tests/tests/icu/AndroidManifest.xml b/tests/tests/icu/AndroidManifest.xml
new file mode 100644
index 0000000..7d99c0a
--- /dev/null
+++ b/tests/tests/icu/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.icu.cts">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.icu.cts.IcuTestRunner"
+ android:targetPackage="android.icu.cts"
+ android:label="ICU4J library tests."/>
+</manifest>
diff --git a/tests/tests/icu/AndroidTest.xml b/tests/tests/icu/AndroidTest.xml
new file mode 100644
index 0000000..299956d
--- /dev/null
+++ b/tests/tests/icu/AndroidTest.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS ICU test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsIcuTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="runner" value="android.icu.cts.IcuTestRunner" /><!-- override AJUR -->
+ <option name="package" value="android.icu.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/icu/CtsIcuTestCases_arm.xml b/tests/tests/icu/CtsIcuTestCases_arm.xml
new file mode 100644
index 0000000..96f0701
--- /dev/null
+++ b/tests/tests/icu/CtsIcuTestCases_arm.xml
@@ -0,0 +1,563 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<TestPackage AndroidFramework="Android 1.0"
+ appNameSpace="android.icu.cts"
+ appPackageName="com.ibm.icu.dev.test"
+ name="CtsIcuTestCases"
+ runner=".IcuTestRunner"
+ version="1.0">
+
+ <!--
+ ICU tests are run against ICU as a standalone library so the package names are com.ibm.icu.*.
+ Each test class has one dummy method called "run-everything". This is because CTS will not try
+ to run a class if there is no known test method on it. The IcuTestRunner is aware of this and
+ pretends to run the method "run-everything", but actually dispatches the run to ICU's own test
+ runner. If the test is successful, a return code of 0 from ICU's test runner will be detected
+ and we report that the "run-everything" method passed. If there is any failure in the class,
+ we report that "run-everything" failed and print out the detailed method by method listing
+ from ICU about what actually failed, as the stack trace for the failure in "run-everything".
+ -->
+
+ <TestSuite name="com">
+ <TestSuite name="ibm">
+ <TestSuite name="icu">
+ <TestSuite name="dev">
+ <TestSuite name="test">
+ <TestSuite name="translit">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="PrettyPrinterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TransliteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RegexUtilitiesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ReplaceableTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RoundTripTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="AnyScriptTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ErrorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UnicodeMapTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="CompoundTransliteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestUnicodeProperty">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="util">
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="ICUResourceBundleCollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ULocaleCollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="GenderInfoTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="BytesTrieTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="LocaleDataTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CurrencyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RegionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ULocaleTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="StringTokenizerTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CharsTrieTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CompactArrayTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="LocaleBuilderTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TrieMapTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ICUServiceThreadTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ICUBinaryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ICUResourceBundleTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="DebugUtilitiesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="SimplePatternFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="LocaleMatcherTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UtilityTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="Trie2Test">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ICUServiceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="VersionInfoTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="LocalePriorityListTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TrieTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TextTrieMapTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="search">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="SearchTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="collator">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="LotusCollationKoreanTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationTurkishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationMiscTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationAPITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationServiceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="AlphabeticIndexTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationFinnishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationDummyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationRegressionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationChineseTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationGermanTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="G7CollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationSpanishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="CollationCreationMethodTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UCAConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationKanaTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationFrenchTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationIteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationThaiTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationFrozenMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationThreadTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationEnglishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CollationCurrencyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="format">
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="GlobalizationPreferencesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RbnfLenientScannerTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="PluralRangesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="SelectFormatUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="PluralRulesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="RelativeDateTimeFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RBNFParseTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TimeUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CompactDecimalFormatTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RbnfRoundTripTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RbnfTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="SelectFormatAPITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="PluralFormatTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="BigNumberFormatTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ListFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="DateTimeGeneratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="NumberFormatSpecificationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="MeasureUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="ScientificNumberFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="PluralFormatUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="compression">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ExhaustiveTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="DecompressionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="text">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="SpoofCheckerTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="iterator">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestUCharacterIterator">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="duration">
+ <TestSuite name="languages">
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_en">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_es">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_fr">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_he_IL">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_hi">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_it">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_ja">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_ko">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_zh_Hans">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_zh_Hans_SG">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_zh_Hant">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="Test_zh_Hant_HK">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="ResourceBasedPeriodFormatterDataServiceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ICUDurationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="PeriodBuilderFactoryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="PeriodBuilderTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="PeriodTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="DataReadWriteTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RegressionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="rbbi">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RBBITestExtended">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="SimpleBITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="BreakIteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RBBITestMonkey">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="RBBITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="BreakIteratorRegTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="lang">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestUScript">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UPropertyAliasesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UTF16Test">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UCharacterCategoryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UnicodeSetStringSpanTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UnicodeSetTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UCharacterCaseTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UCharacterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UCharacterThreadTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UCharacterSurrogateTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestUScriptRun">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UCharacterDirectionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="charsetdet">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestCharsetDetector">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="normalizer">
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="TestDeprecatedNormalizerAPI">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="NormalizationMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestCanonicalIterator">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="BasicTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="NormalizerRegressionTests">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="UTS46Test">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a"
+ name="UnicodeNormalizerConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="bidi">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="BidiTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="BiDiConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="shaping">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="ArabicShapingRegTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="stringprep">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestStringPrep">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="IDNAConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestIDNA">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestStringPrepProfiles">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestIDNARef">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="timezone">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TimeZoneTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TimeZoneRuleTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TimeZoneRegression">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TimeZoneBoundaryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TimeZoneOffsetLocalTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="bigdec">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="DiagBigDecimal">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="calendar">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="CalendarTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="AstroTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="HolidayTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="timescale">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TimeScaleMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TimeScaleAPITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TimeScaleDataTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="charset">
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestSelection">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestCharset">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestCase abis="armeabi-v7a arm64-v8a" name="TestLocaleNamePackaging">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
+</TestPackage>
diff --git a/tests/tests/icu/CtsIcuTestCases_mips.xml b/tests/tests/icu/CtsIcuTestCases_mips.xml
new file mode 100644
index 0000000..beeae32
--- /dev/null
+++ b/tests/tests/icu/CtsIcuTestCases_mips.xml
@@ -0,0 +1,563 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<TestPackage AndroidFramework="Android 1.0"
+ appNameSpace="android.icu.cts"
+ appPackageName="com.ibm.icu.dev.test"
+ name="CtsIcuTestCases"
+ runner=".IcuTestRunner"
+ version="1.0">
+
+ <!--
+ ICU tests are run against ICU as a standalone library so the package names are com.ibm.icu.*.
+ Each test class has one dummy method called "run-everything". This is because CTS will not try
+ to run a class if there is no known test method on it. The IcuTestRunner is aware of this and
+ pretends to run the method "run-everything", but actually dispatches the run to ICU's own test
+ runner. If the test is successful, a return code of 0 from ICU's test runner will be detected
+ and we report that the "run-everything" method passed. If there is any failure in the class,
+ we report that "run-everything" failed and print out the detailed method by method listing
+ from ICU about what actually failed, as the stack trace for the failure in "run-everything".
+ -->
+
+ <TestSuite name="com">
+ <TestSuite name="ibm">
+ <TestSuite name="icu">
+ <TestSuite name="dev">
+ <TestSuite name="test">
+ <TestSuite name="translit">
+ <TestCase abis="mips mips64" name="PrettyPrinterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TransliteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RegexUtilitiesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ReplaceableTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RoundTripTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="AnyScriptTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ErrorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UnicodeMapTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="CompoundTransliteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TestUnicodeProperty">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="util">
+ <TestCase abis="mips mips64"
+ name="ICUResourceBundleCollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ULocaleCollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="GenderInfoTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="BytesTrieTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="LocaleDataTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CurrencyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RegionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ULocaleTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="StringTokenizerTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CharsTrieTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CompactArrayTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="LocaleBuilderTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TrieMapTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ICUServiceThreadTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ICUBinaryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ICUResourceBundleTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="DebugUtilitiesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="SimplePatternFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="LocaleMatcherTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UtilityTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="Trie2Test">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ICUServiceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="VersionInfoTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="LocalePriorityListTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TrieTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TextTrieMapTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="search">
+ <TestCase abis="mips mips64" name="SearchTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="collator">
+ <TestCase abis="mips mips64" name="LotusCollationKoreanTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationTurkishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationMiscTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationAPITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationServiceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="AlphabeticIndexTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationFinnishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationDummyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationRegressionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationChineseTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationGermanTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="G7CollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationSpanishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="CollationCreationMethodTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UCAConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationKanaTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationFrenchTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationIteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationThaiTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationFrozenMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationThreadTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationEnglishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CollationCurrencyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="format">
+ <TestCase abis="mips mips64"
+ name="GlobalizationPreferencesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RbnfLenientScannerTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="PluralRangesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="SelectFormatUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="PluralRulesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="RelativeDateTimeFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RBNFParseTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TimeUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="CompactDecimalFormatTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RbnfRoundTripTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RbnfTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="SelectFormatAPITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="PluralFormatTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="BigNumberFormatTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ListFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="DateTimeGeneratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="NumberFormatSpecificationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="MeasureUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="ScientificNumberFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="PluralFormatUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="compression">
+ <TestCase abis="mips mips64" name="ExhaustiveTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="DecompressionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="text">
+ <TestCase abis="mips mips64" name="SpoofCheckerTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="iterator">
+ <TestCase abis="mips mips64" name="TestUCharacterIterator">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="duration">
+ <TestSuite name="languages">
+ <TestCase abis="mips mips64"
+ name="Test_en">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_es">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_fr">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_he_IL">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_hi">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_it">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_ja">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_ko">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_zh_Hans">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_zh_Hans_SG">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_zh_Hant">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="Test_zh_Hant_HK">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestCase abis="mips mips64"
+ name="ResourceBasedPeriodFormatterDataServiceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ICUDurationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="PeriodBuilderFactoryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="PeriodBuilderTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="PeriodTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="DataReadWriteTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RegressionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="rbbi">
+ <TestCase abis="mips mips64" name="RBBITestExtended">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="SimpleBITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="BreakIteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RBBITestMonkey">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="RBBITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="BreakIteratorRegTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="lang">
+ <TestCase abis="mips mips64" name="TestUScript">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UPropertyAliasesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UTF16Test">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UCharacterCategoryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UnicodeSetStringSpanTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UnicodeSetTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UCharacterCaseTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UCharacterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UCharacterThreadTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UCharacterSurrogateTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TestUScriptRun">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UCharacterDirectionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="charsetdet">
+ <TestCase abis="mips mips64" name="TestCharsetDetector">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="normalizer">
+ <TestCase abis="mips mips64"
+ name="TestDeprecatedNormalizerAPI">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="NormalizationMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TestCanonicalIterator">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="BasicTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="ConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="NormalizerRegressionTests">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="UTS46Test">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64"
+ name="UnicodeNormalizerConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="bidi">
+ <TestCase abis="mips mips64" name="BidiTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="BiDiConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="shaping">
+ <TestCase abis="mips mips64" name="ArabicShapingRegTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="stringprep">
+ <TestCase abis="mips mips64" name="TestStringPrep">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="IDNAConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TestIDNA">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TestStringPrepProfiles">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TestIDNARef">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="timezone">
+ <TestCase abis="mips mips64" name="TimeZoneTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TimeZoneRuleTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TimeZoneRegression">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TimeZoneBoundaryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TimeZoneOffsetLocalTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="bigdec">
+ <TestCase abis="mips mips64" name="DiagBigDecimal">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="calendar">
+ <TestCase abis="mips mips64" name="CalendarTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="AstroTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="HolidayTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="timescale">
+ <TestCase abis="mips mips64" name="TimeScaleMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TimeScaleAPITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TimeScaleDataTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="charset">
+ <TestCase abis="mips mips64" name="TestSelection">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="mips mips64" name="TestCharset">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestCase abis="mips mips64" name="TestLocaleNamePackaging">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
+</TestPackage>
diff --git a/tests/tests/icu/CtsIcuTestCases_x86.xml b/tests/tests/icu/CtsIcuTestCases_x86.xml
new file mode 100644
index 0000000..31140f2
--- /dev/null
+++ b/tests/tests/icu/CtsIcuTestCases_x86.xml
@@ -0,0 +1,563 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<TestPackage AndroidFramework="Android 1.0"
+ appNameSpace="android.icu.cts"
+ appPackageName="com.ibm.icu.dev.test"
+ name="CtsIcuTestCases"
+ runner=".IcuTestRunner"
+ version="1.0">
+
+ <!--
+ ICU tests are run against ICU as a standalone library so the package names are com.ibm.icu.*.
+ Each test class has one dummy method called "run-everything". This is because CTS will not try
+ to run a class if there is no known test method on it. The IcuTestRunner is aware of this and
+ pretends to run the method "run-everything", but actually dispatches the run to ICU's own test
+ runner. If the test is successful, a return code of 0 from ICU's test runner will be detected
+ and we report that the "run-everything" method passed. If there is any failure in the class,
+ we report that "run-everything" failed and print out the detailed method by method listing
+ from ICU about what actually failed, as the stack trace for the failure in "run-everything".
+ -->
+
+ <TestSuite name="com">
+ <TestSuite name="ibm">
+ <TestSuite name="icu">
+ <TestSuite name="dev">
+ <TestSuite name="test">
+ <TestSuite name="translit">
+ <TestCase abis="x86 x86_64" name="PrettyPrinterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TransliteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RegexUtilitiesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ReplaceableTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RoundTripTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="AnyScriptTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ErrorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UnicodeMapTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="CompoundTransliteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TestUnicodeProperty">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="util">
+ <TestCase abis="x86 x86_64"
+ name="ICUResourceBundleCollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ULocaleCollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="GenderInfoTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="BytesTrieTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="LocaleDataTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CurrencyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RegionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ULocaleTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="StringTokenizerTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CharsTrieTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CompactArrayTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="LocaleBuilderTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TrieMapTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ICUServiceThreadTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ICUBinaryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ICUResourceBundleTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="DebugUtilitiesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="SimplePatternFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="LocaleMatcherTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UtilityTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="Trie2Test">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ICUServiceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="VersionInfoTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="LocalePriorityListTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TrieTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TextTrieMapTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="search">
+ <TestCase abis="x86 x86_64" name="SearchTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="collator">
+ <TestCase abis="x86 x86_64" name="LotusCollationKoreanTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationTurkishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationMiscTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationAPITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationServiceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="AlphabeticIndexTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationFinnishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationDummyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationRegressionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationChineseTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationGermanTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="G7CollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationSpanishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="CollationCreationMethodTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UCAConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationKanaTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationFrenchTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationIteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationThaiTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationFrozenMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationThreadTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationEnglishTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CollationCurrencyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="format">
+ <TestCase abis="x86 x86_64"
+ name="GlobalizationPreferencesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RbnfLenientScannerTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="PluralRangesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="SelectFormatUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="PluralRulesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="RelativeDateTimeFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RBNFParseTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TimeUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="CompactDecimalFormatTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RbnfRoundTripTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RbnfTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="SelectFormatAPITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="PluralFormatTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="BigNumberFormatTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ListFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="DateTimeGeneratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="NumberFormatSpecificationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="MeasureUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="ScientificNumberFormatterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="PluralFormatUnitTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="compression">
+ <TestCase abis="x86 x86_64" name="ExhaustiveTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="DecompressionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="text">
+ <TestCase abis="x86 x86_64" name="SpoofCheckerTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="iterator">
+ <TestCase abis="x86 x86_64" name="TestUCharacterIterator">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="duration">
+ <TestSuite name="languages">
+ <TestCase abis="x86 x86_64"
+ name="Test_en">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_es">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_fr">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_he_IL">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_hi">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_it">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_ja">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_ko">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_zh_Hans">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_zh_Hans_SG">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_zh_Hant">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="Test_zh_Hant_HK">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestCase abis="x86 x86_64"
+ name="ResourceBasedPeriodFormatterDataServiceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ICUDurationTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="PeriodBuilderFactoryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="PeriodBuilderTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="PeriodTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="DataReadWriteTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RegressionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="rbbi">
+ <TestCase abis="x86 x86_64" name="RBBITestExtended">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="SimpleBITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="BreakIteratorTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RBBITestMonkey">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="RBBITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="BreakIteratorRegTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="lang">
+ <TestCase abis="x86 x86_64" name="TestUScript">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UPropertyAliasesTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UTF16Test">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UCharacterCategoryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UnicodeSetStringSpanTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UnicodeSetTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UCharacterCaseTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UCharacterTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UCharacterThreadTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UCharacterSurrogateTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TestUScriptRun">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UCharacterDirectionTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="charsetdet">
+ <TestCase abis="x86 x86_64" name="TestCharsetDetector">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="normalizer">
+ <TestCase abis="x86 x86_64"
+ name="TestDeprecatedNormalizerAPI">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="NormalizationMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TestCanonicalIterator">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="BasicTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="ConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="NormalizerRegressionTests">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="UTS46Test">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64"
+ name="UnicodeNormalizerConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="bidi">
+ <TestCase abis="x86 x86_64" name="BidiTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="BiDiConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="shaping">
+ <TestCase abis="x86 x86_64" name="ArabicShapingRegTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="stringprep">
+ <TestCase abis="x86 x86_64" name="TestStringPrep">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="IDNAConformanceTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TestIDNA">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TestStringPrepProfiles">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TestIDNARef">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="timezone">
+ <TestCase abis="x86 x86_64" name="TimeZoneTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TimeZoneRuleTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TimeZoneRegression">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TimeZoneBoundaryTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TimeZoneOffsetLocalTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="bigdec">
+ <TestCase abis="x86 x86_64" name="DiagBigDecimal">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="calendar">
+ <TestCase abis="x86 x86_64" name="CalendarTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="AstroTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="HolidayTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="timescale">
+ <TestCase abis="x86 x86_64" name="TimeScaleMonkeyTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TimeScaleAPITest">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TimeScaleDataTest">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestSuite name="charset">
+ <TestCase abis="x86 x86_64" name="TestSelection">
+ <Test name="run-everything"/>
+ </TestCase>
+ <TestCase abis="x86 x86_64" name="TestCharset">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ <TestCase abis="x86 x86_64" name="TestLocaleNamePackaging">
+ <Test name="run-everything"/>
+ </TestCase>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
+</TestPackage>
diff --git a/tests/tests/icu/src/android/icu/cts/IcuTestRunner.java b/tests/tests/icu/src/android/icu/cts/IcuTestRunner.java
new file mode 100644
index 0000000..5861b94
--- /dev/null
+++ b/tests/tests/icu/src/android/icu/cts/IcuTestRunner.java
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+package android.icu.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.os.Bundle;
+import android.os.Debug;
+import android.test.InstrumentationTestRunner;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A drop-in replacement for AndroidJUnitTestRunner, which understands the same arguments, and has
+ * similar functionality, but runs ICU tests instead of calling the JUnit wrapper.
+ */
+public final class IcuTestRunner extends Instrumentation {
+
+ private static final String TAG = "IcuTestRunner";
+
+ /** Bundle parameter names to be sent to the host. */
+ public static final String ARGUMENT_TEST_CLASS = "class";
+ public static final String ARGUMENT_TEST_FILE = "testFile";
+
+ /** Token to identify results sent by this class. */
+ public static final String REPORT_KEY_ID = "id";
+ /** This token is use to identify the ICU test class when sending results back to the host. */
+ public static final String REPORT_KEY_NAME_CLASS = "class";
+ /** We need to have a "method" to run. We use this token to send the placeholder method. */
+ public static final String REPORT_KEY_NAME_TEST = "test";
+ /** Token for the current test number being run. */
+ public static final String REPORT_KEY_NUM_CURRENT = "current";
+ /** Token for the total number of tests. Must be consistent with the host side and sent
+ * otherwise the host will assume something went wrong and run each test individually.
+ */
+ public static final String REPORT_KEY_NUMTOTAL = "numtests";
+ /** Token representing how long (in seconds) the current test took to execute. */
+ public static final String REPORT_KEY_RUNTIME = "runtime";
+ /** Token for sending stack traces back to the host. This is displayed in the final report, so
+ * we put the ICU detailed breakdown of tests run so it is clear which test method failed.
+ */
+ public static final String REPORT_KEY_STACK = "stack";
+ /** Indicates to the host monitoring this test that a particular test has started. This token is
+ * required to be sent for the host to pickup that the test was run.
+ */
+ public static final int REPORT_VALUE_RESULT_START = 1;
+ /** An identifier for tests run using this class. */
+ public static final String REPORT_VALUE_ID = "IcuTestRunner";
+ /** The name of a non-existent method for the sake of having a method name. This is required
+ * because cts-tradefed needs to know which method on the test framework to run, but we don't
+ * have that information, so we use this placeholder instead.
+ */
+ public static final String DUMMY_METHOD_NAME = "run-everything";
+
+ /** Wait for the debugger before starting the tests. */
+ private boolean debug;
+
+ /** Only count the number of tests, and not run them. */
+ private boolean testCountOnly;
+
+ /** Contains all the wrapped ICU tests to be run in this invocation. */
+ private Set<IcuTestUtils.IcuTestWrapper> tests;
+
+
+ @Override
+ public void onCreate(Bundle args) {
+ Log.d("IcuTestRunner", "In OnCreate");
+
+ this.debug = args.getBoolean("debug");
+ this.testCountOnly = args.getBoolean("count");
+
+ // The test can be run specifying a list of classes to run, or as cts-tradefed does it,
+ // by passing a fileName with a test to run on each line.
+ List<String> classList;
+ if (args.getString(ARGUMENT_TEST_FILE) != null) {
+ // The tests are specified in a file.
+ try {
+ classList = readTestsFromFile(args.getString(ARGUMENT_TEST_FILE));
+ } catch (IOException err) {
+ finish(Activity.RESULT_CANCELED, new Bundle());
+ return;
+ }
+ } else if (args.getString(ARGUMENT_TEST_FILE) != null) {
+ // The tests are specified in a String passed in the bundle.
+ String[] classes = args.getString(ARGUMENT_TEST_CLASS).split(",");
+ classList = new ArrayList<>(Arrays.asList(classes));
+ } else {
+ // null means the runner should run all tests.
+ classList = null;
+ }
+
+ // Use all classes if a set isn't provided
+ if (classList == null) {
+ tests = IcuTestUtils.createTestAllWrappers();
+ Log.d(TAG, "Running all tests");
+ } else {
+ tests = IcuTestUtils.createTestWrappers(classList);
+ Log.d(TAG, "Running the following tests:" + classList);
+ }
+ start();
+ }
+
+ @Override
+ public void onStart() {
+ if (debug) {
+ Debug.waitForDebugger();
+ }
+
+ if (testCountOnly) {
+ Bundle testCountResult = new Bundle();
+ testCountResult.putInt(REPORT_KEY_NUMTOTAL, this.tests.size());
+ finish(Activity.RESULT_OK, testCountResult);
+ return;
+ }
+
+ int totalSuccess = 0;
+ int totalFailures = 0;
+ List<String> failedClasses = new LinkedList<>();
+
+ for (IcuTestUtils.IcuTestWrapper testWrapper : this.tests) {
+ String className = testWrapper.getTestClassName() + '\n';
+
+ Bundle currentTestResult = sendStartTestInfo(className, totalSuccess + totalFailures);
+
+ StringBuilder result = new StringBuilder();
+ try {
+ StringWriter logs = new StringWriter();
+ Log.d("IcuTestRunner", "Executing test: " + className);
+ long startTime = System.currentTimeMillis();
+ int resultCode = testWrapper.call(new PrintWriter(logs));
+ long timeTaken = System.currentTimeMillis() - startTime;
+ currentTestResult.putFloat(REPORT_KEY_RUNTIME, timeTaken / 1000);
+ if (resultCode != 0) {
+ totalFailures++;
+ failedClasses.add(className);
+ // Include the detailed logs from ICU as the stack trace.
+ currentTestResult.putString(REPORT_KEY_STACK, logs.toString());
+ // Also append the logs to the console output.
+ result.append("Failure: ").append(className).append(logs.toString());
+ currentTestResult.putString(REPORT_KEY_STREAMRESULT, result.toString());
+ sendStatus(InstrumentationTestRunner.REPORT_VALUE_RESULT_ERROR,
+ currentTestResult);
+ } else {
+ totalSuccess++;
+ result.append("Success: ").append(className).append(logs.toString());
+ currentTestResult.putString(REPORT_KEY_STREAMRESULT, result.toString());
+ sendStatus(InstrumentationTestRunner.REPORT_VALUE_RESULT_OK, currentTestResult);
+ }
+ result.append("Total time taken: ").append(timeTaken).append("ms\n");
+ } catch (Exception e) {
+ currentTestResult.putString(REPORT_KEY_STACK,
+ "Test code threw exception: " + e.getMessage() + '\n');
+ result.append(e.getMessage());
+ sendStatus(InstrumentationTestRunner.REPORT_VALUE_RESULT_ERROR,
+ currentTestResult);
+ }
+ }
+ Bundle results = new Bundle();
+ if (totalFailures == 0) {
+ results.putString(REPORT_KEY_STREAMRESULT, "All " + totalSuccess + " tests passed.");
+ } else {
+ String report = "Failures " + totalFailures + '\n';
+ for (String classname : failedClasses) {
+ report += classname + '\n';
+ }
+ results.putString(REPORT_KEY_STREAMRESULT, report);
+ }
+
+ finish(Activity.RESULT_OK, results);
+ }
+
+
+ /**
+ * Send an update to the test runner informing it we are starting a test. If this is not run
+ * then the test runner will think the test was never run, and mark it as failed.
+ * @param className The name of the class being tested. Note in this CTS-ICU interoperability
+ * layer, there is no method names, as we only support running whole classes.
+ * @return A bundle containing test class, method (dummy), and report name. This bundle has
+ * been sent back to the host.
+ */
+ private Bundle sendStartTestInfo(String className, int testNum) {
+ Bundle data = new Bundle();
+ data.putString(REPORT_KEY_ID, REPORT_VALUE_ID);
+ data.putInt(REPORT_KEY_NUMTOTAL, 1);
+ data.putInt(REPORT_KEY_NUM_CURRENT, testNum);
+ data.putString(REPORT_KEY_NAME_CLASS, className);
+ data.putString(REPORT_KEY_NAME_TEST, DUMMY_METHOD_NAME); // Dummy method to work with cts.
+ sendStatus(REPORT_VALUE_RESULT_START, data);
+ return data;
+ }
+
+ /**
+ * Read tests from a specified file.
+ * @return class names of tests. If there was an error reading the file, null is returned.
+ */
+ private static List<String> readTestsFromFile(String fileName) throws IOException {
+ try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
+ List<String> tests = new ArrayList<>();
+ String line;
+ while ((line = br.readLine()) != null) {
+ tests.add(line);
+ }
+ return tests;
+ } catch (IOException err) {
+ Log.e(TAG, "There was an error reading the test class list: " + err.getMessage());
+ throw err;
+ }
+ }
+
+}
diff --git a/tests/tests/icu/src/android/icu/cts/IcuTestUtils.java b/tests/tests/icu/src/android/icu/cts/IcuTestUtils.java
new file mode 100644
index 0000000..fb9af99
--- /dev/null
+++ b/tests/tests/icu/src/android/icu/cts/IcuTestUtils.java
@@ -0,0 +1,238 @@
+/*
+ * 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.
+ */
+
+package android.icu.cts;
+
+import com.ibm.icu.dev.test.TestFmwk;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A thin wrapper around ICU's tests, and utilities to resolve them.
+ */
+final class IcuTestUtils {
+
+ /**
+ * The field on TestGroup which has the list of classes in it.
+ */
+ private static final Field classesToTest;
+ static {
+ // Find the field, and complain if it is not where we expected it to be.
+ try {
+ classesToTest = TestFmwk.TestGroup.class.getDeclaredField("names");
+ classesToTest.setAccessible(true); // It's private by default.
+ } catch (NoSuchFieldException nsfe) {
+ throw new RuntimeException("Class structure of ICU tests have changed.", nsfe);
+ }
+ }
+
+ // Instances of this class shouldn't be made.
+ private IcuTestUtils() {}
+
+ /**
+ * Resolve the individual ICU tests from a base test class which must implement TestFmwk.
+ * A TestGroup class in ICU has a private String[] containing all the class names which
+ * are run when the TestGroup is run.
+ *
+ * @param parent the base class to start looking at.
+ */
+ public static Set<IcuTestWrapper> getBaseTests(Class<?> parent)
+ throws InstantiationException, IllegalAccessException {
+
+ Set<IcuTestWrapper> tests = new HashSet<>();
+
+ // If the parent class is an instance of TestGroup, then it will have a String[] classes
+ // field which tells us where we need to go looking for the base test classes. We can then
+ // recursively call this method which will resolve the base classes from the classes we
+ // have discovered in that field.
+ if (TestFmwk.TestGroup.class.isAssignableFrom(parent)) {
+
+ String[] children = (String[]) classesToTest.get(parent.newInstance());
+
+ for (String child : children) {
+ try {
+ /* Get the children through a recursive call, and add to sets. */
+ tests.addAll(getBaseTests(Class.forName(child)));
+ } catch (ClassNotFoundException cnfe) {
+ // Try to extract the full class name by prepending the parent package.
+ // (In case the class name was specified relative to the TestGroup).
+ String fixed = parent.getCanonicalName().replaceAll("[a-zA-Z0-9]+$", child);
+
+ try {
+ tests.addAll(getBaseTests(Class.forName(fixed)));
+ } catch (ClassNotFoundException unused) {
+ // We make sure to add any failures to find a test, in a way that will cause
+ // that test to fail. This is to make sure that the user is properly
+ // informed that the test was not run. Use parent exception because that
+ // has the actual classname and not our /guess/ to normalise the class name.
+ tests.add(new FailTest(child, cnfe));
+ }
+ }
+ }
+
+ } else if (TestFmwk.class.isAssignableFrom(parent)) {
+ // Otherwise, if the parent class is instead an instance of TestFmwk instead, this
+ // will be a base test. We can simply add parent to the set of classes and return.
+ tests.add(new IcuTestAdapter(parent));
+ }
+
+ return tests;
+ }
+
+ /**
+ * Resolve all the ICU tests and return a set of IcuTestWrappers which will run them.
+ * See {@link IcuTestUtils#createTestWrappers(Iterable<String>)}.
+ */
+ public static Set<IcuTestWrapper> createTestAllWrappers() {
+ return createTestWrappers(Collections.singleton("com.ibm.icu.dev.test.TestAll"));
+ }
+
+ /**
+ * Resolves a set of tests in ICU from a list of class names. These class names should reference
+ * classes under the classpath com.ibm.icu.dev.test.* and extend TestFmwk (the ICU base test
+ * class). This will return a set of individual tests, any TestGroup's found will be recursively
+ * processed to extract base classes out of them, and those tests wrapped for running.
+ * @return A set of test wrappers which can be run to determine the test outcome.
+ */
+ public static Set<IcuTestWrapper> createTestWrappers(Iterable<String> classNames) {
+ Set<IcuTestWrapper> wrappedSet = new HashSet<>();
+
+ for (String className : classNames) {
+ // Work around the limitation of CTS where a test method must be provided. We only
+ // support running classes in ICU, so discard the mock test method.
+ if (className.contains("#")) {
+ className = className.substring(0, className.indexOf("#"));
+ }
+ try {
+ wrappedSet.addAll(getBaseTests(Class.forName(className)));
+ } catch (ClassNotFoundException cnfe) {
+ /* Failure to resolve the base class */
+ wrappedSet.add(new FailTest(className, cnfe));
+ } catch (InstantiationException | IllegalAccessException e) {
+ /* An error while finding the classes */
+ wrappedSet.add(new FailTest(className,
+ new RuntimeException("Error finding test classes: " + e)));
+ }
+ }
+ return wrappedSet;
+ }
+
+
+ /**
+ * A common interface for wrapping tests to be run with IcuTestRunner.
+ */
+ public interface IcuTestWrapper {
+ /**
+ * Returns true if there was an error fetching or resolving this test.
+ * Otherwise, the test is ready to be run and this returns false.
+ */
+ boolean isError();
+
+ /**
+ * Returns the ICU class that this test will call through to.
+ */
+ String getTestClassName();
+
+ /**
+ * Execute the test and provide the return code.
+ * 0 means that the test was successfully run.
+ */
+ int call(PrintWriter pw) throws Exception;
+ }
+
+ /**
+ * Wrapper around failure to resolve a specified ICU test class.
+ * This could be due to a class not being resolved, which was
+ * specified in the ICU test suite, a user provided class which
+ * could not be found, or an error in instantiating the class.
+ */
+ private static class FailTest implements IcuTestWrapper {
+
+ public FailTest(String attemptedClassName, Exception error) {
+ this.error = error;
+ this.className = attemptedClassName;
+ }
+
+ private String className;
+ private Exception error;
+
+ public String getTestClassName() {
+ return className;
+ }
+
+ public boolean isError() {
+ return true;
+ }
+
+ public int call(PrintWriter unused) throws Exception {
+ throw error;
+ }
+ }
+
+ /**
+ * Wrap an ICU test class and override the run method so we can handle executing the test and
+ * extracting the return code, output stream, and any exceptions.
+ */
+ private static class IcuTestAdapter implements IcuTestWrapper {
+
+ /**
+ * Fully qualified name of the test class.
+ */
+ private final String name;
+
+ /**
+ * Class object from which the test will be instantiated and run.
+ */
+ private final Class<?> icuTestClass;
+
+ public IcuTestAdapter(Class<?> testClass) {
+ if (!TestFmwk.class.isAssignableFrom(testClass)) {
+ throw new IllegalArgumentException("There was an error in the testing framework."
+ + "A test class was found which is not an instance of TestFmwk: "
+ + testClass);
+ }
+
+ this.name = testClass.getCanonicalName();
+ this.icuTestClass = testClass;
+ }
+
+ @Override
+ public boolean isError() {
+ return false;
+ }
+
+ @Override
+ public String getTestClassName() {
+ return this.name;
+ }
+
+ @Override
+ public int call(PrintWriter pw) {
+ try {
+ TestFmwk instance = (TestFmwk) icuTestClass.newInstance();
+ return instance.run(new String[]{}, pw);
+
+ } catch (IllegalAccessException | InstantiationException iae) {
+ throw new RuntimeException("Failed to create test class: " + icuTestClass);
+ }
+ }
+ }
+
+}
diff --git a/tests/tests/jni/Android.mk b/tests/tests/jni/Android.mk
index 7d55698..4b4e770 100644
--- a/tests/tests/jni/Android.mk
+++ b/tests/tests/jni/Android.mk
@@ -27,6 +27,9 @@
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
LOCAL_JNI_SHARED_LIBRARIES := libjnitest libnativehelper_compat_libc++
diff --git a/tests/tests/jni/AndroidManifest.xml b/tests/tests/jni/AndroidManifest.xml
index 843b322..2724573 100644
--- a/tests/tests/jni/AndroidManifest.xml
+++ b/tests/tests/jni/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.jni">
+ package="android.jni.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -24,7 +24,7 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.jni"
+ android:targetPackage="android.jni.cts"
android:label="CTS tests of calling native code via JNI">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/jni/AndroidTest.xml b/tests/tests/jni/AndroidTest.xml
new file mode 100644
index 0000000..8ec1df6
--- /dev/null
+++ b/tests/tests/jni/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS JNI test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsJniTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.jni.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index e51bc04..ba43824 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -18,6 +18,11 @@
LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner core-tests-support
LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -26,8 +31,6 @@
LOCAL_SDK_VERSION := current
-cts_runtime_hint := 28
-
include $(BUILD_CTS_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/keystore/AndroidManifest.xml b/tests/tests/keystore/AndroidManifest.xml
index 106a0dc..3678f63 100644
--- a/tests/tests/keystore/AndroidManifest.xml
+++ b/tests/tests/keystore/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.keystore">
+ package="android.keystore.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.INTERNET" />
@@ -25,8 +25,8 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.keystore"
- android:label="CTS tests of com.android.cts.keystore">
+ android:targetPackage="android.keystore.cts"
+ android:label="CTS tests of android.keystore.cts">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/tests/keystore/AndroidTest.xml b/tests/tests/keystore/AndroidTest.xml
new file mode 100644
index 0000000..844cd2a
--- /dev/null
+++ b/tests/tests/keystore/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Keystore test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsKeystoreTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.keystore.cts" />
+ <option name="runtime-hint" value="16m39s" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
index f7cc586..1efcb7f 100644
--- a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
@@ -27,7 +27,7 @@
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
-import com.android.cts.keystore.R;
+import android.keystore.cts.R;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
diff --git a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
index 1a24fb2..60a48e0 100644
--- a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
@@ -21,7 +21,7 @@
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
-import com.android.cts.keystore.R;
+import android.keystore.cts.R;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
diff --git a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
index ea3940d..de60e37 100644
--- a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
@@ -20,7 +20,7 @@
import android.security.keystore.KeyProtection;
import android.test.AndroidTestCase;
-import com.android.cts.keystore.R;
+import android.keystore.cts.R;
import java.security.KeyPair;
import java.security.Security;
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyFactoryTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyFactoryTest.java
index d552631..fb853c9 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyFactoryTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyFactoryTest.java
@@ -22,7 +22,7 @@
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
-import com.android.cts.keystore.R;
+import android.keystore.cts.R;
import java.io.InputStream;
import java.security.InvalidKeyException;
diff --git a/tests/tests/keystore/src/android/keystore/cts/RSASignatureTest.java b/tests/tests/keystore/src/android/keystore/cts/RSASignatureTest.java
index e28fdff..d31f2e4 100644
--- a/tests/tests/keystore/src/android/keystore/cts/RSASignatureTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/RSASignatureTest.java
@@ -28,7 +28,7 @@
import java.util.Collection;
import java.util.List;
-import com.android.cts.keystore.R;
+import android.keystore.cts.R;
import android.content.Context;
import android.security.keystore.KeyProperties;
diff --git a/tests/tests/keystore/src/android/keystore/cts/SignatureTest.java b/tests/tests/keystore/src/android/keystore/cts/SignatureTest.java
index 6fb3954..4fa8899 100644
--- a/tests/tests/keystore/src/android/keystore/cts/SignatureTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/SignatureTest.java
@@ -16,7 +16,7 @@
package android.keystore.cts;
-import com.android.cts.keystore.R;
+import android.keystore.cts.R;
import java.security.InvalidKeyException;
import java.security.KeyPair;
diff --git a/tests/tests/libcorelegacy22/Android.mk b/tests/tests/libcorelegacy22/Android.mk
index fb3c503..5b114f2 100644
--- a/tests/tests/libcorelegacy22/Android.mk
+++ b/tests/tests/libcorelegacy22/Android.mk
@@ -29,4 +29,7 @@
LOCAL_SDK_VERSION := 22
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/libcorelegacy22/AndroidManifest.xml b/tests/tests/libcorelegacy22/AndroidManifest.xml
index 4ff9ec2..131613e 100644
--- a/tests/tests/libcorelegacy22/AndroidManifest.xml
+++ b/tests/tests/libcorelegacy22/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.libcorelegacy22">
+ package="android.libcorelegacy22.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.READ_LOGS" />
@@ -25,7 +25,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.libcorelegacy22"
+ android:targetPackage="android.libcorelegacy22.cts"
android:label="CTS tests of android APIs last available in API 22">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/libcorelegacy22/AndroidTest.xml b/tests/tests/libcorelegacy22/AndroidTest.xml
new file mode 100644
index 0000000..cdc6611
--- /dev/null
+++ b/tests/tests/libcorelegacy22/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS Legacy Libcore test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsLibcoreLegacy22TestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.libcorelegacy22.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/location/Android.mk b/tests/tests/location/Android.mk
index 62d0d5d..6e71659 100644
--- a/tests/tests/location/Android.mk
+++ b/tests/tests/location/Android.mk
@@ -21,6 +21,9 @@
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/location/AndroidManifest.xml b/tests/tests/location/AndroidManifest.xml
index 5016f49..f9985ba 100644
--- a/tests/tests/location/AndroidManifest.xml
+++ b/tests/tests/location/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.location">
+ package="android.location.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -28,7 +28,7 @@
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.location"
+ android:targetPackage="android.location.cts"
android:label="CTS tests of android.location">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/location/AndroidTest.xml b/tests/tests/location/AndroidTest.xml
new file mode 100644
index 0000000..178e8d1
--- /dev/null
+++ b/tests/tests/location/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<configuration description="Config for CTS Location test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsLocationTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.location.cts" />
+ <option name="runtime-hint" value="1m26s" />
+ </test>
+
+</configuration>
diff --git a/tests/tests/location2/Android.mk b/tests/tests/location2/Android.mk
index 5b227b2..5e9d7da 100644
--- a/tests/tests/location2/Android.mk
+++ b/tests/tests/location2/Android.mk
@@ -21,6 +21,9 @@
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/location2/AndroidManifest.xml b/tests/tests/location2/AndroidManifest.xml
index b2e0802..766aab4 100644
--- a/tests/tests/location2/AndroidManifest.xml
+++ b/tests/tests/location2/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.location2">
+ package="android.location2.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -27,7 +27,7 @@
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.location2"
+ android:targetPackage="android.location2.cts"
android:label="CTS tests of android.location">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/location2/AndroidTest.xml b/tests/tests/location2/AndroidTest.xml
new file mode 100644
index 0000000..5829249
--- /dev/null
+++ b/tests/tests/location2/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<configuration description="Config for CTS Location test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsLocation2TestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.location2.cts" />
+ </test>
+
+</configuration>
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index a911ea5..dff08f5 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -32,14 +32,18 @@
# don't include this package in any target
LOCAL_MODULE_TAGS := optional
+
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
# include both the 32 and 64 bit versions
LOCAL_MULTILIB := both
-LOCAL_STATIC_JAVA_LIBRARIES := \
- ctsmediautil ctsdeviceutil ctstestserver ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner
LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++
@@ -49,9 +53,11 @@
# uncomment when b/13249737 is fixed
#LOCAL_SDK_VERSION := current
+
LOCAL_JAVA_LIBRARIES += android.test.runner org.apache.http.legacy
-cts_runtime_hint := 265
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/AndroidManifest.xml
index cdc0e60..7645e0c 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.media">
+ package="android.media.cts">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -88,7 +88,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.media"
+ android:targetPackage="android.media.cts"
android:label="CTS tests of android.media">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/media/AndroidTest.xml b/tests/tests/media/AndroidTest.xml
new file mode 100644
index 0000000..5131fe4
--- /dev/null
+++ b/tests/tests/media/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Media test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsMediaTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.media.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/media/DynamicConfig.xml b/tests/tests/media/DynamicConfig.xml
new file mode 100644
index 0000000..702157d
--- /dev/null
+++ b/tests/tests/media/DynamicConfig.xml
@@ -0,0 +1,29 @@
+<!-- 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.
+-->
+
+<DynamicConfig>
+ <Config key="DecoderTest-VIDEO_URL">http://redirector.gvt1.com/videoplayback?id=c80658495af60617&itag=18&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=46A04ED550CA83B79B60060BA80C79FDA5853D26.49582D382B4A9AFAA163DED38D2AE531D85603C0&key=ik0&user=android-device-test</Config>
+ <Config key="StreamingMediaPlayerTest-testHTTP_H264Base_AAC_Video1">http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=18&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=667AEEF54639926662CE62361400B8F8C1753B3F.15F46C382C68A9F121BA17BF1F56BEDEB4B06091&key=ik0&user=android-device-test</Config>
+ <Config key="StreamingMediaPlayerTest-testHTTP_H264Base_AAC_Video2">http://www.youtube.com/api/manifest/hls_variant/id/0168724d02bd9945/itag/5/source/youtube/playlist_type/DVR/ip/0.0.0.0/ipbits/0/expire/19000000000/sparams/ip,ipbits,expire,id,itag,source,playlist_type/signature/773AB8ACC68A96E5AA481996AD6A1BBCB70DCB87.95733B544ACC5F01A1223A837D2CF04DF85A3360/key/ik0/file/m3u8</Config>
+ <Config key="MediaCodecCapabilitiesTest-testAvcHigh31">http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=22&source=youtube&user=android-device-test&sparams=ip,ipbits,expire,id,itag,source,user&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=179525311196616BD8E1381759B0E5F81A9E91B5.C4A50E44059FEBCC6BBC78E3B3A4E0E0065777&key=ik0</Config>
+ <Config key="StreamingMediaPlayerTest-testHTTP_MPEG4SP_AAC_Video2">http://redirector.gvt1.com/videoplayback?id=c80658495af60617&itag=17&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=70E979A621001201BC18622BDBF914FA870BDA40.6E78890B80F4A33A18835F775B1FF64F0A4D0003&key=ik0&user=android-device-test</Config>
+ <Config key="StreamingMediaPlayerTest-testHTTP_MPEG4SP_AAC_Video1">http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=17&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=837198AAADF6F36BA6B2D324F690A7C5B7AFE3FF.7138CE5E36D718220726C1FC305497FF2D082249&key=ik0&user=android-device-test</Config>
+ <Config key="MediaCodecCapabilitiesTest-testAvcBaseline12">http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=160&source=youtube&user=android-device-test&sparams=ip,ipbits,expire,id,itag,source,user&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=9EDCA0B395B8A949C511FD5E59B9F805CFF797FD.702DE9BA7AF96785FD6930AD2DD693A0486C880E&key=ik0</Config>
+ <Config key="DecoderTest-AUDIO_URL">http://redirector.gvt1.com/videoplayback?id=c80658495af60617&itag=18&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=46A04ED550CA83B79B60060BA80C79FDA5853D26.49582D382B4A9AFAA163DED38D2AE531D85603C0&key=ik0&user=android-device-test</Config>
+ <Config key="MediaCodecCapabilitiesTest-testAvcBaseline30">http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=18&source=youtube&user=android-device-test&sparams=ip,ipbits,expire,id,itag,source,user&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=7DCDE3A6594D0B91A27676A3CDC3A87B149F82EA.7A83031734CB1EDCE06766B6228842F954927960&key=ik0</Config>
+ <Config key="MediaCodecCapabilitiesTest-testAvcHigh40">http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=137&source=youtube&user=android-device-test&sparams=ip,ipbits,expire,id,itag,source,user&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=B0976085596DD42DEA3F08307F76587241CB132B.043B719C039E8B92F45391ADC0BE3665E2332930&key=ik0</Config>
+ <Config key="StreamingMediaPlayerTest-testHTTP_H263_AMR_Video2">http://redirector.gvt1.com/videoplayback?id=c80658495af60617&itag=13&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=508D82AB36939345BF6B8D0623CB6CABDD9C64C3.9B3336A96846DF38E5343C46AA57F6CF2956E427&key=ik0&user=android-device-test</Config>
+ <Config key="StreamingMediaPlayerTest-testHTTP_H263_AMR_Video1">http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=13&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=5729247E22691EBB3E804DDD523EC42DC17DD8CE.443B81C1E8E6D64E4E1555F568BA46C206507D78&key=ik0&user=android-device-test</Config>
+</DynamicConfig>
diff --git a/tests/tests/media/libaudiojni/Android.mk b/tests/tests/media/libaudiojni/Android.mk
index a6c1bfc..6a11a91 100644
--- a/tests/tests/media/libaudiojni/Android.mk
+++ b/tests/tests/media/libaudiojni/Android.mk
@@ -34,6 +34,7 @@
LOCAL_C_INCLUDES += $(call include-path-for, libaudiojni) \
$(call include-path-for, wilhelm)
-LOCAL_SHARED_LIBRARIES := libandroid liblog libnativehelper libOpenSLES libutils
+LOCAL_SHARED_LIBRARIES := libandroid liblog libnativehelper_compat_libc++ libOpenSLES libutils
+LOCAL_CXX_STL := libc++_static
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/libaudiojni/sl-utils.cpp b/tests/tests/media/libaudiojni/sl-utils.cpp
index 1aa89ba..4dbb08d 100644
--- a/tests/tests/media/libaudiojni/sl-utils.cpp
+++ b/tests/tests/media/libaudiojni/sl-utils.cpp
@@ -91,8 +91,10 @@
static SLObjectItf createEngine() {
static SLEngineOption EngineOption[] = {
+ {
(SLuint32) SL_ENGINEOPTION_THREADSAFE,
(SLuint32) SL_BOOLEAN_TRUE
+ },
};
// create engine in thread-safe mode
SLObjectItf engine;
diff --git a/tests/tests/media/res/raw/video_720x480_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_640x360_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz
similarity index 100%
rename from tests/tests/media/res/raw/video_720x480_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz.mp4
rename to tests/tests/media/res/raw/video_640x360_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index 34469b79..0b8b88e 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.content.pm.PackageManager;
diff --git a/tests/tests/media/src/android/media/cts/AudioEffectTest.java b/tests/tests/media/src/android/media/cts/AudioEffectTest.java
index dce7680..b7b7f9e 100644
--- a/tests/tests/media/src/android/media/cts/AudioEffectTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioEffectTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.res.AssetFileDescriptor;
import android.media.audiofx.AudioEffect;
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerStub.java b/tests/tests/media/src/android/media/cts/AudioManagerStub.java
index 290b866..947acec 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerStub.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerStub.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.app.Activity;
import android.cts.util.CTSResult;
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index a0163e5..16b1cf3 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -35,7 +35,7 @@
import static android.media.AudioManager.VIBRATE_TYPE_RINGER;
import static android.provider.Settings.System.SOUND_EFFECTS_ENABLED;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.content.res.Resources;
diff --git a/tests/tests/media/src/android/media/cts/AudioPreProcessingTest.java b/tests/tests/media/src/android/media/cts/AudioPreProcessingTest.java
index de5b698..27aa866 100644
--- a/tests/tests/media/src/android/media/cts/AudioPreProcessingTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioPreProcessingTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index 41afab4..84c676f 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -16,9 +16,6 @@
package android.media.cts;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -35,9 +32,12 @@
import android.os.Message;
import android.util.Log;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
public class AudioRecordTest extends CtsAndroidTestCase {
private final static String TAG = "AudioRecordTest";
@@ -966,38 +966,39 @@
}
// report this
- ReportLog log = getReportLog();
- log.printValue(reportName + ": startRecording lag", coldInputStartTime,
+ DeviceReportLog log = new DeviceReportLog();
+ log.addValue(reportName + ": startRecording lag", coldInputStartTime,
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": stop execution time", stopTime - stopRequestTime,
+ log.addValue(reportName + ": stop execution time", stopTime - stopRequestTime,
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Total record time expected", TEST_TIME_MS,
+ log.addValue(reportName + ": Total record time expected", TEST_TIME_MS,
ResultType.NEUTRAL, ResultUnit.MS);
- log.printValue(reportName + ": Total record time actual", endTime - firstSampleTime,
+ log.addValue(reportName + ": Total record time actual", endTime - firstSampleTime,
ResultType.NEUTRAL, ResultUnit.MS);
- log.printValue(reportName + ": Total markers expected", markerPeriods,
+ log.addValue(reportName + ": Total markers expected", markerPeriods,
ResultType.NEUTRAL, ResultUnit.COUNT);
- log.printValue(reportName + ": Total markers actual", markerList.size(),
+ log.addValue(reportName + ": Total markers actual", markerList.size(),
ResultType.NEUTRAL, ResultUnit.COUNT);
- log.printValue(reportName + ": Total periods expected", updatePeriods,
+ log.addValue(reportName + ": Total periods expected", updatePeriods,
ResultType.NEUTRAL, ResultUnit.COUNT);
- log.printValue(reportName + ": Total periods actual", periodicList.size(),
+ log.addValue(reportName + ": Total periods actual", periodicList.size(),
ResultType.NEUTRAL, ResultUnit.COUNT);
- log.printValue(reportName + ": Average Marker diff", markerStat.getAvg(),
+ log.addValue(reportName + ": Average Marker diff", markerStat.getAvg(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Maximum Marker abs diff", markerStat.getMaxAbs(),
+ log.addValue(reportName + ": Maximum Marker abs diff", markerStat.getMaxAbs(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Average Marker abs diff", markerStat.getAvgAbs(),
+ log.addValue(reportName + ": Average Marker abs diff", markerStat.getAvgAbs(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Average Periodic diff", periodicStat.getAvg(),
+ log.addValue(reportName + ": Average Periodic diff", periodicStat.getAvg(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Maximum Periodic abs diff", periodicStat.getMaxAbs(),
+ log.addValue(reportName + ": Maximum Periodic abs diff", periodicStat.getMaxAbs(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Average Periodic abs diff", periodicStat.getAvgAbs(),
+ log.addValue(reportName + ": Average Periodic abs diff", periodicStat.getAvgAbs(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printSummary(reportName + ": Unified abs diff",
+ log.setSummary(reportName + ": Unified abs diff",
(periodicStat.getAvgAbs() + markerStat.getAvgAbs()) / 2,
ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.submit(getInstrumentation());
}
private class MockOnRecordPositionUpdateListener
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index 1884493..a2d6cfb 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -28,14 +28,13 @@
import android.media.PlaybackParams;
import android.util.Log;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
-import java.nio.ByteOrder;
import java.nio.ByteBuffer;
-import java.nio.ShortBuffer;
import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
public class AudioTrackTest extends CtsAndroidTestCase {
private String TAG = "AudioTrackTest";
@@ -2026,15 +2025,16 @@
track.release();
// Log the average jitter
if (cumulativeJitterCount > 0) {
- ReportLog log = getReportLog();
+ DeviceReportLog log = new DeviceReportLog();
final float averageJitterInFrames = cumulativeJitter / cumulativeJitterCount;
final float averageJitterInMs = averageJitterInFrames * 1000 / TEST_SR;
final float maxJitterInMs = maxJitter * 1000 / TEST_SR;
// ReportLog needs at least one Value and Summary.
- log.printValue("Maximum Jitter", maxJitterInMs,
+ log.addValue("Maximum Jitter", maxJitterInMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printSummary("Average Jitter", averageJitterInMs,
+ log.setSummary("Average Jitter", averageJitterInMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.submit(getInstrumentation());
}
}
diff --git a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
index e059e36..37affd0 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
@@ -16,21 +16,20 @@
package android.media.cts;
-import java.util.ArrayList;
-
import android.cts.util.CtsAndroidTestCase;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.AudioTrack.OnPlaybackPositionUpdateListener;
-import android.media.cts.AudioHelper;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.util.Log;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+
+import java.util.ArrayList;
public class AudioTrack_ListenerTest extends CtsAndroidTestCase {
private final static String TAG = "AudioTrack_ListenerTest";
@@ -206,22 +205,23 @@
}
// report this
- ReportLog log = getReportLog();
- log.printValue(reportName + ": Average Marker diff", markerStat.getAvg(),
+ DeviceReportLog log = new DeviceReportLog();
+ log.addValue(reportName + ": Average Marker diff", markerStat.getAvg(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Maximum Marker abs diff", markerStat.getMaxAbs(),
+ log.addValue(reportName + ": Maximum Marker abs diff", markerStat.getMaxAbs(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Average Marker abs diff", markerStat.getAvgAbs(),
+ log.addValue(reportName + ": Average Marker abs diff", markerStat.getAvgAbs(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Average Periodic diff", periodicStat.getAvg(),
+ log.addValue(reportName + ": Average Periodic diff", periodicStat.getAvg(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Maximum Periodic abs diff", periodicStat.getMaxAbs(),
+ log.addValue(reportName + ": Maximum Periodic abs diff", periodicStat.getMaxAbs(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printValue(reportName + ": Average Periodic abs diff", periodicStat.getAvgAbs(),
+ log.addValue(reportName + ": Average Periodic abs diff", periodicStat.getAvgAbs(),
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.printSummary(reportName + ": Unified abs diff",
+ log.setSummary(reportName + ": Unified abs diff",
(periodicStat.getAvgAbs() + markerStat.getAvgAbs()) / 2,
ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.submit(getInstrumentation());
}
private class MockOnPlaybackPositionUpdateListener
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 6765051..448b417 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -1087,8 +1087,8 @@
testDecode(R.raw.video_352x288_mp4_hevc_600kbps_30fps_aac_stereo_128kbps_44100hz, 299);
}
- public void testHEVCDecode720x480() throws Exception {
- testDecode(R.raw.video_720x480_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ public void testHEVCDecode640x360() throws Exception {
+ testDecode(R.raw.video_640x360_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz, 299);
}
public void testHEVCDecode30fps1280x720Tv() throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
index a999135..b49f07e 100644
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
@@ -58,7 +58,7 @@
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.cts.media.R;
+import android.media.cts.R;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -1292,7 +1292,7 @@
void connect() throws Exception {
Intent intent = new Intent();
- intent.setClassName("com.android.cts.media",
+ intent.setClassName("android.media.cts",
"android.media.cts.RemoteVirtualDisplayService");
mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
if (!mConnectionWait.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
diff --git a/tests/tests/media/src/android/media/cts/EncoderTest.java b/tests/tests/media/src/android/media/cts/EncoderTest.java
index 4b2a168..c8cea22 100644
--- a/tests/tests/media/src/android/media/cts/EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/EncoderTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.media.MediaCodec;
@@ -26,16 +26,21 @@
import android.test.AndroidTestCase;
import android.util.Log;
+import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
public class EncoderTest extends AndroidTestCase {
private static final String TAG = "EncoderTest";
private static final boolean VERBOSE = false;
- private static final int kNumInputBytes = 256 * 1024;
- private static final long kTimeoutUs = 10000;
+ private static final int kNumInputBytes = 512 * 1024;
+ private static final long kTimeoutUs = 100;
@Override
public void setContext(Context context) {
@@ -121,15 +126,19 @@
private void testEncoderWithFormats(
String mime, List<MediaFormat> formats) {
List<String> componentNames = getEncoderNamesForType(mime);
+ ExecutorService pool = Executors.newFixedThreadPool(3);
for (String componentName : componentNames) {
- Log.d(TAG, "testing component '" + componentName + "'");
for (MediaFormat format : formats) {
- Log.d(TAG, " testing format '" + format + "'");
assertEquals(mime, format.getString(MediaFormat.KEY_MIME));
- testEncoder(componentName, format);
+ pool.execute(new EncoderRun(componentName, format));
}
}
+ try {
+ pool.shutdown();
+ pool.awaitTermination(5, TimeUnit.MINUTES);
+ } catch (InterruptedException e) {
+ }
}
private List<String> getEncoderNamesForType(String mime) {
@@ -151,15 +160,41 @@
return names;
}
- private int queueInputBuffer(
- MediaCodec codec, ByteBuffer[] inputBuffers, int index) {
- ByteBuffer buffer = inputBuffers[index];
- buffer.clear();
+ // See bug 25843966
+ private long[] mBadSeeds = {
+ 101833462733980l, // fail @ 23680 in all-random mode
+ 273262699095706l, // fail @ 58880 in all-random mode
+ 137295510492957l, // fail @ 35840 in zero-lead mode
+ 57821391502855l, // fail @ 32000 in zero-lead mode
+ };
+ private Random mRandom = new Random(1);
+
+ private int queueInputBuffer(
+ MediaCodec codec, ByteBuffer[] inputBuffers, int index,
+ boolean random, boolean zeroLead) {
+ ByteBuffer buffer = inputBuffers[index];
+ buffer.rewind();
int size = buffer.limit();
- byte[] zeroes = new byte[size];
- buffer.put(zeroes);
+ if (random) {
+ if (zeroLead) {
+ buffer.putInt(0);
+ buffer.putInt(0);
+ buffer.putInt(0);
+ buffer.putInt(0);
+ }
+ while (true) {
+ try {
+ buffer.putInt(mRandom.nextInt());
+ } catch (BufferOverflowException ex) {
+ break;
+ }
+ }
+ } else {
+ byte[] zeroes = new byte[size];
+ buffer.put(zeroes);
+ }
codec.queueInputBuffer(index, 0 /* offset */, size, 0 /* timeUs */, 0);
@@ -172,7 +207,35 @@
codec.releaseOutputBuffer(index, false /* render */);
}
+ class EncoderRun implements Runnable {
+ String mComponentName;
+ MediaFormat mFormat;
+
+ EncoderRun(String componentName, MediaFormat format) {
+ mComponentName = componentName;
+ mFormat = format;
+ }
+ @Override
+ public void run() {
+ testEncoder(mComponentName, mFormat);
+ }
+ }
+
private void testEncoder(String componentName, MediaFormat format) {
+ Log.i(TAG, "testEncoder " + componentName + "/" + format);
+ // test with all zeroes/silence
+ testEncoder(componentName, format, false, 0, false);
+
+ // test with random data, with and without a few leading zeroes
+ for (int i = 0; i < mBadSeeds.length; i++) {
+ testEncoder(componentName, format, true, mBadSeeds[i], false);
+ testEncoder(componentName, format, true, mBadSeeds[i], true);
+ }
+ }
+
+ private void testEncoder(String componentName, MediaFormat format, boolean random,
+ long startSeed, boolean zeroLead) {
+ mRandom.setSeed(startSeed);
MediaCodec codec;
try {
codec = MediaCodec.createByCodecName(componentName);
@@ -220,7 +283,7 @@
doneSubmittingInput = true;
} else {
int size = queueInputBuffer(
- codec, codecInputBuffers, index);
+ codec, codecInputBuffers, index, random, zeroLead);
numBytesSubmitted += size;
diff --git a/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java b/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
index 8650d20..1af825c 100644
--- a/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
+++ b/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
@@ -35,7 +35,7 @@
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
-import com.android.cts.media.R;
+import android.media.cts.R;
import java.io.File;
import java.io.IOException;
diff --git a/tests/tests/media/src/android/media/cts/FaceDetectorStub.java b/tests/tests/media/src/android/media/cts/FaceDetectorStub.java
index b1cb82d..6635fda 100644
--- a/tests/tests/media/src/android/media/cts/FaceDetectorStub.java
+++ b/tests/tests/media/src/android/media/cts/FaceDetectorStub.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.app.Activity;
import android.media.FaceDetector.Face;
diff --git a/tests/tests/media/src/android/media/cts/FaceDetectorTest.java b/tests/tests/media/src/android/media/cts/FaceDetectorTest.java
index 4eebd52..4df0475 100644
--- a/tests/tests/media/src/android/media/cts/FaceDetectorTest.java
+++ b/tests/tests/media/src/android/media/cts/FaceDetectorTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Intent;
diff --git a/tests/tests/media/src/android/media/cts/FaceDetector_FaceTest.java b/tests/tests/media/src/android/media/cts/FaceDetector_FaceTest.java
index 32c68fb..9dc06ec2 100644
--- a/tests/tests/media/src/android/media/cts/FaceDetector_FaceTest.java
+++ b/tests/tests/media/src/android/media/cts/FaceDetector_FaceTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Intent;
diff --git a/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java b/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
index cc28b86..f1b2972 100644
--- a/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
diff --git a/tests/tests/media/src/android/media/cts/JetPlayerTest.java b/tests/tests/media/src/android/media/cts/JetPlayerTest.java
index 4df3555..dce792a 100644
--- a/tests/tests/media/src/android/media/cts/JetPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/JetPlayerTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.res.AssetFileDescriptor;
diff --git a/tests/tests/media/src/android/media/cts/LoudnessEnhancerTest.java b/tests/tests/media/src/android/media/cts/LoudnessEnhancerTest.java
index 5b4d1aa..7c36588 100644
--- a/tests/tests/media/src/android/media/cts/LoudnessEnhancerTest.java
+++ b/tests/tests/media/src/android/media/cts/LoudnessEnhancerTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.media.audiofx.AudioEffect;
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java b/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
index 02bdd7f..3e8458b 100644
--- a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
@@ -33,7 +33,7 @@
private static final long TIME_OUT_MS = 3000L;
private static final long WAIT_TIME_FOR_NO_RESPONSE_MS = 500L;
private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
- "com.android.cts.media", "android.media.cts.StubMediaBrowserService");
+ "android.media.cts", "android.media.cts.StubMediaBrowserService");
private final Object mWaitLock = new Object();
private final MediaBrowser.ConnectionCallback mConnectionCallback =
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserTest.java b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
index 7dd978f..40a86c0 100644
--- a/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
@@ -30,7 +30,7 @@
// The maximum time to wait for an operation.
private static final long TIME_OUT_MS = 3000L;
private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
- "com.android.cts.media", "android.media.cts.StubMediaBrowserService");
+ "android.media.cts", "android.media.cts.StubMediaBrowserService");
private static final ComponentName TEST_INVALID_BROWSER_SERVICE = new ComponentName(
"invalid.package", "invalid.ServiceClassName");
private final StubConnectionCallback mConnectionCallback = new StubConnectionCallback();
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index 71cbd61..5b2936b 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -185,6 +185,7 @@
if (!checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileBaseline, AVCLevel3)) {
return; // skip
}
+
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=18&source=youtube&user=android-device-test"
+ "&sparams=ip,ipbits,expire,id,itag,source,user"
@@ -198,6 +199,7 @@
if (!checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileHigh, AVCLevel31)) {
return; // skip
}
+
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=22&source=youtube&user=android-device-test"
+ "&sparams=ip,ipbits,expire,id,itag,source,user"
@@ -215,6 +217,7 @@
MediaUtils.skipTest(TAG, "fragmented mp4 not supported");
return;
}
+
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=137&source=youtube&user=android-device-test"
+ "&sparams=ip,ipbits,expire,id,itag,source,user"
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index d3ab54f..d6709dd 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.res.AssetFileDescriptor;
import android.cts.util.MediaUtils;
diff --git a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
index 9db54ff..9958e26 100644
--- a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 54e6ef1..751e3d8 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
diff --git a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
index 0f664a5..562feba 100644
--- a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
@@ -27,7 +27,7 @@
import android.test.AndroidTestCase;
import android.util.Log;
-import com.android.cts.media.R;
+import android.media.cts.R;
import java.io.File;
import java.io.IOException;
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
index 640083f..147bce4 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
@@ -46,7 +46,7 @@
* from an HTTP server over a simulated "flaky" network.
*/
public class MediaPlayerFlakyNetworkTest extends MediaPlayerTestBase {
- private static final String PKG = "com.android.cts.media";
+ private static final String PKG = "android.media.cts";
private static final String[] TEST_VIDEOS = {
"raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz",
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceStubActivity.java b/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceStubActivity.java
index c47995c..779a808 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceStubActivity.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceStubActivity.java
@@ -15,7 +15,7 @@
*/
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.app.Activity;
import android.content.res.AssetFileDescriptor;
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceTest.java
index fc81cac..ae314d2 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceTest.java
@@ -24,12 +24,12 @@
public class MediaPlayerSurfaceTest extends ActivityInstrumentationTestCase2<MediaPlayerSurfaceStubActivity> {
public MediaPlayerSurfaceTest() {
- super("com.android.cts.media", MediaPlayerSurfaceStubActivity.class);
+ super("android.media.cts", MediaPlayerSurfaceStubActivity.class);
}
public void testSetSurface() throws Exception {
Bundle extras = new Bundle();
- MediaPlayerSurfaceStubActivity activity = launchActivity("com.android.cts.media",
+ MediaPlayerSurfaceStubActivity activity = launchActivity("android.media.cts",
MediaPlayerSurfaceStubActivity.class, extras);
activity.playVideo();
activity.finish();
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 861df41..bcc1e8d 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -15,13 +15,13 @@
*/
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.cts.util.MediaUtils;
-import android.hardware.Camera;
+import android.graphics.Rect;
import android.media.AudioManager;
import android.media.MediaCodec;
import android.media.MediaDataSource;
@@ -50,7 +50,6 @@
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.List;
import java.util.StringTokenizer;
import java.util.UUID;
import java.util.Vector;
@@ -81,6 +80,8 @@
private File mOutFile;
+ private int mBoundsCount;
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -860,34 +861,15 @@
return getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
- private Camera mCamera;
private void testRecordedVideoPlaybackWithAngle(int angle) throws Exception {
- int width = RECORDED_VIDEO_WIDTH;
- int height = RECORDED_VIDEO_HEIGHT;
+ final int width = RECORDED_VIDEO_WIDTH;
+ final int height = RECORDED_VIDEO_HEIGHT;
final String file = RECORDED_FILE;
final long durationMs = RECORDED_DURATION_MS;
if (!hasCamera()) {
return;
}
-
- boolean isSupported = false;
- mCamera = Camera.open(0);
- Camera.Parameters parameters = mCamera.getParameters();
- List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
- for (Camera.Size size : previewSizes)
- {
- if (size.width == width && size.height == height) {
- isSupported = true;
- break;
- }
- }
- mCamera.release();
- mCamera = null;
- if (!isSupported) {
- width = previewSizes.get(0).width;
- height = previewSizes.get(0).height;
- }
checkOrientation(angle);
recordVideo(width, height, angle, file, durationMs);
checkDisplayedVideoSize(width, height, angle, file);
@@ -1347,6 +1329,7 @@
mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+ mBoundsCount = 0;
mMediaPlayer.setOnTimedTextListener(new MediaPlayer.OnTimedTextListener() {
@Override
public void onTimedText(MediaPlayer mp, TimedText text) {
@@ -1371,6 +1354,13 @@
mSelectedTimedTextIndex, subtitleTrackIndex);
mOnTimedTextCalled.signal();
}
+ Rect bounds = text.getBounds();
+ if (bounds != null) {
+ Log.d(LOG_TAG, "bounds: " + bounds);
+ mBoundsCount++;
+ Rect expected = new Rect(0, 0, 352, 288);
+ assertEquals("wrong bounds", expected, bounds);
+ }
}
}
});
@@ -1427,6 +1417,8 @@
mOnTimedTextCalled.reset();
assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2500) >= 2);
mMediaPlayer.stop();
+
+ assertEquals("Wrong bounds count", 2, mBoundsCount);
}
public void testGetTrackInfo() throws Throwable {
diff --git a/tests/tests/media/src/android/media/cts/MediaRandomTest.java b/tests/tests/media/src/android/media/cts/MediaRandomTest.java
index e928a8f..a8fc703 100644
--- a/tests/tests/media/src/android/media/cts/MediaRandomTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRandomTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.media.MediaRecorder;
import android.media.MediaPlayer;
@@ -158,7 +158,7 @@
}
public MediaRandomTest() {
- super("com.android.cts.media", MediaStubActivity.class);
+ super("android.media.cts", MediaStubActivity.class);
}
private void loadSource(int resid) throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index 4c90e56..e7ae935 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -90,7 +90,7 @@
private ConditionVariable mMaxFileSizeCond;
public MediaRecorderTest() {
- super("com.android.cts.media", MediaStubActivity.class);
+ super("android.media.cts", MediaStubActivity.class);
OUTPUT_PATH = new File(Environment.getExternalStorageDirectory(),
"record.out").getAbsolutePath();
OUTPUT_PATH2 = new File(Environment.getExternalStorageDirectory(),
@@ -392,6 +392,17 @@
return 1;
}
+ public void testRecordAudioFromAudioSourceUnprocessed() throws Exception {
+ if (!hasMicrophone()) {
+ return; // skip
+ }
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.UNPROCESSED);
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ mMediaRecorder.setOutputFile(OUTPUT_PATH);
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
+ recordMedia(MAX_FILE_SIZE, mOutFile);
+ }
+
public void testGetAudioSourceMax() throws Exception {
final int max = MediaRecorder.getAudioSourceMax();
assertTrue(MediaRecorder.AudioSource.DEFAULT <= max);
@@ -402,6 +413,7 @@
assertTrue(MediaRecorder.AudioSource.VOICE_DOWNLINK <= max);
assertTrue(MediaRecorder.AudioSource.VOICE_RECOGNITION <= max);
assertTrue(MediaRecorder.AudioSource.VOICE_UPLINK <= max);
+ assertTrue(MediaRecorder.AudioSource.UNPROCESSED <= max);
}
public void testRecorderAudio() throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java b/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
index ddf87b8..0272298 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.ComponentName;
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerTest.java b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
index af7cfaa..ce93cb1 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.ComponentName;
import android.content.ContentResolver;
diff --git a/tests/tests/media/src/android/media/cts/MediaStubActivity.java b/tests/tests/media/src/android/media/cts/MediaStubActivity.java
index df6d736..48dde25 100644
--- a/tests/tests/media/src/android/media/cts/MediaStubActivity.java
+++ b/tests/tests/media/src/android/media/cts/MediaStubActivity.java
@@ -15,7 +15,7 @@
*/
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/media/src/android/media/cts/MediaSyncTest.java b/tests/tests/media/src/android/media/cts/MediaSyncTest.java
index de5a5f5..e211682 100644
--- a/tests/tests/media/src/android/media/cts/MediaSyncTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSyncTest.java
@@ -15,7 +15,7 @@
*/
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.content.pm.PackageManager;
diff --git a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
index e7b08e9..deb561b 100644
--- a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
diff --git a/tests/tests/media/src/android/media/cts/ParamsTest.java b/tests/tests/media/src/android/media/cts/ParamsTest.java
index 5e32828..113be32 100644
--- a/tests/tests/media/src/android/media/cts/ParamsTest.java
+++ b/tests/tests/media/src/android/media/cts/ParamsTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.media.PlaybackParams;
import android.media.SyncParams;
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTest.java b/tests/tests/media/src/android/media/cts/ResourceManagerTest.java
index 7305651..5f16bc5 100644
--- a/tests/tests/media/src/android/media/cts/ResourceManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/ResourceManagerTest.java
@@ -23,13 +23,13 @@
extends ActivityInstrumentationTestCase2<ResourceManagerStubActivity> {
public ResourceManagerTest() {
- super("com.android.cts.media", ResourceManagerStubActivity.class);
+ super("android.media.cts", ResourceManagerStubActivity.class);
}
private void doTestReclaimResource(int type1, int type2) throws Exception {
Bundle extras = new Bundle();
ResourceManagerStubActivity activity = launchActivity(
- "com.android.cts.media", ResourceManagerStubActivity.class, extras);
+ "android.media.cts", ResourceManagerStubActivity.class, extras);
activity.testReclaimResource(type1, type2);
activity.finish();
}
diff --git a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
index 4693036..0045577 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
@@ -15,7 +15,7 @@
*/
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.app.Activity;
@@ -34,7 +34,7 @@
public class RingtoneManagerTest
extends ActivityInstrumentationTestCase2<RingtonePickerActivity> {
- private static final String PKG = "com.android.cts.media";
+ private static final String PKG = "android.media.cts";
private static final String TAG = "RingtoneManagerTest";
private RingtonePickerActivity mActivity;
diff --git a/tests/tests/media/src/android/media/cts/SoundPoolAacTest.java b/tests/tests/media/src/android/media/cts/SoundPoolAacTest.java
index a5eaf6b..9e37e39 100644
--- a/tests/tests/media/src/android/media/cts/SoundPoolAacTest.java
+++ b/tests/tests/media/src/android/media/cts/SoundPoolAacTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
public class SoundPoolAacTest extends SoundPoolTest {
diff --git a/tests/tests/media/src/android/media/cts/SoundPoolMidiTest.java b/tests/tests/media/src/android/media/cts/SoundPoolMidiTest.java
index a8c640e..d7900e1 100644
--- a/tests/tests/media/src/android/media/cts/SoundPoolMidiTest.java
+++ b/tests/tests/media/src/android/media/cts/SoundPoolMidiTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
public class SoundPoolMidiTest extends SoundPoolTest {
diff --git a/tests/tests/media/src/android/media/cts/SoundPoolOggTest.java b/tests/tests/media/src/android/media/cts/SoundPoolOggTest.java
index d35a93e..70330be 100644
--- a/tests/tests/media/src/android/media/cts/SoundPoolOggTest.java
+++ b/tests/tests/media/src/android/media/cts/SoundPoolOggTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
public class SoundPoolOggTest extends SoundPoolTest {
diff --git a/tests/tests/media/src/android/media/cts/SoundPoolTest.java b/tests/tests/media/src/android/media/cts/SoundPoolTest.java
index 23c4a7c..9022731 100644
--- a/tests/tests/media/src/android/media/cts/SoundPoolTest.java
+++ b/tests/tests/media/src/android/media/cts/SoundPoolTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index ce61d76..0464cb6 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -80,6 +80,7 @@
+ ".443B81C1E8E6D64E4E1555F568BA46C206507D78"
+ "&key=ik0&user=android-device-test", 176, 144);
}
+
public void testHTTP_H263_AMR_Video2() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_H263, MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
return; // skip
@@ -105,6 +106,7 @@
+ ".7138CE5E36D718220726C1FC305497FF2D082249"
+ "&key=ik0&user=android-device-test", 176, 144);
}
+
public void testHTTP_MPEG4SP_AAC_Video2() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
return; // skip
@@ -130,6 +132,7 @@
+ ".15F46C382C68A9F121BA17BF1F56BEDEB4B06091"
+ "&key=ik0&user=android-device-test", 640, 360);
}
+
public void testHTTP_H264Base_AAC_Video2() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
return; // skip
diff --git a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
index 8797b9b..b999847 100644
--- a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
@@ -36,7 +36,7 @@
import com.android.cts.util.ResultType;
import com.android.cts.util.ResultUnit;
-import com.android.cts.util.Stat;
+import com.android.compatibility.common.util.Stat;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -475,16 +475,16 @@
352, 288, true /* isGoog */);
}
- public void testHEVC0720x0480Other() throws Exception {
+ public void testHEVC0640x0360Other() throws Exception {
decode(VIDEO_HEVC,
- R.raw.video_720x480_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz,
- 720, 480, false /* isGoog */);
+ R.raw.video_640x360_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz,
+ 640, 360, false /* isGoog */);
}
- public void testHEVC0720x0480Goog() throws Exception {
+ public void testHEVC0640x0360Goog() throws Exception {
decode(VIDEO_HEVC,
- R.raw.video_720x480_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz,
- 720, 480, true /* isGoog */);
+ R.raw.video_640x360_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz,
+ 640, 360, true /* isGoog */);
}
public void testHEVC1280x0720Other() throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/VideoEditorTest.java b/tests/tests/media/src/android/media/cts/VideoEditorTest.java
index 37a8246..c1097f8 100644
--- a/tests/tests/media/src/android/media/cts/VideoEditorTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoEditorTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.test.ActivityInstrumentationTestCase2;
diff --git a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
index fb1521d..79b7543 100644
--- a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.media.cts.CodecUtils;
@@ -57,7 +57,7 @@
private static final long INIT_TIMEOUT_MS = 2000;
private static final String SOURCE_URL =
- "android.resource://com.android.cts.media/raw/video_480x360_mp4_h264_871kbps_30fps";
+ "android.resource://android.media.cts/raw/video_480x360_mp4_h264_871kbps_30fps";
private final boolean DEBUG = false;
diff --git a/tests/tests/media/src/android/media/cts/VideoSurfaceView.java b/tests/tests/media/src/android/media/cts/VideoSurfaceView.java
index 229c6f6..76c3015 100644
--- a/tests/tests/media/src/android/media/cts/VideoSurfaceView.java
+++ b/tests/tests/media/src/android/media/cts/VideoSurfaceView.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import java.io.IOException;
diff --git a/tests/tests/media/src/android/media/cts/VirtualizerTest.java b/tests/tests/media/src/android/media/cts/VirtualizerTest.java
index ac8eb84..0fc9f31 100644
--- a/tests/tests/media/src/android/media/cts/VirtualizerTest.java
+++ b/tests/tests/media/src/android/media/cts/VirtualizerTest.java
@@ -24,7 +24,7 @@
import android.test.AndroidTestCase;
import android.util.Log;
-import com.android.cts.media.R;
+import android.media.cts.R;
import java.util.Arrays;
diff --git a/tests/tests/media/src/android/media/cts/VisualizerTest.java b/tests/tests/media/src/android/media/cts/VisualizerTest.java
index 0d46ca7..141e339 100644
--- a/tests/tests/media/src/android/media/cts/VisualizerTest.java
+++ b/tests/tests/media/src/android/media/cts/VisualizerTest.java
@@ -16,7 +16,7 @@
package android.media.cts;
-import com.android.cts.media.R;
+import android.media.cts.R;
import android.content.Context;
import android.media.audiofx.AudioEffect;
diff --git a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
index 133b91d..0395ec7 100644
--- a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
+++ b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
@@ -30,7 +30,7 @@
import android.os.Handler;
import android.test.AndroidTestCase;
import android.util.Log;
-import com.android.cts.media.R;
+import android.media.cts.R;
import java.io.File;
import java.io.FileInputStream;
diff --git a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java b/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
index be7e721..5552f6c 100644
--- a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
@@ -21,7 +21,7 @@
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.util.Log;
-import com.android.cts.media.R;
+import android.media.cts.R;
import java.io.File;
import java.util.ArrayList;
diff --git a/tests/tests/mediastress/Android.mk b/tests/tests/mediastress/Android.mk
index d78ddac..38d8bf6 100644
--- a/tests/tests/mediastress/Android.mk
+++ b/tests/tests/mediastress/Android.mk
@@ -20,11 +20,16 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# Include both the 32 and 64 bit versions
LOCAL_MULTILIB := both
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
+LOCAL_HOST_SHARED_LIBRARIES := compatibility-device-media-preconditions
+
LOCAL_JNI_SHARED_LIBRARIES := libctsmediastress_jni
LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -33,8 +38,6 @@
LOCAL_SDK_VERSION := current
-cts_runtime_hint := 170
-
include $(BUILD_CTS_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/mediastress/AndroidManifest.xml b/tests/tests/mediastress/AndroidManifest.xml
index 9d48c8c..e4ab36c 100644
--- a/tests/tests/mediastress/AndroidManifest.xml
+++ b/tests/tests/mediastress/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.mediastress">
+ package="android.mediastress.cts">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -40,7 +40,7 @@
android:label="NativeMedia" />
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.mediastress"
+ android:targetPackage="android.mediastress.cts"
android:label="Media stress tests InstrumentationRunner" >
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/mediastress/AndroidTest.xml b/tests/tests/mediastress/AndroidTest.xml
new file mode 100644
index 0000000..43eae94
--- /dev/null
+++ b/tests/tests/mediastress/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Media Stress test cases">
+ <target_preparer class="android.mediastress.cts.preconditions.MediaPreparer" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsMediaStressTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.mediastress.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/mediastress/preconditions/Android.mk b/tests/tests/mediastress/preconditions/Android.mk
new file mode 100644
index 0000000..5838386
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/Android.mk
@@ -0,0 +1,34 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := compatibility-host-util cts-tradefed_v2 tradefed-prebuilt
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := compatibility-host-media-preconditions
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
new file mode 100644
index 0000000..ab5b65d
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
@@ -0,0 +1,363 @@
+/*
+ * 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.
+ */
+package android.mediastress.cts.preconditions;
+
+import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
+import com.android.compatibility.common.util.DynamicConfigHostSide;
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.Log;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.ZipUtil;
+
+import java.awt.Dimension;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipFile;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * Ensures that the appropriate media files exist on the device
+ */
+@OptionClass(alias="media-preparer")
+public class MediaPreparer extends PreconditionPreparer {
+
+ @Option(name = "local-media-path",
+ description = "Absolute path of the media files directory, containing" +
+ "'bbb_short' and 'bbb_full' directories")
+ protected String mLocalMediaPath = null;
+
+ @Option(name = "skip-media-download",
+ description = "Whether to skip the media files precondition")
+ protected boolean mSkipMediaDownload = false;
+
+ /*
+ * The default name of local directory into which media files will be downloaded, if option
+ * "local-media-path" is not provided. This directory will live inside the temp directory.
+ */
+ protected static final String MEDIA_FOLDER_NAME = "android-cts-media";
+
+ /* The key used to retrieve the media files URL from the dynamic configuration */
+ private static final String MEDIA_FILES_URL_KEY = "MediaFilesUrl";
+
+ /* For a target preparer, the "module" of the configuration is the test suite */
+ private static final String DYNAMIC_CONFIG_MODULE = "cts_v2";
+
+ /*
+ * The message printed when the maximum video playback resolution cannot be found in the
+ * output of 'dumpsys'. When this is the case, media files of all resolutions must be pushed
+ * to the device.
+ */
+ private static final String MAX_PLAYBACK_RES_FAILURE_MSG =
+ "Unable to parse maximum video playback resolution, pushing all media files";
+
+ private static final String LOG_TAG = MediaPreparer.class.getSimpleName();
+
+ /* Constants identifying resolutions of the media files to be copied */
+ protected static final int RES_176_144 = 0; // 176x144 resolution
+ protected static final int RES_DEFAULT = 1; // default max video playback resolution, 480x360
+ protected static final int RES_720_480 = 2; // 720x480 resolution
+ protected static final int RES_1280_720 = 3; // 1280x720 resolution
+ protected static final int RES_1920_1080 = 4; // 1920x1080 resolution
+
+ protected static final Dimension[] resolutions = { // indices meant to align with constants above
+ new Dimension(176, 144),
+ new Dimension(480, 360),
+ new Dimension(720, 480),
+ new Dimension(1280, 720),
+ new Dimension(1920, 1080)
+ };
+
+ /*
+ * The pathnames of the device's directories that hold media files for the tests.
+ * These depend on the device's mount point, which is retrieved in the MediaPreparer's run
+ * method.
+ *
+ * These fields are exposed for unit testing
+ */
+ protected String baseDeviceShortDir;
+ protected String baseDeviceFullDir;
+
+ /*
+ * Returns a string representation of the dimension
+ * For dimension of width = 480 and height = 360, the resolution string is "480x360"
+ */
+ private static String resolutionString(Dimension resolution) {
+ return String.format("%dx%d", resolution.width, resolution.height);
+ }
+
+ /*
+ * Loops through the predefined maximum video playback resolutions from largest to smallest,
+ * And returns the greatest resolution that is strictly smaller than the width and height
+ * provided in the arguments
+ */
+ private Dimension getMaxVideoPlaybackResolution(int width, int height) {
+ for (int resIndex = resolutions.length - 1; resIndex >= RES_DEFAULT; resIndex--) {
+ Dimension resolution = resolutions[resIndex];
+ if (width >= resolution.width && height >= resolution.height) {
+ return resolution;
+ }
+ }
+ return resolutions[RES_DEFAULT];
+ }
+
+ /*
+ * Returns the maximum video playback resolution of the device, in the form of a Dimension
+ * object. This method parses dumpsys output to find resolutions listed under the
+ * 'mBaseDisplayInfo' field. The value for 'smallest app' is used as an estimate for
+ * maximum video playback resolution, and is rounded down to the nearest dimension in the
+ * resolutions array.
+ *
+ * This method is exposed for unit testing.
+ */
+ protected Dimension getMaxVideoPlaybackResolution(ITestDevice device)
+ throws DeviceNotAvailableException {
+ String dumpsysOutput =
+ device.executeShellCommand("dumpsys display | grep mBaseDisplayInfo");
+ Pattern pattern = Pattern.compile("smallest app (\\d+) x (\\d+)");
+ Matcher matcher = pattern.matcher(dumpsysOutput);
+ if(!matcher.find()) {
+ // could not find resolution in dumpsysOutput, return largest max playback resolution
+ // so that preparer copies all media files
+ CLog.e(MAX_PLAYBACK_RES_FAILURE_MSG);
+ return resolutions[RES_1920_1080];
+ }
+
+ int first;
+ int second;
+ try {
+ first = Integer.parseInt(matcher.group(1));
+ second = Integer.parseInt(matcher.group(2));
+ } catch (NumberFormatException e) {
+ CLog.e(MAX_PLAYBACK_RES_FAILURE_MSG);
+ return resolutions[RES_1920_1080];
+ }
+ // dimensions in dumpsys output seem consistently reversed
+ // here we make note of which dimension is the larger of the two
+ int height = Math.min(first, second);
+ int width = Math.max(first, second);
+ return getMaxVideoPlaybackResolution(width, height);
+ }
+
+ /*
+ * Returns true if all necessary media files exist on the device, and false otherwise.
+ *
+ * This method is exposed for unit testing.
+ */
+ protected boolean mediaFilesExistOnDevice(ITestDevice device, Dimension mvpr)
+ throws DeviceNotAvailableException{
+ int resIndex = RES_176_144;
+ while (resIndex <= RES_1920_1080) {
+ Dimension copiedResolution = resolutions[resIndex];
+ if (copiedResolution.width > mvpr.width || copiedResolution.height > mvpr.height) {
+ break; // we don't need to check for resolutions greater than or equal to this
+ }
+ String resString = resolutionString(copiedResolution);
+ String deviceShortFilePath = baseDeviceShortDir + resString;
+ String deviceFullFilePath = baseDeviceFullDir + resString;
+ if (!device.doesFileExist(deviceShortFilePath) ||
+ !device.doesFileExist(deviceFullFilePath)) { // media files must be copied
+ return false;
+ }
+ resIndex++;
+ }
+ return true;
+ }
+
+ /* A simple helper to print messages to the tradefed console */
+ private static void printInfo(String info) {
+ LogUtil.printLog(Log.LogLevel.INFO, LOG_TAG, info);
+ }
+
+ /*
+ * After downloading and unzipping the media files, mLocalMediaPath must be the path to the
+ * directory containing 'bbb_short' and 'bbb_full' directories, as it is defined in its
+ * description as an option.
+ * After extraction, this directory exists one level below the the directory 'mediaFolder'.
+ * If the 'mediaFolder' contains anything other than exactly one subdirectory, a
+ * TargetSetupError is thrown. Otherwise, the mLocalMediaPath variable is set to the path of
+ * this subdirectory.
+ */
+ private void updateLocalMediaPath(File mediaFolder) throws TargetSetupError {
+ String[] subDirs = mediaFolder.list();
+ if (subDirs.length != 1) {
+ throw new TargetSetupError(String.format(
+ "Unexpected contents in directory %s", mLocalMediaPath));
+ }
+ File newMediaFolder = new File(mediaFolder, subDirs[0]);
+ mLocalMediaPath = newMediaFolder.toString();
+ }
+
+ /*
+ * Copies the media files to the host from a predefined URL
+ * Updates mLocalMediaPath to be the pathname of the directory containing bbb_short and
+ * bbb_full media directories.
+ */
+ private void downloadMediaToHost() throws TargetSetupError {
+
+ URL url;
+ try {
+ DynamicConfigHostSide config = new DynamicConfigHostSide(DYNAMIC_CONFIG_MODULE);
+ String mediaUrlString = config.getConfig(MEDIA_FILES_URL_KEY);
+ url = new URL(mediaUrlString);
+ } catch (IOException | XmlPullParserException e) {
+ throw new TargetSetupError("Trouble finding media file download location with " +
+ "dynamic configuration");
+ }
+
+ File mediaFolder = new File(mLocalMediaPath);
+ File mediaFolderZip = new File(mediaFolder.getName() + ".zip");
+ try {
+
+ mediaFolder.mkdirs();
+ mediaFolderZip.createNewFile();
+
+ URLConnection conn = url.openConnection();
+ InputStream in = conn.getInputStream();
+ BufferedOutputStream out =
+ new BufferedOutputStream(new FileOutputStream(mediaFolderZip));
+ byte[] buffer = new byte[1024];
+ int count;
+ printInfo("Downloading media files to host");
+ while ((count = in.read(buffer)) >= 0) {
+ out.write(buffer, 0, count);
+ }
+ out.flush();
+ out.close();
+ in.close();
+
+ printInfo("Unzipping media files");
+ ZipUtil.extractZip(new ZipFile(mediaFolderZip), mediaFolder);
+
+ } catch (IOException e) {
+ FileUtil.recursiveDelete(mediaFolder);
+ FileUtil.recursiveDelete(mediaFolderZip);
+ throw new TargetSetupError("Failed to open media files on host");
+ }
+ }
+
+ /*
+ * Pushes directories containing media files to the device for all directories that:
+ * - are not already present on the device
+ * - contain video files of a resolution less than or equal to the device's
+ * max video playback resolution
+ *
+ * This method is exposed for unit testing.
+ */
+ protected void copyMediaFiles(ITestDevice device, Dimension mvpr)
+ throws DeviceNotAvailableException {
+
+ int resIndex = RES_176_144;
+ while (resIndex <= RES_1920_1080) {
+ Dimension copiedResolution = resolutions[resIndex];
+ String resString = resolutionString(copiedResolution);
+ if (copiedResolution.width > mvpr.width || copiedResolution.height > mvpr.height) {
+ printInfo(String.format(
+ "Device cannot support resolutions %s and larger, media copying complete",
+ resString));
+ return;
+ }
+ String deviceShortFilePath = baseDeviceShortDir + resString;
+ String deviceFullFilePath = baseDeviceFullDir + resString;
+ if (!device.doesFileExist(deviceShortFilePath) ||
+ !device.doesFileExist(deviceFullFilePath)) {
+ printInfo(String.format("Copying files of resolution %s to device", resString));
+ String localShortDirName = "bbb_short/" + resString;
+ String localFullDirName = "bbb_full/" + resString;
+ File localShortDir = new File(mLocalMediaPath, localShortDirName);
+ File localFullDir = new File(mLocalMediaPath, localFullDirName);
+ // push short directory of given resolution, if not present on device
+ if(!device.doesFileExist(deviceShortFilePath)) {
+ device.pushDir(localShortDir, deviceShortFilePath);
+ }
+ // push full directory of given resolution, if not present on device
+ if(!device.doesFileExist(deviceFullFilePath)) {
+ device.pushDir(localFullDir, deviceFullFilePath);
+ }
+ }
+ resIndex++;
+ }
+ }
+
+ // Initialize directory strings where media files live on device
+ protected void setMountPoint(ITestDevice device) {
+ String mountPoint = device.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
+ baseDeviceShortDir = String.format("%s/test/bbb_short/", mountPoint);
+ baseDeviceFullDir = String.format("%s/test/bbb_full/", mountPoint);
+ }
+
+ @Override
+ public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+ BuildError, DeviceNotAvailableException {
+
+ if (mSkipMediaDownload) {
+ // skip this precondition
+ return;
+ }
+
+ setMountPoint(device);
+ Dimension mvpr = getMaxVideoPlaybackResolution(device);
+ if (mediaFilesExistOnDevice(device, mvpr)) {
+ // if files already on device, do nothing
+ printInfo("Media files found on the device");
+ return;
+ }
+
+ File mediaFolder;
+ if (mLocalMediaPath == null) {
+ // Option 'local-media-path' has not been defined
+ try {
+ // find system's temp directory, create folder MEDIA_FOLDER_NAME inside
+ File tmpFile = File.createTempFile(MEDIA_FOLDER_NAME, null);
+ String tmpDir = tmpFile.getParent();
+ mediaFolder = new File(tmpDir, MEDIA_FOLDER_NAME);
+ // delete temp file used for locating temp directory
+ tmpFile.delete();
+ } catch (IOException e) {
+ throw new TargetSetupError("Unable to create host temp directory for media files");
+ }
+ mLocalMediaPath = mediaFolder.getAbsolutePath();
+ if(!mediaFolder.exists()){
+ // directory has not been created by previous runs of MediaPreparer
+ // download media into mLocalMediaPath
+ downloadMediaToHost();
+ }
+ updateLocalMediaPath(mediaFolder);
+ }
+
+ printInfo(String.format("Media files located on host at: %s", mLocalMediaPath));
+ copyMediaFiles(device, mvpr);
+ }
+
+}
diff --git a/tests/tests/mediastress/preconditions/tests/Android.mk b/tests/tests/mediastress/preconditions/tests/Android.mk
new file mode 100644
index 0000000..48fdcfc
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/tests/Android.mk
@@ -0,0 +1,31 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := easymock
+
+LOCAL_JAVA_LIBRARIES := compatibility-host-util cts-tradefed_v2 tradefed-prebuilt compatibility-host-media-preconditions
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := compatibility-host-media-preconditions-tests
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tests/tests/mediastress/preconditions/tests/run_tests.sh b/tests/tests/mediastress/preconditions/tests/run_tests.sh
new file mode 100755
index 0000000..1a47caf
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/tests/run_tests.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# 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.
+
+# Helper script for running unit tests for compatibility libraries
+
+CTS_DIR=$(dirname ${0})/../../../../..
+source ${CTS_DIR}/test_defs.sh
+
+JARS="
+ compatibility-host-util\
+ cts-tradefed_v2\
+ compatibility-host-media-preconditions\
+ compatibility-host-media-preconditions-tests"
+
+run_tests "android.mediastress.cts.preconditions.MediaPreparerTest" "${JARS}" "${@}"
diff --git a/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java b/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java
new file mode 100644
index 0000000..54ab025
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+package android.mediastress.cts.preconditions;
+
+import com.android.ddmlib.IDevice;
+import com.android.tradefed.build.BuildInfo;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.awt.Dimension;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+
+public class MediaPreparerTest extends TestCase {
+
+ private MediaPreparer mMediaPreparer;
+ private IBuildInfo mMockBuildInfo;
+ private ITestDevice mMockDevice;
+ private OptionSetter mOptionSetter;
+
+ private final Dimension DEFAULT_DIMENSION =
+ MediaPreparer.resolutions[MediaPreparer.RES_DEFAULT];
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mMediaPreparer = new MediaPreparer();
+ mMockDevice = EasyMock.createMock(ITestDevice.class);
+ mMockBuildInfo = new BuildInfo("0", "", "");
+ mOptionSetter = new OptionSetter(mMediaPreparer);
+ }
+
+ public void testSetMountPoint() throws Exception {
+ EasyMock.expect(mMockDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE)).andReturn(
+ "/sdcard").once();
+ EasyMock.replay(mMockDevice);
+ mMediaPreparer.setMountPoint(mMockDevice);
+ assertEquals(mMediaPreparer.baseDeviceShortDir, "/sdcard/test/bbb_short/");
+ assertEquals(mMediaPreparer.baseDeviceFullDir, "/sdcard/test/bbb_full/");
+ }
+
+ public void testCopyMediaFiles() throws Exception {
+ // by jumping directly into copyMediaFiles, the baseDeviceShortDir variable won't be set
+ // thus, the string "null" replaces the variable
+ EasyMock.expect(mMockDevice.doesFileExist("null176x144")).andReturn(true).anyTimes();
+ EasyMock.expect(mMockDevice.doesFileExist("null480x360")).andReturn(true).anyTimes();
+ EasyMock.replay(mMockDevice);
+ mMediaPreparer.copyMediaFiles(mMockDevice, DEFAULT_DIMENSION);
+ }
+
+ public void testMediaFilesExistOnDeviceTrue() throws Exception {
+ // by jumping directly into copyMediaFiles, the baseDeviceShortDir variable won't be set
+ // thus, the string "null" replaces the variable
+ EasyMock.expect(mMockDevice.doesFileExist("null176x144")).andReturn(true).anyTimes();
+ EasyMock.expect(mMockDevice.doesFileExist("null480x360")).andReturn(true).anyTimes();
+ EasyMock.replay(mMockDevice);
+ assertTrue(mMediaPreparer.mediaFilesExistOnDevice(mMockDevice, DEFAULT_DIMENSION));
+ }
+
+ public void testMediaFilesExistOnDeviceFalse() throws Exception {
+ // by jumping directly into copyMediaFiles, the baseDeviceShortDir variable won't be set
+ // thus, the string "null" replaces the variable
+ EasyMock.expect(mMockDevice.doesFileExist("null176x144")).andReturn(false).anyTimes();
+ EasyMock.expect(mMockDevice.doesFileExist("null480x360")).andReturn(true).anyTimes();
+ EasyMock.replay(mMockDevice);
+ assertFalse(mMediaPreparer.mediaFilesExistOnDevice(mMockDevice, DEFAULT_DIMENSION));
+ }
+
+ public void testGetMaxVideoPlaybackResolutionFound() throws Exception {
+ String mockDumpsysOutput = "mBaseDisplayInfo=DisplayInfo{\"Built-in Screen\", uniqueId " +
+ "\"local:0\", app 1440 x 2560, real 1440 x 2560, largest app 1440 x 2560, " +
+ "smallest app 360 x 480, mode 1, defaultMode 1, modes [{id=1, width=1440, " +
+ "height=2560, fps=60.0}], rotation 0, density 560 (494.27 x 492.606) dpi, " +
+ "layerStack 0, appVsyncOff 2500000, presDeadline 17666667, type BUILT_IN, state " +
+ "ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}\n";
+ EasyMock.expect(mMockDevice.executeShellCommand(
+ "dumpsys display | grep mBaseDisplayInfo")).andReturn(mockDumpsysOutput).once();
+ EasyMock.replay(mMockDevice);
+ Dimension result = mMediaPreparer.getMaxVideoPlaybackResolution(mMockDevice);
+ assertEquals(result, DEFAULT_DIMENSION);
+ }
+
+ public void testGetMaxVideoPlaybackResolutionNotFound() throws Exception {
+ String mockDumpsysOutput = "incorrect output";
+ EasyMock.expect(mMockDevice.executeShellCommand(
+ "dumpsys display | grep mBaseDisplayInfo")).andReturn(mockDumpsysOutput).once();
+ EasyMock.replay(mMockDevice);
+ Dimension result = mMediaPreparer.getMaxVideoPlaybackResolution(mMockDevice);
+ assertEquals(result, MediaPreparer.resolutions[MediaPreparer.RES_1920_1080]);
+ }
+
+ public void testSkipMediaDownload() throws Exception {
+ mOptionSetter.setOptionValue("skip-media-download", "true");
+ EasyMock.replay();
+ mMediaPreparer.run(mMockDevice, mMockBuildInfo);
+ }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java
index d39bc16..68d1e51 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java
@@ -27,7 +27,7 @@
import android.view.SurfaceHolder;
import android.view.SurfaceView;
-import com.android.cts.mediastress.R;
+import android.mediastress.cts.R;
public class MediaFrameworkTest extends Activity implements SurfaceHolder.Callback {
private static String TAG = "MediaFrameworkTest";
diff --git a/tests/tests/midi/Android.mk b/tests/tests/midi/Android.mk
index f202933..10ecdf1 100755
--- a/tests/tests/midi/Android.mk
+++ b/tests/tests/midi/Android.mk
@@ -22,6 +22,9 @@
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/midi/AndroidTest.xml b/tests/tests/midi/AndroidTest.xml
new file mode 100644
index 0000000..c95ab89
--- /dev/null
+++ b/tests/tests/midi/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS MIDI test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsMidiTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.midi.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/nativemedia/Android.mk b/tests/tests/nativemedia/Android.mk
index 5053e7d..ba2da56 100644
--- a/tests/tests/nativemedia/Android.mk
+++ b/tests/tests/nativemedia/Android.mk
@@ -1 +1,15 @@
+# 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.
+
include $(call all-subdir-makefiles)
diff --git a/tests/tests/nativemedia/sl/Android.mk b/tests/tests/nativemedia/sl/Android.mk
index 28dfeff..32241f3 100644
--- a/tests/tests/nativemedia/sl/Android.mk
+++ b/tests/tests/nativemedia/sl/Android.mk
@@ -1,8 +1,22 @@
+# 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.
+
# Build the unit tests.
LOCAL_PATH:= $(call my-dir)
-test_executable := NativeMediaTest_SL
+test_executable := CtsNativeMediaSlTestCases
list_executable := $(test_executable)_list
include $(CLEAR_VARS)
@@ -33,6 +47,10 @@
libgtest
LOCAL_CTS_TEST_PACKAGE := android.nativemedia.sl
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_EXECUTABLE)
include $(CLEAR_VARS)
diff --git a/tests/tests/nativemedia/sl/AndroidTest.xml b/tests/tests/nativemedia/sl/AndroidTest.xml
new file mode 100644
index 0000000..c73c1b4
--- /dev/null
+++ b/tests/tests/nativemedia/sl/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<configuration description="Config for CTS Native Media Open SL ES test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="CtsNativeMediaSlTestCases->/data/local/tmp/CtsNativeMediaSlTestCases" />
+ <option name="append-bitness" value="true" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="CtsNativeMediaSlTestCases" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/nativemedia/xa/Android.mk b/tests/tests/nativemedia/xa/Android.mk
index 52126c3..1d3608f 100644
--- a/tests/tests/nativemedia/xa/Android.mk
+++ b/tests/tests/nativemedia/xa/Android.mk
@@ -1,8 +1,22 @@
+# 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.
+
# Build the unit tests.
LOCAL_PATH:= $(call my-dir)
-test_executable := NativeMediaTest_XA
+test_executable := CtsNativeMediaXaTestCases
list_executable := $(test_executable)_list
include $(CLEAR_VARS)
@@ -32,6 +46,10 @@
libgtest \
LOCAL_CTS_TEST_PACKAGE := android.nativemedia.xa
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_EXECUTABLE)
include $(CLEAR_VARS)
diff --git a/tests/tests/nativemedia/xa/AndroidTest.xml b/tests/tests/nativemedia/xa/AndroidTest.xml
new file mode 100644
index 0000000..229d8aa
--- /dev/null
+++ b/tests/tests/nativemedia/xa/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<configuration description="Config for CTS Native Media OpenMax AL test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="CtsNativeMediaXaTestCases->/data/local/tmp/CtsNativeMediaXaTestCases" />
+ <option name="append-bitness" value="true" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="CtsNativeMediaXaTestCases" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/nativeopengl/Android.mk b/tests/tests/nativeopengl/Android.mk
deleted file mode 100644
index d2192ad..0000000
--- a/tests/tests/nativeopengl/Android.mk
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsNativeOpenGLTestCases
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-# Include both the 32 and 64 bit versions
-LOCAL_MULTILIB := both
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctswrappedgtest
-
-LOCAL_JNI_SHARED_LIBRARIES := libnativeopengltests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_GTEST_PACKAGE)
-
-# Include the associated library's makefile.
-include $(LOCAL_PATH)/libnativeopengltests/Android.mk
diff --git a/tests/tests/nativeopengl/AndroidManifest.xml b/tests/tests/nativeopengl/AndroidManifest.xml
deleted file mode 100644
index 72d87ac..0000000
--- a/tests/tests/nativeopengl/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 2013 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.
- */
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.opengl.cts">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- <activity android:name="com.android.opengl.cts.GLTestActivity"/>
- </application>
-
- <!-- This is a self-instrumenting test package. -->
- <instrumentation android:name="GLTestInstrumentation"
- android:targetPackage="com.android.opengl.cts"
- android:label="Native OpenGL tests">
- </instrumentation>
-</manifest>
diff --git a/tests/tests/nativeopengl/CtsNativeOpenGLTestCases_list.txt b/tests/tests/nativeopengl/CtsNativeOpenGLTestCases_list.txt
deleted file mode 100644
index 8daf3b2..0000000
--- a/tests/tests/nativeopengl/CtsNativeOpenGLTestCases_list.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-EGLCleanupTest.
- TestCorrect
-EGLCreateContextTest.
- BadAttributeFails
-GLTest.
- ClearColorTest
diff --git a/tests/tests/nativeopengl/libnativeopengltests/Android.mk b/tests/tests/nativeopengl/libnativeopengltests/Android.mk
deleted file mode 100644
index 9338d8b..0000000
--- a/tests/tests/nativeopengl/libnativeopengltests/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2012 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.
-
-#
-# This is the shared library included by the JNI test app.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libnativeopengltests
-
-# Don't include this package in any configuration by default.
-LOCAL_MODULE_TAGS := optional
-
-my_src_dir := ../standalone/jni
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/$(my_src_dir) \
- external/gtest/include
-
-# The sources are in ../standalone/jni/
-LOCAL_SRC_FILES := $(addprefix $(my_src_dir)/, \
- register.cpp \
- GLTestHelper.cpp \
- tests/GLTest_test.cpp \
- tests/EGLCleanup_test.cpp \
- tests/EGLCreateContext_test.cpp \
- )
-
-LOCAL_CXX_STL := libc++
-LOCAL_SHARED_LIBRARIES := libEGL \
- libGLESv2 \
- libandroid \
- liblog \
-
-LOCAL_STATIC_LIBRARIES := libgtest
-
-my_src_dir :=
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestActivity.java b/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestActivity.java
deleted file mode 100644
index 1633a93..0000000
--- a/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestActivity.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2012 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 com.android.opengl.cts;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.os.Bundle;
-import android.test.wrappedgtest.WrappedGTestActivity;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.Surface;
-
-public class GLTestActivity extends WrappedGTestActivity {
-
- private SurfaceView mSurfaceView;
- private SurfaceHolder.Callback mHolderCallback = new SurfaceHolder.Callback() {
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- setSurface(holder.getSurface());
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- setSurface(holder.getSurface());
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- }
- };
-
- public void onCreate(Bundle data) {
- super.onCreate(data);
- mSurfaceView = new SurfaceView(this);
- mSurfaceView.getHolder().addCallback(mHolderCallback);
- setContentView(mSurfaceView);
- System.loadLibrary("nativeopengltests");
- }
-
- private static native void setSurface(Surface surface);
-}
diff --git a/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestInstrumentation.java b/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestInstrumentation.java
deleted file mode 100644
index 913f0eb..0000000
--- a/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestInstrumentation.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2012 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 com.android.opengl.cts;
-
-import android.test.wrappedgtest.WrappedGTestInstrumentation;
-
-/**
- * adb shell am instrument -w com.android.opengl.cts/.GLTestInstrumentation
- */
-public class GLTestInstrumentation extends WrappedGTestInstrumentation {
- public GLTestInstrumentation() {
- mActivityClass = GLTestActivity.class;
- }
-}
diff --git a/tests/tests/nativeopengl/standalone/.gitignore b/tests/tests/nativeopengl/standalone/.gitignore
deleted file mode 100644
index 1d1cdd2..0000000
--- a/tests/tests/nativeopengl/standalone/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-bin/
-build.xml
-gen/
-libs/
-local.properties
-obj/
-proguard-project.txt
-project.properties
diff --git a/tests/tests/nativeopengl/standalone/AndroidManifest.xml b/tests/tests/nativeopengl/standalone/AndroidManifest.xml
deleted file mode 100644
index 9092f69..0000000
--- a/tests/tests/nativeopengl/standalone/AndroidManifest.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 2013 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.
- */
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.gltest"
- android:versionCode="1"
- android:versionName="1.0"
- android:debuggable="true" >
-
- <uses-sdk
- android:minSdkVersion="8"
- android:targetSdkVersion="15" />
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-
- <application android:label="NativeGLTest">
- <activity android:name=".GLTestActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
-</manifest>
diff --git a/tests/tests/nativeopengl/standalone/jni/Android.mk b/tests/tests/nativeopengl/standalone/jni/Android.mk
deleted file mode 100644
index 53d9bbf..0000000
--- a/tests/tests/nativeopengl/standalone/jni/Android.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2013 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.
-#
-
-MY_LOCAL_PATH := $(call my-dir)
-MY_GTEST_PATH := $(MY_LOCAL_PATH)/../../../../../../external/gtest
-
-# gtest
-
-LOCAL_PATH := $(MY_GTEST_PATH)
-
-include $(CLEAR_VARS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_MODULE := libgtest
-LOCAL_C_INCLUDES := $(MY_GTEST_PATH)/include
-LOCAL_SRC_FILES := src/gtest-all.cc
-
-include $(BUILD_STATIC_LIBRARY)
-
-# nativetests
-
-LOCAL_PATH := $(MY_LOCAL_PATH)
-
-include $(CLEAR_VARS)
-
-LIB_PATH := $(LOCAL_PATH)/../libs/$(TARGET_ARCH_ABI)/
-LOCAL_C_INCLUDES := $(MY_GTEST_PATH)/include
-LOCAL_LDLIBS := -L$(LIB_PATH) -landroid -lEGL -lGLESv2 -llog
-LOCAL_STATIC_LIBRARIES := libgtest
-LOCAL_MODULE := nativeopengltests
-LOCAL_SRC_FILES := GLTestHelper.cpp \
- register.cpp \
- tests/GLTest_test.cpp \
- tests/EGLCleanup_test.cpp \
- tests/EGLCreateContext_test.cpp
-
-LOCAL_SHARED_LIBRARIES := libgtest
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/nativeopengl/standalone/jni/Application.mk b/tests/tests/nativeopengl/standalone/jni/Application.mk
deleted file mode 100644
index 76d05a7..0000000
--- a/tests/tests/nativeopengl/standalone/jni/Application.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2013 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.
-#
-
-APP_STL := stlport_shared
diff --git a/tests/tests/nativeopengl/standalone/jni/GLTestHelper.cpp b/tests/tests/nativeopengl/standalone/jni/GLTestHelper.cpp
deleted file mode 100644
index d1f29d5..0000000
--- a/tests/tests/nativeopengl/standalone/jni/GLTestHelper.cpp
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#define LOG_TAG "GLTest"
-#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
-#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
-
-#include <android/log.h>
-#include <android/native_window.h>
-#include <GLTestHelper.h>
-
-// this listener is used to forward the subset of
-// gtest output needed to generate CTS results
-class CTSGTestListener : public EmptyTestEventListener {
-public:
- CTSGTestListener(JNIEnv *env, jobject activity)
- : mActivity(activity), mEnv(env) {
-
- jclass clazz = env->FindClass(
- "android/test/wrappedgtest/WrappedGTestActivity");
- mSendStatusID = env->GetMethodID(clazz, "sendStatus",
- "(Ljava/lang/String;)V");
- mMessageBuffer = new char[2048];
- }
-
- ~CTSGTestListener() {
- delete[] mMessageBuffer;
- }
-
-private:
- jobject mActivity;
- JNIEnv * mEnv;
- jmethodID mSendStatusID;
- char * mMessageBuffer;
-
- virtual void OnTestIterationStart(const UnitTest& unit_test,
- int iteration) {
- snprintf(mMessageBuffer, sizeof(char) * 2048,
- "[==========] Running %i tests from %i test cases.",
- unit_test.test_to_run_count(),
- unit_test.test_case_to_run_count());
-
- mEnv->CallVoidMethod(mActivity, mSendStatusID,
- mEnv->NewStringUTF(mMessageBuffer));
- }
-
- virtual void OnTestStart(const TestInfo& test_info) {
- snprintf(mMessageBuffer, sizeof(char) * 2048, "[ RUN ] %s.%s",
- test_info.test_case_name(), test_info.name());
-
- mEnv->CallVoidMethod(mActivity, mSendStatusID,
- mEnv->NewStringUTF(mMessageBuffer));
- }
-
- virtual void OnTestPartResult(const TestPartResult& result) {
- if (result.type() == TestPartResult::kSuccess) {
- return;
- }
-
- snprintf(mMessageBuffer, sizeof(char) * 2048, "%s:%i: Failure\n%s",
- result.file_name(), result.line_number(), result.message());
-
- mEnv->CallVoidMethod(mActivity, mSendStatusID,
- mEnv->NewStringUTF(mMessageBuffer));
- }
-
- virtual void OnTestEnd(const TestInfo& test_info) {
- const char * result = test_info.result()->Passed() ?
- "[ OK ] " : "[ FAILED ] ";
-
- snprintf(mMessageBuffer, sizeof(char) * 2048, "%s%s.%s (%lli ms)",
- result, test_info.test_case_name(), test_info.name(),
- test_info.result()->elapsed_time());
-
- mEnv->CallVoidMethod(mActivity, mSendStatusID,
- mEnv->NewStringUTF(mMessageBuffer));
- }
-
- virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) {
- snprintf(mMessageBuffer, sizeof(char) * 2048,
- "[==========] %i tests from %i test cases ran. (%lli ms total)",
- unit_test.test_to_run_count(),
- unit_test.test_case_to_run_count(), unit_test.elapsed_time());
-
- mEnv->CallVoidMethod(mActivity, mSendStatusID,
- mEnv->NewStringUTF(mMessageBuffer));
- }
-};
-
-// this listener is similar to the default gtest listener
-// but it outputs the results to the log instead of stdout
-class LogGTestListener : public EmptyTestEventListener {
-
-private:
- virtual void OnTestIterationStart(const UnitTest& unit_test,
- int iteration) {
- LOGI("[==========] Running %i tests from %i test cases.\n",
- unit_test.test_to_run_count(),
- unit_test.test_case_to_run_count());
- }
-
- virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) {
- LOGI("[==========] Global test environment set-up.\n");
- }
-
- virtual void OnTestCaseStart(const TestCase& test_case) {
- LOGI("[----------] %i tests from %s\n",
- test_case.test_to_run_count(),
- test_case.name());
-
- }
-
- virtual void OnTestStart(const TestInfo& test_info) {
- LOGI("[ RUN ] %s.%s\n", test_info.test_case_name(),
- test_info.name());
-
- }
-
- virtual void OnTestPartResult(const TestPartResult& result) {
- if (result.type() == TestPartResult::kSuccess) {
- return;
- }
-
- LOGI("%s:%i: Failure\n%s\n", result.file_name(), result.line_number(),
- result.message());
- }
-
- virtual void OnTestEnd(const TestInfo& test_info) {
- const char * result = test_info.result()->Passed() ?
- "[ OK ] " : "[ FAILED ] ";
-
- LOGI("%s%s.%s (%lli ms)\n", result, test_info.test_case_name(),
- test_info.name(), test_info.result()->elapsed_time());
- }
-
-
- virtual void OnTestCaseEnd(const TestCase& test_case) {
- LOGI("[----------] %i tests from %s (%lli ms total)\n",
- test_case.test_to_run_count(), test_case.name(),
- test_case.elapsed_time());
-
- }
-
- virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) {
- LOGI("[==========] Global test environment tear-down.\n");
- }
-
- void PrintFailedTests(const UnitTest& unit_test) {
- const int failed_test_count = unit_test.failed_test_count();
- if (failed_test_count == 0) {
- return;
- }
-
- for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
- const TestCase& test_case = *unit_test.GetTestCase(i);
-
- if (!test_case.should_run() || test_case.failed_test_count() == 0) {
- continue;
- }
-
- for (int j = 0; j < test_case.total_test_count(); ++j) {
- const TestInfo& test_info = *test_case.GetTestInfo(j);
- if (!test_info.should_run() || test_info.result()->Passed()) {
- continue;
- }
- LOGI("[ FAILED ] %s.%s\n", test_case.name(),
- test_info.name());
- }
- }
- }
- virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) {
- LOGI("[==========] %i tests from %i test cases ran. (%lli ms total)\n",
- unit_test.test_to_run_count(),
- unit_test.test_case_to_run_count(), unit_test.elapsed_time());
-
- LOGI("[ PASSED ] %i tests\n", unit_test.successful_test_count());
-
- if(unit_test.Passed()) {
- return;
- }
-
- LOGI("[ FAILED ] %i tests, listed below:\n",
- unit_test.failed_test_count());
-
- PrintFailedTests(unit_test);
-
- LOGI("\n%2d FAILED TESTS\n", unit_test.failed_test_count());
- }
-};
-
-ANativeWindow* GLTestHelper::mWindow;
-
-ANativeWindow* GLTestHelper::getWindow() {
- return mWindow;
-}
-
-void GLTestHelper::setWindow(JNIEnv *env, jobject obj, jobject surface) {
- mWindow = ANativeWindow_fromSurface(env, surface);
-}
-
-int GLTestHelper::runGTests(TestEventListener * listener, char * filter) {
-
- if (filter) {
- ::testing::GTEST_FLAG(filter) = filter;
- }
-
- int argc = 0;
- InitGoogleTest(&argc, (char**)NULL);
-
- TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
- delete listeners.Release(listeners.default_result_printer());
-
- listeners.Append(listener);
- int result = RUN_ALL_TESTS();
- return result;
-}
-
-int GLTestHelper::runTests(JNIEnv *env, jobject obj, jstring filter) {
- LogGTestListener * listener = new LogGTestListener();
-
- char * filter_cstr = NULL;
-
- // set filter if there is one
- if (filter) {
- filter_cstr = new char[512];
- const char * ptr = env->GetStringUTFChars(filter, NULL);
- snprintf(filter_cstr, sizeof(char) * 512, "%s", ptr);
- env->ReleaseStringUTFChars(filter, ptr);
- }
-
- int result = runGTests(listener, filter_cstr);
-
- if (filter_cstr) {
- delete[] filter_cstr;
- }
-
- delete listener;
- return result;
-}
-
-int GLTestHelper::runTestsCTS(JNIEnv *env, jobject obj, jobject activity) {
- CTSGTestListener * listener = new CTSGTestListener(env, activity);
- int result = runGTests(listener, NULL);
- delete listener;
- return result;
-}
-
-int GLTestHelper::registerNative(JNIEnv * env) {
-
- jclass clazz = env->FindClass("com/android/opengl/cts/GLTestActivity");
-
- jthrowable exception = env->ExceptionOccurred();
- // CTS class not found, assume stand-alone application
- if (exception) {
- env->ExceptionClear();
-
- if (!env->IsInstanceOf(env->ExceptionOccurred(),
- env->FindClass("java/lang/NoClassDefFoundError"))) {
- env->Throw(exception);
- }
-
- //
- JNINativeMethod standaloneMethods[] = {
- // name, signature, function
- { "setSurface", "(Landroid/view/Surface;)V", (void*)(GLTestHelper::setWindow) },
- { "runTests", "(Ljava/lang/String;)V", (void*)(GLTestHelper::runTests) },
- };
-
- return env->RegisterNatives(
- env->FindClass("com/android/gltest/GLTestActivity"),
- standaloneMethods,
- sizeof(standaloneMethods) / sizeof(JNINativeMethod));
- }
-
- // GLTestActivity methods
- JNINativeMethod glTestActMethods[] = {
- // name, signature, function
- { "setSurface", "(Landroid/view/Surface;)V", (void*)(GLTestHelper::setWindow) },
- };
-
- int result = env->RegisterNatives(clazz, glTestActMethods,
- sizeof(glTestActMethods) / sizeof(JNINativeMethod));
-
- if (result) {
- return result;
- }
-
- // WrappedGTestActivity methods
- JNINativeMethod wrappedGTestActMethods[] = {
- // name, signature, function
- { "runTests", "(Landroid/test/wrappedgtest/WrappedGTestActivity;)I",
- (void*)(GLTestHelper::runTestsCTS) },
- };
-
- return env->RegisterNatives(
- env->FindClass("android/test/wrappedgtest/WrappedGTestActivity"),
- wrappedGTestActMethods,
- sizeof(wrappedGTestActMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/tests/nativeopengl/standalone/jni/GLTestHelper.h b/tests/tests/nativeopengl/standalone/jni/GLTestHelper.h
deleted file mode 100644
index d09d2f1..0000000
--- a/tests/tests/nativeopengl/standalone/jni/GLTestHelper.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#ifndef ANDROID_GL_TEST_HELPER_H
-#define ANDROID_GL_TEST_HELPER_H
-
-#include <android/native_window_jni.h>
-#include <gtest/gtest.h>
-
-using namespace testing;
-
-class GLTestHelper
-{
-private:
- static ANativeWindow* mWindow;
- static int runGTests(TestEventListener* listener, char * filter);
- static int runTests(JNIEnv* env, jobject obj, jstring filter);
- static int runTestsCTS(JNIEnv* env, jobject obj, jobject activity);
-public:
- static ANativeWindow* getWindow();
- static void setWindow(JNIEnv* env, jobject obj, jobject surface);
- static int registerNative(JNIEnv* env);
-};
-
-
-
-#endif // ANDROID_GL_TEST_HELPER_H
diff --git a/tests/tests/nativeopengl/standalone/jni/register.cpp b/tests/tests/nativeopengl/standalone/jni/register.cpp
deleted file mode 100644
index 8dd14ed..0000000
--- a/tests/tests/nativeopengl/standalone/jni/register.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#include <jni.h>
-#include <GLTestHelper.h>
-
-/*
- * This function is called automatically by the system when this
- * library is loaded. We use it to register all our native functions,
- * which is the recommended practice for Android.
- */
-jint JNI_OnLoad(JavaVM *vm, void *reserved) {
- JNIEnv *env = NULL;
-
- if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
- return JNI_ERR;
- }
-
- if (GLTestHelper::registerNative(env)) {
- return JNI_ERR;
- }
-
- return JNI_VERSION_1_4;
-}
diff --git a/tests/tests/nativeopengl/standalone/jni/tests/EGLCleanup_test.cpp b/tests/tests/nativeopengl/standalone/jni/tests/EGLCleanup_test.cpp
deleted file mode 100644
index 2daa2fe..0000000
--- a/tests/tests/nativeopengl/standalone/jni/tests/EGLCleanup_test.cpp
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#define LOG_TAG "EGLCleanup"
-#include <android/log.h>
-#include <jni.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include <gtest/gtest.h>
-
-#include <GLTestHelper.h>
-
-#include <pthread.h>
-
-#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-
-namespace android {
-
-/**
- * Tests EGL cleanup edge cases.
- */
-class EGLCleanupTest : public ::testing::Test {
-protected:
- EGLCleanupTest() {}
-
- virtual void SetUp() {
- // Termination of a terminated display is defined to be a no-op.
- // Android uses a refcounted implementation, so terminate it a few
- // times to make sure it's really dead. Without this, we might not
- // get all the way into the driver eglTerminate implementation
- // when we call eglTerminate.
- EGLDisplay disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (disp != EGL_NO_DISPLAY) {
- ALOGD("speculative terminate");
- eglTerminate(disp);
- eglTerminate(disp);
- eglTerminate(disp);
- }
- }
- virtual void TearDown() {}
-};
-
-/**
- * Perform an operation and then start a new thread.
- *
- * The trick here is that some code may be helpfully releasing storage in
- * pthread_key destructors. Those run after the thread returns out of the
- * initial function, but before the thread fully exits. We want them to
- * run concurrently with the next thread's initialization so we can confirm
- * that the specified behavior of eglTerminate vs. eglInitialize holds.
- */
-class ChainedThread {
-public:
- enum TestType {
- TEST_CORRECT,
- TEST_NO_RELEASE_CURRENT
- };
-
- ChainedThread(TestType testType) : mEglDisplay(EGL_NO_DISPLAY),
- mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT),
- mTestType(testType), mIteration(0), mResult(true) {
- pthread_mutex_init(&mLock, NULL);
- pthread_cond_init(&mCond, NULL);
- }
- ~ChainedThread() {
- // could get fancy and clean up the mutex
- }
-
- /* start here */
- bool start() {
- lock();
- bool result = startThread_l();
- unlock();
- return result;
- }
-
- /* waits until test is done; when finished, call getResult() */
- bool waitForEnd() {
- lock();
- int err = pthread_cond_wait(&mCond, &mLock);
- if (err != 0) {
- ALOGW("pthread_cond_wait failed: %d", err);
- }
- unlock();
- return err == 0;
- }
-
- /* returns the result; true means success */
- bool getResult() {
- return mResult;
- }
-
-private:
- enum { MAX_ITERATIONS = 450 };
-
- EGLDisplay mEglDisplay;
- EGLSurface mEglSurface;
- EGLContext mEglContext;
-
- TestType mTestType;
- int mIteration;
- bool mResult;
- pthread_mutex_t mLock;
- pthread_cond_t mCond;
-
- // Assertions set a flag in Java and return from the current method (which
- // must be declared to return void). They do not throw a C++ exception.
- //
- // Because we're running in a separate thread, which is not attached to
- // the VM, the assert macros don't help us much. We could attach to the
- // VM (by linking to libdvm.so and calling a global function), but the
- // assertions won't cause the test to stop, which makes them less valuable.
- //
- // So instead we just return a boolean out of functions that can fail.
-
- /* call this to start the test */
- bool startThread_l() {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- pthread_t newThread;
- int err = pthread_create(&newThread, &attr, ChainedThread::func,
- (void*) this);
- return (err == 0);
- }
-
- /* thread entry point */
- static void* func(void* arg) {
- ChainedThread* obj = static_cast<ChainedThread*>(arg);
- obj->doWork();
- return NULL;
- }
-
- bool lock() {
- int err = pthread_mutex_lock(&mLock);
- if (err != 0) {
- ALOGW("pthread_mutex_lock failed: %d", err);
- }
- return err == 0;
- }
-
- bool unlock() {
- int err = pthread_mutex_unlock(&mLock);
- if (err != 0) {
- ALOGW("pthread_mutex_unlock failed: %d", err);
- }
- return err == 0;
- }
-
- /* main worker */
- void doWork() {
- lock();
-
- if ((mIteration % 25) == 0) {
- ALOGD("iteration %d\n", mIteration);
- }
-
- mIteration++;
- bool result = runTest_l();
- if (!result) {
- ALOGW("failed at iteration %d, stopping test", mIteration);
- mResult = false;
- mIteration = MAX_ITERATIONS;
- }
-
- if (mIteration < MAX_ITERATIONS) {
- // still going, try to start the next one
- if (!startThread_l()) {
- ALOGW("Unable to start thread at iter=%d", mIteration);
- mResult = false;
- mIteration = MAX_ITERATIONS;
- }
- }
-
- if (mIteration >= MAX_ITERATIONS) {
- ALOGD("Test ending, signaling main thread");
- pthread_cond_signal(&mCond);
- }
-
- unlock();
- }
-
- /* setup, use, release EGL */
- bool runTest_l() {
- if (!eglSetup()) {
- return false;
- }
- if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
- mEglContext))
- {
- ALOGW("eglMakeCurrent failed: 0x%x", eglGetError());
- return false;
- }
- if (!eglRelease_l()) {
- return false;
- }
-
- return true;
- }
-
- /*
- * Sets up EGL. Creates a 1280x720 pbuffer, which is large enough to
- * cause a rapid and highly visible memory leak if we fail to discard it.
- */
- bool eglSetup() {
- static const EGLint kConfigAttribs[] = {
- EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_NONE
- };
- static const EGLint kContextAttribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
- static const EGLint kPbufferAttribs[] = {
- EGL_WIDTH, 1280,
- EGL_HEIGHT, 720,
- EGL_NONE
- };
-
- //usleep(25000);
-
- mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (mEglDisplay == EGL_NO_DISPLAY) {
- ALOGW("eglGetDisplay failed: 0x%x", eglGetError());
- return false;
- }
-
- EGLint majorVersion, minorVersion;
- if (!eglInitialize(mEglDisplay, &majorVersion, &minorVersion)) {
- ALOGW("eglInitialize failed: 0x%x", eglGetError());
- return false;
- }
-
- EGLConfig eglConfig;
- EGLint numConfigs = 0;
- if (!eglChooseConfig(mEglDisplay, kConfigAttribs, &eglConfig,
- 1, &numConfigs)) {
- ALOGW("eglChooseConfig failed: 0x%x", eglGetError());
- return false;
- }
-
- mEglSurface = eglCreatePbufferSurface(mEglDisplay, eglConfig,
- kPbufferAttribs);
- if (mEglSurface == EGL_NO_SURFACE) {
- ALOGW("eglCreatePbufferSurface failed: 0x%x", eglGetError());
- return false;
- }
-
- mEglContext = eglCreateContext(mEglDisplay, eglConfig, EGL_NO_CONTEXT,
- kContextAttribs);
- if (mEglContext == EGL_NO_CONTEXT) {
- ALOGW("eglCreateContext failed: 0x%x", eglGetError());
- return false;
- }
-
- return true;
- }
-
- /*
- * Releases EGL. How we do that depends on the type of test we're
- * running.
- */
- bool eglRelease_l() {
- if (mEglDisplay == EGL_NO_DISPLAY) {
- ALOGW("No display to release");
- return false;
- }
-
- switch (mTestType) {
- case TEST_CORRECT:
- eglTerminate(mEglDisplay);
- eglReleaseThread();
- break;
- case TEST_NO_RELEASE_CURRENT:
- eglDestroyContext(mEglDisplay, mEglContext);
- eglDestroySurface(mEglDisplay, mEglSurface);
- eglTerminate(mEglDisplay);
- break;
- default:
- ALOGE("Unknown test type %d", mTestType);
- break;
- }
-
- int err = eglGetError();
- if (err != EGL_SUCCESS) {
- ALOGW("eglRelease failed: 0x%x", err);
- return false;
- }
- return true;
- }
-};
-
-
-/* do things correctly */
-TEST_F(EGLCleanupTest, TestCorrect) {
- ALOGI("Starting TEST_CORRECT");
- ChainedThread cht(ChainedThread::TEST_CORRECT);
-
- // start initial thread
- ASSERT_TRUE(cht.start());
-
- // wait for the end
- cht.waitForEnd();
- bool result = cht.getResult();
- ASSERT_TRUE(result);
-}
-
-/* try it without un-currenting the surfaces and context
-TEST _F(EGLCleanupTest, TestNoReleaseCurrent) {
- ALOGI("Starting TEST_NO_RELEASE_CURRENT");
- ChainedThread cht(ChainedThread::TEST_NO_RELEASE_CURRENT);
-
- // start initial thread
- ASSERT_TRUE(cht.start());
-
- // wait for the end
- cht.waitForEnd();
- bool result = cht.getResult();
- ASSERT_TRUE(result);
-}
-*/
-
-} // namespace android
diff --git a/tests/tests/nativeopengl/standalone/jni/tests/EGLCreateContext_test.cpp b/tests/tests/nativeopengl/standalone/jni/tests/EGLCreateContext_test.cpp
deleted file mode 100644
index b7e5f7c..0000000
--- a/tests/tests/nativeopengl/standalone/jni/tests/EGLCreateContext_test.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#include <android/native_window.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-
-#include <gtest/gtest.h>
-
-#include <android/log.h>
-
-#include "GLTestHelper.h"
-
-#define LOG_TAG "EGLCreateContext_test"
-#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
-#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
-
-namespace android {
-
-static int getGlVersion() {
- const char* s = (const char*)glGetString(GL_VERSION);
- if (!s)
- return 0;
- int major, minor;
- if (sscanf(s, "OpenGL ES %d.%d", &major, &minor) != 2)
- return 0;
- return major;
-}
-
-class EGLCreateContextTest : public ::testing::Test {
-
-protected:
-
- EGLCreateContextTest()
- : mEglDisplay(EGL_NO_DISPLAY),
- mEglConfig(0),
- mEglWindowSurface(EGL_NO_SURFACE),
- mEglContext(EGL_NO_CONTEXT)
- {}
-
- virtual void SetUp() {
- // static const EGLint SURFACE_ATTRIBS[] = {
- // EGL_NONE
- // };
-
- mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
-
- EGLint major, minor;
- ASSERT_TRUE(eglInitialize(mEglDisplay, &major, &minor));
-
- EGLint numConfigs = 0;
- ASSERT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(),
- &mEglConfig, 1, &numConfigs));
- ASSERT_GE(1, numConfigs);
- ASSERT_NE((EGLConfig)0, mEglConfig);
-
- mEglWindowSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig,
- GLTestHelper::getWindow(), getWindowSurfaceAttribs());
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_SURFACE, mEglWindowSurface);
- }
-
- virtual void TearDown() {
- if (mEglContext != EGL_NO_CONTEXT) {
- eglDestroyContext(mEglDisplay, mEglContext);
- }
- if (mEglWindowSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mEglDisplay, mEglWindowSurface);
- }
- if (mEglDisplay != EGL_NO_DISPLAY) {
- eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- eglTerminate(mEglDisplay);
- }
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- }
-
- virtual const EGLint* getConfigAttribs() {
- static const EGLint ATTRIBS[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_NONE
- };
- return ATTRIBS;
- }
-
- virtual const EGLint* getWindowSurfaceAttribs() {
- return NULL;
- }
-
- EGLDisplay mEglDisplay;
- EGLConfig mEglConfig;
- EGLSurface mEglWindowSurface;
- EGLContext mEglContext;
-};
-
-TEST_F(EGLCreateContextTest, BadAttributeFails) {
- // First check that we can successfully create a context
- EGLint attribs[5] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE, EGL_NONE, EGL_NONE,
- };
- mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
- attribs);
- ASSERT_NE(mEglContext, EGL_NO_CONTEXT);
- ASSERT_EQ(eglGetError(), EGL_SUCCESS);
- ASSERT_EQ(EGL_TRUE, eglDestroyContext(mEglDisplay, mEglContext));
- mEglContext = EGL_NO_CONTEXT;
-
- // Now add an invalid attribute and make sure eglCreateContext fails
- attribs[2] = EGL_BAD_ATTRIBUTE; // error code, not a valid attribute
- mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
- attribs);
- ASSERT_EQ(mEglContext, EGL_NO_CONTEXT);
- ASSERT_EQ(eglGetError(), EGL_BAD_ATTRIBUTE);
-}
-
-} // namespace android
diff --git a/tests/tests/nativeopengl/standalone/jni/tests/GLTest_test.cpp b/tests/tests/nativeopengl/standalone/jni/tests/GLTest_test.cpp
deleted file mode 100644
index 5df090d..0000000
--- a/tests/tests/nativeopengl/standalone/jni/tests/GLTest_test.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-
-#include <android/native_window.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include <gtest/gtest.h>
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <GLTestHelper.h>
-
-
-namespace android {
-
-class GLTest : public ::testing::Test {
-
-protected:
-
- GLTest():
- mEglDisplay(EGL_NO_DISPLAY),
- mEglSurface(EGL_NO_SURFACE),
- mEglContext(EGL_NO_CONTEXT) {
- }
-
-
- virtual void SetUp() {
- mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
-
- EGLint majorVersion;
- EGLint minorVersion;
- EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- EGLint numConfigs = 0;
- EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
- 1, &numConfigs));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
- if (displaySecsEnv != NULL) {
- mDisplaySecs = atoi(displaySecsEnv);
- if (mDisplaySecs < 0) {
- mDisplaySecs = 0;
- }
- } else {
- mDisplaySecs = 0;
- }
-
- if (mDisplaySecs > 0) {
- mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
- GLTestHelper::getWindow(), NULL);
- } else {
- EGLint pbufferAttribs[] = {
- EGL_WIDTH, getSurfaceWidth(),
- EGL_HEIGHT, getSurfaceHeight(),
- EGL_NONE };
-
- mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
- pbufferAttribs);
- }
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
-
- mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
- getContextAttribs());
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
-
- EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
- mEglContext));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- EGLint w, h;
- EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
- glViewport(0, 0, w, h);
- ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
- }
-
- virtual void TearDown() {
- // Display the result
- if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
- eglSwapBuffers(mEglDisplay, mEglSurface);
- sleep(mDisplaySecs);
- }
-
- if (mEglContext != EGL_NO_CONTEXT) {
- eglDestroyContext(mEglDisplay, mEglContext);
- }
- if (mEglSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mEglDisplay, mEglSurface);
- }
- if (mEglDisplay != EGL_NO_DISPLAY) {
- eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- eglTerminate(mEglDisplay);
- }
- ASSERT_EQ(EGL_SUCCESS, eglGetError());
- }
-
- virtual EGLint const* getConfigAttribs() {
- static EGLint sDefaultConfigAttribs[] = {
- EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 16,
- EGL_STENCIL_SIZE, 8,
- EGL_NONE };
-
- return sDefaultConfigAttribs;
- }
-
- virtual EGLint const* getContextAttribs() {
- static EGLint sDefaultContextAttribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE };
-
- return sDefaultContextAttribs;
- }
-
- virtual EGLint getSurfaceWidth() {
- return 512;
- }
-
- virtual EGLint getSurfaceHeight() {
- return 512;
- }
-
- bool checkPixel(GLubyte * actual, GLubyte * expected, int tolerance) {
- for (int i = 0; i < 4; i++) {
- if (abs(actual[i] - expected[i]) > tolerance) {
- return false;
- }
- }
- return true;
- }
-
- ::testing::AssertionResult AssertPixel(const char* a_expr,
- const char* e_expr, const char* t_expr, GLubyte * actual,
- GLubyte * expected, int tolerance) {
-
- if (checkPixel(actual, expected, tolerance)) {
- return ::testing::AssertionSuccess();
- }
-
- return ::testing::AssertionFailure()
- << "Pixel comparison failed with tolerance " << tolerance << "\n"
- << "Actual: r=" << (int)actual[0] << " g=" << (int)actual[1]
- << " b=" << (int)actual[2] << " a=" << (int)actual[3] << "\n"
- << "Expected: r=" << (int)expected[0] << " g=" << (int)expected[1]
- << " b=" << (int)expected[2] << " a=" << (int)expected[3] << "\n";
- }
-
- int mDisplaySecs;
-
- EGLDisplay mEglDisplay;
- EGLSurface mEglSurface;
- EGLContext mEglContext;
- EGLConfig mGlConfig;
-};
-
-TEST_F(GLTest, ClearColorTest) {
- glClearColor(0.2, 0.2, 0.2, 0.2);
- glClear(GL_COLOR_BUFFER_BIT);
- GLubyte expected[4] = { 51, 51, 51, 51 };
- GLubyte pixel[4];
- glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
- ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
- ASSERT_PRED_FORMAT3(AssertPixel, pixel, expected, 2);
-}
-
-} // namespace android
diff --git a/tests/tests/nativeopengl/standalone/src/com/android/gltest/GLTestActivity.java b/tests/tests/nativeopengl/standalone/src/com/android/gltest/GLTestActivity.java
deleted file mode 100644
index f0c250b..0000000
--- a/tests/tests/nativeopengl/standalone/src/com/android/gltest/GLTestActivity.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2013 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 com.android.gltest;
-
-import android.app.Activity;
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.Surface;
-
-public class GLTestActivity extends Activity {
-
- private class TestThread extends Thread {
-
- public void run() {
- // it is possible to set the GTest filter flag from here
- // for example "GLTest.ClearColorTest" to run that specific test only
- runTests(null);
-
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
-
- finish();
- System.exit(0);
- }
- }
-
- private SurfaceView mSurfaceView;
-
- private SurfaceHolder.Callback mHolderCallback = new SurfaceHolder.Callback() {
-
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- setSurface(holder.getSurface());
- }
-
- public void surfaceCreated(SurfaceHolder holder) {
- setSurface(holder.getSurface());
- Thread t = new TestThread();
- t.start();
- }
-
- public void surfaceDestroyed(SurfaceHolder holder) {
- }
- };
-
- @SuppressWarnings("deprecation")
- @Override
- public void onCreate(Bundle savedInstanceState) {
- if (checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
- == PackageManager.PERMISSION_GRANTED) {
- KeyguardManager keyguardManager =
- (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
- keyguardManager.newKeyguardLock("gltest").disableKeyguard();
- }
-
- super.onCreate(savedInstanceState);
-
- mSurfaceView = new SurfaceView(this);
- mSurfaceView.getHolder().addCallback(mHolderCallback);
- setContentView(mSurfaceView);
- System.loadLibrary("stlport_shared");
- System.loadLibrary("nativeopengltests");
- }
-
- private static native void setSurface(Surface surface);
- private static native void runTests(String filter);
-}
diff --git a/tests/tests/ndef/Android.mk b/tests/tests/ndef/Android.mk
index ba78f29..0c93e80 100644
--- a/tests/tests/ndef/Android.mk
+++ b/tests/tests/ndef/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/ndef/AndroidManifest.xml b/tests/tests/ndef/AndroidManifest.xml
index e0244e1..dcec27d 100644
--- a/tests/tests/ndef/AndroidManifest.xml
+++ b/tests/tests/ndef/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.ndef">
+ package="android.ndef.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -24,7 +24,7 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.ndef"
+ android:targetPackage="android.ndef.cts"
android:label="CTS tests of NDEF data classes">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/ndef/AndroidTest.xml b/tests/tests/ndef/AndroidTest.xml
new file mode 100644
index 0000000..cfb40d3
--- /dev/null
+++ b/tests/tests/ndef/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS NDEF test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsNdefTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.ndef.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/net/Android.mk b/tests/tests/net/Android.mk
index 56729b6..608ea47 100644
--- a/tests/tests/net/Android.mk
+++ b/tests/tests/net/Android.mk
@@ -40,6 +40,9 @@
# uncomment when b/13249961 is fixed
#LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/net/AndroidManifest.xml b/tests/tests/net/AndroidManifest.xml
index 001e294..2bc8216 100644
--- a/tests/tests/net/AndroidManifest.xml
+++ b/tests/tests/net/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.net">
+ package="android.net.cts">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -35,7 +35,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.net"
+ android:targetPackage="android.net.cts"
android:label="CTS tests of android.net">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/net/AndroidTest.xml b/tests/tests/net/AndroidTest.xml
new file mode 100644
index 0000000..dc80339
--- /dev/null
+++ b/tests/tests/net/AndroidTest.xml
@@ -0,0 +1,25 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS Net test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsNetTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.net.cts" />
+ <option name="runtime-hint" value="9m4s" />
+ </test>
+</configuration>
diff --git a/tests/tests/opengl/Android.mk b/tests/tests/opengl/Android.mk
index 3844807..4b02263 100644
--- a/tests/tests/opengl/Android.mk
+++ b/tests/tests/opengl/Android.mk
@@ -35,10 +35,10 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
# Include the associated library's makefile.
include $(LOCAL_PATH)/libopengltest/Android.mk
-
-
-
diff --git a/tests/tests/opengl/AndroidManifest.xml b/tests/tests/opengl/AndroidManifest.xml
index 363b9aa..cc0ab8f 100644
--- a/tests/tests/opengl/AndroidManifest.xml
+++ b/tests/tests/opengl/AndroidManifest.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.opengl"
+ package="android.opengl.cts"
android:versionCode="1"
android:versionName="1.0" >
@@ -23,7 +23,7 @@
<uses-feature android:glEsVersion="0x00020000"/>
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.opengl" >
+ android:targetPackage="android.opengl.cts" >
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/tests/opengl/AndroidTest.xml b/tests/tests/opengl/AndroidTest.xml
new file mode 100644
index 0000000..124d072
--- /dev/null
+++ b/tests/tests/opengl/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS OpenGL test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsOpenGLTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.opengl.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/opengl/libopengltest/Android.mk b/tests/tests/opengl/libopengltest/Android.mk
index a141550..afa94dc 100755
--- a/tests/tests/opengl/libopengltest/Android.mk
+++ b/tests/tests/opengl/libopengltest/Android.mk
@@ -36,6 +36,8 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+LOCAL_CXX_STL := libc++_static
+
LOCAL_SHARED_LIBRARIES := libGLESv2 liblog
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/openglperf/Android.mk b/tests/tests/openglperf/Android.mk
index 9d2d184..8fbb7d1 100644
--- a/tests/tests/openglperf/Android.mk
+++ b/tests/tests/openglperf/Android.mk
@@ -36,6 +36,9 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
# Make the replica island app and copy it to CTS out dir.
diff --git a/tests/tests/openglperf/AndroidManifest.xml b/tests/tests/openglperf/AndroidManifest.xml
index a213e51..9335a65 100644
--- a/tests/tests/openglperf/AndroidManifest.xml
+++ b/tests/tests/openglperf/AndroidManifest.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.openglperf"
+ package="android.openglperf.cts"
android:versionCode="1"
android:versionName="1.0" >
@@ -32,7 +32,7 @@
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
<instrumentation
- android:targetPackage="com.android.cts.openglperf"
+ android:targetPackage="android.openglperf.cts"
android:name="android.support.test.runner.AndroidJUnitRunner">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/openglperf/AndroidTest.xml b/tests/tests/openglperf/AndroidTest.xml
new file mode 100644
index 0000000..630bd05
--- /dev/null
+++ b/tests/tests/openglperf/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<configuration description="Config for CTS OpenGL Performance test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsOpenGlPerfTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.openglperf.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index 3326fb1..0568ef4 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -36,6 +36,9 @@
LOCAL_PACKAGE_NAME := CtsOsTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# uncomment when b/13282254 is fixed
#LOCAL_SDK_VERSION := current
LOCAL_JAVA_LIBRARIES += android.test.runner
diff --git a/tests/tests/os/AndroidTest.xml b/tests/tests/os/AndroidTest.xml
new file mode 100644
index 0000000..1676c88
--- /dev/null
+++ b/tests/tests/os/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Configuration for OS Tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsOsTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.cts.os" />
+ <option name="runtime-hint" value="3m15s" />
+ </test>
+</configuration>
diff --git a/tests/tests/os/src/android/os/cts/MessengerTest.java b/tests/tests/os/src/android/os/cts/MessengerTest.java
index 72bf247..5bf9428 100644
--- a/tests/tests/os/src/android/os/cts/MessengerTest.java
+++ b/tests/tests/os/src/android/os/cts/MessengerTest.java
@@ -30,6 +30,7 @@
import android.os.Messenger;
import android.os.Parcel;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.test.AndroidTestCase;
import java.io.FileDescriptor;
@@ -88,6 +89,11 @@
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
}
+ @Override
+ public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ResultReceiver resultReceiver) {
+ }
+
};
// Create another messenger to send msg.
diff --git a/tests/tests/permission/Android.mk b/tests/tests/permission/Android.mk
index 49cec4d..0b79ceb 100644
--- a/tests/tests/permission/Android.mk
+++ b/tests/tests/permission/Android.mk
@@ -19,6 +19,11 @@
LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# Include both the 32 and 64 bit versions
LOCAL_MULTILIB := both
diff --git a/tests/tests/permission/AndroidManifest.xml b/tests/tests/permission/AndroidManifest.xml
index fa03335..8b08009 100644
--- a/tests/tests/permission/AndroidManifest.xml
+++ b/tests/tests/permission/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.permission">
+ package="android.permission.cts">
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<application>
@@ -41,8 +41,8 @@
relies on hidden APIs.
-->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.permission"
- android:label="CTS tests of com.android.cts.permission">
+ android:targetPackage="android.permission.cts"
+ android:label="CTS tests of android.permission">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/tests/permission/AndroidTest.xml b/tests/tests/permission/AndroidTest.xml
new file mode 100644
index 0000000..f64db70
--- /dev/null
+++ b/tests/tests/permission/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Permission test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPermissionTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.permission.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index d5c5279..d20e550 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -262,6 +262,20 @@
}
@MediumTest
+ public void testProcSelfPagemapNotAccessible() {
+ // Note: can't use f.canRead() here, since the security check is done
+ // during the open() process. access(R_OK) return OK even through
+ // open() eventually fails.
+ try {
+ new FileInputStream("/proc/self/pagemap");
+ fail("Device is missing the following kernel security patch: "
+ + "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=ab676b7d6fbf4b294bf198fb27ade5b0e865c7ce");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+ }
+
+ @MediumTest
public void testTcpDefaultRwndSane() throws Exception {
File f = new File("/proc/sys/net/ipv4/tcp_default_init_rwnd");
assertTrue(f.canRead());
diff --git a/tests/tests/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
index 91ffdf4..72b5530 100644
--- a/tests/tests/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
@@ -38,7 +38,7 @@
private PermissionStubActivity mActivity;
public NoActivityRelatedPermissionTest() {
- super("com.android.cts.permission", PermissionStubActivity.class);
+ super("android.permission.cts", PermissionStubActivity.class);
}
@Override
diff --git a/tests/tests/permission/src/android/permission/cts/RebootPermissionTest.java b/tests/tests/permission/src/android/permission/cts/RebootPermissionTest.java
index 4d54098..2c6e08e 100644
--- a/tests/tests/permission/src/android/permission/cts/RebootPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/RebootPermissionTest.java
@@ -40,6 +40,7 @@
public void testBroadcastReboot() {
try {
mContext.sendBroadcast(new Intent(Intent.ACTION_REBOOT));
+ fail("SecurityException expected!");
} catch (SecurityException e) {
// expected
}
diff --git a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
index 607f301..cfafd9a 100644
--- a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
@@ -17,6 +17,7 @@
package android.permission.cts;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.telephony.TelephonyManager;
@@ -61,6 +62,12 @@
} catch (SecurityException e) {
// expected
}
+ try {
+ String id = mTelephonyManager.getDeviceId(0);
+ fail("Got device ID: " + id);
+ } catch (SecurityException e) {
+ // expected
+ }
}
/**
@@ -159,4 +166,50 @@
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
assertEquals(audioMode, mAudioManager.getMode());
}
+
+ /**
+ * Verify that Telephony related broadcasts are protected.
+ */
+ @SmallTest
+ public void testProtectedBroadcasts() {
+ try {
+ Intent intent = new Intent("android.intent.action.SIM_STATE_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent("android.intent.action.SERVICE_STATE");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent("android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent(
+ "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent(
+ "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent(
+ "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent("android.intent.action.SIG_STR");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+
+ }
}
diff --git a/tests/tests/permission2/Android.mk b/tests/tests/permission2/Android.mk
index 29d5e03..3378cd9 100755
--- a/tests/tests/permission2/Android.mk
+++ b/tests/tests/permission2/Android.mk
@@ -19,6 +19,11 @@
LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_JAVA_LIBRARIES := telephony-common
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
diff --git a/tests/tests/permission2/AndroidManifest.xml b/tests/tests/permission2/AndroidManifest.xml
index 984d124..6429dab 100755
--- a/tests/tests/permission2/AndroidManifest.xml
+++ b/tests/tests/permission2/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.permission2">
+ package="android.permission2.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -63,7 +63,7 @@
android:maxSdkVersion="9000" />
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.permission2"
+ android:targetPackage="android.permission2.cts"
android:label="More CTS tests for permissions">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/permission2/AndroidTest.xml b/tests/tests/permission2/AndroidTest.xml
new file mode 100644
index 0000000..b814aa7
--- /dev/null
+++ b/tests/tests/permission2/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS Permission test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPermission2TestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.permission2.cts" />
+ <option name="runtime-hint" value="2m" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/preference/Android.mk b/tests/tests/preference/Android.mk
index 7534641..398571f 100644
--- a/tests/tests/preference/Android.mk
+++ b/tests/tests/preference/Android.mk
@@ -20,6 +20,9 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/preference/AndroidManifest.xml b/tests/tests/preference/AndroidManifest.xml
index 3cc3ef8..e5fd710 100644
--- a/tests/tests/preference/AndroidManifest.xml
+++ b/tests/tests/preference/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.preference">
+ package="android.preference.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -28,8 +28,8 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.preference"
- android:label="CTS tests of android.os">
+ android:targetPackage="android.preference.cts"
+ android:label="CTS tests of android.preference">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/tests/preference/AndroidTest.xml b/tests/tests/preference/AndroidTest.xml
new file mode 100644
index 0000000..f9074fe
--- /dev/null
+++ b/tests/tests/preference/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Preference test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPreferenceTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.preference.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/preference/src/android/preference/cts/PreferenceActivityTest.java b/tests/tests/preference/src/android/preference/cts/PreferenceActivityTest.java
index 51ebc7d..162f200 100644
--- a/tests/tests/preference/src/android/preference/cts/PreferenceActivityTest.java
+++ b/tests/tests/preference/src/android/preference/cts/PreferenceActivityTest.java
@@ -16,7 +16,7 @@
package android.preference.cts;
-import com.android.cts.preference.R;
+import android.preference.cts.R;
import android.content.Intent;
import android.preference.PreferenceActivity;
@@ -69,4 +69,4 @@
assertEquals(prefScreen, mActivity.getPreferenceScreen());
}
-}
\ No newline at end of file
+}
diff --git a/tests/tests/preference2/Android.mk b/tests/tests/preference2/Android.mk
index 59fedc8..8dabf2c 100644
--- a/tests/tests/preference2/Android.mk
+++ b/tests/tests/preference2/Android.mk
@@ -22,6 +22,9 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/preference2/AndroidManifest.xml b/tests/tests/preference2/AndroidManifest.xml
index 2dbd53a..8d2b823 100644
--- a/tests/tests/preference2/AndroidManifest.xml
+++ b/tests/tests/preference2/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.preference2">
+ package="android.preference2.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -36,8 +36,8 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.preference2"
- android:label="CTS Test Cases for android.preference">
+ android:targetPackage="android.preference2.cts"
+ android:label="CTS Test Cases for android.preference2">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/tests/preference2/AndroidTest.xml b/tests/tests/preference2/AndroidTest.xml
new file mode 100644
index 0000000..96dfe0e
--- /dev/null
+++ b/tests/tests/preference2/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Preference test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPreference2TestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.preference2.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/preference2/res/xml/pref_cb.xml b/tests/tests/preference2/res/xml/pref_cb.xml
index b5f77b9..73dc3d8 100755
--- a/tests/tests/preference2/res/xml/pref_cb.xml
+++ b/tests/tests/preference2/res/xml/pref_cb.xml
@@ -13,7 +13,7 @@
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:in="http://schemas.android.com/apk/res/com.android.cts.preference2" >
+ xmlns:in="http://schemas.android.com/apk/res/android.preference2.cts" >
<PreferenceCategory android:title="@string/inline_preferences" >
<android.preference2.cts.CustomCheckBoxPreference
diff --git a/tests/tests/preference2/src/android/preference2/cts/CheckBoxPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/CheckBoxPreferenceTest.java
index de129e0..cf8bfde 100644
--- a/tests/tests/preference2/src/android/preference2/cts/CheckBoxPreferenceTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/CheckBoxPreferenceTest.java
@@ -19,7 +19,7 @@
import android.preference.CheckBoxPreference;
import android.test.ActivityInstrumentationTestCase2;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
public class CheckBoxPreferenceTest
extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreference.java b/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreference.java
index d51eddd..64cc360 100644
--- a/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreference.java
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreference.java
@@ -15,7 +15,7 @@
*/
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.content.Context;
import android.content.res.TypedArray;
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreference.java b/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreference.java
index db584ac..20346b1 100644
--- a/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreference.java
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreference.java
@@ -15,7 +15,7 @@
*/
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.content.Context;
import android.content.res.TypedArray;
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreference.java b/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreference.java
index 51fdf13..007f475 100644
--- a/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreference.java
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreference.java
@@ -15,7 +15,7 @@
*/
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.content.Context;
import android.content.res.TypedArray;
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomPreference.java b/tests/tests/preference2/src/android/preference2/cts/CustomPreference.java
index 7506bd0..4875acc1 100644
--- a/tests/tests/preference2/src/android/preference2/cts/CustomPreference.java
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomPreference.java
@@ -15,7 +15,7 @@
*/
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.content.Context;
import android.content.res.TypedArray;
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomPreferenceGroup.java b/tests/tests/preference2/src/android/preference2/cts/CustomPreferenceGroup.java
index 26e1bcf..c4771d3 100644
--- a/tests/tests/preference2/src/android/preference2/cts/CustomPreferenceGroup.java
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomPreferenceGroup.java
@@ -15,7 +15,7 @@
*/
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.content.Context;
import android.content.res.TypedArray;
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreference.java b/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreference.java
index 54e7861..6793c50 100644
--- a/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreference.java
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreference.java
@@ -16,7 +16,7 @@
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.content.Context;
import android.content.res.TypedArray;
diff --git a/tests/tests/preference2/src/android/preference2/cts/DialogPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/DialogPreferenceTest.java
index 1136cee..edcef0c 100644
--- a/tests/tests/preference2/src/android/preference2/cts/DialogPreferenceTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/DialogPreferenceTest.java
@@ -20,7 +20,7 @@
import android.preference.DialogPreference;
import android.test.ActivityInstrumentationTestCase2;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
public class DialogPreferenceTest
extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
diff --git a/tests/tests/preference2/src/android/preference2/cts/FragmentPreferences.java b/tests/tests/preference2/src/android/preference2/cts/FragmentPreferences.java
index dacc192..7efbe76 100644
--- a/tests/tests/preference2/src/android/preference2/cts/FragmentPreferences.java
+++ b/tests/tests/preference2/src/android/preference2/cts/FragmentPreferences.java
@@ -16,7 +16,7 @@
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/preference2/src/android/preference2/cts/ListPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/ListPreferenceTest.java
index 32596ff..743b51e 100644
--- a/tests/tests/preference2/src/android/preference2/cts/ListPreferenceTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/ListPreferenceTest.java
@@ -19,7 +19,7 @@
import android.preference.ListPreference;
import android.test.ActivityInstrumentationTestCase2;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
public class ListPreferenceTest
extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceFromCodeActivity.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceFromCodeActivity.java
index e76c95a..7a67e3e 100644
--- a/tests/tests/preference2/src/android/preference2/cts/PreferenceFromCodeActivity.java
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceFromCodeActivity.java
@@ -16,7 +16,7 @@
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceGroupTest.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceGroupTest.java
index 109ea77..fe0b3b2 100644
--- a/tests/tests/preference2/src/android/preference2/cts/PreferenceGroupTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceGroupTest.java
@@ -16,7 +16,7 @@
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceTest.java
index 328e074..b2907f3 100644
--- a/tests/tests/preference2/src/android/preference2/cts/PreferenceTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceTest.java
@@ -22,7 +22,7 @@
import android.preference.PreferenceGroup;
import android.test.ActivityInstrumentationTestCase2;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
public class PreferenceTest
extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeaders.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeaders.java
index 1bb5637..a44cb7e6 100644
--- a/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeaders.java
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeaders.java
@@ -20,7 +20,7 @@
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.widget.Button;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import java.util.List;
/**
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferencesFromXml.java b/tests/tests/preference2/src/android/preference2/cts/PreferencesFromXml.java
index 0a61461..1aff9f5 100644
--- a/tests/tests/preference2/src/android/preference2/cts/PreferencesFromXml.java
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferencesFromXml.java
@@ -16,7 +16,7 @@
package android.preference2.cts;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
import android.os.Bundle;
import android.preference.PreferenceActivity;
diff --git a/tests/tests/preference2/src/android/preference2/cts/SwitchPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/SwitchPreferenceTest.java
index 3bd42d2..218c55a 100644
--- a/tests/tests/preference2/src/android/preference2/cts/SwitchPreferenceTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/SwitchPreferenceTest.java
@@ -20,7 +20,7 @@
import android.preference.SwitchPreference;
import android.test.ActivityInstrumentationTestCase2;
-import com.android.cts.preference2.R;
+import android.preference2.cts.R;
public class SwitchPreferenceTest
extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
diff --git a/tests/tests/print/Android.mk b/tests/tests/print/Android.mk
index 2ece2cf..211b5ee 100644
--- a/tests/tests/print/Android.mk
+++ b/tests/tests/print/Android.mk
@@ -18,12 +18,17 @@
LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CtsPrintTestCases
LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator ctsdeviceutil
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/print/AndroidManifest.xml b/tests/tests/print/AndroidManifest.xml
index b4a2905..c7edf6d 100644
--- a/tests/tests/print/AndroidManifest.xml
+++ b/tests/tests/print/AndroidManifest.xml
@@ -17,7 +17,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.print">
+ package="android.print.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -72,7 +72,7 @@
</application>
<instrumentation android:name="android.support.test.uiautomator.UiAutomatorInstrumentationTestRunner"
- android:targetPackage="com.android.cts.print"
+ android:targetPackage="android.print.cts"
android:label="Tests for the print APIs."/>
</manifest>
diff --git a/tests/tests/print/AndroidTest.xml b/tests/tests/print/AndroidTest.xml
new file mode 100644
index 0000000..21d8f03
--- /dev/null
+++ b/tests/tests/print/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Print test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPrintTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.print.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/print/res/drawable/red_printer.xml b/tests/tests/print/res/drawable/red_printer.xml
new file mode 100644
index 0000000..1bd7a4f
--- /dev/null
+++ b/tests/tests/print/res/drawable/red_printer.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:pathData="M10,18h28v13h-28z"
+ android:fillAlpha="1"
+ android:fillColor="#cccccc"
+ android:strokeColor="#00000000"/>
+ <path
+ android:pathData="M13,7L13,10L9,10C7,10 4,13 4,15L4,35L13,35L13,40L35,40L35,35L44,35L44,15C44,13 41,10 39,10L35,10L35,7L13,7zM14,8L34,8L34,10L14,10L14,8zM10,18L38,18L38,31L35,31L35,23L13,23L13,31L10,31L10,18zM14,24L34,24L34,39L14,39L14,24z"
+ android:fillColor="#0000ff"
+ android:strokeColor="#00000000"/>
+ <path
+ android:pathData="M14,24h20v15h-20z"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:strokeColor="#00000000"/>
+ <path
+ android:pathData="M14,8h20v2h-20z"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:strokeColor="#00000000"/>
+</vector>
diff --git a/tests/tests/print/res/raw/yellow_printer.png b/tests/tests/print/res/raw/yellow_printer.png
new file mode 100644
index 0000000..2e1cc8d
--- /dev/null
+++ b/tests/tests/print/res/raw/yellow_printer.png
Binary files differ
diff --git a/tests/tests/print/res/xml/printservice.xml b/tests/tests/print/res/xml/printservice.xml
index 5579b81..2765a39 100644
--- a/tests/tests/print/res/xml/printservice.xml
+++ b/tests/tests/print/res/xml/printservice.xml
@@ -17,6 +17,6 @@
-->
<print-service xmlns:android="http://schemas.android.com/apk/res/android"
- android:settingsActivity="android.print.services.SettingsActivity"
- android:addPrintersActivity="android.print.services.AddPrintersActivity"
- android:advancedPrintOptionsActivity="android.print.services.CustomPrintOptionsActivity"/>
+ android:settingsActivity="android.print.cts.services.SettingsActivity"
+ android:addPrintersActivity="android.print.cts.services.AddPrintersActivity"
+ android:advancedPrintOptionsActivity="android.print.cts.services.CustomPrintOptionsActivity"/>
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
old mode 100755
new mode 100644
index ea61806..2b62504
--- a/tests/tests/print/src/android/print/cts/BasePrintTest.java
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -41,20 +41,20 @@
import android.print.PrintDocumentAdapter.WriteResultCallback;
import android.print.PrintManager;
import android.print.PrinterId;
-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.print.pdf.PrintedPdfDocument;
+import android.printservice.CustomPrinterIconCallback;
import android.printservice.PrintJob;
import android.printservice.PrintService;
-import android.support.test.uiautomator.UiAutomatorTestCase;
+import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
+import android.test.InstrumentationTestCase;
import android.util.DisplayMetrics;
+import android.util.LocaleList;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
@@ -75,25 +75,30 @@
/**
* This is the base class for print tests.
*/
-public abstract class BasePrintTest extends UiAutomatorTestCase {
+public abstract class BasePrintTest extends InstrumentationTestCase {
private static final long OPERATION_TIMEOUT = 100000000;
-
private static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler";
-
protected static final String PRINT_JOB_NAME = "Test";
-
private static final String PM_CLEAR_SUCCESS_OUTPUT = "Success";
-
private static final String COMMAND_LIST_ENABLED_IME_COMPONENTS = "ime list -s";
-
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 PrintDocumentActivity mActivity;
+ private UiDevice mUiDevice;
- private Locale mOldLocale;
+ /**
+ * Return the UI device
+ *
+ * @return the UI device
+ */
+ public UiDevice getUiDevice() {
+ return mUiDevice;
+ }
+
+ private LocaleList mOldLocale;
private CallCounter mCancelOperationCounter;
private CallCounter mLayoutCallCounter;
@@ -109,12 +114,13 @@
ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
.executeShellCommand(COMMAND_LIST_ENABLED_IME_COMPONENTS);
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(new FileInputStream(pfd.getFileDescriptor())));
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(new FileInputStream(pfd.getFileDescriptor())))) {
- String line;
- while ((line = reader.readLine()) != null) {
- imeList.add(line);
+ String line;
+ while ((line = reader.readLine()) != null) {
+ imeList.add(line);
+ }
}
String[] imeArray = new String[imeList.size()];
@@ -154,9 +160,10 @@
return;
}
+ mUiDevice = UiDevice.getInstance(getInstrumentation());
+
// Make sure we start with a clean slate.
clearPrintSpoolerData();
- enablePrintServices();
disableImes();
// Workaround for dexmaker bug: https://code.google.com/p/dexmaker/issues/detail?id=2
@@ -167,11 +174,11 @@
// Set to US locale.
Resources resources = getInstrumentation().getTargetContext().getResources();
Configuration oldConfiguration = resources.getConfiguration();
- if (!oldConfiguration.locale.equals(Locale.US)) {
- mOldLocale = oldConfiguration.locale;
+ if (!oldConfiguration.getLocales().getPrimary().equals(Locale.US)) {
+ mOldLocale = oldConfiguration.getLocales();
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
Configuration newConfiguration = new Configuration(oldConfiguration);
- newConfiguration.locale = Locale.US;
+ newConfiguration.setLocale(Locale.US);
resources.updateConfiguration(newConfiguration, displayMetrics);
}
@@ -203,30 +210,33 @@
Resources resources = getInstrumentation().getTargetContext().getResources();
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
Configuration newConfiguration = new Configuration(resources.getConfiguration());
- newConfiguration.locale = mOldLocale;
+ newConfiguration.setLocales(mOldLocale);
mOldLocale = null;
resources.updateConfiguration(newConfiguration, displayMetrics);
}
- disablePrintServices();
- // Make sure the spooler is cleaned.
+ // Make sure the spooler is cleaned, this also un-approves all services
clearPrintSpoolerData();
super.tearDown();
}
- protected void print(final PrintDocumentAdapter adapter) {
+ protected void print(final PrintDocumentAdapter adapter, final PrintAttributes attributes) {
// Initiate printing as if coming from the app.
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
PrintManager printManager = (PrintManager) getActivity()
.getSystemService(Context.PRINT_SERVICE);
- printManager.print("Print job", adapter, null);
+ printManager.print("Print job", adapter, attributes);
}
});
}
+ protected void print(PrintDocumentAdapter adapter) {
+ print(adapter, null);
+ }
+
protected void onCancelOperationCalled() {
mCancelOperationCounter.call();
}
@@ -292,18 +302,12 @@
}
}
- protected void selectPrinter(String printerName) throws UiObjectNotFoundException {
+ protected void selectPrinter(String printerName) throws UiObjectNotFoundException, IOException {
try {
- UiObject destinationSpinner = new UiObject(new UiSelector().resourceId(
+ UiObject destinationSpinner = mUiDevice.findObject(new UiSelector().resourceId(
"com.android.printspooler:id/destination_spinner"));
destinationSpinner.click();
- UiObject printerOption = new UiObject(new UiSelector().text(printerName));
- if (!printerOption.exists()) {
- // Scroll through the spinner
- UiScrollable printerSpinner = new UiScrollable(new UiSelector().scrollable(true));
- printerSpinner.setAsVerticalList();
- printerOption = printerSpinner.getChildByText(new UiSelector().text(printerName), printerName);
- }
+ UiObject printerOption = mUiDevice.findObject(new UiSelector().text(printerName));
printerOption.click();
} catch (UiObjectNotFoundException e) {
dumpWindowHierarchy();
@@ -311,12 +315,24 @@
}
}
- protected void changeOrientation(String orientation) throws UiObjectNotFoundException {
+ 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"));
+ } else {
+ button = uiDevice.findObject(new UiSelector().resourceId("android:id/button2"));
+ }
+ button.click();
+ }
+
+ protected void changeOrientation(String orientation)
+ throws UiObjectNotFoundException, IOException {
try {
- UiObject orientationSpinner = new UiObject(new UiSelector().resourceId(
+ UiObject orientationSpinner = mUiDevice.findObject(new UiSelector().resourceId(
"com.android.printspooler:id/orientation_spinner"));
orientationSpinner.click();
- UiObject orientationOption = new UiObject(new UiSelector().text(orientation));
+ UiObject orientationOption = mUiDevice.findObject(new UiSelector().text(orientation));
orientationOption.click();
} catch (UiObjectNotFoundException e) {
dumpWindowHierarchy();
@@ -324,12 +340,12 @@
}
}
- protected void changeMediaSize(String mediaSize) throws UiObjectNotFoundException {
+ protected void changeMediaSize(String mediaSize) throws UiObjectNotFoundException, IOException {
try {
- UiObject mediaSizeSpinner = new UiObject(new UiSelector().resourceId(
+ UiObject mediaSizeSpinner = mUiDevice.findObject(new UiSelector().resourceId(
"com.android.printspooler:id/paper_size_spinner"));
mediaSizeSpinner.click();
- UiObject mediaSizeOption = new UiObject(new UiSelector().text(mediaSize));
+ UiObject mediaSizeOption = mUiDevice.findObject(new UiSelector().text(mediaSize));
mediaSizeOption.click();
} catch (UiObjectNotFoundException e) {
dumpWindowHierarchy();
@@ -337,12 +353,12 @@
}
}
- protected void changeColor(String color) throws UiObjectNotFoundException {
+ protected void changeColor(String color) throws UiObjectNotFoundException, IOException {
try {
- UiObject colorSpinner = new UiObject(new UiSelector().resourceId(
+ UiObject colorSpinner = mUiDevice.findObject(new UiSelector().resourceId(
"com.android.printspooler:id/color_spinner"));
colorSpinner.click();
- UiObject colorOption = new UiObject(new UiSelector().text(color));
+ UiObject colorOption = mUiDevice.findObject(new UiSelector().text(color));
colorOption.click();
} catch (UiObjectNotFoundException e) {
dumpWindowHierarchy();
@@ -350,12 +366,12 @@
}
}
- protected void changeDuplex(String duplex) throws UiObjectNotFoundException {
+ protected void changeDuplex(String duplex) throws UiObjectNotFoundException, IOException {
try {
- UiObject duplexSpinner = new UiObject(new UiSelector().resourceId(
+ UiObject duplexSpinner = mUiDevice.findObject(new UiSelector().resourceId(
"com.android.printspooler:id/duplex_spinner"));
duplexSpinner.click();
- UiObject duplexOption = new UiObject(new UiSelector().text(duplex));
+ UiObject duplexOption = mUiDevice.findObject(new UiSelector().text(duplex));
duplexOption.click();
} catch (UiObjectNotFoundException e) {
dumpWindowHierarchy();
@@ -363,9 +379,9 @@
}
}
- protected void clickPrintButton() throws UiObjectNotFoundException {
+ protected void clickPrintButton() throws UiObjectNotFoundException, IOException {
try {
- UiObject printButton = new UiObject(new UiSelector().resourceId(
+ UiObject printButton = mUiDevice.findObject(new UiSelector().resourceId(
"com.android.printspooler:id/print_button"));
printButton.click();
} catch (UiObjectNotFoundException e) {
@@ -374,47 +390,35 @@
}
}
- private void dumpWindowHierarchy() {
+ private void dumpWindowHierarchy() throws IOException {
String name = "print-test-failure-" + System.currentTimeMillis() + ".xml";
File file = new File(getActivity().getFilesDir(), name);
- getUiDevice().dumpWindowHierarchy(file.toString());
+ try (FileOutputStream os = new FileOutputStream(file.toString())) {
+ mUiDevice.dumpWindowHierarchy(os);
+ }
}
protected PrintDocumentActivity getActivity() {
return mActivity;
}
- private void createActivity() {
+ protected void createActivity() {
mActivity = launchActivity(
getInstrumentation().getTargetContext().getPackageName(),
PrintDocumentActivity.class, null);
}
protected void openPrintOptions() throws UiObjectNotFoundException {
- UiObject expandHandle = new UiObject(new UiSelector().resourceId(
+ UiObject expandHandle = mUiDevice.findObject(new UiSelector().resourceId(
"com.android.printspooler:id/expand_collapse_handle"));
expandHandle.click();
}
protected void clearPrintSpoolerData() throws Exception {
assertTrue("failed to clear print spooler data",
- SystemUtil.runShellCommand(getInstrumentation(),
- String.format("pm clear %s", PRINT_SPOOLER_PACKAGE_NAME))
- .contains(PM_CLEAR_SUCCESS_OUTPUT));
- }
-
- private void enablePrintServices() throws Exception {
- String pkgName = getInstrumentation().getContext().getPackageName();
- String enabledServicesValue = String.format("%s/%s:%s/%s",
- pkgName, FirstPrintService.class.getCanonicalName(),
- pkgName, SecondPrintService.class.getCanonicalName());
- SystemUtil.runShellCommand(getInstrumentation(),
- "settings put secure enabled_print_services " + enabledServicesValue);
- }
-
- private void disablePrintServices() throws Exception {
- SystemUtil.runShellCommand(getInstrumentation(),
- "settings put secure enabled_print_services \"\"");
+ SystemUtil.runShellCommand(getInstrumentation(), String.format(
+ "pm clear --user %d %s", CURRENT_USER_ID, PRINT_SPOOLER_PACKAGE_NAME))
+ .contains(PM_CLEAR_SUCCESS_OUTPUT));
}
protected void verifyLayoutCall(InOrder inOrder, PrintDocumentAdapter mock,
@@ -461,7 +465,8 @@
protected PrinterDiscoverySessionCallbacks createMockPrinterDiscoverySessionCallbacks(
Answer<Void> onStartPrinterDiscovery, Answer<Void> onStopPrinterDiscovery,
Answer<Void> onValidatePrinters, Answer<Void> onStartPrinterStateTracking,
- Answer<Void> onStopPrinterStateTracking, Answer<Void> onDestroy) {
+ Answer<Void> onRequestCustomPrinterIcon, Answer<Void> onStopPrinterStateTracking,
+ Answer<Void> onDestroy) {
PrinterDiscoverySessionCallbacks callbacks = mock(PrinterDiscoverySessionCallbacks.class);
doCallRealMethod().when(callbacks).setSession(any(StubbablePrinterDiscoverySession.class));
@@ -482,6 +487,10 @@
doAnswer(onStartPrinterStateTracking).when(callbacks).onStartPrinterStateTracking(
any(PrinterId.class));
}
+ if (onRequestCustomPrinterIcon != null) {
+ doAnswer(onRequestCustomPrinterIcon).when(callbacks).onRequestCustomPrinterIcon(
+ any(PrinterId.class), any(CustomPrinterIconCallback.class));
+ }
if (onStopPrinterStateTracking != null) {
doAnswer(onStopPrinterStateTracking).when(callbacks).onStopPrinterStateTracking(
any(PrinterId.class));
diff --git a/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
index b9fd50a..dcea91f 100644
--- a/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
+++ b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
@@ -146,6 +146,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for finish.
waitForAdapterFinishCallbackCalled();
@@ -258,6 +261,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for finish.
waitForAdapterFinishCallbackCalled();
@@ -386,6 +392,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for finish.
waitForAdapterFinishCallbackCalled();
@@ -598,6 +607,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for finish.
waitForAdapterFinishCallbackCalled();
@@ -667,7 +679,7 @@
return null;
}
- }, null, null, null, null, null);
+ }, null, null, null, null, null, null);
}
private PrintServiceCallbacks createSecondMockPrintServiceCallbacks() {
diff --git a/tests/tests/print/src/android/print/cts/PrintAttributesTest.java b/tests/tests/print/src/android/print/cts/PrintAttributesTest.java
new file mode 100644
index 0000000..855f587
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/PrintAttributesTest.java
@@ -0,0 +1,648 @@
+/*
+ * 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.
+ */
+
+package android.print.cts;
+
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintDocumentAdapter.LayoutResultCallback;
+import android.print.PrintDocumentAdapter.WriteResultCallback;
+import android.print.PrintDocumentInfo;
+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.printservice.PrintJob;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Test that the print attributes are correctly propagated through the print framework
+ */
+public class PrintAttributesTest extends BasePrintTest {
+ private final String PRINTER_NAME = "Test printer";
+
+ private final Margins[] MIN_MARGINS = {
+ new Margins(0, 0, 0, 0), new Margins(10, 10, 10, 10), new Margins(20, 20, 20, 20),
+ };
+
+ private final MediaSize MEDIA_SIZES[] = {
+ MediaSize.ISO_A3, MediaSize.ISO_A4, MediaSize.ISO_A5
+ };
+
+ private final int COLOR_MODES[] = {
+ PrintAttributes.COLOR_MODE_MONOCHROME, PrintAttributes.COLOR_MODE_COLOR
+ };
+
+ private final int DUPLEX_MODES[] = {
+ PrintAttributes.DUPLEX_MODE_NONE, PrintAttributes.DUPLEX_MODE_LONG_EDGE,
+ PrintAttributes.DUPLEX_MODE_SHORT_EDGE
+ };
+
+ private final Resolution RESOLUTIONS[] = {
+ new Resolution("300x300", "300x300", 300, 300),
+ new Resolution("600x600", "600x600", 600, 600),
+ new Resolution("1200x1200", "1200x1200", 1200, 1200)
+ };
+
+ /**
+ * Stores the {@link PrintAttributes} passed to the layout method
+ */
+ private PrintAttributes mLayoutAttributes;
+
+ /**
+ * Create a new {@link PrintAttributes} object with the given properties.
+ *
+ * All properties can be null/0 to remain unset.
+ *
+ * @param mediaSize {@link MediaSize} to use
+ * @param colorMode Color mode to use
+ * @param duplexMode Duplex mode to use
+ * @param resolution {@link Resolution} to use
+ *
+ * @return The newly created object or null if no properties are set
+ */
+ private PrintAttributes createAttributes(MediaSize mediaSize, int colorMode, int duplexMode,
+ Resolution resolution) {
+ if (mediaSize == null && colorMode == 0 && duplexMode == 0 && resolution == null) {
+ return null;
+ }
+
+ PrintAttributes.Builder builder = new PrintAttributes.Builder();
+
+ if (mediaSize != null) {
+ builder.setMediaSize(mediaSize);
+ }
+
+ if (colorMode != 0) {
+ builder.setColorMode(colorMode);
+ }
+
+ if (duplexMode != 0) {
+ builder.setDuplexMode(duplexMode);
+ }
+
+ if (resolution != null) {
+ builder.setResolution(resolution);
+ }
+
+ return builder.build();
+ }
+
+ /**
+ * Make {@link #PRINTER_NAME} the default printer by adding it to the history of printers by
+ * printing once.
+ *
+ * @param adapter The {@link PrintDocumentAdapter} used
+ * @throws Exception If the printer could not be made default
+ */
+ private void makeDefaultPrinter(PrintDocumentAdapter adapter)
+ throws Exception {
+ // Perform a full print operation on the printer
+ print(adapter);
+ selectPrinter(PRINTER_NAME);
+ clickPrintButton();
+ answerPrintServicesWarning(true);
+ waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+ // Switch to new activity, which should now use the default printer
+ getActivity().finish();
+ createActivity();
+ }
+
+ /**
+ * Create {@link PrinterDiscoverySessionCallbacks} with a single printer that has the given
+ * capabilities
+ *
+ * @param minMargins The minMargins of the printer
+ * @param mediaSizes The {@link MediaSize media sizes} supported by the printer
+ * @param defaultMediaSize The default {@link MediaSize}
+ * @param colorModes The color modes supported by the printer
+ * @param defaultColorMode The default color mode
+ * @param duplexModes The duplex modes supported by the printer
+ * @param defaultDuplexMode The default duplex mode
+ * @param resolutions The {@link Resolution resolutions} supported by the printer
+ * @param defaultResolution The default {@link Resolution} to use
+ *
+ * @return New {@link PrinterDiscoverySessionCallbacks} with a single printer that has the
+ * given capabilities
+ */
+ private PrinterDiscoverySessionCallbacks createMockPrinterDiscoverySessionCallbacks(
+ final Margins minMargins, final MediaSize mediaSizes[],
+ final MediaSize defaultMediaSize, final int colorModes[], final int defaultColorMode,
+ final int duplexModes[], final int defaultDuplexMode, final Resolution resolutions[],
+ final Resolution defaultResolution) {
+ return createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ StubbablePrinterDiscoverySession session =
+ ((PrinterDiscoverySessionCallbacks) invocation.getMock()).getSession();
+
+ if (session.getPrinters().isEmpty()) {
+ List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+ PrinterId printerId = session.getService().generatePrinterId(PRINTER_NAME);
+
+ PrinterCapabilitiesInfo.Builder builder =
+ new PrinterCapabilitiesInfo.Builder(printerId);
+
+ builder.setMinMargins(minMargins);
+
+ int mediaSizesLength = mediaSizes.length;
+ for (int i = 0; i < mediaSizesLength; i++) {
+ if (mediaSizes[i].equals(defaultMediaSize)) {
+ builder.addMediaSize(mediaSizes[i], true);
+ } else {
+ builder.addMediaSize(mediaSizes[i], false);
+ }
+ }
+
+ int colorModesMask = 0;
+ int colorModesLength = colorModes.length;
+ for (int i = 0; i < colorModesLength; i++) {
+ colorModesMask |= colorModes[i];
+ }
+ builder.setColorModes(colorModesMask, defaultColorMode);
+
+ int duplexModesMask = 0;
+ int duplexModeLength = duplexModes.length;
+ for (int i = 0; i < duplexModeLength; i++) {
+ duplexModesMask |= duplexModes[i];
+ }
+ builder.setDuplexModes(duplexModesMask, defaultDuplexMode);
+
+ int resolutionsLength = resolutions.length;
+ for (int i = 0; i < resolutionsLength; i++) {
+ if (resolutions[i].equals(defaultResolution)) {
+ builder.addResolution(resolutions[i], true);
+ } else {
+ builder.addResolution(resolutions[i], false);
+ }
+ }
+
+ PrinterInfo printer = new PrinterInfo.Builder(printerId, PRINTER_NAME,
+ PrinterInfo.STATUS_IDLE).setCapabilities(builder.build()).build();
+ printers.add(printer);
+
+ session.addPrinters(printers);
+ }
+ return null;
+ }
+ }, null, null, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ return null;
+ }
+ }, null, null, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ // Take a note onDestroy was called.
+ onPrinterDiscoverySessionDestroyCalled();
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Create dummy {@link PrintServiceCallbacks}
+ *
+ * This is needed to as the print framework is trying to talk to any printer even if is not set
+ * up.
+ *
+ * @return Dummy {@link PrintServiceCallbacks}
+ */
+ private PrintServiceCallbacks createDummyMockPrintServiceCallbacks() {
+ return createMockPrintServiceCallbacks(null, null, null);
+ }
+
+ /**
+ * Create a {@link PrintDocumentAdapter} that serves empty pages
+ *
+ * @return A new {@link PrintDocumentAdapter}
+ */
+ private PrintDocumentAdapter createMockPrintDocumentAdapter() {
+ return createMockPrintDocumentAdapter(
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ mLayoutAttributes = (PrintAttributes) invocation.getArguments()[1];
+ LayoutResultCallback callback =
+ (LayoutResultCallback) invocation.getArguments()[3];
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+ .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+ .setPageCount(1)
+ .build();
+ callback.onLayoutFinished(info, false);
+ // 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(mLayoutAttributes, fd, pages[0].getStart(),
+ pages[0].getEnd());
+ 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;
+ }
+ });
+ }
+
+ /**
+ * Set up a single printer with the given capabilities
+ *
+ * @param minMargins The minMargins of the printer
+ * @param mediaSizes The {@link MediaSize media sizes} supported by the printer
+ * @param defaultMediaSize The default {@link MediaSize}
+ * @param colorModes The color modes supported by the printer
+ * @param defaultColorMode The default color mode
+ * @param duplexModes The duplex modes supported by the printer
+ * @param defaultDuplexMode The default duplex mode
+ * @param resolutions The {@link Resolution resolutions} supported by the printer
+ * @param defaultResolution The default {@link Resolution} to use
+ *
+ * @return A {@link PrintDocumentAdapter} that can be used for the new printer
+ */
+ private PrintDocumentAdapter setUpPrinter(Margins minMargins, MediaSize mediaSizes[],
+ MediaSize defaultMediaSize, int colorModes[], int defaultColorMode, int duplexModes[],
+ int defaultDuplexMode, Resolution resolutions[], Resolution defaultResolution) {
+ final PrinterDiscoverySessionCallbacks sessionCallbacks =
+ createMockPrinterDiscoverySessionCallbacks(minMargins, mediaSizes,
+ defaultMediaSize, colorModes, defaultColorMode, duplexModes,
+ defaultDuplexMode, resolutions, defaultResolution);
+
+ PrintServiceCallbacks serviceCallbacks = createMockPrintServiceCallbacks(
+ new Answer<PrinterDiscoverySessionCallbacks>() {
+ @Override
+ public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+ return sessionCallbacks;
+ }
+ },
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ PrintJob printJob = (PrintJob) invocation.getArguments()[0];
+ // We pretend the job is handled immediately.
+ printJob.complete();
+ return null;
+ }
+ }, null);
+
+ // Configure the print services.
+ FirstPrintService.setCallbacks(serviceCallbacks);
+
+ // We need to set up the second print service too, otherwise we get a null pointer in the
+ // print framework
+ SecondPrintService.setCallbacks(createDummyMockPrintServiceCallbacks());
+
+ // Create a print adapter that respects the print contract.
+ return createMockPrintDocumentAdapter();
+ }
+
+ /**
+ * Check if a value is in an array.
+ *
+ * To be use instead of Arrays.asList(array).contains(value) for ints.
+ *
+ * @param array The array the value might be in
+ * @param value The value to search for
+ *
+ * @return true iff the value is in the array
+ */
+ private boolean isInArray(final int array[], int value) {
+ int arrayLength = array.length;
+ for (int i = 0; i < arrayLength; i++) {
+ if (array[i] == value) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Flexible base test for all print attribute tests.
+ *
+ * Asserts that the default and suggested attributes are properly honored by the print
+ * framework.
+ *
+ * @param minMargins The minMargins of the printer
+ * @param mediaSizes The {@link MediaSize media sizes} supported by the printer
+ * @param defaultMediaSize The default {@link MediaSize}
+ * @param colorModes The color modes supported by the printer
+ * @param defaultColorMode The default color mode
+ * @param duplexModes The duplex modes supported by the printer
+ * @param defaultDuplexMode The default duplex mode
+ * @param resolutions The {@link Resolution resolutions} supported by the printer
+ * @param defaultResolution The default {@link Resolution} to use
+ * @param suggestedMediaSize The suggested {@link MediaSize} for the print job
+ * @param suggestedColorMode The suggested color mode for the print job
+ * @param suggestedDuplexMode The suggested duplex mode for the print job
+ * @param suggestedResolution The suggested resolution for the print job
+ *
+ * @throws Exception If anything is unexpected
+ */
+ private void baseTest(Margins minMargins, MediaSize mediaSizes[],
+ MediaSize defaultMediaSize, MediaSize suggestedMediaSize, int colorModes[],
+ int defaultColorMode, int suggestedColorMode, int duplexModes[],
+ int defaultDuplexMode, int suggestedDuplexMode, Resolution resolutions[],
+ Resolution defaultResolution, Resolution suggestedResolution) throws Exception {
+ if (!supportsPrinting()) {
+ return;
+ }
+
+ // Set up printer with supported and default attributes
+ PrintDocumentAdapter adapter =
+ setUpPrinter(minMargins, mediaSizes, defaultMediaSize, colorModes, defaultColorMode,
+ duplexModes, defaultDuplexMode, resolutions, defaultResolution);
+
+ // Make printer default. This is necessary as a different default printer might pre-select
+ // its default attributes and thereby overrides the defaults of the tested printer.
+ makeDefaultPrinter(adapter);
+
+ // Select suggested attributes
+ PrintAttributes suggestedAttributes = createAttributes(suggestedMediaSize,
+ suggestedColorMode, suggestedDuplexMode, suggestedResolution);
+
+ // Start print action and wait for layout, the result is stored in #layoutAttributes,
+ // @see createMockPrintDocumentAdapter
+ print(adapter, suggestedAttributes);
+ waitForWriteAdapterCallback();
+ clickPrintButton();
+ waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+ // It does not make sense to suggest minMargins, hence the print framework always picks
+ // the one set up for the printer.
+ assertEquals("Min margins not as expected", minMargins, mLayoutAttributes.getMinMargins());
+
+ // Verify that the attributes are honored properly
+ if (suggestedMediaSize != null && Arrays.asList(mediaSizes).contains(suggestedMediaSize)) {
+ assertEquals("Media size not as suggested", suggestedMediaSize,
+ mLayoutAttributes.getMediaSize());
+ } else {
+ assertEquals("Media size not default", defaultMediaSize,
+ mLayoutAttributes.getMediaSize());
+ }
+
+ if (suggestedColorMode != 0 && isInArray(colorModes, suggestedColorMode)) {
+ assertEquals("Color mode not as suggested", suggestedColorMode,
+ mLayoutAttributes.getColorMode());
+ } else {
+ assertEquals("Color mode not default", defaultColorMode,
+ mLayoutAttributes.getColorMode());
+ }
+
+ if (suggestedDuplexMode != 0 && isInArray(duplexModes, suggestedDuplexMode)) {
+ assertEquals("Duplex mode not as suggested", suggestedDuplexMode,
+ mLayoutAttributes.getDuplexMode());
+ } else {
+ assertEquals("Duplex mode not default", defaultDuplexMode,
+ mLayoutAttributes.getDuplexMode());
+ }
+
+ if (suggestedResolution != null
+ && Arrays.asList(resolutions).contains(suggestedResolution)) {
+ assertEquals("Resolution not as suggested", suggestedResolution,
+ mLayoutAttributes.getResolution());
+ } else {
+ assertEquals("Resolution not default", defaultResolution,
+ mLayoutAttributes.getResolution());
+ }
+ }
+
+ /**
+ * Test that attributes are as expected if the default attributes match the suggested ones.
+ *
+ * This test sets the default and suggested attributes to the first selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testDefaultMatchesSuggested0() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[0],
+ MEDIA_SIZES, MEDIA_SIZES[0], MEDIA_SIZES[0],
+ COLOR_MODES, COLOR_MODES[0], COLOR_MODES[0],
+ DUPLEX_MODES, DUPLEX_MODES[0], DUPLEX_MODES[0],
+ RESOLUTIONS, RESOLUTIONS[0], RESOLUTIONS[0]);
+ }
+
+ /**
+ * Test that attributes are as expected if the default attributes match the suggested ones.
+ *
+ * This test sets the default and suggested attributes to the second selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testDefaultMatchesSuggested1() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[1],
+ MEDIA_SIZES, MEDIA_SIZES[1], MEDIA_SIZES[1],
+ COLOR_MODES, COLOR_MODES[1], COLOR_MODES[1],
+ DUPLEX_MODES, DUPLEX_MODES[1], DUPLEX_MODES[1],
+ RESOLUTIONS, RESOLUTIONS[1], RESOLUTIONS[1]);
+ }
+
+ /**
+ * Test that attributes are as expected if the default attributes match the suggested ones.
+ *
+ * This test sets the default and suggested attributes to the third selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testDefaultMatchesSuggested2() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[2],
+ MEDIA_SIZES, MEDIA_SIZES[2], MEDIA_SIZES[2],
+ // There are only two color modes, hence pick [1]
+ COLOR_MODES, COLOR_MODES[1], COLOR_MODES[1],
+ DUPLEX_MODES, DUPLEX_MODES[2], DUPLEX_MODES[2],
+ RESOLUTIONS, RESOLUTIONS[2], RESOLUTIONS[2]);
+ }
+
+ /**
+ * Test that attributes are as expected if the no suggestion is given.
+ *
+ * This test sets the default attributes to the first selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testNoSuggestion0() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[0],
+ MEDIA_SIZES, MEDIA_SIZES[0], null,
+ COLOR_MODES, COLOR_MODES[0], 0,
+ DUPLEX_MODES, DUPLEX_MODES[0], 0,
+ RESOLUTIONS, RESOLUTIONS[0], null);
+ }
+
+ /**
+ * Test that attributes are as expected if the no suggestion is given.
+ *
+ * This test sets the default attributes to the second selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testNoSuggestion1() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[1],
+ MEDIA_SIZES, MEDIA_SIZES[1], null,
+ COLOR_MODES, COLOR_MODES[1], 0,
+ DUPLEX_MODES, DUPLEX_MODES[1], 0,
+ RESOLUTIONS, RESOLUTIONS[1], null);
+ }
+
+ /**
+ * Test that attributes are as expected if the no suggestion is given.
+ *
+ * This test sets the default attributes to the third selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testNoSuggestion2() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[2],
+ MEDIA_SIZES, MEDIA_SIZES[2], null,
+ // There are only two color modes, hence pick [1]
+ COLOR_MODES, COLOR_MODES[1], 0,
+ DUPLEX_MODES, DUPLEX_MODES[2], 0,
+ RESOLUTIONS, RESOLUTIONS[2], null);
+ }
+
+ /**
+ * Test that attributes are as expected if only the {@link MediaSize} is suggested.
+ *
+ * This test sets the default attributes to the first selection, but the {@link MediaSize} is
+ * suggested to be the second selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testMediaSizeSuggestion0() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[0],
+ MEDIA_SIZES, MEDIA_SIZES[0], MEDIA_SIZES[1],
+ COLOR_MODES, COLOR_MODES[0], 0,
+ DUPLEX_MODES, DUPLEX_MODES[0], 0,
+ RESOLUTIONS, RESOLUTIONS[0], null);
+ }
+
+ /**
+ * Test that attributes are as expected if only the {@link MediaSize} is suggested.
+ *
+ * This test sets the default attributes to the second selection, but the {@link MediaSize} is
+ * suggested to be the first selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testMediaSizeSuggestion1() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[1],
+ MEDIA_SIZES, MEDIA_SIZES[1], MEDIA_SIZES[0],
+ COLOR_MODES, COLOR_MODES[1], 0,
+ DUPLEX_MODES, DUPLEX_MODES[1], 0,
+ RESOLUTIONS, RESOLUTIONS[1], null);
+ }
+
+ /**
+ * Test that attributes are as expected if only the duplex mode is suggested.
+ *
+ * This test sets the default attributes to the first selection, but the duplex mode is
+ * suggested to be the second selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testDuplexModeSuggestion0() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[0],
+ MEDIA_SIZES, MEDIA_SIZES[0], null,
+ COLOR_MODES, COLOR_MODES[0], 0,
+ DUPLEX_MODES, DUPLEX_MODES[0], DUPLEX_MODES[1],
+ RESOLUTIONS, RESOLUTIONS[0], null);
+ }
+
+ /**
+ * Test that attributes are as expected if only the duplex mode is suggested.
+ *
+ * This test sets the default attributes to the second selection, but the duplex mode is
+ * suggested to be the first selection.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testDuplexModeSuggestion1() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[1],
+ MEDIA_SIZES, MEDIA_SIZES[1], null,
+ COLOR_MODES, COLOR_MODES[1], 0,
+ DUPLEX_MODES, DUPLEX_MODES[1], DUPLEX_MODES[0],
+ RESOLUTIONS, RESOLUTIONS[1], null);
+ }
+
+ /**
+ * Test that attributes are as expected if all attributes are suggested and different from the
+ * default attributes.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testSuggestedDifferentFromDefault() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[0],
+ MEDIA_SIZES, MEDIA_SIZES[0], MEDIA_SIZES[1],
+ COLOR_MODES, COLOR_MODES[0], COLOR_MODES[1],
+ DUPLEX_MODES, DUPLEX_MODES[0], DUPLEX_MODES[1],
+ RESOLUTIONS, RESOLUTIONS[0], RESOLUTIONS[1]);
+ }
+
+ /**
+ * Test that attributes are as expected if all attributes are suggested but all of them are not
+ * supported by the printer.
+ *
+ * @throws Exception If anything is unexpected
+ */
+ public void testIllegalSuggested() throws Exception {
+ // available default suggestion
+ baseTest( MIN_MARGINS[0],
+ Arrays.copyOfRange(MEDIA_SIZES, 0, 1), MEDIA_SIZES[0], MEDIA_SIZES[1],
+ Arrays.copyOfRange(COLOR_MODES, 0, 1), COLOR_MODES[0], COLOR_MODES[1],
+ Arrays.copyOfRange(DUPLEX_MODES, 0, 1), DUPLEX_MODES[0], DUPLEX_MODES[1],
+ Arrays.copyOfRange(RESOLUTIONS, 0, 1), RESOLUTIONS[0], RESOLUTIONS[1]);
+ }
+}
diff --git a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
index 9f1e3a5..24eb951 100644
--- a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
@@ -122,6 +122,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for finish.
waitForAdapterFinishCallbackCalled();
@@ -142,6 +145,7 @@
.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);
@@ -256,6 +260,7 @@
.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);
@@ -363,6 +368,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for a finish.
waitForAdapterFinishCallbackCalled();
@@ -383,6 +391,7 @@
.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);
@@ -552,6 +561,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for a finish.
waitForAdapterFinishCallbackCalled();
@@ -572,6 +584,7 @@
.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);
@@ -613,6 +626,7 @@
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(new Margins(200, 200, 200, 200))
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+ .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
.build();
verifyLayoutCall(inOrder, adapter, fourthOldAttributes, fourthNewAttributes, true);
@@ -699,6 +713,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for a finish.
waitForAdapterFinishCallbackCalled();
@@ -718,6 +735,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -823,6 +841,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for a finish.
waitForAdapterFinishCallbackCalled();
@@ -842,6 +863,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -932,6 +954,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for a finish.
waitForAdapterFinishCallbackCalled();
@@ -951,6 +976,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -1058,6 +1084,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -1152,6 +1179,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -1224,6 +1252,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -1306,6 +1335,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -1350,7 +1380,6 @@
Object[] args = invocation.getArguments();
ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
WriteResultCallback callback = (WriteResultCallback) args[3];
- PageRange[] pages = (PageRange[]) args[0];
writeBlankPages(printAttributes[0], fd, Integer.MAX_VALUE, Integer.MAX_VALUE);
fd.close();
// Write wrong pages.
@@ -1398,6 +1427,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -1469,6 +1499,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -1548,6 +1579,7 @@
.setMediaSize(MediaSize.NA_LETTER)
.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);
@@ -1636,7 +1668,7 @@
}
return null;
}
- }, null, null, null, null, new Answer<Void>() {
+ }, null, null, null, null, null, new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
// Take a note onDestroy was called.
diff --git a/tests/tests/print/src/android/print/cts/PrintServicesTest.java b/tests/tests/print/src/android/print/cts/PrintServicesTest.java
new file mode 100644
index 0000000..c8fc265
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/PrintServicesTest.java
@@ -0,0 +1,576 @@
+/*
+ * 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.
+ */
+
+package android.print.cts;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintDocumentAdapter.LayoutResultCallback;
+import android.print.PrintDocumentAdapter.WriteResultCallback;
+import android.print.PrintDocumentInfo;
+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.printservice.CustomPrinterIconCallback;
+import android.printservice.PrintJob;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+
+import junit.framework.AssertionFailedError;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Test the interface from a print service to the print manager
+ */
+public class PrintServicesTest extends BasePrintTest {
+ private static final String PRINTER_NAME = "Test printer";
+ private static final int NUM_PAGES = 2;
+
+ /** The print job processed in the test */
+ private static PrintJob mPrintJob;
+
+ /** The current progress of #mPrintJob once read from the system */
+ private static float mPrintProgress;
+
+ /** Printer under test */
+ private static PrinterInfo mPrinter;
+
+ /** The printer discovery session used in this test */
+ private static StubbablePrinterDiscoverySession mDiscoverySession;
+
+ /** The current status of #mPrintJob once read from the system */
+ private static CharSequence mPrintStatus;
+
+ /** The custom printer icon to use */
+ private Icon mIcon;
+
+ /**
+ * Create a mock {@link PrintDocumentAdapter} that provides {@link #NUM_PAGES} empty pages.
+ *
+ * @return The mock adapter
+ */
+ private PrintDocumentAdapter createMockPrintDocumentAdapter() {
+ final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+ return createMockPrintDocumentAdapter(
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+ LayoutResultCallback callback = (LayoutResultCallback) invocation
+ .getArguments()[3];
+
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+ .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+ .setPageCount(NUM_PAGES)
+ .build();
+
+ callback.onLayoutFinished(info, false);
+
+ // 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, pages[0].getStart(),
+ pages[0].getEnd());
+ 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;
+ }
+ });
+ }
+
+ /**
+ * Create a mock {@link PrinterDiscoverySessionCallbacks} that discovers a single printer with
+ * minimal capabilities.
+ *
+ * @return The mock session callbacks
+ */
+ private PrinterDiscoverySessionCallbacks createFirstMockPrinterDiscoverySessionCallbacks() {
+ return createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ // Get the session.
+ mDiscoverySession = ((PrinterDiscoverySessionCallbacks) invocation.getMock())
+ .getSession();
+
+ if (mDiscoverySession.getPrinters().isEmpty()) {
+ List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+
+ // Add the printer.
+ PrinterId printerId = mDiscoverySession.getService()
+ .generatePrinterId(PRINTER_NAME);
+
+ PrinterCapabilitiesInfo capabilities = new PrinterCapabilitiesInfo.Builder(
+ printerId)
+ .setMinMargins(new Margins(200, 200, 200, 200))
+ .addMediaSize(MediaSize.ISO_A4, true)
+ .addResolution(new Resolution("300x300", "300x300", 300, 300),
+ true)
+ .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+ PrintAttributes.COLOR_MODE_COLOR)
+ .build();
+
+ Intent infoIntent = new Intent(getActivity(), Activity.class);
+ PendingIntent infoPendingIntent = PendingIntent.getActivity(getActivity(), 0,
+ infoIntent, PendingIntent.FLAG_IMMUTABLE);
+
+ mPrinter = new PrinterInfo.Builder(printerId, PRINTER_NAME,
+ PrinterInfo.STATUS_IDLE)
+ .setCapabilities(capabilities)
+ .setDescription("Minimal capabilities")
+ .setInfoIntent(infoPendingIntent)
+ .build();
+ printers.add(mPrinter);
+
+ mDiscoverySession.addPrinters(printers);
+ }
+ return null;
+ }
+ }, null, null, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ return null;
+ }
+ }, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ CustomPrinterIconCallback callback = (CustomPrinterIconCallback) invocation
+ .getArguments()[1];
+
+ if (mIcon != null) {
+ callback.onCustomPrinterIconLoaded(mIcon);
+ }
+ return null;
+ }
+ }, null, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ // Take a note onDestroy was called.
+ onPrinterDiscoverySessionDestroyCalled();
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Get the current progress of #mPrintJob
+ *
+ * @return The current progress
+ * @throws InterruptedException If the thread was interrupted while setting the progress
+ */
+ private float getProgress() throws InterruptedException {
+ final PrintServicesTest synchronizer = PrintServicesTest.this;
+
+ synchronized (synchronizer) {
+ Runnable getter = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (synchronizer) {
+ mPrintProgress = mPrintJob.getInfo().getProgress();
+
+ synchronizer.notify();
+ }
+ }
+ };
+
+ (new Handler(Looper.getMainLooper())).post(getter);
+
+ synchronizer.wait();
+ }
+
+ return mPrintProgress;
+ }
+
+ /**
+ * Get the current status of #mPrintJob
+ *
+ * @return The current status
+ * @throws InterruptedException If the thread was interrupted while getting the status
+ */
+ private CharSequence getStatus() throws InterruptedException {
+ final PrintServicesTest synchronizer = PrintServicesTest.this;
+
+ synchronized (synchronizer) {
+ Runnable getter = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (synchronizer) {
+ mPrintStatus = mPrintJob.getInfo().getStatus();
+
+ synchronizer.notify();
+ }
+ }
+ };
+
+ (new Handler(Looper.getMainLooper())).post(getter);
+
+ synchronizer.wait();
+ }
+
+ return mPrintStatus;
+ }
+
+ /**
+ * Check if a print progress is correct.
+ *
+ * @param desiredProgress The expected @{link PrintProgresses}
+ * @throws Exception If anything goes wrong or this takes more than 5 seconds
+ */
+ private void checkNotification(float desiredProgress,
+ CharSequence desiredStatus) throws Exception {
+ final long TIMEOUT = 5000;
+ final Date start = new Date();
+
+ while ((new Date()).getTime() - start.getTime() < TIMEOUT) {
+ if (desiredProgress == getProgress()
+ && desiredStatus.toString().equals(getStatus().toString())) {
+ return;
+ }
+
+ Thread.sleep(200);
+ }
+
+ throw new TimeoutException("Progress or status not updated in " + TIMEOUT + " ms");
+ }
+
+ /**
+ * Set a new progress and status for #mPrintJob
+ *
+ * @param progress The new progress to set
+ * @param status The new status to set
+ * @throws InterruptedException If the thread was interrupted while setting
+ */
+ private void setProgressAndStatus(final float progress, final CharSequence status)
+ throws InterruptedException {
+ final PrintServicesTest synchronizer = PrintServicesTest.this;
+
+ synchronized (synchronizer) {
+ Runnable completer = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (synchronizer) {
+ mPrintJob.setProgress(progress);
+ mPrintJob.setStatus(status);
+
+ synchronizer.notify();
+ }
+ }
+ };
+
+ (new Handler(Looper.getMainLooper())).post(completer);
+
+ synchronizer.wait();
+ }
+ }
+
+ /**
+ * Progress print job and check the print job state.
+ *
+ * @param progress How much to progress
+ * @param status The status to set
+ * @throws Exception If anything goes wrong.
+ */
+ private void progress(float progress, CharSequence status) throws Exception {
+ setProgressAndStatus(progress, status);
+
+ // Check that progress of job is correct
+ checkNotification(progress, status);
+ }
+
+ /**
+ * Create mock service callback for a session.
+ *
+ * @param sessionCallbacks The callbacks of the sessopm
+ */
+ private PrintServiceCallbacks createFirstMockPrinterServiceCallbacks(
+ final PrinterDiscoverySessionCallbacks sessionCallbacks) {
+ return createMockPrintServiceCallbacks(
+ new Answer<PrinterDiscoverySessionCallbacks>() {
+ @Override
+ public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+ return sessionCallbacks;
+ }
+ },
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ mPrintJob = (PrintJob) invocation.getArguments()[0];
+ mPrintJob.start();
+ onPrintJobQueuedCalled();
+
+ return null;
+ }
+ }, null);
+ }
+
+ /**
+ * Test that the progress and status is propagated correctly.
+ *
+ * @throws Exception If anything is unexpected.
+ */
+ public void testProgress()
+ throws Exception {
+ if (!supportsPrinting()) {
+ return;
+ }
+ // Create the session callbacks that we will be checking.
+ PrinterDiscoverySessionCallbacks sessionCallbacks
+ = createFirstMockPrinterDiscoverySessionCallbacks();
+
+ // Create the service callbacks for the first print service.
+ PrintServiceCallbacks serviceCallbacks = createFirstMockPrinterServiceCallbacks(
+ sessionCallbacks);
+
+ // 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));
+
+ // Create a print adapter that respects the print contract.
+ PrintDocumentAdapter adapter = createMockPrintDocumentAdapter();
+
+ // Start printing.
+ print(adapter);
+
+ // Wait for write of the first page.
+ waitForWriteAdapterCallback();
+
+ // Select the printer.
+ selectPrinter(PRINTER_NAME);
+
+ // Click the print button.
+ clickPrintButton();
+
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
+ // Wait until the print job is queued and #mPrintJob is set
+ waitForServiceOnPrintJobQueuedCallbackCalled();
+
+ // Progress print job and check for appropriate notifications
+ progress(0, "printed 0");
+ progress(0.5f, "printed 50");
+ progress(1, "printed 100");
+
+ // Call complete from the main thread
+ Handler handler = new Handler(Looper.getMainLooper());
+
+ Runnable completer = new Runnable() {
+ @Override
+ public void run() {
+ mPrintJob.complete();
+ }
+ };
+
+ handler.post(completer);
+
+ // Wait for all print jobs to be handled after which the session destroyed.
+ waitForPrinterDiscoverySessionDestroyCallbackCalled();
+ }
+
+ /**
+ * Render a {@link Drawable} into a {@link Bitmap}.
+ *
+ * @param d the drawable to be rendered
+ * @return the rendered bitmap
+ */
+ private static Bitmap renderDrawable(Drawable d) {
+ Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(),
+ Bitmap.Config.ARGB_8888);
+
+ Canvas canvas = new Canvas(bitmap);
+ d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ d.draw(canvas);
+
+ return bitmap;
+ }
+
+ /**
+ * Update the printer
+ *
+ * @param printer the new printer to use
+ * @throws InterruptedException If we were interrupted while the printer was updated.
+ */
+ private void updatePrinter(final PrinterInfo printer)
+ throws InterruptedException {
+ final PrintServicesTest synchronizer = PrintServicesTest.this;
+
+ synchronized (synchronizer) {
+ Runnable updated = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (synchronizer) {
+ ArrayList<PrinterInfo> printers = new ArrayList<>(1);
+ printers.add(printer);
+ mDiscoverySession.addPrinters(printers);
+
+ synchronizer.notifyAll();
+ }
+ }
+ };
+
+ (new Handler(Looper.getMainLooper())).post(updated);
+
+ synchronizer.wait();
+ }
+
+ // Update local copy of printer
+ mPrinter = printer;
+ }
+
+ /**
+ * Assert is the printer icon does not match the bitmap. As the icon update might take some time
+ * we try up to 5 seconds.
+ *
+ * @param bitmap The bitmap to match
+ */
+ private void assertThatIconIs(Bitmap bitmap) {
+ final long TIMEOUT = 5000;
+
+ final long startMillis = SystemClock.uptimeMillis();
+ while (true) {
+ try {
+ if (bitmap.sameAs(renderDrawable(mPrinter.loadIcon(getActivity())))) {
+ return;
+ }
+ final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
+ final long waitMillis = TIMEOUT - elapsedMillis;
+ if (waitMillis <= 0) {
+ throw new AssertionFailedError("Icon does not match bitmap");
+ }
+
+ // We do not get notified about the icon update, hence wait and try again.
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
+ /* ignore */
+ }
+ }
+ }
+
+ /**
+ * Test that the icon get be updated.
+ *
+ * @throws Exception If anything is unexpected.
+ */
+ public void testUpdateIcon()
+ throws Exception {
+ if (!supportsPrinting()) {
+ return;
+ }
+ // Create the session callbacks that we will be checking.
+ final PrinterDiscoverySessionCallbacks sessionCallbacks
+ = createFirstMockPrinterDiscoverySessionCallbacks();
+
+ // Create the service callbacks for the first print service.
+ PrintServiceCallbacks serviceCallbacks = createFirstMockPrinterServiceCallbacks(
+ sessionCallbacks);
+
+ // 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));
+
+ // Create a print adapter that respects the print contract.
+ PrintDocumentAdapter adapter = createMockPrintDocumentAdapter();
+
+ // Start printing.
+ print(adapter);
+
+ // Open printer selection dropdown list to display icon on screen
+ UiObject destinationSpinner = UiDevice.getInstance(getInstrumentation())
+ .findObject(new UiSelector().resourceId(
+ "com.android.printspooler:id/destination_spinner"));
+ destinationSpinner.click();
+
+ // Get the print service's icon
+ PackageManager packageManager = getActivity().getPackageManager();
+ PackageInfo packageInfo = packageManager.getPackageInfo(
+ new ComponentName(getActivity(), FirstPrintService.class).getPackageName(), 0);
+ ApplicationInfo appInfo = packageInfo.applicationInfo;
+ Drawable printServiceIcon = appInfo.loadIcon(packageManager);
+
+ assertThatIconIs(renderDrawable(printServiceIcon));
+
+ // Update icon to resource
+ updatePrinter((new PrinterInfo.Builder(mPrinter)).setIconResourceId(R.drawable.red_printer)
+ .build());
+
+ assertThatIconIs(renderDrawable(getActivity().getDrawable(R.drawable.red_printer)));
+
+ // Update icon to bitmap
+ Bitmap bm = BitmapFactory.decodeResource(getActivity().getResources(),
+ R.raw.yellow_printer);
+ // Icon will be picked up from the discovery session once setHasCustomPrinterIcon is set
+ mIcon = Icon.createWithBitmap(bm);
+ updatePrinter((new PrinterInfo.Builder(mPrinter)).setHasCustomPrinterIcon().build());
+
+ assertThatIconIs(renderDrawable(mIcon.loadDrawable(getActivity())));
+ }
+}
diff --git a/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
index 7ea09e5..a198790 100644
--- a/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
+++ b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
@@ -39,7 +39,6 @@
import android.printservice.PrintJob;
import android.printservice.PrinterDiscoverySession;
-import junit.framework.AssertionFailedError;
import org.mockito.InOrder;
import org.mockito.exceptions.verification.VerificationInOrderFailure;
import org.mockito.invocation.InvocationOnMock;
@@ -123,6 +122,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for all print jobs to be handled after which the session destroyed.
waitForPrinterDiscoverySessionDestroyCallbackCalled();
@@ -157,6 +159,93 @@
inOrder.verify(firstSessionCallbacks).onDestroy();
}
+ public void testCancelPrintServicesAlertDialog() throws Exception {
+ if (!supportsPrinting()) {
+ return;
+ }
+ // Create the session callbacks that we will be checking.
+ final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
+ createFirstMockPrinterDiscoverySessionCallbacks();
+
+ // Create the service callbacks for the first print service.
+ PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+ new Answer<PrinterDiscoverySessionCallbacks>() {
+ @Override
+ public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+ return firstSessionCallbacks;
+ }
+ },
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ PrintJob printJob = (PrintJob) invocation.getArguments()[0];
+ // We pretend the job is handled immediately.
+ printJob.complete();
+ return null;
+ }
+ }, null);
+
+ // Configure the print services.
+ FirstPrintService.setCallbacks(firstServiceCallbacks);
+
+ // Create a print adapter that respects the print contract.
+ PrintDocumentAdapter adapter = createMockPrintDocumentAdapter();
+
+ // Start printing.
+ print(adapter);
+
+ // Wait for write of the first page.
+ waitForWriteAdapterCallback();
+
+ // Select the first printer.
+ selectPrinter(FIRST_PRINTER_NAME);
+
+ // While the printer discovery session is still alive store the
+ // ids of printers as we want to make some assertions about them
+ // but only the print service can create printer ids which means
+ // that we need to get the created ones.
+ PrinterId firstPrinterId = getAddedPrinterIdForLocalId(firstSessionCallbacks,
+ FIRST_PRINTER_LOCAL_ID);
+ assertNotNull("Coundn't find printer:" + FIRST_PRINTER_LOCAL_ID, firstPrinterId);
+
+ // Click the print button.
+ clickPrintButton();
+
+ // Cancel the dialog for the print service cloud warning
+ answerPrintServicesWarning(false);
+
+ // Click the print button again.
+ clickPrintButton();
+
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
+ // Wait for all print jobs to be handled after which the session destroyed.
+ waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+ // Verify the expected calls.
+ InOrder inOrder = inOrder(firstSessionCallbacks);
+
+ // We start discovery as the print dialog was up.
+ List<PrinterId> emptyPrinterIdList = Collections.emptyList();
+ inOrder.verify(firstSessionCallbacks).onStartPrinterDiscovery(
+ emptyPrinterIdList);
+
+ // We selected the first printer and now it should be tracked.
+ inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
+ firstPrinterId);
+
+ // We selected the second printer so the first should not be tracked.
+ inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
+ firstPrinterId);
+
+ // ... next we stop printer discovery...
+ inOrder.verify(firstSessionCallbacks).onStopPrinterDiscovery();
+
+ // ... last the session is destroyed.
+ inOrder.verify(firstSessionCallbacks).onDestroy();
+ }
+
public void testStartPrinterDiscoveryWithHistoricalPrinters() throws Exception {
if (!supportsPrinting()) {
return;
@@ -213,6 +302,9 @@
// Click the print button.
clickPrintButton();
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
// Wait for the print to complete.
waitForAdapterFinishCallbackCalled();
@@ -385,7 +477,7 @@
return null;
}
- }, null, new Answer<Void>() {
+ }, null, null, new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
// Take a note onDestroy was called.
diff --git a/tests/tests/print/src/android/print/cts/PrinterInfoTest.java b/tests/tests/print/src/android/print/cts/PrinterInfoTest.java
new file mode 100644
index 0000000..fd7ea8c
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/PrinterInfoTest.java
@@ -0,0 +1,421 @@
+/*
+ * 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.
+ */
+
+package android.print.cts;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintDocumentAdapter.LayoutResultCallback;
+import android.print.PrintDocumentAdapter.WriteResultCallback;
+import android.print.PrintDocumentInfo;
+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.printservice.CustomPrinterIconCallback;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+import android.text.TextUtils;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests all allowed types of printerInfo
+ */
+public class PrinterInfoTest extends BasePrintTest {
+ private static final int NUM_PAGES = 2;
+
+ private static final String NAMED_PRINTERS_NAME_PREFIX = "Printer ";
+
+ /** The printer discovery session used in this test */
+ private static StubbablePrinterDiscoverySession mDiscoverySession;
+
+ /** The custom printer icon to use */
+ private Icon mIcon;
+
+ /**
+ * Create a mock {@link PrintDocumentAdapter} that provides {@link #NUM_PAGES} empty pages.
+ *
+ * @return The mock adapter
+ */
+ private PrintDocumentAdapter createMockPrintDocumentAdapter() {
+ final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+ return createMockPrintDocumentAdapter(
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+ LayoutResultCallback callback = (LayoutResultCallback) invocation
+ .getArguments()[3];
+
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+ .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+ .setPageCount(NUM_PAGES)
+ .build();
+
+ callback.onLayoutFinished(info, false);
+
+ // 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, pages[0].getStart(),
+ pages[0].getEnd());
+ 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;
+ }
+ });
+ }
+
+ private boolean isValidStatus(int status) {
+ return status == PrinterInfo.STATUS_IDLE
+ || status == PrinterInfo.STATUS_BUSY
+ || status == PrinterInfo.STATUS_UNAVAILABLE;
+ }
+
+ /**
+ * Create a mock {@link PrinterDiscoverySessionCallbacks} that discovers a printers with all
+ * possible combinations of interesting printers.
+ *
+ * @return The mock session callbacks
+ */
+ private PrinterDiscoverySessionCallbacks createFirstMockPrinterDiscoverySessionCallbacks() {
+ return createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ // Get the session.
+ mDiscoverySession = ((PrinterDiscoverySessionCallbacks) invocation.getMock())
+ .getSession();
+
+ if (mDiscoverySession.getPrinters().isEmpty()) {
+ final int INVALID_RES_ID = 0xffffffff;
+
+ final PrinterInfo.Builder badPrinter = new PrinterInfo.Builder(
+ mDiscoverySession.getService().generatePrinterId("bad printer"),
+ "badPrinter", PrinterInfo.STATUS_UNAVAILABLE);
+
+ String[] localPrinterIds = {
+ "Printer", null
+ };
+
+ String[] names = {
+ NAMED_PRINTERS_NAME_PREFIX, "", null
+ };
+ int[] statusList = {
+ PrinterInfo.STATUS_IDLE, PrinterInfo.STATUS_BUSY,
+ PrinterInfo.STATUS_UNAVAILABLE, 0, 42
+ };
+ int[] iconResourceIds = {
+ R.drawable.red_printer, 0, INVALID_RES_ID, -1
+ };
+
+ boolean[] hasCustomPrinterIcons = {
+ true, false
+ };
+
+ String[] descriptions = {
+ "Description", "", null
+ };
+
+ PendingIntent[] infoIntents = {
+ PendingIntent.getActivity(getActivity(), 0,
+ new Intent(getActivity(), Activity.class),
+ PendingIntent.FLAG_IMMUTABLE),
+ null
+ };
+
+ PrinterCapabilitiesInfo[] capabilityList = {
+ // The printerId not used in PrinterCapabilitiesInfo
+ new PrinterCapabilitiesInfo.Builder(mDiscoverySession.getService()
+ .generatePrinterId("unused"))
+ .setMinMargins(new Margins(200, 200, 200, 200))
+ .addMediaSize(MediaSize.ISO_A4, true)
+ .addResolution(
+ new Resolution("300x300", "300x300", 300, 300),
+ true)
+ .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+ PrintAttributes.COLOR_MODE_COLOR)
+ .build(),
+ null
+ };
+
+ List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+ for (String localPrinterId : localPrinterIds) {
+ for (String name : names) {
+ for (int status : statusList) {
+ for (int iconResourceId : iconResourceIds) {
+ for (boolean hasCustomPrinterIcon : hasCustomPrinterIcons) {
+ for (String description : descriptions) {
+ for (PendingIntent infoIntent : infoIntents) {
+ for (PrinterCapabilitiesInfo capabilities
+ : capabilityList) {
+ PrinterId printerId = null;
+ if (localPrinterId != null) {
+ printerId = mDiscoverySession.getService()
+ .generatePrinterId(localPrinterId
+ + printers.size());
+ }
+
+ // Constructor
+ PrinterInfo.Builder b = null;
+ RuntimeException e = null;
+ try {
+ b = new PrinterInfo.Builder(
+ printerId, name, status);
+ } catch (RuntimeException ex) {
+ e = ex;
+ }
+
+ // Expect exception if any of the parameters was
+ // bad
+ if (printerId == null
+ || TextUtils.isEmpty(name)
+ || !isValidStatus(status)) {
+ if (e == null) {
+ throw new IllegalStateException();
+ } else {
+ b = badPrinter;
+ }
+ } else if (e != null) {
+ throw e;
+ }
+
+ // IconResourceId
+ e = null;
+ try {
+ b.setIconResourceId(iconResourceId);
+ } catch (RuntimeException ex) {
+ e = ex;
+ }
+
+ // Expect exception if iconResourceId was bad
+ // We do allow invalid Ids as the printerInfo
+ // might be created after the package of the
+ // printer is already gone if the printer is a
+ // historical printer.
+ if (iconResourceId < 0) {
+ if (e == null) {
+ throw new IllegalStateException();
+ } else {
+ b = badPrinter;
+ }
+ } else if (e != null) {
+ throw e;
+ }
+
+ // Status
+ e = null;
+ try {
+ b.setStatus(status);
+ } catch (RuntimeException ex) {
+ e = ex;
+ }
+
+ // Expect exception is status is not valid
+ if (!isValidStatus(status)) {
+ if (e == null) {
+ throw new IllegalStateException();
+ } else {
+ b = badPrinter;
+ }
+ } else if (e != null) {
+ throw e;
+ }
+
+ // Name
+ e = null;
+ try {
+ b.setName(name);
+ } catch (RuntimeException ex) {
+ e = ex;
+ }
+
+ // Expect exception if name is empty
+ if (TextUtils.isEmpty(name)) {
+ if (e == null) {
+ throw new IllegalStateException();
+ } else {
+ b = badPrinter;
+ }
+ } else if (e != null) {
+ throw e;
+ }
+
+ // hasCustomPrinterIcon
+ if (hasCustomPrinterIcon) {
+ b.setHasCustomPrinterIcon();
+ }
+
+ // Description
+ b.setDescription(description);
+
+ // InfoIntent
+ b.setInfoIntent(infoIntent);
+
+ // Capabilities
+ b.setCapabilities(capabilities);
+
+ PrinterInfo printer = b.build();
+
+ // Don't create bad printers
+ if (b == badPrinter) {
+ continue;
+ }
+
+ // Verify get* methods
+ if (printer.getId() != printerId
+ || printer.getName() != name
+ || printer.getStatus() != status
+ || printer
+ .getDescription() != description
+ || printer.getCapabilities()
+ != capabilities) {
+ throw new IllegalStateException();
+ }
+
+ printers.add(printer);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ mDiscoverySession.addPrinters(printers);
+ }
+ return null;
+ }
+ }, null, null, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ return null;
+ }
+ }, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ CustomPrinterIconCallback callback = (CustomPrinterIconCallback) invocation
+ .getArguments()[1];
+
+ if (mIcon != null) {
+ callback.onCustomPrinterIconLoaded(mIcon);
+ }
+ return null;
+ }
+ }, null, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ // Take a note onDestroy was called.
+ onPrinterDiscoverySessionDestroyCalled();
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Create mock service callback for a session.
+ *
+ * @param sessionCallbacks The callbacks of the session
+ */
+ private PrintServiceCallbacks createFirstMockPrinterServiceCallbacks(
+ final PrinterDiscoverySessionCallbacks sessionCallbacks) {
+ return createMockPrintServiceCallbacks(
+ new Answer<PrinterDiscoverySessionCallbacks>() {
+ @Override
+ public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+ return sessionCallbacks;
+ }
+ },
+ null, null);
+ }
+
+ /**
+ * Test that all printInfos possible can be used and that invalid printInfos throw exceptions.
+ *
+ * @throws Exception If anything is unexpected.
+ */
+ public void testPrinterInfos()
+ throws Exception {
+ if (!supportsPrinting()) {
+ return;
+ }
+ // 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);
+
+ // 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));
+
+ // Create a print adapter that respects the print contract.
+ PrintDocumentAdapter adapter = createMockPrintDocumentAdapter();
+
+ // Start printing.
+ print(adapter);
+
+ // Wait for write of the first page.
+ waitForWriteAdapterCallback();
+
+ // Open destination spinner
+ UiObject destinationSpinner = getUiDevice().findObject(new UiSelector().resourceId(
+ "com.android.printspooler:id/destination_spinner"));
+ destinationSpinner.click();
+ }
+}
diff --git a/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java b/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java
index 6b2c3a9..2e0e729 100644
--- a/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java
+++ b/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java
@@ -17,6 +17,7 @@
package android.print.cts.services;
import android.print.PrinterId;
+import android.printservice.CustomPrinterIconCallback;
import java.util.List;
@@ -40,6 +41,9 @@
public abstract void onStartPrinterStateTracking(PrinterId printerId);
+ public abstract void onRequestCustomPrinterIcon(PrinterId printerId,
+ CustomPrinterIconCallback callback);
+
public abstract void onStopPrinterStateTracking(PrinterId printerId);
public abstract void onDestroy();
diff --git a/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java b/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java
index fdc2713..4c2d8b8 100644
--- a/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java
+++ b/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java
@@ -17,6 +17,7 @@
package android.print.cts.services;
import android.print.PrinterId;
+import android.printservice.CustomPrinterIconCallback;
import android.printservice.PrintService;
import android.printservice.PrinterDiscoverySession;
@@ -68,6 +69,14 @@
}
@Override
+ public void onRequestCustomPrinterIcon(PrinterId printerId,
+ CustomPrinterIconCallback callback) {
+ if (mCallbacks != null) {
+ mCallbacks.onRequestCustomPrinterIcon(printerId, callback);
+ }
+ }
+
+ @Override
public void onStopPrinterStateTracking(PrinterId printerId) {
if (mCallbacks != null) {
mCallbacks.onStopPrinterStateTracking(printerId);
diff --git a/tests/tests/provider/Android.mk b/tests/tests/provider/Android.mk
index 5064d4b..6542c81 100644
--- a/tests/tests/provider/Android.mk
+++ b/tests/tests/provider/Android.mk
@@ -25,6 +25,11 @@
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
diff --git a/tests/tests/provider/AndroidManifest.xml b/tests/tests/provider/AndroidManifest.xml
index ed180f6..b4836d0 100644
--- a/tests/tests/provider/AndroidManifest.xml
+++ b/tests/tests/provider/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.provider">
+ package="android.provider.cts">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
@@ -50,7 +50,7 @@
</activity>
<service android:name="android.provider.cts.contacts.account.MockAccountService"
- process="com.android.cts.provider"
+ process="android.provider.cts"
android:exported="true">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator"/>
@@ -72,14 +72,14 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.provider"
+ android:targetPackage="android.provider.cts"
android:label="CTS tests of android.provider">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
<instrumentation android:name="android.provider.cts.CalendarTest$CalendarEmmaTestRunner"
- android:targetPackage="com.android.cts.provider"
+ android:targetPackage="android.provider.cts"
android:label="Augmented CTS tests of Calendar provider"/>
</manifest>
diff --git a/tests/tests/provider/AndroidTest.xml b/tests/tests/provider/AndroidTest.xml
index ae603a3..4c87f9c 100644
--- a/tests/tests/provider/AndroidTest.xml
+++ b/tests/tests/provider/AndroidTest.xml
@@ -1,22 +1,25 @@
<?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
- -->
-<configuration description="Test module config for provider">
- <include name="common-config" />
- <option name="cts-apk-installer:test-file-name" value="CtsProviderTestCases.apk" />
- <option name="run-command:run-command"
- value="ime enable com.android.cts.provider/.MockInputMethodService" />
+<!-- 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.
+-->
+<configuration description="Config for CTS Provider test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsProviderTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.provider.cts" />
+ <option name="runtime-hint" value="7m19s" />
+ </test>
</configuration>
\ No newline at end of file
diff --git a/tests/tests/provider/OldAndroidTest.xml b/tests/tests/provider/OldAndroidTest.xml
new file mode 100644
index 0000000..bd22d8f
--- /dev/null
+++ b/tests/tests/provider/OldAndroidTest.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+<configuration description="Test module config for provider">
+ <include name="common-config" />
+ <option name="run-command:run-command"
+ value="ime enable android.provider.cts/.MockInputMethodService" />
+</configuration>
diff --git a/tests/tests/provider/src/android/provider/cts/CalendarTest.java b/tests/tests/provider/src/android/provider/cts/CalendarTest.java
index c9e2213..df31a19 100644
--- a/tests/tests/provider/src/android/provider/cts/CalendarTest.java
+++ b/tests/tests/provider/src/android/provider/cts/CalendarTest.java
@@ -3279,7 +3279,7 @@
@MediumTest
public void testMutatorSetCorrectly() {
String account = "ec_account";
- String packageName = "com.android.cts.provider";
+ String packageName = "android.provider.cts";
int seed = 0;
// Clean up just in case
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_OrganizationTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_OrganizationTest.java
index 2de3b05..fa83d4f 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_OrganizationTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_OrganizationTest.java
@@ -16,9 +16,12 @@
package android.provider.cts;
+import junit.framework.Assert;
+
import android.content.res.Resources;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Organization;
+import android.provider.ContactsContract.Data;
import android.test.AndroidTestCase;
public class ContactsContract_CommonDataKinds_OrganizationTest extends AndroidTestCase {
@@ -51,4 +54,10 @@
assertTrue(res != 0);
assertEquals(label, Organization.getTypeLabel(mResources, Im.TYPE_CUSTOM, label));
}
+
+ public void testPhoneticNameStyleColumnName() throws Exception {
+ // Make sure the column name is data10 and not phonetic_name_style
+ // from the parent class.
+ assertEquals(Data.DATA10, Organization.PHONETIC_NAME_STYLE);
+ }
}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_StatusUpdatesTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_StatusUpdatesTest.java
index 2f3cdeb..375d7b2 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_StatusUpdatesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_StatusUpdatesTest.java
@@ -33,7 +33,7 @@
public class ContactsContract_StatusUpdatesTest extends AndroidTestCase {
- private static final String ACCOUNT_TYPE = "com.android.cts.provider";
+ private static final String ACCOUNT_TYPE = "android.provider.cts";
private static final String ACCOUNT_NAME = "ContactsContract_StatusUpdatesTest";
private ContentResolver mResolver;
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_StructuredPhoneticName.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_StructuredPhoneticName.java
index 4efd9a7..42bc6d2 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_StructuredPhoneticName.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_StructuredPhoneticName.java
@@ -24,6 +24,7 @@
import android.provider.ContactsContract.AggregationExceptions;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.DisplayNameSources;
import android.provider.ContactsContract.RawContacts;
import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
@@ -72,6 +73,12 @@
DisplayNameSources.STRUCTURED_PHONETIC_NAME);
}
+ public void testPhoneticNameStyleColumnName() throws Exception {
+ // Make sure the column name is data11 and not phonetic_name_style
+ // from the parent class.
+ assertEquals(Data.DATA11, StructuredName.PHONETIC_NAME_STYLE);
+ }
+
public void testPhoneticStructuredName_phoneticPriority1() throws Exception {
// Setup: one raw contact has a complex phonetic name and the other a simple given name
TestRawContact rawContact1 = mBuilder.newRawContact()
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsTest.java
index 4d1cb86..ff785fd 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsTest.java
@@ -220,12 +220,12 @@
try {
Context context = getInstrumentation().getTargetContext();
InputStream inputStream = context.getResources().openRawResource(
- com.android.cts.provider.R.drawable.testimage);
+ android.provider.cts.R.drawable.testimage);
int size = inputStream.available();
byte[] data = new byte[size];
inputStream.read(data);
BitmapDrawable sourceDrawable = (BitmapDrawable) context.getResources().getDrawable(
- com.android.cts.provider.R.drawable.testimage);
+ android.provider.cts.R.drawable.testimage);
// Test: insert
ContentValues value = new ContentValues();
value.put(Photos.PERSON_ID, 1);
diff --git a/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java b/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
index 6b5de96..d887aa7 100644
--- a/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
+++ b/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
@@ -257,7 +257,7 @@
Context context = getInstrumentation().getTargetContext();
try {
InputStream inputStream = context.getResources().openRawResource(
- com.android.cts.provider.R.drawable.testimage);
+ android.provider.cts.R.drawable.testimage);
int size = inputStream.available();
byte[] data = new byte[size];
inputStream.read(data);
@@ -275,12 +275,12 @@
assertNull(photoStream);
bitmap = People.loadContactPhoto(context, mPeopleRowsAdded.get(0),
- com.android.cts.provider.R.drawable.size_48x48, null);
+ android.provider.cts.R.drawable.size_48x48, null);
assertEquals(96, bitmap.getWidth());
assertEquals(64, bitmap.getHeight());
bitmap = People.loadContactPhoto(context, null,
- com.android.cts.provider.R.drawable.size_48x48, null);
+ android.provider.cts.R.drawable.size_48x48, null);
assertNotNull(bitmap);
} catch (IOException e) {
fail("Unexpected IOException");
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStoreAudioTestHelper.java b/tests/tests/provider/src/android/provider/cts/MediaStoreAudioTestHelper.java
index c9eb506..56d74f3 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStoreAudioTestHelper.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStoreAudioTestHelper.java
@@ -107,7 +107,7 @@
public static final String DISPLAY_NAME = "Jam -Michael Jackson";
public static final String INTERNAL_DATA =
- "/data/data/com.android.cts.provider/files/Jam.mp3";
+ "/data/data/android.provider.cts/files/Jam.mp3";
public static final String FILE_NAME = "Jam.mp3";
@@ -190,7 +190,7 @@
Environment.getExternalStorageDirectory().getPath() + "/" + FILE_NAME;
public static final String INTERNAL_DATA =
- "/data/data/com.android.cts.provider/files/Jam_live.mp3";
+ "/data/data/android.provider.cts/files/Jam_live.mp3";
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java
index 84da62a..3bd81ce 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java
@@ -16,7 +16,7 @@
package android.provider.cts;
-import com.android.cts.provider.R;
+import android.provider.cts.R;
import android.content.ContentResolver;
import android.content.ContentValues;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_PlaylistsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_PlaylistsTest.java
index 8dcb1a8..463dfcb 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_PlaylistsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_PlaylistsTest.java
@@ -112,7 +112,7 @@
public void testStoreAudioPlaylistsInternal() {
ContentValues values = new ContentValues();
values.put(Playlists.NAME, "My favourites");
- values.put(Playlists.DATA, "/data/data/com.android.cts.provider/files/my_favorites.pl");
+ values.put(Playlists.DATA, "/data/data/android.provider.cts/files/my_favorites.pl");
long dateAdded = System.currentTimeMillis();
values.put(Playlists.DATE_ADDED, dateAdded);
long dateModified = System.currentTimeMillis();
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_Playlists_MembersTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_Playlists_MembersTest.java
index 58c1cdf..cc69942 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_Playlists_MembersTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_Playlists_MembersTest.java
@@ -454,7 +454,7 @@
public void testStoreAudioPlaylistsMembersInternal() {
ContentValues values = new ContentValues();
values.put(Playlists.NAME, "My favourites");
- values.put(Playlists.DATA, "/data/data/com.android.cts.provider/files/my_favorites.pl");
+ values.put(Playlists.DATA, "/data/data/android.provider.cts/files/my_favorites.pl");
long dateAdded = System.currentTimeMillis();
values.put(Playlists.DATE_ADDED, dateAdded);
long dateModified = System.currentTimeMillis();
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
index 8fc5df1..3ccc61b 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
@@ -16,7 +16,7 @@
package android.provider.cts;
-import com.android.cts.provider.R;
+import android.provider.cts.R;
import android.content.ContentResolver;
import android.content.ContentUris;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
index 7469f8e..589b5cd 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
@@ -16,7 +16,7 @@
package android.provider.cts;
-import com.android.cts.provider.R;
+import android.provider.cts.R;
import android.content.ContentResolver;
import android.content.ContentValues;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
index ec9db8b..db3db6b 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
@@ -16,7 +16,7 @@
package android.provider.cts;
-import com.android.cts.provider.R;
+import android.provider.cts.R;
import android.content.ContentResolver;
import android.content.ContentUris;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
index 89de9c6..e50f18a 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
@@ -16,7 +16,7 @@
package android.provider.cts;
-import com.android.cts.provider.R;
+import android.provider.cts.R;
import android.content.ContentResolver;
import android.content.ContentValues;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
index f84b75c..5ec765c 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
@@ -17,7 +17,7 @@
package android.provider.cts;
-import com.android.cts.provider.R;
+import android.provider.cts.R;
import android.content.ContentResolver;
import android.content.ContentValues;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
index 974eeb71..9c41274 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
@@ -16,7 +16,7 @@
package android.provider.cts;
-import com.android.cts.provider.R;
+import android.provider.cts.R;
import android.content.ContentResolver;
import android.content.ContentUris;
diff --git a/tests/tests/provider/src/android/provider/cts/PhotoUtil.java b/tests/tests/provider/src/android/provider/cts/PhotoUtil.java
index ec4fdef..4debd8f 100644
--- a/tests/tests/provider/src/android/provider/cts/PhotoUtil.java
+++ b/tests/tests/provider/src/android/provider/cts/PhotoUtil.java
@@ -16,7 +16,7 @@
package android.provider.cts;
-import com.android.cts.provider.R;
+import android.provider.cts.R;
import android.content.Context;
import android.cts.util.FileUtils;
diff --git a/tests/tests/renderscript/Android.mk b/tests/tests/renderscript/Android.mk
index 5266e34..9f196ca 100644
--- a/tests/tests/renderscript/Android.mk
+++ b/tests/tests/renderscript/Android.mk
@@ -37,5 +37,8 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/renderscript/AndroidManifest.xml b/tests/tests/renderscript/AndroidManifest.xml
index 6e67f9e..c6b3891 100644
--- a/tests/tests/renderscript/AndroidManifest.xml
+++ b/tests/tests/renderscript/AndroidManifest.xml
@@ -19,7 +19,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.renderscript">
+ package="android.renderscript.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -30,7 +30,7 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.renderscript"
+ android:targetPackage="android.renderscript.cts"
android:label="CTS tests of Renderscript component">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/renderscript/AndroidTest.xml b/tests/tests/renderscript/AndroidTest.xml
new file mode 100644
index 0000000..2e69534
--- /dev/null
+++ b/tests/tests/renderscript/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Configuration for Renderscript Tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsRenderscriptTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.renderscript.cts" />
+ <option name="runtime-hint" value="9m35s" />
+ </test>
+</configuration>
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/refocus/RefocusTest.java b/tests/tests/renderscript/src/android/renderscript/cts/refocus/RefocusTest.java
index 666d9c5..b8fbdfe 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/refocus/RefocusTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/refocus/RefocusTest.java
@@ -25,7 +25,7 @@
import android.renderscript.cts.RSBaseCompute;
import android.util.Log;
-import com.android.cts.renderscript.R;
+import android.renderscript.cts.R;
import java.io.IOException;
diff --git a/tests/tests/renderscriptlegacy/Android.mk b/tests/tests/renderscriptlegacy/Android.mk
index 31d8ed9..6aca19b 100644
--- a/tests/tests/renderscriptlegacy/Android.mk
+++ b/tests/tests/renderscriptlegacy/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := 19
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/renderscriptlegacy/AndroidManifest.xml b/tests/tests/renderscriptlegacy/AndroidManifest.xml
index 0c0498a..bd1184f 100644
--- a/tests/tests/renderscriptlegacy/AndroidManifest.xml
+++ b/tests/tests/renderscriptlegacy/AndroidManifest.xml
@@ -19,7 +19,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.renderscriptlegacy">
+ package="android.renderscriptlegacy.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -28,7 +28,7 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.renderscriptlegacy"
+ android:targetPackage="android.renderscriptlegacy.cts"
android:label="CTS tests of Renderscript component">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/renderscriptlegacy/AndroidTest.xml b/tests/tests/renderscriptlegacy/AndroidTest.xml
new file mode 100644
index 0000000..3523dfe
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Configuration for Renderscript legacy Tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsRenderscriptLegacyTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.renderscriptlegacy.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/rscpp/Android.mk b/tests/tests/rscpp/Android.mk
index 0eb32b5..35e61fa 100644
--- a/tests/tests/rscpp/Android.mk
+++ b/tests/tests/rscpp/Android.mk
@@ -35,5 +35,8 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
include $(LOCAL_PATH)/librscpptest/Android.mk
diff --git a/tests/tests/rscpp/AndroidManifest.xml b/tests/tests/rscpp/AndroidManifest.xml
index b68ebc3..035d242 100644
--- a/tests/tests/rscpp/AndroidManifest.xml
+++ b/tests/tests/rscpp/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.rscpp">
+ package="android.rscpp.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -24,7 +24,7 @@
<!-- This is a self-instrumenting test package. -->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.rscpp"
+ android:targetPackage="android.rscpp.cts"
android:label="CTS tests of RenderScript C++ component">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/rscpp/AndroidTest.xml b/tests/tests/rscpp/AndroidTest.xml
new file mode 100644
index 0000000..1e7c41f
--- /dev/null
+++ b/tests/tests/rscpp/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<configuration description="Configuration for renderscript cpp Tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsRsCppTestCases.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.rscpp.cts" />
+ <option name="runtime-hint" value="2m" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/rscpp/librscpptest/clear_object.rs b/tests/tests/rscpp/librscpptest/clear_object.rs
index 70ba42b..cb6a0ad 100644
--- a/tests/tests/rscpp/librscpptest/clear_object.rs
+++ b/tests/tests/rscpp/librscpptest/clear_object.rs
@@ -1,5 +1,5 @@
#pragma version(1)
-#pragma rs java_package_name(com.android.cts.rscpp)
+#pragma rs java_package_name(android.rscpp.cts)
rs_allocation allocation;
diff --git a/tests/tests/rscpp/librscpptest/fe_all.rs b/tests/tests/rscpp/librscpptest/fe_all.rs
index dc20ba7..d5076bf 100644
--- a/tests/tests/rscpp/librscpptest/fe_all.rs
+++ b/tests/tests/rscpp/librscpptest/fe_all.rs
@@ -1,5 +1,5 @@
#pragma version(1)
-#pragma rs java_package_name(com.android.cts.rscpp)
+#pragma rs java_package_name(android.rscpp.cts)
void test_i8(const char *ain, uchar *aout) {
aout[0] = ain[0] + 1;
diff --git a/tests/tests/rscpp/librscpptest/setelementat.rs b/tests/tests/rscpp/librscpptest/setelementat.rs
index 5a84552..fc706de 100644
--- a/tests/tests/rscpp/librscpptest/setelementat.rs
+++ b/tests/tests/rscpp/librscpptest/setelementat.rs
@@ -1,5 +1,5 @@
#pragma version(1)
-#pragma rs java_package_name(com.android.cts.rscpp)
+#pragma rs java_package_name(android.rscpp.cts)
#pragma rs_fp_relaxed
int memset_toValue = 0;
diff --git a/tests/tests/rscpp/librscpptest/shared.rsh b/tests/tests/rscpp/librscpptest/shared.rsh
index c5599d7..70668e0 100644
--- a/tests/tests/rscpp/librscpptest/shared.rsh
+++ b/tests/tests/rscpp/librscpptest/shared.rsh
@@ -1,5 +1,5 @@
#pragma version(1)
-#pragma rs java_package_name(com.android.cts.rscpp)
+#pragma rs java_package_name(android.rscpp.cts)
static int64_t g_time;
diff --git a/tests/tests/sax/Android.mk b/tests/tests/sax/Android.mk
index a468778..192edfc 100644
--- a/tests/tests/sax/Android.mk
+++ b/tests/tests/sax/Android.mk
@@ -29,4 +29,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/sax/AndroidManifest.xml b/tests/tests/sax/AndroidManifest.xml
index 63c568b..c15bd7a 100644
--- a/tests/tests/sax/AndroidManifest.xml
+++ b/tests/tests/sax/AndroidManifest.xml
@@ -16,14 +16,14 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.sax">
+ package="android.sax.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.sax"
+ android:targetPackage="android.sax.cts"
android:label="CTS tests of android.sax">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/sax/AndroidTest.xml b/tests/tests/sax/AndroidTest.xml
new file mode 100644
index 0000000..14ec1c3
--- /dev/null
+++ b/tests/tests/sax/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS SAX test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSaxTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.sax.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index 08750d6..a6e7a45 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -14,6 +14,55 @@
LOCAL_PATH:= $(call my-dir)
+test_executable := CtsAslrMallocTestCases
+list_executable := $(test_executable)_list
+
+include $(CLEAR_VARS)
+LOCAL_MODULE:= $(test_executable)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES := \
+ external/gtest/include
+
+LOCAL_SRC_FILES := \
+ src/AslrMallocTest.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libbase \
+ libutils \
+ liblog \
+
+LOCAL_STATIC_LIBRARIES := \
+ libgtest
+
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+include $(BUILD_CTS_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_MODULE := $(list_executable)
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+ src/AslrMallocTest.cpp
+
+LOCAL_CFLAGS := \
+ -DBUILD_ONLY \
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog
+
+include $(BUILD_HOST_NATIVE_TEST)
+
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
@@ -21,7 +70,7 @@
# Include both the 32 and 64 bit versions
LOCAL_MULTILIB := both
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestserver ctstestrunner ctsdeviceutil guava
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestserver ctstestrunner ctsdeviceutil compatibility-device-util guava
LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy
@@ -34,6 +83,9 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 3039f81..7a67b08 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -16,12 +16,13 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.security">
+ package="android.security.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -39,8 +40,8 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.security"
- android:label="CTS tests of com.android.cts.security">
+ android:targetPackage="android.security.cts"
+ android:label="CTS tests of android.security.cts">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
new file mode 100644
index 0000000..ddbb4dc
--- /dev/null
+++ b/tests/tests/security/AndroidTest.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<configuration description="Config for CTS security test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSecurityTestCases.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="CtsAslrMallocTestCases->/data/local/tmp/CtsAslrMallocTestCases" />
+ <option name="append-bitness" value="true" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="CtsAslrMallocTestCases" />
+ <option name="runtime-hint" value="3m30s" />
+ </test>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.security.cts" />
+ <option name="runtime-hint" value="3m15s" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 327eefc..07bad55 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -32,9 +32,9 @@
android_security_cts_MMapExecutableTest.cpp \
android_security_cts_AudioPolicyBinderTest.cpp \
android_security_cts_EncryptionTest.cpp \
- android_security_cts_MediaPlayerInfoLeakTest.cpp \
- android_security_cts_AudioEffectBinderTest.cpp \
android_security_cts_AudioFlingerBinderTest.cpp \
+ android_security_cts_AudioEffectBinderTest.cpp \
+ android_security_cts_MediaPlayerInfoLeakTest.cpp \
android_security_cts_StagefrightFoundationTest.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 6dc025a..99ceda2 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -27,8 +27,8 @@
extern int register_android_security_cts_AudioPolicyBinderTest(JNIEnv* env);
extern int register_android_security_cts_AudioFlingerBinderTest(JNIEnv* env);
extern int register_android_security_cts_EncryptionTest(JNIEnv* env);
-extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
extern int register_android_security_cts_AudioEffectBinderTest(JNIEnv* env);
+extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
extern int register_android_security_cts_StagefrightFoundationTest(JNIEnv* env);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
@@ -74,11 +74,15 @@
return JNI_ERR;
}
- if (register_android_security_cts_MediaPlayerInfoLeakTest(env)) {
+ if (register_android_security_cts_AudioFlingerBinderTest(env)) {
return JNI_ERR;
}
- if (register_android_security_cts_AudioEffectBinderTest(env)) {
+ if (register_android_security_cts_AudioEffectBinderTest(env)) {
+ return JNI_ERR;
+ }
+
+ if (register_android_security_cts_MediaPlayerInfoLeakTest(env)) {
return JNI_ERR;
}
diff --git a/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp b/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp
index c916122..fb80d6b 100644
--- a/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp
@@ -92,6 +92,9 @@
status_t status = AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
"0", "");
+ if (status != NO_ERROR) {
+ return false;
+ }
bool mute;
status = AudioSystem::getMasterMute(&mute);
@@ -133,6 +136,9 @@
status_t status = AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
"0", "");
+ if (status != NO_ERROR) {
+ return false;
+ }
float vol;
status = AudioSystem::getMasterVolume(&vol);
diff --git a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
index 350309b..ec7e4bd 100644
--- a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
@@ -35,6 +35,7 @@
#include <inttypes.h>
#include <linux/sysctl.h>
#include <arpa/inet.h>
+#include <linux/ipc.h>
/*
* Returns true iff this device is vulnerable to CVE-2013-2094.
@@ -251,6 +252,25 @@
return true;
}
+#define SHMEMSIZE 0x1 /* request one page */
+static jboolean android_security_cts_NativeCodeTest_doSysVipcTest(JNIEnv*, jobject)
+{
+ key_t key = 0x1a25;
+
+#if defined(__i386__) || (_MIPS_SIM == _MIPS_SIM_ABI32)
+ /* system call does not exist for x86 or mips 32 */
+ return true;
+#else
+ /*
+ * Not supported in bionic. Must directly invoke syscall
+ * Only acceptable errno is ENOSYS: shmget syscall
+ * function not implemented
+ */
+ return ((syscall(SYS_shmget, key, SHMEMSIZE, IPC_CREAT | 0666) == -1)
+ && (errno == ENOSYS));
+#endif
+}
+
static JNINativeMethod gMethods[] = {
{ "doPerfEventTest", "()Z",
(void *) android_security_cts_NativeCodeTest_doPerfEventTest },
@@ -266,6 +286,8 @@
(void *) android_security_cts_NativeCodeTest_doNvmapIocFromIdTest },
{ "doPingPongRootTest", "()Z",
(void *) android_security_cts_NativeCodeTest_doPingPongRootTest },
+ { "doSysVipcTest", "()Z",
+ (void *) android_security_cts_NativeCodeTest_doSysVipcTest },
};
int register_android_security_cts_NativeCodeTest(JNIEnv* env)
diff --git a/tests/tests/security/src/AslrMallocTest.cpp b/tests/tests/security/src/AslrMallocTest.cpp
new file mode 100644
index 0000000..6e773cb
--- /dev/null
+++ b/tests/tests/security/src/AslrMallocTest.cpp
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "AslrMallocTest"
+
+#if !defined(BUILD_ONLY)
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <linux/limits.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <unordered_set>
+#endif
+
+#include <gtest/gtest.h>
+#include <string>
+#include <utils/Log.h>
+
+/* minimum entropy for malloc return addresses */
+const size_t minEntropyBits = 8;
+
+/* test using the following allocation sizes */
+const size_t allocSizes[] = {
+ 1 << 8, // small
+ 1 << 16, // large
+ 1 << 23 // huge
+};
+
+/* when started using this argument followed by the allocation size,
+ * performs malloc(size) and prints out the address */
+static const std::string argPrint = "--print-malloc-address";
+
+#if !defined(BUILD_ONLY)
+class AslrMallocTest : public ::testing::Test
+{
+protected:
+ std::string self_;
+
+ AslrMallocTest() {}
+ virtual ~AslrMallocTest() {}
+
+ virtual void SetUp()
+ {
+ /* path to self for exec */
+ char path[PATH_MAX];
+ auto size = readlink("/proc/self/exe", path, sizeof(path));
+ ASSERT_TRUE(size > 0 && size < PATH_MAX);
+ path[size] = '\0';
+ self_ = path;
+ }
+
+ void GetAddress(size_t allocSize, uintptr_t& address)
+ {
+ int fds[2];
+ ASSERT_TRUE(pipe(fds) != -1);
+
+ auto pid = fork();
+ ASSERT_TRUE(pid != -1);
+
+ if (pid == 0) {
+ /* child process */
+ ASSERT_TRUE(TEMP_FAILURE_RETRY(dup2(fds[1], STDOUT_FILENO)) != -1);
+
+ for (auto fd : fds) {
+ TEMP_FAILURE_RETRY(close(fd));
+ }
+
+ /* exec self to print malloc output */
+ ASSERT_TRUE(execl(self_.c_str(), self_.c_str(), argPrint.c_str(),
+ android::base::StringPrintf("%zu", allocSize).c_str(),
+ nullptr) != -1);
+ }
+
+ /* parent process */
+ TEMP_FAILURE_RETRY(close(fds[1]));
+
+ std::string output;
+ ASSERT_TRUE(android::base::ReadFdToString(fds[0], &output));
+ TEMP_FAILURE_RETRY(close(fds[0]));
+
+ int status;
+ ASSERT_TRUE(waitpid(pid, &status, 0) != -1);
+ ASSERT_TRUE(WEXITSTATUS(status) == EXIT_SUCCESS);
+
+ ASSERT_TRUE(android::base::ParseUint(output.c_str(), &address));
+ }
+
+ void TestRandomization()
+ {
+ /* should be sufficient to see minEntropyBits when rounded up */
+ size_t iterations = 2 * (1 << minEntropyBits);
+
+ for (auto size : allocSizes) {
+ ALOGV("running %zu iterations for allocation size %zu",
+ iterations, size);
+
+ /* collect unique return addresses */
+ std::unordered_set<uintptr_t> addresses;
+
+ for (size_t i = 0; i < iterations; ++i) {
+ uintptr_t address;
+ GetAddress(size, address);
+
+ addresses.emplace(address);
+ }
+
+ size_t entropy = static_cast<size_t>(0.5 +
+ log2(static_cast<double>(addresses.size())));
+
+ ALOGV("%zu bits of entropy for allocation size %zu (minimum %zu)",
+ entropy, size, minEntropyBits);
+ ALOGE_IF(entropy < minEntropyBits,
+ "insufficient entropy for malloc(%zu)", size);
+ ASSERT_TRUE(entropy >= minEntropyBits);
+ }
+ }
+};
+#else /* defined(BUILD_ONLY) */
+class AslrMallocTest : public ::testing::Test
+{
+protected:
+ void TestRandomization() {}
+};
+#endif
+
+TEST_F(AslrMallocTest, testMallocRandomization) {
+ TestRandomization();
+}
+
+int main(int argc, char **argv)
+{
+#if !defined(BUILD_ONLY)
+ if (argc == 3 && argPrint == argv[1]) {
+ size_t size;
+
+ if (!android::base::ParseUint(argv[2], &size)) {
+ return EXIT_FAILURE;
+ }
+
+ printf("%p", malloc(size));
+ return EXIT_SUCCESS;
+ }
+#endif
+
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/tests/tests/security/src/android/security/cts/AslrTest.java b/tests/tests/security/src/android/security/cts/AslrTest.java
index 913b49b..774df87 100644
--- a/tests/tests/security/src/android/security/cts/AslrTest.java
+++ b/tests/tests/security/src/android/security/cts/AslrTest.java
@@ -16,20 +16,89 @@
package android.security.cts;
+import android.test.InstrumentationTestCase;
import junit.framework.TestCase;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import android.cts.util.ReadElf;
/**
* Verify that ASLR is properly enabled on Android Compatible devices.
*/
-public class AslrTest extends TestCase {
+public class AslrTest extends InstrumentationTestCase {
+
+ private static final int aslrMinEntropyBits = 8;
+
+ private static final String TAG = "AslrTest";
+
+ private String readMappingAddress(String mappingName) throws Exception {
+ ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
+ .executeShellCommand("/system/bin/cat /proc/self/maps");
+
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(new FileInputStream(pfd.getFileDescriptor())));
+
+ Pattern p = Pattern.compile("^([a-f0-9]+)\\-.+\\[" + mappingName + "\\]$");
+ String line;
+
+ while ((line = reader.readLine()) != null) {
+ Matcher m = p.matcher(line);
+
+ if (m.matches()) {
+ return m.group(1);
+ }
+ }
+
+ return null;
+ }
+
+ private int calculateEntropyBits(String mappingName) throws Exception {
+ HashMap<String, Integer> addresses = new HashMap<String, Integer>();
+
+ // Sufficient number of iterations to ensure we should see at least
+ // aslrMinEntropyBits
+ for (int i = 0; i < 2 * (1 << aslrMinEntropyBits); i++) {
+ addresses.put(readMappingAddress(mappingName), 1);
+ }
+
+ double entropy = Math.log(addresses.size()) / Math.log(2);
+
+ Log.i(TAG, String.format("%.1f", entropy) +
+ " bits of entropy for " + mappingName);
+
+ return (int) Math.round(entropy);
+ }
+
+ private void testMappingEntropy(String mappingName) throws Exception {
+ if (readMappingAddress(mappingName) == null) {
+ Log.i(TAG, mappingName + " does not exist");
+ return;
+ }
+
+ int entropy = calculateEntropyBits(mappingName);
+
+ assertTrue("Insufficient " + mappingName + " randomization (" +
+ entropy + " bits, >= " + aslrMinEntropyBits + " required)",
+ entropy >= aslrMinEntropyBits);
+ }
+
+ public void testRandomization() throws Exception {
+ testMappingEntropy("stack");
+ testMappingEntropy("heap");
+ testMappingEntropy("anon:libc_malloc");
+ }
public void testOneExecutableIsPie() throws IOException {
assertTrue(ReadElf.read(new File("/system/bin/cat")).isPIE());
@@ -51,5 +120,4 @@
}
}
}
-
}
diff --git a/tests/tests/security/src/android/security/cts/CertificateData.java b/tests/tests/security/src/android/security/cts/CertificateData.java
index 0c311e0..59803d3 100644
--- a/tests/tests/security/src/android/security/cts/CertificateData.java
+++ b/tests/tests/security/src/android/security/cts/CertificateData.java
@@ -73,7 +73,6 @@
"8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4",
"2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19",
"BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD",
- "97:81:79:50:D8:1C:96:70:CC:34:D8:09:CF:79:44:31:36:7E:F4:74",
"85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF",
"58:11:9F:0E:12:82:87:EA:50:FD:D9:87:45:6F:4F:78:DC:FA:D6:D4",
"9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB",
@@ -82,7 +81,6 @@
"B4:35:D4:E1:11:9D:1C:66:90:A7:49:EB:B3:94:BD:63:7B:A7:82:B7",
"A9:E9:78:08:14:37:58:88:F2:05:19:B0:6D:2B:0D:2B:60:16:90:7D",
"60:D6:89:74:B5:C2:65:9E:8A:0F:C1:88:7C:88:D2:46:69:1B:18:2C",
- "D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A",
"D8:EB:6B:41:51:92:59:E0:F3:E7:85:00:C0:3D:B6:88:97:C9:EE:FC",
"66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B",
"DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9",
@@ -97,12 +95,10 @@
"70:17:9B:86:8C:00:A4:FA:60:91:52:22:3F:9F:3E:32:BD:E0:05:62",
"A0:A1:AB:90:C9:FC:84:7B:3B:12:61:E8:97:7D:5F:D3:22:61:D3:CC",
"D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49",
- "A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B",
"B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6",
"2E:14:DA:EC:28:F0:FA:1E:8E:38:9A:4E:AB:EB:26:C0:0A:D3:83:C3",
"DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12",
"CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7",
- "69:BD:8C:F4:9C:D3:00:FB:59:2E:17:93:CA:55:6A:F3:EC:AA:35:FB",
"13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6",
"5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25",
"49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99",
@@ -172,7 +168,6 @@
"89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E",
"E0:B4:32:2E:B2:F6:A5:68:B6:54:53:84:48:18:4A:50:36:87:43:84",
"7E:04:DE:89:6A:3E:66:6D:00:E6:87:D3:3F:FA:D9:3B:E8:3D:34:9E",
- "99:A6:9B:E6:1A:FE:88:6B:4D:2B:82:00:7C:B8:54:FC:31:7E:15:39",
"6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1",
"31:F1:FD:68:22:63:20:EE:C6:3B:3F:9D:EA:4A:3E:53:7C:7C:39:17",
"F9:CD:0E:2C:DA:76:24:C1:8F:BD:F0:F0:AB:B6:45:B8:F7:FE:D5:7A",
diff --git a/tests/tests/security/src/android/security/cts/HwRngTest.java b/tests/tests/security/src/android/security/cts/HwRngTest.java
index f9ce6be..7654b6f 100644
--- a/tests/tests/security/src/android/security/cts/HwRngTest.java
+++ b/tests/tests/security/src/android/security/cts/HwRngTest.java
@@ -17,11 +17,10 @@
package android.security.cts;
import android.cts.util.CtsAndroidTestCase;
-import com.android.cts.util.ReportLog;
-import com.android.cts.util.ResultType;
-import com.android.cts.util.ResultUnit;
-import junit.framework.TestCase;
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@@ -51,18 +50,19 @@
* Reports whether the {@code /dev/hw_random} device is found. This test always passes.
*/
public void testDeviceFilePresent() {
- ReportLog report = getReportLog();
+ DeviceReportLog report = new DeviceReportLog();
// Need to report at least one value, otherwise summary won't be logged.
- report.printValue(
+ report.addValue(
DEV_HW_RANDOM + " found",
DEV_HW_RANDOM.exists() ? 1 : 0,
ResultType.WARNING,
ResultUnit.NONE);
- report.printSummary(
+ report.setSummary(
"Hardware RNG exposed",
DEV_HW_RANDOM.exists() ? 1 : 0,
ResultType.WARNING,
ResultUnit.NONE);
+ report.submit(getInstrumentation());
}
/**
diff --git a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
index 06ef5fd..6ae0d69 100644
--- a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
@@ -16,7 +16,7 @@
package android.security.cts;
-import com.android.cts.security.R;
+import android.security.cts.R;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
diff --git a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
index 9dff6dd..5298196 100644
--- a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -33,7 +33,7 @@
import java.io.IOException;
import java.io.RandomAccessFile;
-import com.android.cts.security.R;
+import android.security.cts.R;
public class MediaServerCrashTest extends AndroidTestCase {
private static final String TAG = "MediaServerCrashTest";
diff --git a/tests/tests/security/src/android/security/cts/NativeCodeTest.java b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
index ab41b4f..5ec6ddc 100644
--- a/tests/tests/security/src/android/security/cts/NativeCodeTest.java
+++ b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
@@ -64,6 +64,15 @@
+ "https://github.com/torvalds/linux/commit/a134f083e79f",
doPingPongRootTest());
}
+
+ public void testSysVipc() throws Exception {
+ assertTrue("Android does not support Sys V IPC, it must "
+ + "be removed from the kernel. In the kernel config: "
+ + "Change \"CONFIG_SYSVIPC=y\" to \"# CONFIG_SYSVIPC is not set\" "
+ + "and rebuild.",
+ doSysVipcTest());
+ }
+
/**
* Returns true iff this device is vulnerable to CVE-2013-2094.
* A patch for CVE-2013-2094 can be found at
@@ -140,4 +149,25 @@
*/
private static native boolean doPingPongRootTest();
+ /**
+ * Test that SysV IPC has been removed from the kernel.
+ *
+ * Returns true if SysV IPC has been removed.
+ *
+ * System V IPCs are not compliant with Android's application lifecycle because allocated
+ * resources are not freed by the low memory killer. This lead to global kernel resource leakage.
+ *
+ * For example, there is no way to automatically release a SysV semaphore
+ * allocated in the kernel when:
+ * - a buggy or malicious process exits
+ * - a non-buggy and non-malicious process crashes or is explicitly killed.
+ *
+ * Killing processes automatically to make room for new ones is an
+ * important part of Android's application lifecycle implementation. This means
+ * that, even assuming only non-buggy and non-malicious code, it is very likely
+ * that over time, the kernel global tables used to implement SysV IPCs will fill
+ * up.
+ */
+ private static native boolean doSysVipcTest();
+
}
diff --git a/tests/tests/security/src/android/security/cts/OpenSSLEarlyCCSTest.java b/tests/tests/security/src/android/security/cts/OpenSSLEarlyCCSTest.java
index 9cdb288..bba75dc 100644
--- a/tests/tests/security/src/android/security/cts/OpenSSLEarlyCCSTest.java
+++ b/tests/tests/security/src/android/security/cts/OpenSSLEarlyCCSTest.java
@@ -26,8 +26,6 @@
import android.test.InstrumentationTestCase;
import android.util.Log;
-import com.android.cts.security.R;
-
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
diff --git a/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java b/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java
index 12fcee4..61a03a1 100644
--- a/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java
+++ b/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java
@@ -20,8 +20,6 @@
import android.test.InstrumentationTestCase;
import android.util.Log;
-import com.android.cts.security.R;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index 069fa72..0b76cb5 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -16,8 +16,6 @@
package android.security.cts;
-import com.android.cts.security.R;
-
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -35,10 +33,13 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class PackageSignatureTest extends AndroidTestCase {
private static final String TAG = PackageSignatureTest.class.getSimpleName();
+ private static final Pattern TEST_PACKAGE_PATTERN = Pattern.compile("android\\.[^\\.]+\\.cts");
public void testPackageSignatures() throws Exception {
Set<String> badPackages = new HashSet<String>();
@@ -109,8 +110,8 @@
private boolean isWhitelistedPackage(String packageName) {
// Don't check the signatures of CTS test packages on the device.
// devicesetup is the APK CTS loads to collect information needed in the final report
- return packageName.startsWith("com.android.cts")
- || WHITELISTED_PACKAGES.contains(packageName);
+ final Matcher matcher = TEST_PACKAGE_PATTERN.matcher(packageName);
+ return matcher.matches() || WHITELISTED_PACKAGES.contains(packageName);
}
private static final int DEFAULT_BUFFER_BYTES = 1024 * 4;
diff --git a/tests/tests/security/src/android/security/cts/RestrictedInformationTest.java b/tests/tests/security/src/android/security/cts/RestrictedInformationTest.java
new file mode 100644
index 0000000..d0247e9
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/RestrictedInformationTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package android.security.cts;
+
+import android.test.AndroidTestCase;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+import android.content.pm.PackageManager;
+import android.net.wifi.WifiManager;
+import android.content.Context;
+
+/**
+ * Check that restricted information is not available
+ * to the untrusted_app domain
+ */
+public class RestrictedInformationTest extends AndroidTestCase {
+ /*
+ * Test that wifi Mac address is not available through sysfs
+ */
+ public void testWifiMacAddr() throws Exception {
+ /* if wifi does not exist, exit - PASS */
+ PackageManager pm = getContext().getPackageManager();
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_WIFI))
+ return;
+
+ /* Wifi exists, but is not on - FAIL */
+ WifiManager wifi = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+ assertTrue("Wifi must be enabled to pass this test.", wifi.isWifiEnabled());
+
+ /* Enumerate through the interfaces */
+ Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
+
+ while (theInterfaces.hasMoreElements()) {
+ NetworkInterface netif = theInterfaces.nextElement();
+ String name = netif.getName();
+ /* some devices label wifi network interface as eth */
+ if (!name.contains("wlan") && !name.contains("eth"))
+ continue;
+ /* PASS means that getHardwareAddress throws a socket exception */
+ try {
+ byte[] hwAddr = netif.getHardwareAddress();
+ fail("Mac address for " + name + "is accessible: " + new String(hwAddr) +
+ "\nTo pass this test, label the address with the sysfs_mac_address\n" +
+ "selinux label. " +
+ "e.g. https://android-review.googlesource.com/#/c/162180/1\n");
+ } catch (SocketException se) {/* socket exception if MAC blocked - PASS */}
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 17a4c75..9873823 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -22,6 +22,8 @@
*/
package android.security.cts;
+import android.test.AndroidTestCase;
+import android.util.Log;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
@@ -45,7 +47,7 @@
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
-import com.android.cts.security.R;
+import android.security.cts.R;
/**
diff --git a/tests/tests/speech/Android.mk b/tests/tests/speech/Android.mk
index 3ab78b8..e8828ee 100755
--- a/tests/tests/speech/Android.mk
+++ b/tests/tests/speech/Android.mk
@@ -25,6 +25,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_PACKAGE_NAME := CtsSpeechTestCases
# Needed for testing M API
diff --git a/tests/tests/speech/AndroidManifest.xml b/tests/tests/speech/AndroidManifest.xml
index 2e7f0b6..cd5d46c 100755
--- a/tests/tests/speech/AndroidManifest.xml
+++ b/tests/tests/speech/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.speech">
+ package="android.speech.tts.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -34,7 +34,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.speech"
+ android:targetPackage="android.speech.tts.cts"
android:label="CTS tests of android.speech">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/speech/AndroidTest.xml b/tests/tests/speech/AndroidTest.xml
new file mode 100644
index 0000000..08df58e
--- /dev/null
+++ b/tests/tests/speech/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Speech test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSpeechTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.speech.tts.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java
index 9d460e2..01ba17a 100644
--- a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java
+++ b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java
@@ -35,7 +35,7 @@
public class TextToSpeechWrapper {
private static final String LOG_TAG = "TextToSpeechServiceTest";
- public static final String MOCK_TTS_ENGINE = "com.android.cts.speech";
+ public static final String MOCK_TTS_ENGINE = "android.speech.tts.cts";
private final Context mContext;
private TextToSpeech mTts;
diff --git a/tests/tests/systemui/Android.mk b/tests/tests/systemui/Android.mk
index 1a15fd2..9ce6e47 100644
--- a/tests/tests/systemui/Android.mk
+++ b/tests/tests/systemui/Android.mk
@@ -19,6 +19,11 @@
# don't include this package in any target
LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
diff --git a/tests/tests/systemui/AndroidManifest.xml b/tests/tests/systemui/AndroidManifest.xml
index bf5df5b..2cdb36f 100644
--- a/tests/tests/systemui/AndroidManifest.xml
+++ b/tests/tests/systemui/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.systemui">
+ package="android.systemui.cts">
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -27,7 +27,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.systemui">
+ android:targetPackage="android.systemui.cts">
</instrumentation>
</manifest>
diff --git a/tests/tests/systemui/AndroidTest.xml b/tests/tests/systemui/AndroidTest.xml
new file mode 100644
index 0000000..d98dae6
--- /dev/null
+++ b/tests/tests/systemui/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS SystemUI test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSystemUiTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.systemui.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/systemui/src/android/systemui/cts/ColorUtils.java b/tests/tests/systemui/src/android/systemui/cts/ColorUtils.java
new file mode 100644
index 0000000..a26b2ad
--- /dev/null
+++ b/tests/tests/systemui/src/android/systemui/cts/ColorUtils.java
@@ -0,0 +1,68 @@
+/*
+ * 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
+ */
+
+package android.systemui.cts;
+
+/**
+ * Copies of non-public {@link android.graphics.Color} APIs
+ */
+public class ColorUtils {
+
+ public static float brightness(int argb) {
+ int r = (argb >> 16) & 0xFF;
+ int g = (argb >> 8) & 0xFF;
+ int b = argb & 0xFF;
+
+ int V = Math.max(b, Math.max(r, g));
+
+ return (V / 255.f);
+ }
+
+ public static float hue(int argb) {
+ int r = (argb >> 16) & 0xFF;
+ int g = (argb >> 8) & 0xFF;
+ int b = argb & 0xFF;
+
+ int V = Math.max(b, Math.max(r, g));
+ int temp = Math.min(b, Math.min(r, g));
+
+ float H;
+
+ if (V == temp) {
+ H = 0;
+ } else {
+ final float vtemp = (float) (V - temp);
+ final float cr = (V - r) / vtemp;
+ final float cg = (V - g) / vtemp;
+ final float cb = (V - b) / vtemp;
+
+ if (r == V) {
+ H = cb - cg;
+ } else if (g == V) {
+ H = 2 + cr - cb;
+ } else {
+ H = 4 + cg - cr;
+ }
+
+ H /= 6.f;
+ if (H < 0) {
+ H++;
+ }
+ }
+
+ return H;
+ }
+}
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightStatusBarActivity.java b/tests/tests/systemui/src/android/systemui/cts/LightStatusBarActivity.java
new file mode 100644
index 0000000..b33cc77
--- /dev/null
+++ b/tests/tests/systemui/src/android/systemui/cts/LightStatusBarActivity.java
@@ -0,0 +1,58 @@
+/*
+ * 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
+ */
+package android.systemui.cts;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+
+
+/**
+ * An activity that exercises SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
+ */
+public class LightStatusBarActivity extends Activity {
+
+ private View mContent;
+
+ public void onCreate(Bundle bundle){
+ super.onCreate(bundle);
+
+ mContent = new View(this);
+ mContent.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT));
+ setContentView(mContent);
+ }
+
+ public void setLightStatusBar(boolean lightStatusBar) {
+ int vis = getWindow().getDecorView().getSystemUiVisibility();
+ if (lightStatusBar) {
+ vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ } else {
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ }
+ getWindow().getDecorView().setSystemUiVisibility(vis);
+ }
+
+ public int getTop() {
+ return mContent.getLocationOnScreen()[1];
+ }
+
+ public int getWidth() {
+ return mContent.getWidth();
+ }
+}
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightStatusBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightStatusBarTests.java
new file mode 100644
index 0000000..879eac5
--- /dev/null
+++ b/tests/tests/systemui/src/android/systemui/cts/LightStatusBarTests.java
@@ -0,0 +1,235 @@
+/*
+ * 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
+ */
+
+package android.systemui.cts;
+
+import android.app.ActivityManager;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.support.test.InstrumentationRegistry;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Test for light status bar.
+ */
+public class LightStatusBarTests extends ActivityInstrumentationTestCase2<LightStatusBarActivity> {
+
+ public static final String TAG = "LightStatusBarTests";
+
+ public static final String DUMP_PATH = "/sdcard/lightstatustest.png";
+
+ public LightStatusBarTests() {
+ super(LightStatusBarActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // As the way to access Instrumentation is changed in the new runner, we need to inject it
+ // manually into ActivityInstrumentationTestCase2. ActivityInstrumentationTestCase2 will
+ // be marked as deprecated and replaced with ActivityTestRule.
+ injectInstrumentation(InstrumentationRegistry.getInstrumentation());
+ }
+
+ public void testLightStatusBarIcons() throws Throwable {
+ PackageManager pm = getInstrumentation().getContext().getPackageManager();
+ if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
+ || pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
+ || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+ // No status bar on TVs and watches.
+ return;
+ }
+
+ if (!ActivityManager.isHighEndGfx()) {
+ // non-highEndGfx devices don't do colored system bars.
+ return;
+ }
+
+ requestLightStatusBar(Color.RED /* background */);
+ Thread.sleep(1000);
+
+ Bitmap bitmap = takeStatusBarScreenshot();
+ Stats s = evaluateLightStatusBarBitmap(bitmap, Color.RED /* background */);
+ boolean success = false;
+
+ try {
+ assertMoreThan("Not enough background pixels", 0.3f,
+ (float) s.backgroundPixels / s.totalPixels(),
+ "Is the status bar background showing correctly (solid red)?");
+
+ assertMoreThan("Not enough pixels colored as in the spec", 0.1f,
+ (float) s.iconPixels / s.foregroundPixels(),
+ "Are the status bar icons colored according to the spec "
+ + "(60% black and 24% black)?");
+
+ assertLessThan("Too many lighter pixels lighter than the background", 0.05f,
+ (float) s.sameHueLightPixels / s.foregroundPixels(),
+ "Are the status bar icons dark?");
+
+ assertLessThan("Too many pixels with a changed hue", 0.05f,
+ (float) s.unexpectedHuePixels / s.foregroundPixels(),
+ "Are the status bar icons color-free?");
+
+ success = true;
+ } finally {
+ if (!success) {
+ Log.e(TAG, "Dumping failed bitmap to " + DUMP_PATH);
+ dumpBitmap(bitmap);
+ }
+ }
+ }
+
+ private void assertMoreThan(String what, float expected, float actual, String hint) {
+ if (!(actual > expected)) {
+ fail(what + ": expected more than " + expected * 100 + "%, but only got " + actual * 100
+ + "%; " + hint);
+ }
+ }
+
+ private void assertLessThan(String what, float expected, float actual, String hint) {
+ if (!(actual < expected)) {
+ fail(what + ": expected less than " + expected * 100 + "%, but got " + actual * 100
+ + "%; " + hint);
+ }
+ }
+
+ private void requestLightStatusBar(final int background) throws Throwable {
+ final LightStatusBarActivity activity = getActivity();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ activity.getWindow().setStatusBarColor(background);
+ activity.setLightStatusBar(true);
+ }
+ });
+ }
+
+ private static class Stats {
+ int backgroundPixels;
+ int iconPixels;
+ int sameHueDarkPixels;
+ int sameHueLightPixels;
+ int unexpectedHuePixels;
+
+ int totalPixels() {
+ return backgroundPixels + iconPixels + sameHueDarkPixels
+ + sameHueLightPixels + unexpectedHuePixels;
+ }
+
+ int foregroundPixels() {
+ return iconPixels + sameHueDarkPixels
+ + sameHueLightPixels + unexpectedHuePixels;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{bg=%d, ic=%d, dark=%d, light=%d, bad=%d}",
+ backgroundPixels, iconPixels, sameHueDarkPixels, sameHueLightPixels,
+ unexpectedHuePixels);
+ }
+ }
+
+ private Stats evaluateLightStatusBarBitmap(Bitmap bitmap, int background) {
+ int iconColor = 0x99000000;
+ int iconPartialColor = 0x3d000000;
+
+ int mixedIconColor = mixSrcOver(background, iconColor);
+ int mixedIconPartialColor = mixSrcOver(background, iconPartialColor);
+
+ int[] pixels = new int[bitmap.getHeight() * bitmap.getWidth()];
+ bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
+
+ Stats s = new Stats();
+ float eps = 0.005f;
+
+ for (int c : pixels) {
+ if (c == background) {
+ s.backgroundPixels++;
+ continue;
+ }
+
+ // What we expect the icons to be colored according to the spec.
+ if (c == mixedIconColor || c == mixedIconPartialColor) {
+ s.iconPixels++;
+ continue;
+ }
+
+ // Due to anti-aliasing, there will be deviations from the ideal icon color, but it
+ // should still be mostly the same hue.
+ float hueDiff = Math.abs(ColorUtils.hue(background) - ColorUtils.hue(c));
+ if (hueDiff < eps || hueDiff > 1 - eps) {
+ // .. it shouldn't be lighter than the original background though.
+ if (ColorUtils.brightness(c) > ColorUtils.brightness(background)) {
+ s.sameHueLightPixels++;
+ } else {
+ s.sameHueDarkPixels++;
+ }
+ continue;
+ }
+
+ s.unexpectedHuePixels++;
+ }
+
+ return s;
+ }
+
+ private void dumpBitmap(Bitmap bitmap) {
+ FileOutputStream fileStream = null;
+ try {
+ fileStream = new FileOutputStream(DUMP_PATH);
+ bitmap.compress(Bitmap.CompressFormat.PNG, 85, fileStream);
+ fileStream.flush();
+ } catch (Exception e) {
+ Log.e(TAG, "Dumping bitmap failed.", e);
+ } finally {
+ if (fileStream != null) {
+ try {
+ fileStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private int mixSrcOver(int background, int foreground) {
+ int bgAlpha = Color.alpha(background);
+ int bgRed = Color.red(background);
+ int bgGreen = Color.green(background);
+ int bgBlue = Color.blue(background);
+
+ int fgAlpha = Color.alpha(foreground);
+ int fgRed = Color.red(foreground);
+ int fgGreen = Color.green(foreground);
+ int fgBlue = Color.blue(foreground);
+
+ return Color.argb(fgAlpha + (255 - fgAlpha) * bgAlpha / 255,
+ fgRed + (255 - fgAlpha) * bgRed / 255,
+ fgGreen + (255 - fgAlpha) * bgGreen / 255,
+ fgBlue + (255 - fgAlpha) * bgBlue / 255);
+ }
+
+ private Bitmap takeStatusBarScreenshot() {
+ Bitmap fullBitmap = getInstrumentation().getUiAutomation().takeScreenshot();
+ return Bitmap.createBitmap(fullBitmap, 0, 0,
+ getActivity().getWidth(), getActivity().getTop());
+ }
+}
diff --git a/tests/tests/systemui/src/com/android/cts/systemui/ColorUtils.java b/tests/tests/systemui/src/com/android/cts/systemui/ColorUtils.java
deleted file mode 100644
index 626a179..0000000
--- a/tests/tests/systemui/src/com/android/cts/systemui/ColorUtils.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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
- */
-
-package com.android.cts.systemui;
-
-/**
- * Copies of non-public {@link android.graphics.Color} APIs
- */
-public class ColorUtils {
-
- public static float brightness(int argb) {
- int r = (argb >> 16) & 0xFF;
- int g = (argb >> 8) & 0xFF;
- int b = argb & 0xFF;
-
- int V = Math.max(b, Math.max(r, g));
-
- return (V / 255.f);
- }
-
- public static float hue(int argb) {
- int r = (argb >> 16) & 0xFF;
- int g = (argb >> 8) & 0xFF;
- int b = argb & 0xFF;
-
- int V = Math.max(b, Math.max(r, g));
- int temp = Math.min(b, Math.min(r, g));
-
- float H;
-
- if (V == temp) {
- H = 0;
- } else {
- final float vtemp = (float) (V - temp);
- final float cr = (V - r) / vtemp;
- final float cg = (V - g) / vtemp;
- final float cb = (V - b) / vtemp;
-
- if (r == V) {
- H = cb - cg;
- } else if (g == V) {
- H = 2 + cr - cb;
- } else {
- H = 4 + cg - cr;
- }
-
- H /= 6.f;
- if (H < 0) {
- H++;
- }
- }
-
- return H;
- }
-}
diff --git a/tests/tests/systemui/src/com/android/cts/systemui/LightStatusBarActivity.java b/tests/tests/systemui/src/com/android/cts/systemui/LightStatusBarActivity.java
deleted file mode 100644
index 3722320..0000000
--- a/tests/tests/systemui/src/com/android/cts/systemui/LightStatusBarActivity.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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
- */
-package com.android.cts.systemui;
-
-import android.app.Activity;
-import android.graphics.Color;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-
-
-/**
- * An activity that exercises SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
- */
-public class LightStatusBarActivity extends Activity {
-
- private View mContent;
-
- public void onCreate(Bundle bundle){
- super.onCreate(bundle);
-
- mContent = new View(this);
- mContent.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT));
- setContentView(mContent);
- }
-
- public void setLightStatusBar(boolean lightStatusBar) {
- int vis = getWindow().getDecorView().getSystemUiVisibility();
- if (lightStatusBar) {
- vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- } else {
- vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- }
- getWindow().getDecorView().setSystemUiVisibility(vis);
- }
-
- public int getTop() {
- return mContent.getLocationOnScreen()[1];
- }
-
- public int getWidth() {
- return mContent.getWidth();
- }
-}
diff --git a/tests/tests/systemui/src/com/android/cts/systemui/LightStatusBarTests.java b/tests/tests/systemui/src/com/android/cts/systemui/LightStatusBarTests.java
deleted file mode 100644
index b5bfd51..0000000
--- a/tests/tests/systemui/src/com/android/cts/systemui/LightStatusBarTests.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * 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
- */
-
-package com.android.cts.systemui;
-
-import android.app.ActivityManager;
-import android.content.pm.PackageManager;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.support.test.InstrumentationRegistry;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Test for light status bar.
- */
-public class LightStatusBarTests extends ActivityInstrumentationTestCase2<LightStatusBarActivity> {
-
- public static final String TAG = "LightStatusBarTests";
-
- public static final String DUMP_PATH = "/sdcard/lightstatustest.png";
-
- public LightStatusBarTests() {
- super(LightStatusBarActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // As the way to access Instrumentation is changed in the new runner, we need to inject it
- // manually into ActivityInstrumentationTestCase2. ActivityInstrumentationTestCase2 will
- // be marked as deprecated and replaced with ActivityTestRule.
- injectInstrumentation(InstrumentationRegistry.getInstrumentation());
- }
-
- public void testLightStatusBarIcons() throws Throwable {
- PackageManager pm = getInstrumentation().getContext().getPackageManager();
- if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
- || pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
- || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
- // No status bar on TVs and watches.
- return;
- }
-
- if (!ActivityManager.isHighEndGfx()) {
- // non-highEndGfx devices don't do colored system bars.
- return;
- }
-
- requestLightStatusBar(Color.RED /* background */);
- Thread.sleep(1000);
-
- Bitmap bitmap = takeStatusBarScreenshot();
- Stats s = evaluateLightStatusBarBitmap(bitmap, Color.RED /* background */);
- boolean success = false;
-
- try {
- assertMoreThan("Not enough background pixels", 0.3f,
- (float) s.backgroundPixels / s.totalPixels(),
- "Is the status bar background showing correctly (solid red)?");
-
- assertMoreThan("Not enough pixels colored as in the spec", 0.1f,
- (float) s.iconPixels / s.foregroundPixels(),
- "Are the status bar icons colored according to the spec "
- + "(60% black and 24% black)?");
-
- assertLessThan("Too many lighter pixels lighter than the background", 0.05f,
- (float) s.sameHueLightPixels / s.foregroundPixels(),
- "Are the status bar icons dark?");
-
- assertLessThan("Too many pixels with a changed hue", 0.05f,
- (float) s.unexpectedHuePixels / s.foregroundPixels(),
- "Are the status bar icons color-free?");
-
- success = true;
- } finally {
- if (!success) {
- Log.e(TAG, "Dumping failed bitmap to " + DUMP_PATH);
- dumpBitmap(bitmap);
- }
- }
- }
-
- private void assertMoreThan(String what, float expected, float actual, String hint) {
- if (!(actual > expected)) {
- fail(what + ": expected more than " + expected * 100 + "%, but only got " + actual * 100
- + "%; " + hint);
- }
- }
-
- private void assertLessThan(String what, float expected, float actual, String hint) {
- if (!(actual < expected)) {
- fail(what + ": expected less than " + expected * 100 + "%, but got " + actual * 100
- + "%; " + hint);
- }
- }
-
- private void requestLightStatusBar(final int background) throws Throwable {
- final LightStatusBarActivity activity = getActivity();
- runTestOnUiThread(new Runnable() {
- @Override
- public void run() {
- activity.getWindow().setStatusBarColor(background);
- activity.setLightStatusBar(true);
- }
- });
- }
-
- private static class Stats {
- int backgroundPixels;
- int iconPixels;
- int sameHueDarkPixels;
- int sameHueLightPixels;
- int unexpectedHuePixels;
-
- int totalPixels() {
- return backgroundPixels + iconPixels + sameHueDarkPixels
- + sameHueLightPixels + unexpectedHuePixels;
- }
-
- int foregroundPixels() {
- return iconPixels + sameHueDarkPixels
- + sameHueLightPixels + unexpectedHuePixels;
- }
-
- @Override
- public String toString() {
- return String.format("{bg=%d, ic=%d, dark=%d, light=%d, bad=%d}",
- backgroundPixels, iconPixels, sameHueDarkPixels, sameHueLightPixels,
- unexpectedHuePixels);
- }
- }
-
- private Stats evaluateLightStatusBarBitmap(Bitmap bitmap, int background) {
- int iconColor = 0x99000000;
- int iconPartialColor = 0x3d000000;
-
- int mixedIconColor = mixSrcOver(background, iconColor);
- int mixedIconPartialColor = mixSrcOver(background, iconPartialColor);
-
- int[] pixels = new int[bitmap.getHeight() * bitmap.getWidth()];
- bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
-
- Stats s = new Stats();
- float eps = 0.005f;
-
- for (int c : pixels) {
- if (c == background) {
- s.backgroundPixels++;
- continue;
- }
-
- // What we expect the icons to be colored according to the spec.
- if (c == mixedIconColor || c == mixedIconPartialColor) {
- s.iconPixels++;
- continue;
- }
-
- // Due to anti-aliasing, there will be deviations from the ideal icon color, but it
- // should still be mostly the same hue.
- float hueDiff = Math.abs(ColorUtils.hue(background) - ColorUtils.hue(c));
- if (hueDiff < eps || hueDiff > 1 - eps) {
- // .. it shouldn't be lighter than the original background though.
- if (ColorUtils.brightness(c) > ColorUtils.brightness(background)) {
- s.sameHueLightPixels++;
- } else {
- s.sameHueDarkPixels++;
- }
- continue;
- }
-
- s.unexpectedHuePixels++;
- }
-
- return s;
- }
-
- private void dumpBitmap(Bitmap bitmap) {
- FileOutputStream fileStream = null;
- try {
- fileStream = new FileOutputStream(DUMP_PATH);
- bitmap.compress(Bitmap.CompressFormat.PNG, 85, fileStream);
- fileStream.flush();
- } catch (Exception e) {
- Log.e(TAG, "Dumping bitmap failed.", e);
- } finally {
- if (fileStream != null) {
- try {
- fileStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- private int mixSrcOver(int background, int foreground) {
- int bgAlpha = Color.alpha(background);
- int bgRed = Color.red(background);
- int bgGreen = Color.green(background);
- int bgBlue = Color.blue(background);
-
- int fgAlpha = Color.alpha(foreground);
- int fgRed = Color.red(foreground);
- int fgGreen = Color.green(foreground);
- int fgBlue = Color.blue(foreground);
-
- return Color.argb(fgAlpha + (255 - fgAlpha) * bgAlpha / 255,
- fgRed + (255 - fgAlpha) * bgRed / 255,
- fgGreen + (255 - fgAlpha) * bgGreen / 255,
- fgBlue + (255 - fgAlpha) * bgBlue / 255);
- }
-
- private Bitmap takeStatusBarScreenshot() {
- Bitmap fullBitmap = getInstrumentation().getUiAutomation().takeScreenshot();
- return Bitmap.createBitmap(fullBitmap, 0, 0,
- getActivity().getWidth(), getActivity().getTop());
- }
-}
diff --git a/tests/tests/telecom/Android.mk b/tests/tests/telecom/Android.mk
index 51d97f5..fc03b68 100644
--- a/tests/tests/telecom/Android.mk
+++ b/tests/tests/telecom/Android.mk
@@ -30,4 +30,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index b57e0b6..b4d44db 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.telecom">
+ package="android.telecom.cts">
<uses-sdk android:minSdkVersion="21" />
<uses-permission android:name="android.permission.CALL_PHONE" />>
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -81,7 +81,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.telecom"
+ android:targetPackage="android.telecom.cts"
android:label="CTS tests for android.telecom package">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/telecom/AndroidTest.xml b/tests/tests/telecom/AndroidTest.xml
new file mode 100644
index 0000000..03f64b3
--- /dev/null
+++ b/tests/tests/telecom/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<configuration description="Configuration for Telecom Tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.TokenRequirement">
+ <option name="token" value="sim-card" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTelecomTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.telecom.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
index 879c995..0be05d6 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
@@ -35,8 +35,6 @@
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
-import com.android.cts.telecom.R;
-
/**
* Suites of tests that verifies the various Call details.
*/
@@ -55,12 +53,18 @@
Call.Details.PROPERTY_HIGH_DEF_AUDIO | Call.Details.PROPERTY_WIFI;
public static final String CALLER_DISPLAY_NAME = "CTS test";
public static final int CALLER_DISPLAY_NAME_PRESENTATION = TelecomManager.PRESENTATION_ALLOWED;
+ public static final String TEST_SUBJECT = "test";
+ public static final String TEST_CHILD_NUMBER = "650-555-1212";
+ public static final String TEST_FORWARDED_NUMBER = "650-555-1212";
+ public static final String TEST_EXTRA_KEY = "com.test.extra.TEST";
+ public static final int TEST_EXTRA_VALUE = 10;
private StatusHints mStatusHints;
private Bundle mExtras = new Bundle();
private MockInCallService mInCallService;
private Call mCall;
+ private Connection mConnection;
@Override
protected void setUp() throws Exception {
@@ -75,6 +79,7 @@
Connection connection = super.onCreateOutgoingConnection(
connectionManagerPhoneAccount,
request);
+ mConnection = connection;
// Modify the connection object created with local values.
connection.setConnectionCapabilities(CONNECTION_CAPABILITIES);
connection.setCallerDisplayName(
@@ -135,6 +140,95 @@
}
/**
+ * Tests propagation of the local video capabilities from telephony through to in-call.
+ */
+ public void testCallLocalVideoCapability() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // Note: Local support for video is disabled when a call is in dialing state.
+ mConnection.setConnectionCapabilities(
+ Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
+ assertCallCapabilities(mCall, 0);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_RX);
+ assertCallCapabilities(mCall, 0);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_TX);
+ assertCallCapabilities(mCall, 0);
+
+ mConnection.setConnectionCapabilities(
+ Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
+ assertCallCapabilities(mCall, 0);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_RX);
+ assertCallCapabilities(mCall, 0);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_TX);
+ assertCallCapabilities(mCall, 0);
+
+ // Set call active; we expect the capabilities to make it through now.
+ mConnection.setActive();
+
+ mConnection.setConnectionCapabilities(
+ Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_RX);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_TX);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX);
+
+ mConnection.setConnectionCapabilities(
+ Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_RX);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_TX);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX);
+ }
+
+ /**
+ * Tests passing call capabilities from Connections to Calls.
+ */
+ public void testCallCapabilityPropagation() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_CAN_PAUSE_VIDEO);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_CAN_PAUSE_VIDEO);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_HOLD);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_HOLD);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_MANAGE_CONFERENCE);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_MANAGE_CONFERENCE);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_MERGE_CONFERENCE);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_MERGE_CONFERENCE);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_MUTE);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_MUTE);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_RESPOND_VIA_TEXT);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_RESPOND_VIA_TEXT);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORT_HOLD);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORT_HOLD);
+
+ mConnection.setConnectionCapabilities(Connection.CAPABILITY_SWAP_CONFERENCE);
+ assertCallCapabilities(mCall, Call.Details.CAPABILITY_SWAP_CONFERENCE);
+ }
+
+ /**
* Tests whether the getCallerDisplayName() getter returns the correct object.
*/
public void testCallerDisplayName() {
@@ -279,4 +373,80 @@
assertThat(mCall.getDetails().getVideoState(), is(Integer.class));
}
+
+ /**
+ * Tests communication of {@link Connection#setExtras(Bundle)} through to
+ * {@link Call.Details#getExtras()}.
+ */
+ public void testExtrasPropagation() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ Bundle exampleExtras = new Bundle();
+ exampleExtras.putString(Connection.EXTRA_CALL_SUBJECT, TEST_SUBJECT);
+ exampleExtras.putString(Connection.EXTRA_CHILD_ADDRESS, TEST_CHILD_NUMBER);
+ exampleExtras.putString(Connection.EXTRA_LAST_FORWARDED_NUMBER, TEST_FORWARDED_NUMBER);
+ exampleExtras.putInt(TEST_EXTRA_KEY, TEST_EXTRA_VALUE);
+ mConnection.setExtras(exampleExtras);
+
+ // Make sure we got back a bundle with the call subject key set.
+ assertCallExtras(mCall, Connection.EXTRA_CALL_SUBJECT);
+
+ Bundle callExtras = mCall.getDetails().getExtras();
+ assertEquals(TEST_SUBJECT, callExtras.getString(Connection.EXTRA_CALL_SUBJECT));
+ assertEquals(TEST_CHILD_NUMBER, callExtras.getString(Connection.EXTRA_CHILD_ADDRESS));
+ assertEquals(TEST_FORWARDED_NUMBER,
+ callExtras.getString(Connection.EXTRA_LAST_FORWARDED_NUMBER));
+ assertEquals(TEST_EXTRA_VALUE, callExtras.getInt(TEST_EXTRA_KEY));
+ }
+
+ /**
+ * Asserts that a call's capabilities are as expected.
+ *
+ * @param call The call.
+ * @param capabilities The expected capabilities.
+ */
+ private void assertCallCapabilities(final Call call, final int capabilities) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return capabilities;
+ }
+
+ @Override
+ public Object actual() {
+ return call.getDetails().getCallCapabilities();
+ }
+ },
+ TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Call should have capabilities " + capabilities
+ );
+ }
+
+ /**
+ * Asserts that a call's extras contain a specified key.
+ *
+ * @param call The call.
+ * @param expectedKey The expected extras key.
+ */
+ private void assertCallExtras(final Call call, final String expectedKey) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return expectedKey;
+ }
+
+ @Override
+ public Object actual() {
+ return call.getDetails().getExtras().containsKey(expectedKey) ? expectedKey
+ : "";
+ }
+ },
+ TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Call should have extras key " + expectedKey
+ );
+ }
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/DataObjectUnitTests.java b/tests/tests/telecom/src/android/telecom/cts/DataObjectUnitTests.java
index 1fbe0d5..a088951 100644
--- a/tests/tests/telecom/src/android/telecom/cts/DataObjectUnitTests.java
+++ b/tests/tests/telecom/src/android/telecom/cts/DataObjectUnitTests.java
@@ -39,8 +39,6 @@
import android.telecom.VideoProfile;
import android.test.InstrumentationTestCase;
-import com.android.cts.telecom.R;
-
import java.util.Arrays;
import java.util.List;
diff --git a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
index d1a9723..6e124011 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
@@ -37,7 +37,7 @@
// Non-final to allow modification by tests not in this package (e.g. permission-related
// tests in the Telecom2 test package.
- public static String PACKAGE = "com.android.cts.telecom";
+ public static String PACKAGE = "android.telecom.cts";
public static final String COMPONENT = "android.telecom.cts.CtsConnectionService";
public static final String REMOTE_COMPONENT = "android.telecom.cts.CtsRemoteConnectionService";
public static final String ACCOUNT_ID = "xtstest_CALL_PROVIDER_ID";
diff --git a/tests/tests/telecom2/Android.mk b/tests/tests/telecom2/Android.mk
index 71edb7b..0932292 100644
--- a/tests/tests/telecom2/Android.mk
+++ b/tests/tests/telecom2/Android.mk
@@ -38,9 +38,12 @@
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
- --extra-packages com.android.cts.telecom \
- --rename-manifest-package com.android.cts.telecom2 \
+ --extra-packages android.telecom.cts \
+ --rename-manifest-package android.telecom2.cts \
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/telecom2/AndroidManifest.xml b/tests/tests/telecom2/AndroidManifest.xml
index e618768..50c6945 100644
--- a/tests/tests/telecom2/AndroidManifest.xml
+++ b/tests/tests/telecom2/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.telecom2">
+ package="android.telecom2.cts">
<uses-sdk android:minSdkVersion="21" />
<!--
@@ -74,7 +74,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.telecom2"
+ android:targetPackage="android.telecom2.cts"
android:label="CTS tests for android.telecom package">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/telecom2/AndroidTest.xml b/tests/tests/telecom2/AndroidTest.xml
new file mode 100644
index 0000000..e7ae80c
--- /dev/null
+++ b/tests/tests/telecom2/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Configuration for Telecom2 Tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTelecomTestCases2.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.telecom2.cts" />
+ <option name="runtime-hint" value="6m42s" />
+ </test>
+</configuration>
diff --git a/tests/tests/telephony/Android.mk b/tests/tests/telephony/Android.mk
index 85864f9..ca766e4 100644
--- a/tests/tests/telephony/Android.mk
+++ b/tests/tests/telephony/Android.mk
@@ -30,6 +30,9 @@
LOCAL_PACKAGE_NAME := CtsTelephonyTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# uncomment when b/13250611 is fixed
#LOCAL_SDK_VERSION := current
LOCAL_JAVA_LIBRARIES += android.test.runner
diff --git a/tests/tests/telephony/AndroidManifest.xml b/tests/tests/telephony/AndroidManifest.xml
index a87a54b..6e9545a 100644
--- a/tests/tests/telephony/AndroidManifest.xml
+++ b/tests/tests/telephony/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.telephony">
+ package="android.telephony.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -38,7 +38,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.telephony"
+ android:targetPackage="android.telephony.cts"
android:label="CTS tests of android.telephony">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/telephony/AndroidTest.xml b/tests/tests/telephony/AndroidTest.xml
new file mode 100644
index 0000000..2e6011b
--- /dev/null
+++ b/tests/tests/telephony/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<configuration description="Config for CTS Telephony test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.TokenRequirement">
+ <option name="token" value="sim-card" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTelephonyTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.telephony.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/telephony2/Android.mk b/tests/tests/telephony2/Android.mk
index f405210..792f819 100644
--- a/tests/tests/telephony2/Android.mk
+++ b/tests/tests/telephony2/Android.mk
@@ -28,6 +28,9 @@
LOCAL_PACKAGE_NAME := CtsTelephony2TestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_JAVA_LIBRARIES += android.test.runner
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/telephony2/AndroidManifest.xml b/tests/tests/telephony2/AndroidManifest.xml
index 369f75e..6b8ec0c 100644
--- a/tests/tests/telephony2/AndroidManifest.xml
+++ b/tests/tests/telephony2/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.telephony2">
+ package="android.telephony2.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -24,7 +24,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.telephony2">
+ android:targetPackage="android.telephony2.cts">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/tests/telephony2/AndroidTest.xml b/tests/tests/telephony2/AndroidTest.xml
new file mode 100644
index 0000000..45ee5fa
--- /dev/null
+++ b/tests/tests/telephony2/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Telephony test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTelephony2TestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.telephony2.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/text/Android.mk b/tests/tests/text/Android.mk
index 7b2def1..8e80da8 100644
--- a/tests/tests/text/Android.mk
+++ b/tests/tests/text/Android.mk
@@ -29,6 +29,9 @@
LOCAL_PACKAGE_NAME := CtsTextTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# uncomment when dalvik.annotation.Test* are removed or part of SDK
#LOCAL_SDK_VERSION := current
diff --git a/tests/tests/text/AndroidManifest.xml b/tests/tests/text/AndroidManifest.xml
index 99a6ad5..864f655 100644
--- a/tests/tests/text/AndroidManifest.xml
+++ b/tests/tests/text/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.text">
+ package="android.text.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
@@ -67,11 +67,10 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.text"
+ android:targetPackage="android.text.cts"
android:label="CTS tests of android.text">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
-
diff --git a/tests/tests/text/AndroidTest.xml b/tests/tests/text/AndroidTest.xml
new file mode 100644
index 0000000..4b9d24d
--- /dev/null
+++ b/tests/tests/text/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<configuration description="Config for CTS Text test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTextTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.text.cts" />
+ <option name="runtime-hint" value="3m8s" />
+ </test>
+</configuration>
diff --git a/tests/tests/text/src/android/text/cts/BidiFormatterTest.java b/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
index 5ace8b2..3e5db4d 100644
--- a/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
+++ b/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
@@ -33,7 +33,7 @@
new BidiFormatter.Builder(true /* RTL context */).stereoReset(false).build();
private static final String EN = "abba";
- private static final String HE = "\u05e0\u05e1";
+ private static final String HE = "\u05E0\u05E1";
private static final String LRM = "\u200E";
private static final String RLM = "\u200F";
@@ -49,6 +49,18 @@
assertEquals(true, BidiFormatter.getInstance(true).isRtlContext());
}
+ public void testCachedInstances() {
+ // Test that we get the same cached static instances for simple cases
+ BidiFormatter defaultFormatterInstance = BidiFormatter.getInstance();
+ assertTrue(defaultFormatterInstance == LTR_FMT || defaultFormatterInstance == RTL_FMT);
+
+ assertEquals(LTR_FMT, BidiFormatter.getInstance(false));
+ assertEquals(RTL_FMT, BidiFormatter.getInstance(true));
+
+ assertEquals(LTR_FMT, BidiFormatter.getInstance(false));
+ assertEquals(RTL_FMT, BidiFormatter.getInstance(Locale.forLanguageTag("ar")));
+ }
+
public void testBuilderIsRtlContext() {
assertEquals(false, new BidiFormatter.Builder(false).build().isRtlContext());
assertEquals(true, new BidiFormatter.Builder(true).build().isRtlContext());
diff --git a/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java b/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java
index 195bdf1..cdbc867 100644
--- a/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java
+++ b/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java
@@ -16,7 +16,7 @@
package android.text.cts;
-import com.android.cts.text.R;
+import android.text.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/text/src/android/text/cts/EmojiTest.java b/tests/tests/text/src/android/text/cts/EmojiTest.java
index e1249f3..517d06c 100644
--- a/tests/tests/text/src/android/text/cts/EmojiTest.java
+++ b/tests/tests/text/src/android/text/cts/EmojiTest.java
@@ -33,7 +33,7 @@
public class EmojiTest extends ActivityInstrumentationTestCase2<EmojiCtsActivity> {
public EmojiTest() {
- super("com.android.cts.text", EmojiCtsActivity.class);
+ super("android.text.cts", EmojiCtsActivity.class);
}
protected void setUp() throws Exception {
diff --git a/tests/tests/text/src/android/text/cts/HtmlTest.java b/tests/tests/text/src/android/text/cts/HtmlTest.java
index cf47ab9..0531875 100644
--- a/tests/tests/text/src/android/text/cts/HtmlTest.java
+++ b/tests/tests/text/src/android/text/cts/HtmlTest.java
@@ -198,6 +198,23 @@
ret);
}
+ public void testMarkupFromHtml() throws Exception {
+ Spanned s;
+ final int expectedStart = 6;
+ final int expectedEnd = expectedStart + 6;
+
+ String tags[] = {"del", "s", "strike"};
+ for (String tag : tags) {
+ String source = String.format("Hello <%s>struck</%s> world", tag, tag);
+ Spanned spanned = Html.fromHtml(source);
+ Object[] spans = spanned.getSpans(0, spanned.length(), Object.class);
+ assertEquals(1, spans.length);
+ assertEquals(StrikethroughSpan.class, spans[0].getClass());
+ assertEquals(expectedStart, spanned.getSpanStart(spans[0]));
+ assertEquals(expectedEnd, spanned.getSpanEnd(spans[0]));
+ }
+ }
+
public void testImg() throws Exception {
Spanned s = Html.fromHtml("yes<img src=\"http://example.com/foo.gif\">no");
assertEquals("<p dir=\"ltr\">yes<img src=\"http://example.com/foo.gif\">no</p>\n",
diff --git a/tests/tests/text/src/android/text/cts/MyanmarTest.java b/tests/tests/text/src/android/text/cts/MyanmarTest.java
index d59f2b9..9988ab9 100644
--- a/tests/tests/text/src/android/text/cts/MyanmarTest.java
+++ b/tests/tests/text/src/android/text/cts/MyanmarTest.java
@@ -25,7 +25,7 @@
public class MyanmarTest extends ActivityInstrumentationTestCase2<Activity> {
public MyanmarTest() {
- super("com.android.cts.text", Activity.class);
+ super("android.text.cts", Activity.class);
}
protected void setUp() throws Exception {
diff --git a/tests/tests/text/src/android/text/cts/SpannableStringBuilderSpanTest.java b/tests/tests/text/src/android/text/cts/SpannableStringBuilderSpanTest.java
index 352767c..14bcc8e 100644
--- a/tests/tests/text/src/android/text/cts/SpannableStringBuilderSpanTest.java
+++ b/tests/tests/text/src/android/text/cts/SpannableStringBuilderSpanTest.java
@@ -19,10 +19,15 @@
import java.util.ArrayList;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.Html;
import android.text.SpanWatcher;
import android.text.Spannable;
+import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
+import android.text.style.ParagraphStyle;
+import android.text.style.QuoteSpan;
/**
* Test {@link SpannableStringBuilder}.
@@ -492,4 +497,88 @@
}
// TODO Thoroughly test the SPAN_PARAGRAPH span flag.
+
+
+ @SmallTest
+ public void
+ testReplace_discardsParagraphSpanInSourceIfThereIsNoNewLineBefore()
+ throws Exception {
+ SpannableStringBuilder spannable = new SpannableStringBuilder("1 selection_to_replace");
+ Spanned newText = Html.fromHtml("<blockquote>new text</blockquote>");
+ assertEquals(1, newText.getSpans(0, newText.length(), ParagraphStyle.class).length);
+
+ spannable.replace(2, spannable.length(), newText);
+
+ ParagraphStyle[] paragraphSpans = spannable.getSpans(0, spannable.length(),
+ ParagraphStyle.class);
+ assertEquals(0, paragraphSpans.length);
+ }
+
+ @SmallTest
+ public void testReplace_retainsParagraphSpanInSourceIfThereIsNewLineBefore()
+ throws Exception {
+ SpannableStringBuilder spannable = new SpannableStringBuilder("1\nselection_to_replace");
+ Spanned newText = Html.fromHtml("<blockquote>new text</blockquote>");
+ assertTrue(newText.getSpans(0, newText.length(), ParagraphStyle.class).length > 0);
+
+ spannable.replace(2, spannable.length(), newText);
+
+ ParagraphStyle[] paragraphSpans = spannable.getSpans(0, spannable.length(),
+ ParagraphStyle.class);
+ assertEquals(1, paragraphSpans.length);
+ }
+
+ @SmallTest
+ public void testReplace_retainsParagraphSpanInSourceIfStartIsZero()
+ throws Exception {
+ // copy the paragraph span even if there is no previous character - start is equal to 0
+
+ SpannableStringBuilder spannable = new SpannableStringBuilder("selection_to_replace");
+ Spanned newText = Html.fromHtml("<blockquote>new text</blockquote>");
+ assertTrue(newText.getSpans(0, newText.length(), ParagraphStyle.class).length > 0);
+
+ spannable.replace(0, spannable.length(), newText);
+
+ ParagraphStyle[] paragraphSpans = spannable.getSpans(0, spannable.length(),
+ ParagraphStyle.class);
+ assertEquals(1, paragraphSpans.length);
+ }
+
+ @SmallTest
+ public void testReplace_retainsParagraphSpanInSourceIfEndIsEqualToLengthOfString()
+ throws Exception {
+ // copy the paragraph span even if the final char is not next line, and if the end is
+ // equal to the string length
+
+ SpannableStringBuilder spannable = new SpannableStringBuilder("selection_to_replace\n");
+ // create a spannable that does not have \n at the end. Html.fromHtml adds \n to the end of
+ // the text
+ Spannable newText = new SpannableString("a");
+ newText.setSpan(new QuoteSpan(), 0, 1, Spannable.SPAN_PARAGRAPH);
+ assertTrue(newText.getSpans(0, newText.length(), ParagraphStyle.class).length > 0);
+
+ spannable.replace(spannable.length(), spannable.length(), newText);
+
+ ParagraphStyle[] paragraphSpans = spannable.getSpans(0, spannable.length(),
+ ParagraphStyle.class);
+ assertEquals(1, paragraphSpans.length);
+ }
+
+ @SmallTest
+ public void testReplace_discardsParagraphSpanInSourceIfThereIsNoNewLineAfter()
+ throws Exception {
+ SpannableStringBuilder spannable = new SpannableStringBuilder("r remaining\n");
+ // create a spannable that does not have \n at the end. Html.fromHtml adds \n to the end of
+ // the text
+ Spannable newText = new SpannableString("a");
+ newText.setSpan(new QuoteSpan(), 0, 1, Spannable.SPAN_PARAGRAPH);
+ assertTrue(newText.getSpans(0, newText.length(), ParagraphStyle.class).length > 0);
+
+ spannable.replace(0, 1, newText);
+
+ ParagraphStyle[] paragraphSpans = spannable.getSpans(0, spannable.length(),
+ ParagraphStyle.class);
+ assertEquals(0, paragraphSpans.length);
+ }
+
}
diff --git a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
index 36b081c..4b26eac 100644
--- a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
+++ b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
@@ -553,6 +553,11 @@
UnderlineSpan span2 = new UnderlineSpan();
builder.setSpan(span1, 1, 2, Spanned.SPAN_POINT_POINT);
builder.setSpan(span2, 4, 8, Spanned.SPAN_MARK_POINT);
+
+ Object[] emptySpans = builder.getSpans(0, 10, null);
+ assertNotNull(emptySpans);
+ assertEquals(0, emptySpans.length);
+
UnderlineSpan[] underlineSpans = builder.getSpans(0, 10, UnderlineSpan.class);
assertEquals(2, underlineSpans.length);
assertSame(span1, underlineSpans[0]);
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index 329db88..9dca753 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -980,6 +980,27 @@
}
}
+ public void testGetOffsetForHorizontal_Multilines() {
+ // Emoticons for surrogate pairs tests.
+ String testString = "\uD83D\uDE00\uD83D\uDE01\uD83D\uDE02\uD83D\uDE03\uD83D\uDE04";
+ final float width = mDefaultPaint.measureText(testString, 0, 6);
+ StaticLayout layout = new StaticLayout(testString, mDefaultPaint, (int)width,
+ DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true);
+ // We expect the line break to be after the third emoticon, but we allow flexibility of the
+ // line break algorithm as long as the break is within the string. These other cases might
+ // happen if for example the font has kerning between emoticons.
+ final int lineBreakOffset = layout.getOffsetForHorizontal(1, 0.0f);
+ assertEquals(0, layout.getLineForOffset(lineBreakOffset - 1));
+
+ assertEquals(0, layout.getOffsetForHorizontal(0, 0.0f));
+ assertEquals(lineBreakOffset - 2, layout.getOffsetForHorizontal(0, width));
+ assertEquals(lineBreakOffset - 2, layout.getOffsetForHorizontal(0, width * 2));
+
+ final int lineCount = layout.getLineCount();
+ assertEquals(testString.length(), layout.getOffsetForHorizontal(lineCount - 1, width));
+ assertEquals(testString.length(), layout.getOffsetForHorizontal(lineCount - 1, width * 2));
+ }
+
public void testVeryLargeString() {
final int MAX_COUNT = 1 << 21;
final int WORD_SIZE = 32;
diff --git a/tests/tests/text/src/android/text/cts/TextUtilsTest.java b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
index 9258318..0da1eb4 100644
--- a/tests/tests/text/src/android/text/cts/TextUtilsTest.java
+++ b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
@@ -1330,11 +1330,20 @@
}
public void testIsDigitsOnly() {
+ assertTrue(TextUtils.isDigitsOnly(""));
assertFalse(TextUtils.isDigitsOnly("no digit"));
assertFalse(TextUtils.isDigitsOnly("character and 56 digits"));
assertTrue(TextUtils.isDigitsOnly("0123456789"));
assertFalse(TextUtils.isDigitsOnly("1234 56789"));
+ // U+104A0 OSMANYA DIGIT ZERO
+ assertTrue(TextUtils.isDigitsOnly(new String(Character.toChars(0x104A0))));
+ // U+10858 IMPERIAL ARAMAIC NUMBER ONE
+ assertFalse(TextUtils.isDigitsOnly(new String(Character.toChars(0x10858))));
+
+ assertFalse(TextUtils.isDigitsOnly("\uD801")); // lonely lead surrogate
+ assertFalse(TextUtils.isDigitsOnly("\uDCA0")); // lonely trailing surrogate
+
try {
TextUtils.isDigitsOnly(null);
fail("Should throw NullPointerException!");
@@ -1352,7 +1361,7 @@
public void testIsGraphicChar() {
assertTrue(TextUtils.isGraphic('a'));
- assertTrue(TextUtils.isGraphic("\uBA00"));
+ assertTrue(TextUtils.isGraphic('\uBA00'));
// LINE_SEPARATOR
assertFalse(TextUtils.isGraphic('\u2028'));
@@ -1387,6 +1396,11 @@
assertTrue(TextUtils.isGraphic("a\u2028\u2029\u0085\u0D00\uD800\u0020"));
+ assertTrue(TextUtils.isGraphic("\uD83D\uDC0C")); // U+1F40C SNAIL
+ assertFalse(TextUtils.isGraphic("\uDB40\uDC01")); // U+E0000 (unassigned)
+ assertFalse(TextUtils.isGraphic("\uDB3D")); // unpaired high surrogate
+ assertFalse(TextUtils.isGraphic("\uDC0C")); // unpaired low surrogate
+
try {
TextUtils.isGraphic(null);
fail("Should throw NullPointerException!");
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 9c3c45d..6acfb84 100644
--- a/tests/tests/text/src/android/text/format/cts/FormatterTest.java
+++ b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
@@ -32,9 +32,14 @@
BigDecimal bd = new BigDecimal((long) 1024, mc);
// test different long values with various length
- assertEquals("0.00 B", Formatter.formatFileSize(mContext, 0));
-
- assertEquals("899 B", Formatter.formatFileSize(mContext, 899));
+ assertEquals("0 B", Formatter.formatFileSize(mContext, 0));
+ assertEquals("1 B", Formatter.formatFileSize(mContext, 1));
+ assertEquals("9 B", Formatter.formatFileSize(mContext, 9));
+ assertEquals("10 B", Formatter.formatFileSize(mContext, 10));
+ 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("1.00 KB", Formatter.formatFileSize(mContext, bd.pow(1).longValue()));
@@ -49,7 +54,7 @@
assertEquals("1024 PB", Formatter.formatFileSize(mContext, bd.pow(6).longValue()));
// test Negative value
- assertEquals("-1.00 B", Formatter.formatFileSize(mContext, -1));
+ assertEquals("-1 B", Formatter.formatFileSize(mContext, -1));
}
public void testFormatIpAddress() {
diff --git a/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
index 482edb0..c7a6041 100644
--- a/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
@@ -56,7 +56,7 @@
private MyMetaKeyKeyListener mMetaListener;
public ArrowKeyMovementMethodTest() {
- super("com.android.cts.text", CtsActivity.class);
+ super("android.text.cts", CtsActivity.class);
}
@Override
diff --git a/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java b/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java
index 382fc77..6ab79ad 100644
--- a/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java
+++ b/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java
@@ -35,7 +35,7 @@
private Activity mActivity;
public CharacterPickerDialogTest() {
- super("com.android.cts.text", CtsActivity.class);
+ super("android.text.cts", CtsActivity.class);
}
@Override
diff --git a/tests/tests/text/src/android/text/method/cts/KeyListenerCtsActivity.java b/tests/tests/text/src/android/text/method/cts/KeyListenerCtsActivity.java
index c6483a2..c14f463 100644
--- a/tests/tests/text/src/android/text/method/cts/KeyListenerCtsActivity.java
+++ b/tests/tests/text/src/android/text/method/cts/KeyListenerCtsActivity.java
@@ -16,7 +16,7 @@
package android.text.method.cts;
-import com.android.cts.text.R;
+import android.text.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java b/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
index 8bb2adf..4f89ff3 100644
--- a/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
+++ b/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
@@ -16,7 +16,7 @@
package android.text.method.cts;
-import com.android.cts.text.R;
+import android.text.cts.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
diff --git a/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
index 336921a..520b91f 100644
--- a/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
@@ -56,7 +56,7 @@
private MockClickableSpan mClickable1;
public LinkMovementMethodTest() {
- super("com.android.cts.text", CtsActivity.class);
+ super("android.text.cts", CtsActivity.class);
}
@Override
diff --git a/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java
index 72a8e72..ea679c5 100644
--- a/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java
@@ -63,7 +63,7 @@
private CharSequence mTransformedText;
public PasswordTransformationMethodTest() {
- super("com.android.cts.text", CtsActivity.class);
+ super("android.text.cts", CtsActivity.class);
}
@Override
diff --git a/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java
index dadce15..6b3e149 100644
--- a/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java
@@ -37,7 +37,7 @@
private EditText mEditText;
public ReplacementTransformationMethodTest() {
- super("com.android.cts.text", CtsActivity.class);
+ super("android.text.cts", CtsActivity.class);
}
@Override
diff --git a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
index a8d68dc..49196bdc 100644
--- a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
@@ -54,7 +54,7 @@
private int mScaledTouchSlop;
public ScrollingMovementMethodTest() {
- super("com.android.cts.text", CtsActivity.class);
+ super("android.text.cts", CtsActivity.class);
}
@Override
diff --git a/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java
index 460ce3d..1756a0f 100644
--- a/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java
@@ -28,7 +28,7 @@
public class SingleLineTransformationMethodTest
extends ActivityInstrumentationTestCase2<CtsActivity> {
public SingleLineTransformationMethodTest() {
- super("com.android.cts.text", CtsActivity.class);
+ super("android.text.cts", CtsActivity.class);
}
public void testConstructor() {
diff --git a/tests/tests/text/src/android/text/method/cts/TouchTest.java b/tests/tests/text/src/android/text/method/cts/TouchTest.java
index 343847e..3e26084 100644
--- a/tests/tests/text/src/android/text/method/cts/TouchTest.java
+++ b/tests/tests/text/src/android/text/method/cts/TouchTest.java
@@ -43,7 +43,7 @@
private boolean mReturnFromTouchEvent;
public TouchTest() {
- super("com.android.cts.text", CtsActivity.class);
+ super("android.text.cts", CtsActivity.class);
}
@Override
diff --git a/tests/tests/text/src/android/text/style/cts/DrawableMarginSpanTest.java b/tests/tests/text/src/android/text/style/cts/DrawableMarginSpanTest.java
index 3813a94..775f035 100644
--- a/tests/tests/text/src/android/text/style/cts/DrawableMarginSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/DrawableMarginSpanTest.java
@@ -16,7 +16,7 @@
package android.text.style.cts;
-import com.android.cts.text.R;
+import android.text.cts.R;
import android.graphics.Canvas;
diff --git a/tests/tests/text/src/android/text/style/cts/DynamicDrawableSpanTest.java b/tests/tests/text/src/android/text/style/cts/DynamicDrawableSpanTest.java
index 9723556..8a178f8 100644
--- a/tests/tests/text/src/android/text/style/cts/DynamicDrawableSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/DynamicDrawableSpanTest.java
@@ -16,7 +16,7 @@
package android.text.style.cts;
-import com.android.cts.text.R;
+import android.text.cts.R;
import android.graphics.Canvas;
diff --git a/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java b/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java
index 6f056d0..90282b8 100644
--- a/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java
@@ -16,7 +16,7 @@
package android.text.style.cts;
-import com.android.cts.text.R;
+import android.text.cts.R;
import android.content.Context;
diff --git a/tests/tests/text/src/android/text/style/cts/LocaleSpanTest.java b/tests/tests/text/src/android/text/style/cts/LocaleSpanTest.java
new file mode 100644
index 0000000..93e6cf9
--- /dev/null
+++ b/tests/tests/text/src/android/text/style/cts/LocaleSpanTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.text.style.cts;
+
+import junit.framework.TestCase;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.text.style.LocaleSpan;
+import android.util.LocaleList;
+
+public class LocaleSpanTest extends TestCase {
+
+ public void testGetLocalesMain(@NonNull final LocaleList locales) {
+ final LocaleSpan span = new LocaleSpan(locales);
+ assertEquals(locales.getPrimary(), span.getLocale());
+ assertEquals(locales, span.getLocales());
+
+ final LocaleSpan cloned = cloneViaParcel(span);
+ assertEquals(locales.getPrimary(), cloned.getLocale());
+ assertEquals(locales, cloned.getLocales());
+ }
+
+ public void testGetLocales() {
+ testGetLocalesMain(LocaleList.getEmptyLocaleList());
+ testGetLocalesMain(LocaleList.forLanguageTags("en"));
+ testGetLocalesMain(LocaleList.forLanguageTags("en-GB,en"));
+ testGetLocalesMain(LocaleList.forLanguageTags("de-DE-u-co-phonebk,en-GB,en"));
+ }
+
+ public void testConstructorWithLocaleList() {
+ try {
+ new LocaleSpan((LocaleList) null);
+ } catch (NullPointerException e) {
+ // Expected.
+ return;
+ }
+ fail("NullPointerException must have been thrown.");
+ }
+
+ @NonNull
+ LocaleSpan cloneViaParcel(@NonNull final LocaleSpan original) {
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ original.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ return new LocaleSpan(parcel);
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ }
+ }
+ }
+}
diff --git a/tests/tests/text/src/android/text/style/cts/MockURLSpanTestActivity.java b/tests/tests/text/src/android/text/style/cts/MockURLSpanTestActivity.java
index dbd154b..be06b0d 100644
--- a/tests/tests/text/src/android/text/style/cts/MockURLSpanTestActivity.java
+++ b/tests/tests/text/src/android/text/style/cts/MockURLSpanTestActivity.java
@@ -16,7 +16,7 @@
package android.text.style.cts;
-import com.android.cts.text.R;
+import android.text.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java b/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java
new file mode 100644
index 0000000..ec51216
--- /dev/null
+++ b/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.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.text.style.cts;
+
+import junit.framework.TestCase;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.text.style.SuggestionSpan;
+
+import java.util.Locale;
+
+public class SuggestionSpanTest extends TestCase {
+
+ /**
+ * @param locale a {@link Locale} object.
+ * @return A well-formed BCP 47 language tag representation.
+ */
+ @Nullable
+ private Locale toWellFormedLocale(@Nullable final Locale locale) {
+ if (locale == null) {
+ return null;
+ }
+ // Drop all the malformed data.
+ return Locale.forLanguageTag(locale.toLanguageTag());
+ }
+
+ @NonNull
+ private String getNonNullLocaleString(@Nullable final Locale original) {
+ if (original == null) {
+ return "";
+ }
+ return original.toString();
+ }
+
+ public void testGetLocaleObjectMain(final Locale locale) {
+ final SuggestionSpan span = new SuggestionSpan(locale, new String[0],
+ SuggestionSpan.FLAG_AUTO_CORRECTION);
+ // In the context of SuggestionSpan#getLocaleObject(), we do care only about subtags that
+ // can be interpreted as LanguageTag.
+ assertEquals(toWellFormedLocale(locale), span.getLocaleObject());
+ assertEquals(getNonNullLocaleString(locale), span.getLocale());
+
+ final SuggestionSpan cloned = cloneViaParcel(span);
+ assertEquals(span, cloned);
+ assertEquals(toWellFormedLocale(locale), cloned.getLocaleObject());
+ assertEquals(getNonNullLocaleString(locale), cloned.getLocale());
+ }
+
+ public void testGetLocaleObject() {
+ testGetLocaleObjectMain(Locale.forLanguageTag("en"));
+ testGetLocaleObjectMain(Locale.forLanguageTag("en-GB"));
+ testGetLocaleObjectMain(Locale.forLanguageTag("EN-GB"));
+ testGetLocaleObjectMain(Locale.forLanguageTag("en-gb"));
+ testGetLocaleObjectMain(Locale.forLanguageTag("En-gB"));
+ testGetLocaleObjectMain(Locale.forLanguageTag("und"));
+ testGetLocaleObjectMain(Locale.forLanguageTag("de-DE-u-co-phonebk"));
+ testGetLocaleObjectMain(Locale.forLanguageTag(""));
+ testGetLocaleObjectMain(null);
+ testGetLocaleObjectMain(new Locale(" an ", " i n v a l i d ", "data"));
+ }
+
+ @NonNull
+ SuggestionSpan cloneViaParcel(@NonNull final SuggestionSpan original) {
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ original.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ return new SuggestionSpan(parcel);
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ }
+ }
+ }
+}
diff --git a/tests/tests/text/src/android/text/style/cts/URLSpanCtsActivity.java b/tests/tests/text/src/android/text/style/cts/URLSpanCtsActivity.java
index 8d885bc..be6c8ae 100644
--- a/tests/tests/text/src/android/text/style/cts/URLSpanCtsActivity.java
+++ b/tests/tests/text/src/android/text/style/cts/URLSpanCtsActivity.java
@@ -16,7 +16,7 @@
package android.text.style.cts;
-import com.android.cts.text.R;
+import android.text.cts.R;
import android.app.Activity;
import android.os.Bundle;
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 7cfe56e..330db77 100644
--- a/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
@@ -16,7 +16,7 @@
package android.text.style.cts;
-import com.android.cts.text.R;
+import android.text.cts.R;
import android.app.Activity;
@@ -33,7 +33,7 @@
private Activity mActivity;
public URLSpanTest() {
- super("com.android.cts.text", URLSpanCtsActivity.class);
+ super("android.text.cts", URLSpanCtsActivity.class);
}
@Override
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 e6b91eb..1785f6f 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -18,6 +18,7 @@
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.URLSpan;
@@ -81,9 +82,9 @@
"abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabc";
SpannableString spannable = new SpannableString("name@gmail.com, "
+ "www.google.com, http://www.google.com/language_tools?hl=en, "
- + "a.bc, " // a URL with accepted gTLD so should be linkified
+ + "a.bd, " // a URL with accepted TLD so should be linkified
+ "d.e, f.1, g.12, " // not valid, so should not be linkified
- + "h." + longGTLD + " " // valid, should be linkified
+ + "http://h." + longGTLD + " " // valid, should be linkified
+ "j." + longGTLD + "a"); // not a valid URL (gtld too long), no linkify
assertTrue(Linkify.addLinks(spannable, Linkify.WEB_URLS));
@@ -91,7 +92,7 @@
assertEquals(4, spans.length);
assertEquals("http://www.google.com", spans[0].getURL());
assertEquals("http://www.google.com/language_tools?hl=en", spans[1].getURL());
- assertEquals("http://a.bc", spans[2].getURL());
+ assertEquals("http://a.bd", spans[2].getURL());
assertEquals("http://h." + longGTLD, spans[3].getURL());
assertTrue(Linkify.addLinks(spannable, Linkify.EMAIL_ADDRESSES));
@@ -349,4 +350,214 @@
assertFalse(Linkify.addLinks((Spannable) null, 0));
}
+
+ @SmallTest
+ public void testAddLinks_doesNotAddLinksForUrlWithoutProtocolAndWithoutKnownTld()
+ throws Exception {
+ Spannable spannable = new SpannableString("hey man.its me");
+ boolean linksAdded = Linkify.addLinks(spannable, Linkify.ALL);
+ assertFalse("Should not add link with unknown TLD", linksAdded);
+ }
+
+ @SmallTest
+ public void testAddLinks_shouldNotAddEmailAddressAsUrl() throws Exception {
+ String url = "name@gmail.com";
+ assertAddLinksWithWebUrlFails("Should not recognize email address as URL", url);
+ }
+
+ public void testAddLinks_acceptsUrlsWithCommasInRequestParameterValues() throws Exception {
+ String url = "https://android.com/path?ll=37.4221,-122.0836&z=17&pll=37.4221,-122.0836";
+ assertAddLinksWithWebUrlSucceeds("Should accept commas", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_addsLinksForUrlWithProtocolWithoutTld() throws Exception {
+ String url = "http://android/#notld///a/n/d/r/o/i/d&p1=1&p2=2";
+ assertAddLinksWithWebUrlSucceeds("Should accept URL starting with protocol but does not" +
+ " have TLD", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesProtocolCaseInsensitive() throws Exception {
+ String url = "hTtP://android.com";
+ assertAddLinksWithWebUrlSucceeds("Protocol matching should be case insensitive", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesValidUrlWithSchemeAndHostname() throws Exception {
+ String url = "http://www.android.com";
+ assertAddLinksWithWebUrlSucceeds("Should match valid URL with scheme and hostname", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesValidUrlWithSchemeHostnameAndNewTld() throws Exception {
+ String url = "http://www.android.me";
+ assertAddLinksWithWebUrlSucceeds("Should match valid URL with scheme hostname and new TLD",
+ url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesValidUrlWithHostnameAndNewTld() throws Exception {
+ String url = "android.camera";
+ assertAddLinksWithWebUrlSucceeds("Should match valid URL with hostname and new TLD", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesPunycodeUrl() throws Exception {
+ String url = "http://xn--fsqu00a.xn--unup4y";
+ assertAddLinksWithWebUrlSucceeds("Should match Punycode URL", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesPunycodeUrlWithoutProtocol() throws Exception {
+ String url = "xn--fsqu00a.xn--unup4y";
+ assertAddLinksWithWebUrlSucceeds("Should match Punycode URL without protocol", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_doesNotMatchPunycodeTldThatStartsWithDash() throws Exception {
+ String url = "xn--fsqu00a.-xn--unup4y";
+ assertAddLinksWithWebUrlFails("Should not match Punycode TLD that starts with dash", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_partiallyMatchesPunycodeTldThatEndsWithDash() throws Exception {
+ String url = "http://xn--fsqu00a.xn--unup4y-";
+ assertAddLinksWithWebUrlPartiallyMatches("Should partially match Punycode TLD that ends " +
+ "with dash", "http://xn--fsqu00a.xn--unup4y", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesUrlWithUnicodeDomainName() throws Exception {
+ String url = "http://\uD604\uAE08\uC601\uC218\uC99D.kr";
+ assertAddLinksWithWebUrlSucceeds("Should match URL with Unicode domain name", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesUrlWithUnicodeDomainNameWithoutProtocol() throws Exception {
+ String url = "\uD604\uAE08\uC601\uC218\uC99D.kr";
+ assertAddLinksWithWebUrlSucceeds("Should match URL without protocol and with Unicode " +
+ "domain name", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesUrlWithUnicodeDomainNameAndTld() throws Exception {
+ String url = "\uB3C4\uBA54\uC778.\uD55C\uAD6D";
+ assertAddLinksWithWebUrlSucceeds("Should match URL with Unicode domain name and TLD", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesUrlWithUnicodePath() throws Exception {
+ String url = "http://android.com/\u2019/a";
+ assertAddLinksWithWebUrlSucceeds("Should match URL with Unicode path", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesValidUrlWithPort() throws Exception {
+ String url = "http://www.example.com:8080";
+ assertAddLinksWithWebUrlSucceeds("Should match URL with port", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesUrlWithPortAndQuery() throws Exception {
+ String url = "http://www.example.com:8080/?foo=bar";
+ assertAddLinksWithWebUrlSucceeds("Should match URL with port and query", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesUrlWithTilde() throws Exception {
+ String url = "http://www.example.com:8080/~user/?foo=bar";
+ assertAddLinksWithWebUrlSucceeds("Should match URL with tilde", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesUrlStartingWithHttpAndDoesNotHaveTld() throws Exception {
+ String url = "http://android/#notld///a/n/d/r/o/i/d&p1=1&p2=2";
+ assertAddLinksWithWebUrlSucceeds("Should match URL without a TLD and starting with http",
+ url);
+ }
+
+ @SmallTest
+ public void testAddLinks_doesNotMatchUrlsWithoutProtocolAndWithUnknownTld() throws Exception {
+ String url = "thank.you";
+ assertAddLinksWithWebUrlFails("Should not match URL that does not start with a protocol " +
+ "and does not contain a known TLD", url);
+ }
+
+ @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);
+ }
+
+ @SmallTest
+ public void testAddLinks_doesNotMatchUrlsWithEmojiWithoutProtocolAndWithoutKnownTld()
+ throws Exception {
+ String url = "Thank\u263A.you";
+ assertAddLinksWithWebUrlFails("Should not match URLs containing emoji and with unknown " +
+ "TLD", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesDomainNameWithSurrogatePairs() throws Exception {
+ String url = "android\uD83C\uDF38.com";
+ assertAddLinksWithWebUrlSucceeds("Should match domain name with Unicode surrogate pairs",
+ url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesTldWithSurrogatePairs() throws Exception {
+ String url = "http://android.\uD83C\uDF38com";
+ assertAddLinksWithWebUrlSucceeds("Should match TLD with Unicode surrogate pairs", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_doesNotMatchUrlWithExcludedSurrogate() throws Exception {
+ String url = "android\uD83F\uDFFE.com";
+ assertAddLinksWithWebUrlFails("Should not match URL with excluded Unicode surrogate" +
+ " pair", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesPathWithSurrogatePairs() throws Exception {
+ String url = "http://android.com/path-with-\uD83C\uDF38?v=\uD83C\uDF38f";
+ assertAddLinksWithWebUrlSucceeds("Should match path and query with Unicode surrogate pairs",
+ url);
+ }
+
+ private static void assertAddLinksWithWebUrlSucceeds(String msg, String url) {
+ String str = "start " + url + " end";
+ Spannable spannable = new SpannableString(str);
+
+ boolean linksAdded = Linkify.addLinks(spannable, Linkify.WEB_URLS);
+ URLSpan[] spans = spannable.getSpans(0, str.length(), URLSpan.class);
+
+ assertTrue(msg, linksAdded);
+ assertEquals("Span should start from the beginning of the URL", "start ".length(),
+ spannable.getSpanStart(spans[0]));
+ assertEquals("Span should end at the end of the URL", str.length() - " end".length(),
+ spannable.getSpanEnd(spans[0]));
+ }
+
+ private static void assertAddLinksWithWebUrlFails(String msg, String url) {
+ Spannable spannable = new SpannableString("start " + url + " end");
+ boolean linksAdded = Linkify.addLinks(spannable, Linkify.WEB_URLS);
+ assertFalse(msg, linksAdded);
+ }
+
+ private static void assertAddLinksWithWebUrlPartiallyMatches(String msg, String expected,
+ String url) {
+ Spannable spannable = new SpannableString("start " + url + " end");
+ boolean linksAdded = Linkify.addLinks(spannable, Linkify.WEB_URLS);
+ URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
+ assertTrue(msg, linksAdded);
+ assertEquals(msg, expected, spans[0].getURL().toString());
+ }
}
diff --git a/tests/tests/textureview/Android.mk b/tests/tests/textureview/Android.mk
index f85a738..44fc659 100644
--- a/tests/tests/textureview/Android.mk
+++ b/tests/tests/textureview/Android.mk
@@ -27,6 +27,9 @@
LOCAL_PACKAGE_NAME := CtsTextureViewTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/textureview/AndroidManifest.xml b/tests/tests/textureview/AndroidManifest.xml
index 9ec3f17..6832059 100644
--- a/tests/tests/textureview/AndroidManifest.xml
+++ b/tests/tests/textureview/AndroidManifest.xml
@@ -14,8 +14,7 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.textureview"
- >
+ package="android.textureview.cts">
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -24,7 +23,7 @@
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<instrumentation
- android:targetPackage="com.android.cts.textureview"
+ android:targetPackage="android.textureview.cts"
android:name="android.support.test.runner.AndroidJUnitRunner" >
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/textureview/AndroidTest.xml b/tests/tests/textureview/AndroidTest.xml
new file mode 100644
index 0000000..d60a4a3
--- /dev/null
+++ b/tests/tests/textureview/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS TextureView test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTextureViewTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.textureview.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/theme/Android.mk b/tests/tests/theme/Android.mk
index 134af7c..44d33c4 100644
--- a/tests/tests/theme/Android.mk
+++ b/tests/tests/theme/Android.mk
@@ -16,7 +16,7 @@
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsThemeTestCases
+LOCAL_PACKAGE_NAME := CtsThemeDeviceTestCases
# Don't include this package in any target.
LOCAL_MODULE_TAGS := optional
@@ -28,6 +28,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/theme/AndroidManifest.xml b/tests/tests/theme/AndroidManifest.xml
index 8232d2b..e3ba0c6 100644
--- a/tests/tests/theme/AndroidManifest.xml
+++ b/tests/tests/theme/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.theme">
+ package="android.theme.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
@@ -24,7 +24,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.theme"
+ android:targetPackage="android.theme.cts"
android:label="CTS tests for themes">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/theme/AndroidTest.xml b/tests/tests/theme/AndroidTest.xml
new file mode 100644
index 0000000..82bd476
--- /dev/null
+++ b/tests/tests/theme/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Theme test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsThemeDeviceTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.theme.cts" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/theme/src/android/theme/cts/DeviceDefaultActivity.java b/tests/tests/theme/src/android/theme/cts/DeviceDefaultActivity.java
index 139a48f..623282b 100644
--- a/tests/tests/theme/src/android/theme/cts/DeviceDefaultActivity.java
+++ b/tests/tests/theme/src/android/theme/cts/DeviceDefaultActivity.java
@@ -16,7 +16,7 @@
package android.theme.cts;
-import com.android.cts.theme.R;
+import android.theme.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/transition/Android.mk b/tests/tests/transition/Android.mk
index 3b48e25..d2f53bd 100644
--- a/tests/tests/transition/Android.mk
+++ b/tests/tests/transition/Android.mk
@@ -28,6 +28,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/transition/AndroidManifest.xml b/tests/tests/transition/AndroidManifest.xml
index 0ce1791..3205f28 100644
--- a/tests/tests/transition/AndroidManifest.xml
+++ b/tests/tests/transition/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.transition">
+ package="android.transition.cts">
<uses-sdk android:minSdkVersion="11" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -26,7 +26,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.transition"
+ android:targetPackage="android.transition.cts"
android:label="CTS tests for android.transition package">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/transition/AndroidTest.xml b/tests/tests/transition/AndroidTest.xml
new file mode 100644
index 0000000..5aad82b
--- /dev/null
+++ b/tests/tests/transition/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Transition test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTransitionTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.transition.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
index df1ba19..13badf3 100644
--- a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
@@ -15,16 +15,14 @@
*/
package android.transition.cts;
-import com.android.cts.transition.R;
-
import android.animation.Animator;
import android.animation.ObjectAnimator;
-import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.transition.Scene;
import android.transition.TransitionManager;
import android.transition.TransitionValues;
import android.transition.Visibility;
+import android.transition.cts.R;
import android.view.Choreographer;
import android.view.Choreographer.FrameCallback;
import android.view.View;
@@ -32,12 +30,14 @@
import android.widget.FrameLayout;
import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public class BaseTransitionTest extends ActivityInstrumentationTestCase2<TransitionActivity> {
protected TransitionActivity mActivity;
protected FrameLayout mSceneRoot;
public float mAnimatedValue;
- protected ArrayList<View> mTargets = new ArrayList<>();
+ protected ArrayList<View> mTargets = new ArrayList<View>();
protected TestTransition mTransition;
public BaseTransitionTest() {
@@ -58,18 +58,8 @@
waitForStart(mTransition.listener);
}
- protected static void waitForStart(SimpleTransitionListener listener) throws InterruptedException {
- long endTime = SystemClock.uptimeMillis() + 50;
- synchronized (listener) {
- while (!listener.started) {
- long now = SystemClock.uptimeMillis();
- long waitTime = endTime - now;
- if (waitTime <= 0) {
- throw new InterruptedException();
- }
- listener.wait(waitTime);
- }
- }
+ protected void waitForStart(SimpleTransitionListener listener) throws InterruptedException {
+ assertTrue(listener.startLatch.await(100, TimeUnit.MILLISECONDS));
}
protected void waitForEnd(long waitMillis) throws InterruptedException {
@@ -78,17 +68,7 @@
protected static void waitForEnd(SimpleTransitionListener listener, long waitMillis)
throws InterruptedException {
- long endTime = SystemClock.uptimeMillis() + waitMillis;
- synchronized (listener) {
- while (!listener.ended) {
- long now = SystemClock.uptimeMillis();
- long waitTime = endTime - now;
- if (waitTime <= 0) {
- throw new InterruptedException();
- }
- listener.wait(waitTime);
- }
- }
+ listener.endLatch.await(waitMillis, TimeUnit.MILLISECONDS);
}
protected void startTransition(final int layoutId) throws Throwable {
@@ -125,31 +105,19 @@
// Waits at least one frame and it could be more. The animated values should have changed
// from the previously recorded values by the end of this method.
protected void waitForAnimationFrame() throws Throwable {
- final boolean[] tripped = new boolean[] { false };
+ final CountDownLatch latch = new CountDownLatch(1);
runTestOnUiThread(new Runnable() {
@Override
public void run() {
Choreographer.getInstance().postFrameCallbackDelayed(new FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
- synchronized (tripped) {
- tripped[0] = true;
- tripped.notifyAll();
- }
+ latch.countDown();
}
}, 16); // make sure it is the next animation frame.
}
});
- synchronized (tripped) {
- long endTime = SystemClock.uptimeMillis() + 60;
- while (!tripped[0]) {
- long waitTime = endTime - SystemClock.uptimeMillis();
- if (waitTime <= 0) {
- throw new InterruptedException();
- }
- tripped.wait(waitTime);
- }
- }
+ assertTrue(latch.await(100, TimeUnit.MILLISECONDS));
}
public class TestTransition extends Visibility {
@@ -157,7 +125,7 @@
public TestTransition() {
addListener(listener);
- setDuration(100);
+ setDuration(200);
}
@Override
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeScrollTest.java b/tests/tests/transition/src/android/transition/cts/ChangeScrollTest.java
index f5f076d..9917416 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeScrollTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeScrollTest.java
@@ -15,7 +15,7 @@
*/
package android.transition.cts;
-import com.android.cts.transition.R;
+import android.transition.cts.R;
import android.transition.ChangeScroll;
import android.transition.Transition;
@@ -30,7 +30,7 @@
public void testChangeScroll() throws Throwable {
enterScene(R.layout.scene5);
final Transition transition = new ChangeScroll();
- transition.setDuration(100);
+ transition.setDuration(200);
SimpleTransitionListener listener = new SimpleTransitionListener();
transition.addListener(listener);
runTestOnUiThread(new Runnable() {
@@ -59,7 +59,7 @@
assertTrue(scrollY < 300);
}
});
- waitForEnd(listener, 100);
+ waitForEnd(listener, 250);
runTestOnUiThread(new Runnable() {
@Override
public void run() {
diff --git a/tests/tests/transition/src/android/transition/cts/SimpleTransitionListener.java b/tests/tests/transition/src/android/transition/cts/SimpleTransitionListener.java
index 113f5a5..fb8596a 100644
--- a/tests/tests/transition/src/android/transition/cts/SimpleTransitionListener.java
+++ b/tests/tests/transition/src/android/transition/cts/SimpleTransitionListener.java
@@ -18,50 +18,43 @@
import android.transition.Transition;
import android.transition.Transition.TransitionListener;
+import java.util.concurrent.CountDownLatch;
+
/**
* Listener captures whether each of the methods is called.
*/
class SimpleTransitionListener implements TransitionListener {
public Transition transition;
- public boolean started;
-
- public boolean ended;
-
- public boolean canceled;
-
- public boolean paused;
-
- public boolean resumed;
+ public CountDownLatch startLatch = new CountDownLatch(1);
+ public CountDownLatch endLatch = new CountDownLatch(1);
+ public CountDownLatch cancelLatch = new CountDownLatch(1);
+ public CountDownLatch pauseLatch = new CountDownLatch(1);
+ public CountDownLatch resumeLatch = new CountDownLatch(1);
@Override
- public synchronized void onTransitionStart(Transition transition) {
- started = true;
+ public void onTransitionStart(Transition transition) {
this.transition = transition;
- notifyAll();
+ startLatch.countDown();
}
@Override
- public synchronized void onTransitionEnd(Transition transition) {
- ended = true;
- notifyAll();
+ public void onTransitionEnd(Transition transition) {
+ endLatch.countDown();
}
@Override
- public synchronized void onTransitionCancel(Transition transition) {
- canceled = true;
- notifyAll();
+ public void onTransitionCancel(Transition transition) {
+ cancelLatch.countDown();
}
@Override
- public synchronized void onTransitionPause(Transition transition) {
- paused = true;
- notifyAll();
+ public void onTransitionPause(Transition transition) {
+ pauseLatch.countDown();
}
@Override
- public synchronized void onTransitionResume(Transition transition) {
- resumed = true;
- notifyAll();
+ public void onTransitionResume(Transition transition) {
+ resumeLatch.countDown();
}
}
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionActivity.java b/tests/tests/transition/src/android/transition/cts/TransitionActivity.java
index 8236bd5..be9bf24 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionActivity.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionActivity.java
@@ -31,7 +31,7 @@
import android.view.ViewGroup;
import java.util.ArrayList;
-import com.android.cts.transition.R;
+import android.transition.cts.R;
public class TransitionActivity extends Activity {
@Override
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
index 78db908..8e545ec 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
@@ -15,12 +15,15 @@
*/
package android.transition.cts;
-import com.android.cts.transition.R;
+import android.transition.cts.R;
import android.transition.Scene;
import android.transition.TransitionManager;
import android.view.View;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
public class TransitionManagerTest extends BaseTransitionTest {
public TransitionManagerTest() {
@@ -38,10 +41,10 @@
});
waitForStart();
- waitForEnd(150);
- assertFalse(mTransition.listener.resumed);
- assertFalse(mTransition.listener.paused);
- assertFalse(mTransition.listener.canceled);
+ waitForEnd(300);
+ assertEquals(1, mTransition.listener.resumeLatch.getCount());
+ assertEquals(1, mTransition.listener.pauseLatch.getCount());
+ assertEquals(1, mTransition.listener.cancelLatch.getCount());
assertNotNull(mTransition.listener.transition);
assertEquals(TestTransition.class, mTransition.listener.transition.getClass());
assertTrue(mTransition != mTransition.listener.transition);
@@ -57,11 +60,11 @@
public void testGo() throws Throwable {
startTransition(R.layout.scene1);
waitForStart();
- waitForEnd(150);
+ waitForEnd(300);
- assertFalse(mTransition.listener.resumed);
- assertFalse(mTransition.listener.paused);
- assertFalse(mTransition.listener.canceled);
+ assertEquals(1, mTransition.listener.resumeLatch.getCount());
+ assertEquals(1, mTransition.listener.pauseLatch.getCount());
+ assertEquals(1, mTransition.listener.cancelLatch.getCount());
assertNotNull(mTransition.listener.transition);
assertEquals(TestTransition.class, mTransition.listener.transition.getClass());
assertTrue(mTransition != mTransition.listener.transition);
@@ -87,26 +90,25 @@
});
waitForStart();
- waitForEnd(150);
- assertFalse(mTransition.listener.resumed);
- assertFalse(mTransition.listener.paused);
- assertFalse(mTransition.listener.canceled);
+ waitForEnd(300);
+ assertEquals(1, mTransition.listener.resumeLatch.getCount());
+ assertEquals(1, mTransition.listener.pauseLatch.getCount());
+ assertEquals(1, mTransition.listener.cancelLatch.getCount());
assertNotNull(mTransition.listener.transition);
assertEquals(TestTransition.class, mTransition.listener.transition.getClass());
assertTrue(mTransition != mTransition.listener.transition);
runTestOnUiThread(new Runnable() {
@Override
public void run() {
+ mTransition.listener.startLatch = new CountDownLatch(1);
+ mTransition.listener.endLatch = new CountDownLatch(1);
assertNotNull(mActivity.findViewById(R.id.redSquare));
assertNotNull(mActivity.findViewById(R.id.greenSquare));
- mTransition.listener.started = false;
- mTransition.listener.ended = false;
Scene scene = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, mActivity);
transitionManager.transitionTo(scene);
}
});
- Thread.sleep(50);
- assertFalse(mTransition.listener.started);
+ assertFalse(mTransition.listener.startLatch.await(50, TimeUnit.MILLISECONDS));
endTransition();
}
@@ -124,8 +126,7 @@
transitionManager.transitionTo(scenes[0]);
}
});
- Thread.sleep(50);
- assertFalse(mTransition.listener.started);
+ assertFalse(mTransition.listener.startLatch.await(100, TimeUnit.MILLISECONDS));
runTestOnUiThread(new Runnable() {
@Override
@@ -135,23 +136,22 @@
});
waitForStart();
- waitForEnd(150);
- assertFalse(mTransition.listener.resumed);
- assertFalse(mTransition.listener.paused);
- assertFalse(mTransition.listener.canceled);
+ waitForEnd(300);
+ assertEquals(1, mTransition.listener.resumeLatch.getCount());
+ assertEquals(1, mTransition.listener.pauseLatch.getCount());
+ assertEquals(1, mTransition.listener.cancelLatch.getCount());
assertNotNull(mTransition.listener.transition);
assertEquals(TestTransition.class, mTransition.listener.transition.getClass());
assertTrue(mTransition != mTransition.listener.transition);
runTestOnUiThread(new Runnable() {
@Override
public void run() {
- mTransition.listener.started = false;
- mTransition.listener.ended = false;
+ mTransition.listener.startLatch = new CountDownLatch(1);
+ mTransition.listener.endLatch = new CountDownLatch(1);
transitionManager.transitionTo(scenes[2]);
}
});
- Thread.sleep(50);
- assertFalse(mTransition.listener.started);
+ assertFalse(mTransition.listener.startLatch.await(50, TimeUnit.MILLISECONDS));
endTransition();
}
@@ -161,7 +161,7 @@
startTransition(R.layout.scene1);
waitForStart();
endTransition();
- waitForEnd(50);
+ waitForEnd(100);
}
public void testEndTransitionsBeforeStarted() throws Throwable {
@@ -175,9 +175,8 @@
TransitionManager.endTransitions(mSceneRoot);
}
});
- Thread.sleep(50);
- assertFalse(mTransition.listener.started);
- assertFalse(mTransition.listener.ended);
+ assertFalse(mTransition.listener.startLatch.await(100, TimeUnit.MILLISECONDS));
+ assertFalse(mTransition.listener.endLatch.await(10, TimeUnit.MILLISECONDS));
}
}
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionTest.java b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
index 8a9f3a3..71c85c5 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
@@ -15,7 +15,7 @@
*/
package android.transition.cts;
-import com.android.cts.transition.R;
+import android.transition.cts.R;
import android.animation.ObjectAnimator;
import android.transition.AutoTransition;
@@ -28,6 +28,8 @@
import android.widget.RelativeLayout;
import android.widget.TextView;
+import java.util.concurrent.TimeUnit;
+
public class TransitionTest extends BaseTransitionTest {
public TransitionTest() {
@@ -52,17 +54,17 @@
waitForStart(listener2);
- assertTrue(mTransition.listener.paused);
- assertTrue(mTransition.listener.resumed);
- assertFalse(mTransition.listener.canceled);
- assertFalse(mTransition.listener.ended);
- assertTrue(mTransition.listener.started);
+ assertEquals(0, mTransition.listener.pauseLatch.getCount());
+ assertEquals(0, mTransition.listener.resumeLatch.getCount());
+ assertEquals(1, mTransition.listener.cancelLatch.getCount());
+ assertEquals(1, mTransition.listener.endLatch.getCount());
+ assertEquals(0, mTransition.listener.startLatch.getCount());
- assertFalse(listener2.paused);
- assertFalse(listener2.resumed);
- assertFalse(listener2.canceled);
- assertFalse(listener2.ended);
- assertTrue(listener2.started);
+ assertEquals(1, listener2.pauseLatch.getCount());
+ assertEquals(1, listener2.resumeLatch.getCount());
+ assertEquals(1, listener2.cancelLatch.getCount());
+ assertEquals(1, listener2.endLatch.getCount());
+ assertEquals(0, listener2.startLatch.getCount());
endTransition();
}
@@ -77,8 +79,7 @@
}
});
- Thread.sleep(150);
- assertFalse(mTransition.listener.ended);
+ assertFalse(mTransition.listener.endLatch.await(250, TimeUnit.MILLISECONDS));
}
public void testAddTargetId() throws Throwable {
diff --git a/tests/tests/tv/Android.mk b/tests/tests/tv/Android.mk
index 795b473..88e41d9 100644
--- a/tests/tests/tv/Android.mk
+++ b/tests/tests/tv/Android.mk
@@ -20,6 +20,9 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CtsTvTestCases
diff --git a/tests/tests/tv/AndroidManifest.xml b/tests/tests/tv/AndroidManifest.xml
index 79406e0..7acfc94 100644
--- a/tests/tests/tv/AndroidManifest.xml
+++ b/tests/tests/tv/AndroidManifest.xml
@@ -17,7 +17,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.tv">
+ package="android.tv.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
@@ -110,7 +110,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.tv"
+ android:targetPackage="android.tv.cts"
android:label="Tests for the TV APIs.">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/tv/AndroidTest.xml b/tests/tests/tv/AndroidTest.xml
new file mode 100644
index 0000000..48d5666
--- /dev/null
+++ b/tests/tests/tv/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS TV test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTvTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.tv.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java b/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java
index f5cc2e1..94e8a01 100644
--- a/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java
@@ -27,7 +27,7 @@
import android.test.ActivityInstrumentationTestCase2;
import android.util.ArrayMap;
-import com.android.cts.tv.R;
+import android.tv.cts.R;
import java.util.ArrayList;
import java.util.List;
diff --git a/tests/tests/tv/src/android/media/tv/cts/HardwareSessionTest.java b/tests/tests/tv/src/android/media/tv/cts/HardwareSessionTest.java
index 2f852d7..a7b5805 100644
--- a/tests/tests/tv/src/android/media/tv/cts/HardwareSessionTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/HardwareSessionTest.java
@@ -29,7 +29,7 @@
import android.net.Uri;
import android.test.ActivityInstrumentationTestCase2;
-import com.android.cts.tv.R;
+import android.tv.cts.R;
import java.util.ArrayList;
import java.util.List;
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
index b4bc6eb..8fd1939 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
@@ -31,7 +31,7 @@
import android.net.Uri;
import android.test.AndroidTestCase;
-import com.android.cts.tv.R;
+import android.tv.cts.R;
import java.io.InputStream;
import java.io.OutputStream;
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
index b4c863a..2a3a713 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
@@ -39,7 +39,7 @@
import android.view.View;
import android.widget.LinearLayout;
-import com.android.cts.tv.R;
+import android.tv.cts.R;
import java.util.ArrayList;
import java.util.List;
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvViewStubActivity.java b/tests/tests/tv/src/android/media/tv/cts/TvViewStubActivity.java
index 5035e14..aa2b09f 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvViewStubActivity.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvViewStubActivity.java
@@ -19,7 +19,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.tv.R;
+import android.tv.cts.R;
public class TvViewStubActivity extends Activity {
@Override
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
index 1c59462..db6f2ba 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
@@ -35,7 +35,7 @@
import android.view.InputEvent;
import android.view.KeyEvent;
-import com.android.cts.tv.R;
+import android.tv.cts.R;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/tests/tests/uiautomation/Android.mk b/tests/tests/uiautomation/Android.mk
index bb0fc19..0564489 100644
--- a/tests/tests/uiautomation/Android.mk
+++ b/tests/tests/uiautomation/Android.mk
@@ -18,6 +18,11 @@
LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ub-uiautomator
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/uiautomation/AndroidManifest.xml b/tests/tests/uiautomation/AndroidManifest.xml
index d99e999..fba6b4e 100644
--- a/tests/tests/uiautomation/AndroidManifest.xml
+++ b/tests/tests/uiautomation/AndroidManifest.xml
@@ -17,7 +17,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.app.cts.uiautomation">
+ package="android.app.uiautomation.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -38,7 +38,7 @@
</application>
<instrumentation android:name="android.support.test.uiautomator.UiAutomatorInstrumentationTestRunner"
- android:targetPackage="android.app.cts.uiautomation">
+ android:targetPackage="android.app.uiautomation.cts">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
diff --git a/tests/tests/uiautomation/AndroidTest.xml b/tests/tests/uiautomation/AndroidTest.xml
new file mode 100644
index 0000000..cf15c6b
--- /dev/null
+++ b/tests/tests/uiautomation/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS UI Automation test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsUiAutomationTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.app.uiautomation.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
index 2f3f48c8..478a3f6 100755
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
@@ -66,7 +66,7 @@
// Find the list to scroll around.
UiScrollable listView = new UiScrollable(new UiSelector().resourceId(
- "android.app.cts.uiautomation:id/list_view"));
+ "android.app.uiautomation.cts:id/list_view"));
// Scoll a bit.
listView.scrollToEnd(Integer.MAX_VALUE);
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
index a798b1b..839a290 100644
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
@@ -16,7 +16,7 @@
package android.app.uiautomation.cts;
-import android.app.cts.uiautomation.R;
+import android.app.uiautomation.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
index e6fc743..4ba0f74 100644
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
@@ -17,7 +17,7 @@
package android.app.uiautomation.cts;
import android.app.Activity;
-import android.app.cts.uiautomation.R;
+import android.app.uiautomation.cts.R;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
diff --git a/tests/tests/uidisolation/Android.mk b/tests/tests/uidisolation/Android.mk
index c21b6df..977c432 100644
--- a/tests/tests/uidisolation/Android.mk
+++ b/tests/tests/uidisolation/Android.mk
@@ -21,6 +21,9 @@
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctstestserver
LOCAL_JAVA_LIBRARIES := org.apache.http.legacy
diff --git a/tests/tests/uidisolation/AndroidManifest.xml b/tests/tests/uidisolation/AndroidManifest.xml
index 86efb6f..0d27e37 100644
--- a/tests/tests/uidisolation/AndroidManifest.xml
+++ b/tests/tests/uidisolation/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.uidisolation">
+ package="android.uidisolation.cts">
<uses-library android:name="org.apache.http.legacy" android:required="false" />
@@ -34,7 +34,7 @@
<uses-permission android:name="android.permission.INTERNET"/>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.uidisolation"
+ android:targetPackage="android.uidisolation.cts"
android:label="CTS tests of android.uidisolation">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/uidisolation/AndroidTest.xml b/tests/tests/uidisolation/AndroidTest.xml
new file mode 100644
index 0000000..e7717c0
--- /dev/null
+++ b/tests/tests/uidisolation/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS UID Isolation test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsUidIsolationTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.uidisolation.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/uirendering/Android.mk b/tests/tests/uirendering/Android.mk
index 76707df..33e2a7a 100644
--- a/tests/tests/uirendering/Android.mk
+++ b/tests/tests/uirendering/Android.mk
@@ -19,6 +19,11 @@
# don't include this package in any target
LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
diff --git a/tests/tests/uirendering/AndroidManifest.xml b/tests/tests/uirendering/AndroidManifest.xml
index b8d84a6..8b6e2aa 100644
--- a/tests/tests/uirendering/AndroidManifest.xml
+++ b/tests/tests/uirendering/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.uirendering">
+ package="android.uirendering.cts">
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -27,7 +27,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.uirendering">
+ android:targetPackage="android.uirendering.cts">
</instrumentation>
</manifest>
diff --git a/tests/tests/uirendering/AndroidTest.xml b/tests/tests/uirendering/AndroidTest.xml
new file mode 100644
index 0000000..30c99db
--- /dev/null
+++ b/tests/tests/uirendering/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS UI Rendering test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsUiRenderingTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.uirendering.cts" />
+ <option name="runtime-hint" value="3m" />
+ </test>
+</configuration>
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.java
index 36be5f0f..562b730 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.java
@@ -15,8 +15,8 @@
*/
package android.uirendering.cts.bitmapcomparers;
-import com.android.cts.uirendering.R;
-import com.android.cts.uirendering.ScriptC_ExactComparer;
+import android.uirendering.cts.R;
+import android.uirendering.cts.ScriptC_ExactComparer;
import android.content.res.Resources;
import android.renderscript.Allocation;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.rs b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.rs
index 899a5cc..6425c17 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.rs
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.rs
@@ -1,5 +1,5 @@
#pragma version(1)
-#pragma rs java_package_name(com.android.cts.uirendering)
+#pragma rs java_package_name(android.uirendering.cts)
int WIDTH;
int OFFSET;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java
index 56d9cf5..4a25695 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java
@@ -15,7 +15,7 @@
*/
package android.uirendering.cts.bitmapcomparers;
-import com.android.cts.uirendering.ScriptC_MSSIMComparer;
+import android.uirendering.cts.ScriptC_MSSIMComparer;
import android.content.res.Resources;
import android.graphics.Color;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.rs b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.rs
index 4d8c41b8..b0e86b8 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.rs
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.rs
@@ -1,5 +1,5 @@
#pragma version(1)
-#pragma rs java_package_name(com.android.cts.uirendering)
+#pragma rs java_package_name(android.uirendering.cts)
int WIDTH;
int HEIGHT;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java
index cc2fbba..5cc896b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java
@@ -15,8 +15,8 @@
*/
package android.uirendering.cts.bitmapcomparers;
-import com.android.cts.uirendering.R;
-import com.android.cts.uirendering.ScriptC_MeanSquaredComparer;
+import android.uirendering.cts.R;
+import android.uirendering.cts.ScriptC_MeanSquaredComparer;
import android.content.res.Resources;
import android.graphics.Color;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.rs b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.rs
index b37ad13..3b37609 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.rs
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.rs
@@ -1,5 +1,5 @@
#pragma version(1)
-#pragma rs java_package_name(com.android.cts.uirendering)
+#pragma rs java_package_name(android.uirendering.cts)
int REGION_SIZE;
int WIDTH;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java
index f8304ba..6a78f11 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java
@@ -15,8 +15,8 @@
*/
package android.uirendering.cts.bitmapcomparers;
-import com.android.cts.uirendering.R;
-import com.android.cts.uirendering.ScriptC_ThresholdDifferenceComparer;
+import android.uirendering.cts.R;
+import android.uirendering.cts.ScriptC_ThresholdDifferenceComparer;
import android.content.res.Resources;
import android.graphics.Color;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.rs b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.rs
index de1a129..8a40ad6 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.rs
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.rs
@@ -1,5 +1,5 @@
#pragma version(1)
-#pragma rs java_package_name(com.android.cts.uirendering)
+#pragma rs java_package_name(android.uirendering.cts)
int WIDTH;
int THRESHOLD;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
index 29755d8..d3fdb7b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -29,7 +29,7 @@
import android.uirendering.cts.bitmapverifiers.RectVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.testinfrastructure.CanvasClient;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
public class ExactCanvasTests extends ActivityTestBase {
private final BitmapComparer mExactComparer = new ExactComparer();
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
index 5833f20..bac3629 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
@@ -29,7 +29,7 @@
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.testinfrastructure.CanvasClient;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
public class FontRenderingTests extends ActivityTestBase {
// Thresholds are barely loose enough for differences between sw and hw renderers.
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
index dfaaaea..37329af 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
@@ -16,7 +16,7 @@
package android.uirendering.cts.testclasses;
import android.graphics.Point;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
import android.graphics.Canvas;
import android.graphics.Color;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
index a5f76dd..a1338bc 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
@@ -28,7 +28,7 @@
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.testinfrastructure.ViewInitializer;
import android.view.View;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
public class LayerTests extends ActivityTestBase {
@SmallTest
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
index ff1e9db..30851b6 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
@@ -19,7 +19,7 @@
import android.graphics.Rect;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.bitmapverifiers.RectVerifier;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
import android.test.suitebuilder.annotation.SmallTest;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
index 38777a2..8c00ecc 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
@@ -32,7 +32,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
public class PathClippingTests extends ActivityTestBase {
// draw circle with hole in it, with stroked circle
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
index 85764a6..6500681 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
@@ -30,7 +30,7 @@
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.testinfrastructure.CanvasClient;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
public class ShaderTests extends ActivityTestBase {
@SmallTest
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
index 4582935..2ca8bc8 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
@@ -19,7 +19,7 @@
import android.graphics.Point;
import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
import android.test.suitebuilder.annotation.SmallTest;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -53,4 +53,4 @@
.addLayout(R.layout.simple_shadow_layout, null, true/* HW only */)
.runWithVerifier(verifier);
}
-}
\ No newline at end of file
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
index f1f7c99..2db635f0 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
@@ -11,7 +11,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
/**
* This tests view clipping by modifying properties of blue_padded_layout, and validating
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
index 526f4f9..69cb688 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -123,30 +123,10 @@
getActivity().runOnUiThread(finishRunnable);
}
- static int[] getBitmapPixels(Bitmap bitmap) {
- int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
- bitmap.getPixels(pixels, 0, bitmap.getWidth(),
- 0, 0, bitmap.getWidth(), bitmap.getHeight());
- return pixels;
- }
-
- private Bitmap takeScreenshotImpl(Point testOffset) {
- Bitmap source = getInstrumentation().getUiAutomation().takeScreenshot();
- return Bitmap.createBitmap(source, testOffset.x, testOffset.y, TEST_WIDTH, TEST_HEIGHT);
- }
-
public Bitmap takeScreenshot(Point testOffset) {
getInstrumentation().waitForIdleSync();
- Bitmap bitmap1 = takeScreenshotImpl(testOffset);
- Bitmap bitmap2;
- int count = 0;
- do {
- bitmap2 = bitmap1;
- bitmap1 = takeScreenshotImpl(testOffset);
- count++;
- } while (count < MAX_SCREEN_SHOTS &&
- !Arrays.equals(getBitmapPixels(bitmap2), getBitmapPixels(bitmap1)));
- return bitmap1;
+ Bitmap source = getInstrumentation().getUiAutomation().takeScreenshot();
+ return Bitmap.createBitmap(source, testOffset.x, testOffset.y, TEST_WIDTH, TEST_HEIGHT);
}
/**
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
index 57c67bd..f5dba26 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
@@ -27,7 +27,7 @@
import android.view.ViewTreeObserver;
import android.webkit.WebView;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
/**
* A generic activity that uses a view specified by the user.
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ResourceModifier.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ResourceModifier.java
index 5564b96..9538805 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ResourceModifier.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ResourceModifier.java
@@ -15,7 +15,7 @@
*/
package android.uirendering.cts.testinfrastructure;
-import com.android.cts.uirendering.R;
+import android.uirendering.cts.R;
import android.content.res.Resources;
import android.graphics.Bitmap;
diff --git a/tests/tests/util/Android.mk b/tests/tests/util/Android.mk
index 44a67dc..b63e637 100644
--- a/tests/tests/util/Android.mk
+++ b/tests/tests/util/Android.mk
@@ -21,6 +21,9 @@
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/util/AndroidManifest.xml b/tests/tests/util/AndroidManifest.xml
index e40087a..8c48735 100644
--- a/tests/tests/util/AndroidManifest.xml
+++ b/tests/tests/util/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.util">
+ package="android.util.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.READ_LOGS" />
@@ -25,7 +25,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.util"
+ android:targetPackage="android.util.cts"
android:label="CTS tests of android.util">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/util/AndroidTest.xml b/tests/tests/util/AndroidTest.xml
new file mode 100644
index 0000000..9af993c
--- /dev/null
+++ b/tests/tests/util/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Util test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsUtilTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.util.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/util/src/android/util/cts/LocaleListTest.java b/tests/tests/util/src/android/util/cts/LocaleListTest.java
new file mode 100644
index 0000000..83aeb9d
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/LocaleListTest.java
@@ -0,0 +1,454 @@
+/*
+ * 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.
+ */
+
+package android.util.cts;
+
+import android.os.Parcel;
+import android.util.LocaleList;
+import android.test.AndroidTestCase;
+
+import java.util.Locale;
+
+public class LocaleListTest extends AndroidTestCase {
+ public void testEmptyLocaleList() {
+ LocaleList ll = new LocaleList();
+ assertNotNull(ll);
+ assertTrue(ll.isEmpty());
+ assertEquals(0, ll.size());
+ assertNull(ll.getPrimary());
+ assertNull(ll.get(1));
+ assertNull(ll.get(10));
+
+ ll = new LocaleList((Locale) null);
+ assertNotNull(ll);
+ assertTrue(ll.isEmpty());
+ assertEquals(0, ll.size());
+ assertNull(ll.getPrimary());
+ assertNull(ll.get(1));
+ assertNull(ll.get(10));
+
+ ll = new LocaleList((Locale[]) null);
+ assertNotNull(ll);
+ assertTrue(ll.isEmpty());
+ assertEquals(0, ll.size());
+ assertNull(ll.getPrimary());
+ assertNull(ll.get(1));
+ assertNull(ll.get(10));
+
+ ll = new LocaleList(new Locale[0]);
+ assertNotNull(ll);
+ assertTrue(ll.isEmpty());
+ assertEquals(0, ll.size());
+ assertNull(ll.getPrimary());
+ assertNull(ll.get(1));
+ assertNull(ll.get(10));
+ }
+
+ public void testOneMemberLocaleList() {
+ final LocaleList ll = new LocaleList(Locale.US);
+ assertNotNull(ll);
+ assertFalse(ll.isEmpty());
+ assertEquals(1, ll.size());
+ assertEquals(Locale.US, ll.getPrimary());
+ assertEquals(Locale.US, ll.get(0));
+ assertNull(ll.get(10));
+ }
+
+ public void testTwoMemberLocaleList() {
+ final Locale enPH = Locale.forLanguageTag("en-PH");
+ final Locale[] la = {enPH, Locale.US};
+ final LocaleList ll = new LocaleList(la);
+ assertNotNull(ll);
+ assertFalse(ll.isEmpty());
+ assertEquals(2, ll.size());
+ assertEquals(enPH, ll.getPrimary());
+ assertEquals(enPH, ll.get(0));
+ assertEquals(Locale.US, ll.get(1));
+ assertNull(ll.get(10));
+ }
+
+ public void testNullArguments() {
+ final Locale[] la = {Locale.US, null};
+ LocaleList ll = null;
+ try {
+ ll = new LocaleList(la);
+ fail("Initializing a LocaleList with an array containing null should throw.");
+ } catch (Throwable e) {
+ assertEquals(NullPointerException.class, e.getClass());
+ }
+ }
+
+ public void testRepeatedArguments() {
+ final Locale[] la = {Locale.US, Locale.US};
+ LocaleList ll = null;
+ try {
+ ll = new LocaleList(la);
+ fail("Initializing a LocaleList with an array containing duplicates should throw.");
+ } catch (Throwable e) {
+ assertEquals(IllegalArgumentException.class, e.getClass());
+ }
+ }
+
+ public void testIndexOf() {
+ final LocaleList empty = new LocaleList();
+ assertEquals(-1, empty.indexOf(Locale.US));
+
+ final LocaleList oneMember = new LocaleList(Locale.US);
+ assertEquals(0, oneMember.indexOf(Locale.US));
+ assertEquals(-1, oneMember.indexOf(Locale.ENGLISH));
+
+ final LocaleList twoMember = LocaleList.forLanguageTags("en,fr");
+ assertEquals(0, twoMember.indexOf(Locale.forLanguageTag("en")));
+ assertEquals(1, twoMember.indexOf(Locale.forLanguageTag("fr")));
+ assertEquals(-1, twoMember.indexOf(Locale.forLanguageTag("en-US")));
+ }
+
+ public void testEquals() {
+ final LocaleList empty = new LocaleList();
+ final LocaleList anotherEmpty = new LocaleList();
+ LocaleList oneMember = new LocaleList(Locale.US);
+ LocaleList sameOneMember = new LocaleList(new Locale("en", "US"));
+ LocaleList differentOneMember = new LocaleList(Locale.FRENCH);
+ Locale[] la = {Locale.US, Locale.FRENCH};
+ LocaleList twoMember = new LocaleList(la);
+
+ assertFalse(empty.equals(null));
+ assertFalse(oneMember.equals(null));
+
+ assertFalse(empty.equals(new Object()));
+
+ assertTrue(empty.equals(empty));
+ assertTrue(oneMember.equals(oneMember));
+
+ assertFalse(empty.equals(oneMember));
+ assertFalse(oneMember.equals(twoMember));
+
+ assertFalse(oneMember.equals(differentOneMember));
+
+ assertTrue(empty.equals(anotherEmpty));
+ assertTrue(oneMember.equals(sameOneMember));
+ }
+
+ public void testHashCode() {
+ final LocaleList empty = new LocaleList();
+ final LocaleList anotherEmpty = new LocaleList();
+ Locale[] la1 = {Locale.US};
+ LocaleList oneMember = new LocaleList(la1);
+ LocaleList sameOneMember = new LocaleList(la1);
+
+ assertEquals(empty.hashCode(), anotherEmpty.hashCode());
+ assertEquals(oneMember.hashCode(), sameOneMember.hashCode());
+ }
+
+ public void testToString() {
+ LocaleList ll = new LocaleList();
+ assertEquals("[]", ll.toString());
+
+ final Locale[] la1 = {Locale.US};
+ ll = new LocaleList(la1);
+ assertEquals("["+Locale.US.toString()+"]", ll.toString());
+
+ final Locale[] la2 = {Locale.US, Locale.FRENCH};
+ ll = new LocaleList(la2);
+ assertEquals("["+Locale.US.toString()+","+Locale.FRENCH.toString()+"]", ll.toString());
+ }
+
+ public void testToLanguageTags() {
+ LocaleList ll = new LocaleList();
+ assertEquals("", ll.toLanguageTags());
+
+ final Locale[] la1 = {Locale.US};
+ ll = new LocaleList(la1);
+ assertEquals(Locale.US.toLanguageTag(), ll.toLanguageTags());
+
+ final Locale[] la2 = {Locale.US, Locale.FRENCH};
+ ll = new LocaleList(la2);
+ assertEquals(Locale.US.toLanguageTag()+","+Locale.FRENCH.toLanguageTag(),
+ ll.toLanguageTags());
+ }
+
+ public void testGetEmptyLocaleList() {
+ LocaleList empty = LocaleList.getEmptyLocaleList();
+ LocaleList anotherEmpty = LocaleList.getEmptyLocaleList();
+ LocaleList constructedEmpty = new LocaleList();
+
+ assertEquals(constructedEmpty, empty);
+ assertSame(empty, anotherEmpty);
+ }
+
+ public void testForLanguageTags() {
+ assertEquals(LocaleList.getEmptyLocaleList(), LocaleList.forLanguageTags(null));
+ assertEquals(LocaleList.getEmptyLocaleList(), LocaleList.forLanguageTags(""));
+
+ assertEquals(new LocaleList(Locale.forLanguageTag("en-US")),
+ LocaleList.forLanguageTags("en-US"));
+
+ final Locale[] la = {Locale.forLanguageTag("en-PH"), Locale.forLanguageTag("en-US")};
+ assertEquals(new LocaleList(la), LocaleList.forLanguageTags("en-PH,en-US"));
+ }
+
+ public void testGetDefault() {
+ final LocaleList ll = LocaleList.getDefault();
+ assertNotNull(ll);
+ assertTrue(ll.size() >= 1);
+
+ final Locale defaultLocale = Locale.getDefault();
+ assertTrue(ll.indexOf(defaultLocale) != -1);
+ }
+
+ public void testGetDefault_localeSetDefaultCalled() {
+ final Locale originalLocale = Locale.getDefault();
+ final LocaleList originalLocaleList = LocaleList.getDefault();
+
+ LocaleList.setDefault(LocaleList.forLanguageTags("ae,en,ja"));
+
+ try {
+ Locale.setDefault(Locale.forLanguageTag("fr"));
+ assertEquals("fr,ae,en,ja", LocaleList.getDefault().toLanguageTags());
+
+ Locale.setDefault(Locale.forLanguageTag("de"));
+ assertEquals("de,ae,en,ja", LocaleList.getDefault().toLanguageTags());
+
+ Locale.setDefault(Locale.forLanguageTag("en"));
+ assertEquals("en,ae,ja", LocaleList.getDefault().toLanguageTags());
+
+ Locale.setDefault(Locale.forLanguageTag("es"));
+ assertEquals("es,ae,en,ja", LocaleList.getDefault().toLanguageTags());
+
+ Locale.setDefault(Locale.forLanguageTag("ja"));
+ assertEquals("ja,ae,en", LocaleList.getDefault().toLanguageTags());
+
+ Locale.setDefault(Locale.forLanguageTag("ae"));
+ assertEquals("ae,en,ja", LocaleList.getDefault().toLanguageTags());
+ } finally {
+ // restore the original values
+ LocaleList.setDefault(originalLocaleList, originalLocaleList.indexOf(originalLocale));
+ }
+ }
+
+ public void testSetDefault_null() {
+ try {
+ LocaleList.setDefault(null);
+ fail("Setting the default locale list to null should throw.");
+ } catch (Throwable e) {
+ assertEquals(NullPointerException.class, e.getClass());
+ }
+ }
+
+ public void testSetDefault_empty() {
+ try {
+ LocaleList.setDefault(LocaleList.getEmptyLocaleList());
+ fail("Setting the default locale list to an empty list should throw.");
+ } catch (Throwable e) {
+ assertEquals(IllegalArgumentException.class, e.getClass());
+ }
+ }
+
+ public void testSetDefault_oneLocale() {
+ final Locale originalLocale = Locale.getDefault();
+ final LocaleList originalLocaleList = LocaleList.getDefault();
+
+ final LocaleList locales = LocaleList.forLanguageTags("ae");
+ LocaleList.setDefault(locales);
+ try {
+ assertEquals("ae", Locale.getDefault().toLanguageTag());
+ assertEquals(locales, LocaleList.getDefault());
+ } finally {
+ // restore the original values
+ LocaleList.setDefault(originalLocaleList, originalLocaleList.indexOf(originalLocale));
+ }
+ }
+
+ public void testSetDefault_twoLocales() {
+ final Locale originalLocale = Locale.getDefault();
+ final LocaleList originalLocaleList = LocaleList.getDefault();
+
+ final LocaleList locales = LocaleList.forLanguageTags("ae,en");
+ LocaleList.setDefault(locales);
+ try {
+ assertEquals("ae", Locale.getDefault().toLanguageTag());
+ assertEquals(locales, LocaleList.getDefault());
+ } finally {
+ // restore the original values
+ LocaleList.setDefault(originalLocaleList, originalLocaleList.indexOf(originalLocale));
+ }
+ }
+
+ public void testParcelable() {
+ // Make sure an empty LocaleList can be marshalled/unmarshalled via Parcel.
+ assertEquals(LocaleList.getEmptyLocaleList(),
+ cloneViaParcel(LocaleList.getEmptyLocaleList()));
+
+ // Make sure a non-empty LocaleList can be marshalled/unmarshalled via Parcel.
+ LocaleList original = LocaleList.forLanguageTags("en-PH,en-US");
+ assertEquals(original, cloneViaParcel(original));
+ }
+
+ private static LocaleList cloneViaParcel(final LocaleList original) {
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ original.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ return LocaleList.CREATOR.createFromParcel(parcel);
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ }
+ }
+ }
+
+ public void testGetFirstMatch_noAssets() {
+ String[] noAssets = {};
+ assertNull(LocaleList.getEmptyLocaleList().getFirstMatch(noAssets));
+ assertEquals(
+ Locale.forLanguageTag("fr-BE"),
+ LocaleList.forLanguageTags("fr-BE").getFirstMatch(noAssets));
+ assertEquals(
+ Locale.forLanguageTag("fr-BE"),
+ LocaleList.forLanguageTags("fr-BE,nl-BE").getFirstMatch(noAssets));
+ }
+
+ public void testGetFirstMatch_oneAsset() {
+ String[] oneDutchAsset = {"nl"};
+ assertNull(LocaleList.getEmptyLocaleList().getFirstMatch(oneDutchAsset));
+ assertEquals(
+ Locale.forLanguageTag("fr-BE"),
+ LocaleList.forLanguageTags("fr-BE").getFirstMatch(oneDutchAsset));
+ assertEquals(
+ Locale.forLanguageTag("nl-BE"),
+ LocaleList.forLanguageTags("nl-BE").getFirstMatch(oneDutchAsset));
+ assertEquals(
+ Locale.forLanguageTag("nl-BE"),
+ LocaleList.forLanguageTags("fr-BE,nl-BE").getFirstMatch(oneDutchAsset));
+ assertEquals(
+ Locale.forLanguageTag("nl-BE"),
+ LocaleList.forLanguageTags("nl-BE,fr-BE").getFirstMatch(oneDutchAsset));
+ }
+
+ public void testGetFirstMatch_twoAssets() {
+ String[] FrenchAndDutchAssets = {"fr", "nl"};
+ assertNull(LocaleList.getEmptyLocaleList().getFirstMatch(FrenchAndDutchAssets));
+ assertEquals(
+ Locale.forLanguageTag("fr-BE"),
+ LocaleList.forLanguageTags("fr-BE").getFirstMatch(FrenchAndDutchAssets));
+ assertEquals(
+ Locale.forLanguageTag("nl-BE"),
+ LocaleList.forLanguageTags("nl-BE").getFirstMatch(FrenchAndDutchAssets));
+ assertEquals(
+ Locale.forLanguageTag("fr-BE"),
+ LocaleList.forLanguageTags("fr-BE,nl-BE").getFirstMatch(FrenchAndDutchAssets));
+ assertEquals(
+ Locale.forLanguageTag("nl-BE"),
+ LocaleList.forLanguageTags("nl-BE,fr-BE").getFirstMatch(FrenchAndDutchAssets));
+ }
+
+ public void testGetFirstMatch_oneChineseAsset() {
+ String[] oneChineseAsset = {"zh-CN"}; // Assumed to mean zh-Hans-CN
+ // The following Chinese examples would all match, so they will be chosen.
+ assertEquals(
+ Locale.forLanguageTag("zh"),
+ LocaleList.forLanguageTags("ko-KR,zh").getFirstMatch(oneChineseAsset));
+ assertEquals(
+ Locale.forLanguageTag("zh-CN"),
+ LocaleList.forLanguageTags("ko-KR,zh-CN").getFirstMatch(oneChineseAsset));
+ assertEquals(
+ Locale.forLanguageTag("zh-Hans"),
+ LocaleList.forLanguageTags("ko-KR,zh-Hans").getFirstMatch(oneChineseAsset));
+ assertEquals(
+ Locale.forLanguageTag("zh-Hans-CN"),
+ LocaleList.forLanguageTags("ko-KR,zh-Hans-CN").getFirstMatch(oneChineseAsset));
+ assertEquals(
+ Locale.forLanguageTag("zh-Hans-HK"),
+ LocaleList.forLanguageTags("ko-KR,zh-Hans-HK").getFirstMatch(oneChineseAsset));
+
+ // The following Chinese examples wouldn't match, so the first locale will be chosen
+ // instead.
+ assertEquals(
+ Locale.forLanguageTag("ko-KR"),
+ LocaleList.forLanguageTags("ko-KR,zh-TW").getFirstMatch(oneChineseAsset));
+ assertEquals(
+ Locale.forLanguageTag("ko-KR"),
+ LocaleList.forLanguageTags("ko-KR,zh-Hant").getFirstMatch(oneChineseAsset));
+ assertEquals(
+ Locale.forLanguageTag("ko-KR"),
+ LocaleList.forLanguageTags("ko-KR,zh-Hant-TW").getFirstMatch(oneChineseAsset));
+ }
+
+ public void testGetFirstMatch_serbianCyrillic() {
+ String[] oneSerbianAsset = {"sr"}; // Assumed to mean sr-Cyrl-RS
+ // The following Serbian examples would all match, so they will be chosen.
+ assertEquals(
+ Locale.forLanguageTag("sr"),
+ LocaleList.forLanguageTags("hr-HR,sr").getFirstMatch(oneSerbianAsset));
+ assertEquals(
+ Locale.forLanguageTag("sr-RS"),
+ LocaleList.forLanguageTags("hr-HR,sr-RS").getFirstMatch(oneSerbianAsset));
+ assertEquals(
+ Locale.forLanguageTag("sr-Cyrl"),
+ LocaleList.forLanguageTags("hr-HR,sr-Cyrl").getFirstMatch(oneSerbianAsset));
+ assertEquals(
+ Locale.forLanguageTag("sr-Cyrl-RS"),
+ LocaleList.forLanguageTags("hr-HR,sr-Cyrl-RS").getFirstMatch(oneSerbianAsset));
+ assertEquals(
+ Locale.forLanguageTag("sr-Cyrl-ME"),
+ LocaleList.forLanguageTags("hr-HR,sr-Cyrl-ME").getFirstMatch(oneSerbianAsset));
+
+ // The following Serbian examples wouldn't match, so the first locale will be chosen
+ // instead.
+ assertEquals(
+ Locale.forLanguageTag("hr-HR"),
+ LocaleList.forLanguageTags("hr-HR,sr-ME").getFirstMatch(oneSerbianAsset));
+ assertEquals(
+ Locale.forLanguageTag("hr-HR"),
+ LocaleList.forLanguageTags("hr-HR,sr-Latn").getFirstMatch(oneSerbianAsset));
+ assertEquals(
+ Locale.forLanguageTag("hr-HR"),
+ LocaleList.forLanguageTags("hr-HR,sr-Latn-ME").getFirstMatch(oneSerbianAsset));
+ }
+
+ public void testGetFirstMatch_LtrPseudoLocale() {
+ String[] onePseudoLocale = {"en-XA"};
+ // "en-XA" matches itself
+ assertEquals(
+ Locale.forLanguageTag("en-XA"),
+ LocaleList.forLanguageTags("sr,en-XA").getFirstMatch(onePseudoLocale));
+
+ // "en-XA" doesn't match "en" or "en-US"
+ assertEquals(
+ Locale.forLanguageTag("sr"),
+ LocaleList.forLanguageTags("sr,en").getFirstMatch(onePseudoLocale));
+ assertEquals(
+ Locale.forLanguageTag("sr"),
+ LocaleList.forLanguageTags("sr,en-US").getFirstMatch(onePseudoLocale));
+ }
+
+ public void testGetFirstMatch_RtlPseudoLocale() {
+ String[] onePseudoLocale = {"ar-XB"};
+ // "ar-XB" matches itself
+ assertEquals(
+ Locale.forLanguageTag("ar-XB"),
+ LocaleList.forLanguageTags("sr,ar-XB").getFirstMatch(onePseudoLocale));
+
+ // "ar-XB" doesn't match "ar" or "ar-EG"
+ assertEquals(
+ Locale.forLanguageTag("sr"),
+ LocaleList.forLanguageTags("sr,ar").getFirstMatch(onePseudoLocale));
+ assertEquals(
+ Locale.forLanguageTag("sr"),
+ LocaleList.forLanguageTags("sr,ar-EG").getFirstMatch(onePseudoLocale));
+ }
+}
diff --git a/tests/tests/util/src/android/util/cts/PatternsTest.java b/tests/tests/util/src/android/util/cts/PatternsTest.java
new file mode 100644
index 0000000..61755ef
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/PatternsTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.util.cts;
+
+import android.util.Patterns;
+
+import junit.framework.TestCase;
+
+/**
+ * Test {@link Patterns}.
+ */
+public class PatternsTest extends TestCase {
+
+ public void testWebUrl_matchesUrlsWithCommasInRequestParameterValues() throws Exception {
+ String url = "https://android.com/path?ll=37.4221,-122.0836&z=17&pll=37.4221,-122.0836";
+ assertTrue("WEB_URL pattern should match commas", Patterns.WEB_URL.matcher(url).matches());
+ }
+}
diff --git a/tests/tests/util/src/android/util/cts/PropertyTest.java b/tests/tests/util/src/android/util/cts/PropertyTest.java
new file mode 100644
index 0000000..22ad2c4
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/PropertyTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+package android.util.cts;
+
+import android.graphics.Point;
+import android.util.FloatProperty;
+import android.util.IntProperty;
+import android.util.Property;
+import junit.framework.TestCase;
+
+public class PropertyTest extends TestCase {
+
+ float mFloatValue = -1;
+ int mIntValue = -2;
+ Point mPointValue = new Point(-3, -4);
+
+ 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());
+
+ RAW_FLOAT_PROP.set(this, testFloatValue);
+ assertEquals(RAW_FLOAT_PROP.get(this), mFloatValue);
+
+ RAW_POINT_PROP.set(this, testPointValue);
+ assertEquals(RAW_POINT_PROP.get(this), testPointValue);
+ }
+
+ public void testFloatProperty() throws Exception {
+ float testFloatValue = 5;
+
+ assertFalse(getFloatProp() == testFloatValue);
+ assertEquals(FLOAT_PROP.get(this), getFloatProp());
+
+ FLOAT_PROP.set(this, testFloatValue);
+ assertEquals(FLOAT_PROP.get(this), testFloatValue);
+ }
+
+ public void testIntProperty() throws Exception {
+ int testIntValue = 5;
+
+ assertFalse(getIntProp() == testIntValue);
+ assertEquals(INT_PROP.get(this).intValue(), getIntProp());
+
+ INT_PROP.set(this, testIntValue);
+ assertEquals(INT_PROP.get(this).intValue(), testIntValue);
+ }
+
+ // Utility methods to get/set instance values. Used by Property classes below.
+
+ private void setFloatProp(float value) {
+ mFloatValue = value;
+ }
+
+ private float getFloatProp() {
+ return mFloatValue;
+ }
+
+ private void setIntProp(int value) {
+ mIntValue = value;
+ }
+
+ private int getIntProp() {
+ return mIntValue;
+ }
+
+ private void setPointProp(Point value) {
+ mPointValue = value;
+ }
+
+ private Point getPointProp() {
+ return mPointValue;
+ }
+
+ // Properties. RAW subclass from the generic Property class, the others subclass from
+ // the primtive-friendly IntProperty and FloatProperty subclasses.
+
+ public static final Property<PropertyTest, Point> RAW_POINT_PROP =
+ new Property<PropertyTest, Point>(Point.class, "rawPoint") {
+ @Override
+ public void set(PropertyTest object, Point value) {
+ object.setPointProp(value);
+ }
+
+ @Override
+ public Point get(PropertyTest object) {
+ return object.getPointProp();
+ }
+ };
+
+ public static final Property<PropertyTest, Float> RAW_FLOAT_PROP =
+ new Property<PropertyTest, Float>(Float.class, "rawFloat") {
+ @Override
+ public void set(PropertyTest object, Float value) {
+ object.setFloatProp(value);
+ }
+
+ @Override
+ public Float get(PropertyTest object) {
+ return object.getFloatProp();
+ }
+ };
+
+ public static final Property<PropertyTest, Float> FLOAT_PROP =
+ new FloatProperty<PropertyTest>("float") {
+
+ @Override
+ public void setValue(PropertyTest object, float value) {
+ object.setFloatProp(value);
+ }
+
+ @Override
+ public Float get(PropertyTest object) {
+ return object.getFloatProp();
+ }
+ };
+
+ public static final Property<PropertyTest, Integer> INT_PROP =
+ new IntProperty<PropertyTest>("int") {
+
+ @Override
+ public void setValue(PropertyTest object, int value) {
+ object.setIntProp(value);
+ }
+
+ @Override
+ public Integer get(PropertyTest object) {
+ return object.getIntProp();
+ }
+ };
+}
diff --git a/tests/tests/util/src/android/util/cts/XmlTest.java b/tests/tests/util/src/android/util/cts/XmlTest.java
index 833bd3c..66918ce 100644
--- a/tests/tests/util/src/android/util/cts/XmlTest.java
+++ b/tests/tests/util/src/android/util/cts/XmlTest.java
@@ -391,7 +391,7 @@
public void testAsAttributeSet() {
XmlResourceParser xp = getContext().getResources().getLayout(
- com.android.cts.util.R.layout.xml_test);
+ android.util.cts.R.layout.xml_test);
int eventType = -1;
try {
eventType = xp.getEventType();
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index 027e321..24a351f 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -21,6 +21,9 @@
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index b7e0076..1b84aff 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.view">
+ package="android.view.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application android:label="Android TestCase"
@@ -191,10 +191,18 @@
</intent-filter>
</activity>
+ <activity android:name="android.view.cts.ContentPaneCtsActivity"
+ android:label="ContentPaneCtsActivity">
+ <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"
- android:targetPackage="com.android.cts.view"
+ android:targetPackage="android.view.cts"
android:label="CTS tests of android.view">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/view/AndroidTest.xml b/tests/tests/view/AndroidTest.xml
new file mode 100644
index 0000000..def111d
--- /dev/null
+++ b/tests/tests/view/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS View test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsViewTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.view.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/view/res/layout/view_layout.xml b/tests/tests/view/res/layout/view_layout.xml
index b501a4d..07a9f0d 100644
--- a/tests/tests/view/res/layout/view_layout.xml
+++ b/tests/tests/view/res/layout/view_layout.xml
@@ -102,4 +102,22 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
+ <LinearLayout
+ android:id="@+id/pointer_icon_layout"
+ android:orientation="vertical"
+ android:layout_width="100px"
+ android:layout_height="100px">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="50px"
+ android:pointerShape="crosshair">
+ <View android:layout_width="match_parent"
+ android:layout_height="20px"
+ android:pointerShape="help"/>
+ <View android:layout_width="match_parent"
+ android:layout_height="20px"/>
+ </LinearLayout>
+ </LinearLayout>
+
</LinearLayout>
diff --git a/tests/tests/view/res/menu/menu_settings.xml b/tests/tests/view/res/menu/menu_settings.xml
new file mode 100644
index 0000000..4f210d9
--- /dev/null
+++ b/tests/tests/view/res/menu/menu_settings.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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:title="Settings"/>
+</menu>
diff --git a/tests/tests/view/src/android/view/animation/cts/AccelerateDecelerateInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/AccelerateDecelerateInterpolatorTest.java
index 6e80d00..440e390 100644
--- a/tests/tests/view/src/android/view/animation/cts/AccelerateDecelerateInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AccelerateDecelerateInterpolatorTest.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
@@ -41,7 +41,7 @@
private static final long ALPHA_DURATION = 2000;
public AccelerateDecelerateInterpolatorTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/animation/cts/AccelerateInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/AccelerateInterpolatorTest.java
index 51b2b09..b2be24d 100644
--- a/tests/tests/view/src/android/view/animation/cts/AccelerateInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AccelerateInterpolatorTest.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
@@ -36,7 +36,7 @@
extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
public AccelerateInterpolatorTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
private Activity mActivity;
diff --git a/tests/tests/view/src/android/view/animation/cts/AlphaAnimationTest.java b/tests/tests/view/src/android/view/animation/cts/AlphaAnimationTest.java
index acfe1a6..45eb418 100644
--- a/tests/tests/view/src/android/view/animation/cts/AlphaAnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AlphaAnimationTest.java
@@ -23,7 +23,7 @@
import android.view.animation.AlphaAnimation;
import android.view.animation.Transformation;
-import com.android.cts.view.R;
+import android.view.cts.R;
/**
* Test {@link AlphaAnimation}.
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationSetTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationSetTest.java
index 0b3bf49..49c51e0 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationSetTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationSetTest.java
@@ -33,7 +33,7 @@
import android.view.animation.Transformation;
import android.view.animation.TranslateAnimation;
-import com.android.cts.view.R;
+import android.view.cts.R;
public class AnimationSetTest
@@ -51,7 +51,7 @@
private Activity mActivity;
public AnimationSetTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
index 31440df..a465824 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
@@ -35,6 +35,9 @@
import android.view.animation.Transformation;
import android.view.animation.Animation.AnimationListener;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* Test {@link Animation}.
*/
@@ -51,7 +54,7 @@
private Object mLockObject = new Object();
public AnimationTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
@@ -644,7 +647,82 @@
assertEquals(myAnimation.getRepeatMode(), cloneAnimation.getRepeatMode());
}
+ public void testCancelImmediately() throws Throwable {
+ MyAnimation anim = new MyAnimation();
+ final CountDownLatch latch1 = new CountDownLatch(1);
+ runCanceledAnimation(anim, latch1, false, false);
+ assertTrue(latch1.await(200, TimeUnit.MILLISECONDS));
+ assertFalse(anim.isStillAnimating());
+ }
+
+ public void testRepeatingCancelImmediately() throws Throwable {
+ MyAnimation anim = new MyAnimation();
+ final CountDownLatch latch2 = new CountDownLatch(1);
+ runCanceledAnimation(anim, latch2, true, false);
+ assertTrue(latch2.await(200, TimeUnit.MILLISECONDS));
+ assertFalse(anim.isStillAnimating());
+ }
+
+ public void testCancelDelayed() throws Throwable {
+ MyAnimation anim = new MyAnimation();
+ final CountDownLatch latch3 = new CountDownLatch(1);
+ runCanceledAnimation(anim, latch3, false, true);
+ assertTrue(latch3.await(250, TimeUnit.MILLISECONDS));
+ assertFalse(anim.isStillAnimating());
+ }
+
+ public void testRepeatingCancelDelayed() throws Throwable {
+ MyAnimation anim = new MyAnimation();
+ final CountDownLatch latch4 = new CountDownLatch(1);
+ runCanceledAnimation(anim, latch4, true, true);
+ assertTrue(latch4.await(250, TimeUnit.MILLISECONDS));
+ assertFalse(anim.isStillAnimating());
+ }
+
+ private void runCanceledAnimation(final MyAnimation anim, final CountDownLatch latch,
+ final boolean repeating, final boolean delayed) throws Throwable {
+ // The idea behind this test is that canceling an Animation should result in
+ // it ending, which means not having its getTransformation() method called
+ // anymore. The trick is that cancel() will still allow one more frame to run,
+ // so we have to insert some delay between when we cancel and when we can check
+ // whether it is still animating.
+ runTestOnUiThread(new Runnable() {
+ final View view = mActivity.findViewById(R.id.anim_window);
+ public void run() {
+ anim.setDuration(delayed ? 150 : 100);
+ if (repeating) {
+ anim.setRepeatCount(Animation.INFINITE);
+ }
+ view.startAnimation(anim);
+ if (!delayed) {
+ anim.cancel();
+ } else {
+ view.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ anim.cancel();
+ }
+ }, 50);
+ }
+ view.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ anim.setStillAnimating(false);
+ view.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ latch.countDown();
+ }
+ }, 50);
+ }
+ }, delayed ? 100 : 50);
+ }
+ });
+ }
+
private class MyAnimation extends Animation {
+ boolean mStillAnimating = false;
+
@Override
protected void ensureInterpolator() {
super.ensureInterpolator();
@@ -659,6 +737,20 @@
protected Animation clone() throws CloneNotSupportedException {
return super.clone();
}
+
+ public void setStillAnimating(boolean value) {
+ mStillAnimating = value;
+ }
+
+ public boolean isStillAnimating() {
+ return mStillAnimating;
+ }
+
+ @Override
+ public boolean getTransformation(long currentTime, Transformation outTransformation) {
+ mStillAnimating = true;
+ return super.getTransformation(currentTime, outTransformation);
+ }
}
private class MockAnimationListener implements AnimationListener {
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationTestCtsActivity.java b/tests/tests/view/src/android/view/animation/cts/AnimationTestCtsActivity.java
index 1ef9e48..0316f28 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationTestCtsActivity.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationTestCtsActivity.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationUtilsTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationUtilsTest.java
index 9de0d87..b47613f 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationUtilsTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationUtilsTest.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.content.Context;
@@ -35,7 +35,7 @@
private AnimationTestCtsActivity mActivity;
public AnimationUtilsTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
@@ -45,7 +45,7 @@
}
public void testLoad() {
- // XML file of com.android.cts.view.R.anim.anim_alpha
+ // XML file of android.view.cts.R.anim.anim_alpha
// <alpha xmlns:android="http://schemas.android.com/apk/res/android"
// android:interpolator="@android:anim/accelerate_interpolator"
// android:fromAlpha="0.0"
@@ -61,7 +61,7 @@
android.R.anim.accelerate_interpolator);
assertTrue(interpolator instanceof AccelerateInterpolator);
- // Load LayoutAnimationController from com.android.cts.view.R.anim.anim_gridlayout
+ // Load LayoutAnimationController from android.view.cts.R.anim.anim_gridlayout
// <gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
// android:delay="10%"
// android:rowDelay="50%"
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimatorInflaterTest.java b/tests/tests/view/src/android/view/animation/cts/AnimatorInflaterTest.java
index cc8ada0..3851e94 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimatorInflaterTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimatorInflaterTest.java
@@ -36,7 +36,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import com.android.cts.view.R;
+import android.view.cts.R;
public class AnimatorInflaterTest
extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
@@ -45,7 +45,7 @@
Set<Integer> identityHashes = new HashSet<Integer>();
public AnimatorInflaterTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
private void assertUnique(Object object) {
diff --git a/tests/tests/view/src/android/view/animation/cts/CycleInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/CycleInterpolatorTest.java
index 3297377..3ac5950 100644
--- a/tests/tests/view/src/android/view/animation/cts/CycleInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/CycleInterpolatorTest.java
@@ -29,7 +29,7 @@
import android.view.animation.Interpolator;
import android.view.animation.Transformation;
-import com.android.cts.view.R;
+import android.view.cts.R;
/**
@@ -45,7 +45,7 @@
private static final float ALPHA_DELTA = 0.001f;
public CycleInterpolatorTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/animation/cts/DecelerateInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/DecelerateInterpolatorTest.java
index deb52dd..2400291 100644
--- a/tests/tests/view/src/android/view/animation/cts/DecelerateInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/DecelerateInterpolatorTest.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
@@ -45,7 +45,7 @@
private static final long DECELERATE_ALPHA_DURATION = 2000;
public DecelerateInterpolatorTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimCtsActivity.java b/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimCtsActivity.java
index bf95077..371af41 100644
--- a/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimCtsActivity.java
+++ b/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimCtsActivity.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
import android.database.DataSetObserver;
diff --git a/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimationControllerTest.java b/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimationControllerTest.java
index 54898b4..58efa0e 100644
--- a/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimationControllerTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimationControllerTest.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.content.Context;
@@ -58,7 +58,7 @@
private static final int INDEX_OF_CHILD9 = 8;
public GridLayoutAnimationControllerTest() {
- super("com.android.cts.view", GridLayoutAnimCtsActivity.class);
+ super("android.view.cts", GridLayoutAnimCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/animation/cts/LayoutAnimationControllerTest.java b/tests/tests/view/src/android/view/animation/cts/LayoutAnimationControllerTest.java
index 2f8f36d..adc4192 100644
--- a/tests/tests/view/src/android/view/animation/cts/LayoutAnimationControllerTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/LayoutAnimationControllerTest.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.ListActivity;
@@ -58,7 +58,7 @@
private static final long DEFAULT_MAX_DURATION = 2000;
public LayoutAnimationControllerTest() {
- super("com.android.cts.view", LayoutAnimCtsActivity.class);
+ super("android.view.cts", LayoutAnimCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/animation/cts/LinearInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/LinearInterpolatorTest.java
index 28407f9..23f8608 100644
--- a/tests/tests/view/src/android/view/animation/cts/LinearInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/LinearInterpolatorTest.java
@@ -26,7 +26,7 @@
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
-import com.android.cts.view.R;
+import android.view.cts.R;
/**
@@ -42,7 +42,7 @@
private static final long LINEAR_ALPHA_TIME_STEP = LINEAR_ALPHA_DURATION / 5;
public LinearInterpolatorTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/animation/cts/RotateAnimationTest.java b/tests/tests/view/src/android/view/animation/cts/RotateAnimationTest.java
index 958133a..afeba5c 100644
--- a/tests/tests/view/src/android/view/animation/cts/RotateAnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/RotateAnimationTest.java
@@ -28,7 +28,7 @@
import android.view.animation.RotateAnimation;
import android.view.animation.Transformation;
-import com.android.cts.view.R;
+import android.view.cts.R;
public class RotateAnimationTest
@@ -42,7 +42,7 @@
private static final float TO_DEGREE = 90.0f;
public RotateAnimationTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/animation/cts/ScaleAnimationTest.java b/tests/tests/view/src/android/view/animation/cts/ScaleAnimationTest.java
index e17435e..dc78fa9 100644
--- a/tests/tests/view/src/android/view/animation/cts/ScaleAnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/ScaleAnimationTest.java
@@ -16,7 +16,7 @@
package android.view.animation.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.content.res.XmlResourceParser;
@@ -44,7 +44,7 @@
private AnimationTestCtsActivity mActivity;
public ScaleAnimationTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/animation/cts/TranslateAnimationTest.java b/tests/tests/view/src/android/view/animation/cts/TranslateAnimationTest.java
index 94ab558..06daa72 100644
--- a/tests/tests/view/src/android/view/animation/cts/TranslateAnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/TranslateAnimationTest.java
@@ -28,7 +28,7 @@
import android.view.animation.Transformation;
import android.view.animation.TranslateAnimation;
-import com.android.cts.view.R;
+import android.view.cts.R;
public class TranslateAnimationTest
@@ -48,7 +48,7 @@
private static final float RELATIVE_TO_Y_DELTA = 0.4f;
public TranslateAnimationTest() {
- super("com.android.cts.view", AnimationTestCtsActivity.class);
+ super("android.view.cts", AnimationTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/ContentPaneCtsActivity.java b/tests/tests/view/src/android/view/cts/ContentPaneCtsActivity.java
new file mode 100644
index 0000000..5d7b354
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ContentPaneCtsActivity.java
@@ -0,0 +1,42 @@
+/*
+ * 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.app.Activity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.cts.R;
+
+/**
+ * A simple activity to test "Focus Handling"
+ */
+public class ContentPaneCtsActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setTheme(android.R.style.Theme_Material_Light);
+ setContentView(R.layout.viewtreeobserver_layout);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_settings, menu);
+ return true;
+ }
+}
diff --git a/tests/tests/view/src/android/view/cts/ContentPaneFocusTest.java b/tests/tests/view/src/android/view/cts/ContentPaneFocusTest.java
new file mode 100644
index 0000000..c99679b
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ContentPaneFocusTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.app.Activity;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.cts.R;
+
+public class ContentPaneFocusTest
+ extends ActivityInstrumentationTestCase2<ContentPaneCtsActivity> {
+ public ContentPaneFocusTest() {
+ super("android.view.cts", ContentPaneCtsActivity.class);
+ }
+
+ public void testAccessActionBar() throws Throwable {
+ final Activity activity = getActivity();
+
+ final View v1 = activity.findViewById(R.id.view1);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ v1.requestFocus();
+ }
+ });
+
+ getInstrumentation().waitForIdleSync();
+ sendControlChar('<');
+ getInstrumentation().waitForIdleSync();
+
+ // Should jump to the action bar after control-<
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(v1.hasFocus());
+ View actionBar = activity.findViewById(com.android.internal.R.id.action_bar);
+ assertTrue(actionBar.hasFocus());
+ }
+ });
+ getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
+ getInstrumentation().waitForIdleSync();
+
+ // Should jump to the first view again.
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(v1.hasFocus());
+ }
+ });
+ getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
+ getInstrumentation().waitForIdleSync();
+
+ // Now it shouldn't go up to action bar -- it doesn't allow taking focus once left
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(v1.hasFocus());
+ }
+ });
+ }
+
+ private void sendControlChar(char key) throws Throwable {
+ KeyEvent tempEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A);
+ KeyCharacterMap map = tempEvent.getKeyCharacterMap();
+ KeyEvent[] events = map.getEvents(new char[] {key});
+ for (int i = 0; i < events.length; i++) {
+ long time = SystemClock.uptimeMillis();
+ KeyEvent event = events[i];
+ KeyEvent controlKey = new KeyEvent(time, time, event.getAction(), event.getKeyCode(),
+ event.getRepeatCount(), event.getMetaState() | KeyEvent.META_CTRL_ON);
+ getInstrumentation().sendKeySync(controlKey);
+ }
+ }
+}
diff --git a/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java b/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java
index 012a13d..b25f733 100644
--- a/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java
+++ b/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java
@@ -23,7 +23,7 @@
import android.test.AndroidTestCase;
import android.view.ContextThemeWrapper;
-import com.android.cts.view.R;
+import android.view.cts.R;
public class ContextThemeWrapperTest extends AndroidTestCase {
diff --git a/tests/tests/view/src/android/view/cts/FocusFinderCtsActivity.java b/tests/tests/view/src/android/view/cts/FocusFinderCtsActivity.java
index 14ab577..d2fa729 100644
--- a/tests/tests/view/src/android/view/cts/FocusFinderCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/FocusFinderCtsActivity.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
import android.content.Context;
diff --git a/tests/tests/view/src/android/view/cts/FocusFinderTest.java b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
index 55c288e..6b3b784 100644
--- a/tests/tests/view/src/android/view/cts/FocusFinderTest.java
+++ b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
@@ -34,7 +34,7 @@
private Button mBottomRight;
public FocusFinderTest() {
- super("com.android.cts.view", FocusFinderCtsActivity.class);
+ super("android.view.cts", FocusFinderCtsActivity.class);
}
@Override
@@ -46,6 +46,10 @@
mTopRight = getActivity().topRightButton;
mBottomLeft = getActivity().bottomLeftButton;
mBottomRight = getActivity().bottomRightButton;
+ mTopLeft.setNextFocusLeftId(View.NO_ID);
+ mTopRight.setNextFocusLeftId(View.NO_ID);
+ mBottomLeft.setNextFocusLeftId(View.NO_ID);
+ mBottomRight.setNextFocusLeftId(View.NO_ID);
}
public void testGetInstance() {
@@ -169,4 +173,50 @@
assertEquals(0, deltas[0]);
assertEquals(-1, deltas[1]);
}
+
+ public void testFindNextAndPrevFocusAvoidingChain() {
+ mBottomRight.setNextFocusForwardId(mBottomLeft.getId());
+ mBottomLeft.setNextFocusForwardId(mTopRight.getId());
+ // Follow the chain
+ assertNextFocus(mBottomRight, View.FOCUS_FORWARD, mBottomLeft);
+ assertNextFocus(mBottomLeft, View.FOCUS_FORWARD, mTopRight);
+ assertNextFocus(mTopRight, View.FOCUS_BACKWARD, mBottomLeft);
+ assertNextFocus(mBottomLeft, View.FOCUS_BACKWARD, mBottomRight);
+
+ // Now go to the one not in the chain
+ assertNextFocus(mTopRight, View.FOCUS_FORWARD, mTopLeft);
+ assertNextFocus(mBottomRight, View.FOCUS_BACKWARD, mTopLeft);
+
+ // Now go back to the top of the chain
+ assertNextFocus(mTopLeft, View.FOCUS_FORWARD, mBottomRight);
+ assertNextFocus(mTopLeft, View.FOCUS_BACKWARD, mTopRight);
+
+ // Now make the chain a circle -- this is the pathological case
+ mTopRight.setNextFocusForwardId(mBottomRight.getId());
+ // Fall back to the next one in a chain.
+ assertNextFocus(mTopLeft, View.FOCUS_FORWARD, mTopRight);
+ assertNextFocus(mTopLeft, View.FOCUS_BACKWARD, mBottomRight);
+
+ //Now do branching focus changes
+ mTopRight.setNextFocusForwardId(View.NO_ID);
+ mBottomRight.setNextFocusForwardId(mTopRight.getId());
+ assertNextFocus(mBottomRight, View.FOCUS_FORWARD, mTopRight);
+ assertNextFocus(mBottomLeft, View.FOCUS_FORWARD, mTopRight);
+ // From the tail, it jumps out of the chain
+ assertNextFocus(mTopRight, View.FOCUS_FORWARD, mTopLeft);
+
+ // Back from the head of a tree goes out of the tree
+ // We don't know which is the head of the focus chain since it is branching.
+ View prevFocus1 = mFocusFinder.findNextFocus(mLayout, mBottomLeft, View.FOCUS_BACKWARD);
+ View prevFocus2 = mFocusFinder.findNextFocus(mLayout, mBottomRight, View.FOCUS_BACKWARD);
+ assertTrue(prevFocus1 == mTopLeft || prevFocus2 == mTopLeft);
+
+ // From outside, it chooses an arbitrary head of the chain
+ View nextFocus = mFocusFinder.findNextFocus(mLayout, mTopLeft, View.FOCUS_FORWARD);
+ assertTrue(nextFocus == mBottomRight || nextFocus == mBottomLeft);
+
+ // Going back from the tail of the split chain, it chooses an arbitrary head
+ nextFocus = mFocusFinder.findNextFocus(mLayout, mTopRight, View.FOCUS_BACKWARD);
+ assertTrue(nextFocus == mBottomRight || nextFocus == mBottomLeft);
+ }
}
diff --git a/tests/tests/view/src/android/view/cts/FocusHandlingCtsActivity.java b/tests/tests/view/src/android/view/cts/FocusHandlingCtsActivity.java
index 5489e2a..86a1c9e 100644
--- a/tests/tests/view/src/android/view/cts/FocusHandlingCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/FocusHandlingCtsActivity.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/view/src/android/view/cts/GestureDetectorTest.java b/tests/tests/view/src/android/view/cts/GestureDetectorTest.java
index f06455d..0493088 100644
--- a/tests/tests/view/src/android/view/cts/GestureDetectorTest.java
+++ b/tests/tests/view/src/android/view/cts/GestureDetectorTest.java
@@ -45,7 +45,7 @@
private MotionEvent mButtonPressSecondaryMotionEvent;
public GestureDetectorTest() {
- super("com.android.cts.view", GestureDetectorCtsActivity.class);
+ super("android.view.cts", GestureDetectorCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
index 00b9fe9..9208b13 100644
--- a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
+++ b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.view.cts.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -210,7 +210,7 @@
public void testInflate() {
View view = mLayoutInflater.inflate(
- com.android.cts.view.R.layout.inflater_layout, null);
+ android.view.cts.R.layout.inflater_layout, null);
assertNotNull(view);
view = null;
try {
@@ -385,7 +385,7 @@
public void testInflateTags() {
final View view = mLayoutInflater.inflate(
- com.android.cts.view.R.layout.inflater_layout_tags, null);
+ android.view.cts.R.layout.inflater_layout_tags, null);
assertNotNull(view);
checkViewTag(view, R.id.viewlayout_root, R.id.tag_viewlayout_root, R.string.tag1);
diff --git a/tests/tests/view/src/android/view/cts/MenuInflaterTest.java b/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
index 7e3517f..9ced9c7 100644
--- a/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
+++ b/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
import android.content.res.Resources;
@@ -40,7 +40,7 @@
private Activity mActivity;
public MenuInflaterTest() {
- super("com.android.cts.view", MenuInflaterCtsActivity.class);
+ super("android.view.cts", MenuInflaterCtsActivity.class);
}
@Override
@@ -67,7 +67,7 @@
mMenuInflater = mActivity.getMenuInflater();
}
- mMenuInflater.inflate(com.android.cts.view.R.menu.browser, menu);
+ mMenuInflater.inflate(android.view.cts.R.menu.browser, menu);
assertNotNull(menu);
assertEquals(1, menu.size());
@@ -78,7 +78,7 @@
}
try {
- mMenuInflater.inflate(com.android.cts.view.R.menu.browser, null);
+ mMenuInflater.inflate(android.view.cts.R.menu.browser, null);
fail("should throw NullPointerException");
} catch (NullPointerException e) {
}
@@ -107,7 +107,7 @@
// the titles and icons
menu = createMenu(mActivity);
- mMenuInflater.inflate(com.android.cts.view.R.menu.title_icon, menu);
+ mMenuInflater.inflate(android.view.cts.R.menu.title_icon, menu);
assertEquals("Start", menu.findItem(R.id.start).getTitle());
assertIconUsingDrawableRes((BitmapDrawable) menu.findItem(R.id.start).getIcon(),
@@ -123,7 +123,7 @@
// the orders and categories
menu = createMenu(mActivity);
- mMenuInflater.inflate(com.android.cts.view.R.menu.category_order, menu);
+ mMenuInflater.inflate(android.view.cts.R.menu.category_order, menu);
// default category
assertEquals(R.id.most_used_items, menu.findItem(R.id.first_most_item).getGroupId());
assertEquals(1, menu.findItem(R.id.first_most_item).getOrder());
@@ -147,7 +147,7 @@
// the checkables
menu = createMenu(mActivity);
- mMenuInflater.inflate(com.android.cts.view.R.menu.checkable, menu);
+ mMenuInflater.inflate(android.view.cts.R.menu.checkable, menu);
// noncheckables
assertEquals(R.id.noncheckable_group,
menu.findItem(R.id.noncheckable_item_1).getGroupId());
diff --git a/tests/tests/view/src/android/view/cts/MockView.java b/tests/tests/view/src/android/view/cts/MockView.java
index 579d4fb..d6939dc 100644
--- a/tests/tests/view/src/android/view/cts/MockView.java
+++ b/tests/tests/view/src/android/view/cts/MockView.java
@@ -55,6 +55,7 @@
private boolean mCalledOnSetAlpha = false;
private boolean mCalledOnTouchEvent = false;
private boolean mCalledOnTrackballEvent = false;
+ private boolean mCalledOnHoverEvent = false;
private boolean mCalledOnWindowFocusChanged = false;
private boolean mCalledDispatchRestoreInstanceState = false;
private boolean mCalledDispatchSaveInstanceState = false;
@@ -209,6 +210,12 @@
return super.onTrackballEvent(event);
}
+ @Override
+ public boolean onHoverEvent(MotionEvent event) {
+ mCalledOnHoverEvent = true;
+ return super.onHoverEvent(event);
+ }
+
public boolean hasCalledOnTouchEvent() {
return mCalledOnTouchEvent;
}
@@ -217,6 +224,10 @@
return mCalledOnTrackballEvent;
}
+ public boolean hasCalledOnHoverEvent() {
+ return mCalledOnHoverEvent;
+ }
+
@Override
protected int getSuggestedMinimumHeight() {
return super.getSuggestedMinimumHeight();
@@ -618,6 +629,7 @@
mCalledOnSetAlpha = false;
mCalledOnTouchEvent = false;
mCalledOnTrackballEvent = false;
+ mCalledOnHoverEvent = false;
mCalledOnWindowFocusChanged = false;
mCalledDispatchRestoreInstanceState = false;
mCalledDispatchSaveInstanceState = false;
diff --git a/tests/tests/view/src/android/view/cts/ScaleGestureDetectorTest.java b/tests/tests/view/src/android/view/cts/ScaleGestureDetectorTest.java
index b8ba200..b56d67e 100644
--- a/tests/tests/view/src/android/view/cts/ScaleGestureDetectorTest.java
+++ b/tests/tests/view/src/android/view/cts/ScaleGestureDetectorTest.java
@@ -32,7 +32,7 @@
private Context mContext;
public ScaleGestureDetectorTest() {
- super("com.android.cts.view", ScaleGestureDetectorCtsActivity.class);
+ super("android.view.cts", ScaleGestureDetectorCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/SearchEventActivity.java b/tests/tests/view/src/android/view/cts/SearchEventActivity.java
index 6cc8c85..292ecb9 100644
--- a/tests/tests/view/src/android/view/cts/SearchEventActivity.java
+++ b/tests/tests/view/src/android/view/cts/SearchEventActivity.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/view/src/android/view/cts/SearchEventTest.java b/tests/tests/view/src/android/view/cts/SearchEventTest.java
index 4df52a1..629b3ab 100644
--- a/tests/tests/view/src/android/view/cts/SearchEventTest.java
+++ b/tests/tests/view/src/android/view/cts/SearchEventTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
diff --git a/tests/tests/view/src/android/view/cts/SurfaceViewTest.java b/tests/tests/view/src/android/view/cts/SurfaceViewTest.java
index a84653d..aa97ffd 100644
--- a/tests/tests/view/src/android/view/cts/SurfaceViewTest.java
+++ b/tests/tests/view/src/android/view/cts/SurfaceViewTest.java
@@ -37,7 +37,7 @@
private MockSurfaceView mMockSurfaceView;
public SurfaceViewTest() {
- super("com.android.cts.view", SurfaceViewCtsActivity.class);
+ super("android.view.cts", SurfaceViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/TouchDelegateTest.java b/tests/tests/view/src/android/view/cts/TouchDelegateTest.java
index 34d96bc..47fe6c6 100644
--- a/tests/tests/view/src/android/view/cts/TouchDelegateTest.java
+++ b/tests/tests/view/src/android/view/cts/TouchDelegateTest.java
@@ -44,7 +44,7 @@
private Exception mException;
public TouchDelegateTest() {
- super("com.android.cts.view", MockActivity.class);
+ super("android.view.cts", MockActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/UsingViewsCtsActivity.java b/tests/tests/view/src/android/view/cts/UsingViewsCtsActivity.java
index a5ccbcd..a9361a3 100644
--- a/tests/tests/view/src/android/view/cts/UsingViewsCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/UsingViewsCtsActivity.java
@@ -18,7 +18,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.view.R;
+import android.view.cts.R;
/**
* A simple activity to test "Using Views"
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java b/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java
index 880a450..de1db19 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java
@@ -35,8 +35,8 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(com.android.cts.view.R.layout.viewgrouptest_stub);
- TextView textView = (TextView)findViewById(com.android.cts.view.R.id.viewgrouptest_stub);
+ setContentView(android.view.cts.R.layout.viewgrouptest_stub);
+ TextView textView = (TextView)findViewById(android.view.cts.R.id.viewgrouptest_stub);
textView.setText("test");
}
@@ -49,7 +49,7 @@
mHandler.postDelayed(new Runnable() {
public void run() {
MockLinearLayout mll =
- (MockLinearLayout) findViewById(com.android.cts.view.R.id.
+ (MockLinearLayout) findViewById(android.view.cts.R.id.
mocklinearlayout);
if (!mll.mIsInvalidateChildInParentCalled) {
fail();
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index 7fc5579..1b18fe9 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -59,6 +59,7 @@
import android.view.animation.Animation.AnimationListener;
import android.widget.TextView;
+import java.lang.IndexOutOfBoundsException;
import java.util.ArrayList;
public class ViewGroupTest extends InstrumentationTestCase implements CTSResult{
@@ -338,23 +339,23 @@
Canvas canvas = new Canvas();
MockViewGroup vg = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
- son.setAnimation(new MockAnimation());
- vg.addView(son);
+ MockViewGroup child = new MockViewGroup(mContext);
+ child.setAnimation(new MockAnimation());
+ vg.addView(child);
assertEquals(1, vg.getChildCount());
- assertNotNull(son.getAnimation());
+ assertNotNull(child.getAnimation());
vg.dispatchDraw(canvas);
assertEquals(1, vg.drawChildCalledTime);
- son.setAnimation(new MockAnimation());
+ child.setAnimation(new MockAnimation());
vg.removeAllViewsInLayout();
vg.drawChildCalledTime = 0;
vg.dispatchDraw(canvas);
assertEquals(1, vg.drawChildCalledTime);
- son.setAnimation(new MockAnimation());
+ child.setAnimation(new MockAnimation());
vg.clearDisappearingChildren();
vg.drawChildCalledTime = 0;
@@ -683,11 +684,11 @@
public void testFocusableViewAvailable() {
MockViewGroup vg = new MockViewGroup(mContext);
- MockView son = new MockView(mContext);
- vg.addView(son);
+ MockView child = new MockView(mContext);
+ vg.addView(child);
- son.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
- son.focusableViewAvailable(vg);
+ child.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+ child.focusableViewAvailable(vg);
assertTrue(vg.isFocusableViewAvailable);
}
@@ -695,11 +696,11 @@
public void testFocusSearch() {
MockViewGroup vg = new MockViewGroup(mContext);
MockTextView textView = new MockTextView(mContext);
- MockView son = new MockView(mContext);
- vg.addView(son);
- son.addView(textView);
- assertNotNull(son.focusSearch(textView, 1));
- assertSame(textView, son.focusSearch(textView, 1));
+ MockView child = new MockView(mContext);
+ vg.addView(child);
+ child.addView(textView);
+ assertNotNull(child.focusSearch(textView, 1));
+ assertSame(textView, child.focusSearch(textView, 1));
}
public void testGatherTransparentRegion() {
@@ -726,7 +727,7 @@
public void testGenerateLayoutParamsWithParaAttributeSet() throws Exception{
MockViewGroup vg = new MockViewGroup(mContext);
XmlResourceParser set = mContext.getResources().getLayout(
- com.android.cts.view.R.layout.abslistview_layout);
+ android.view.cts.R.layout.abslistview_layout);
XmlUtils.beginDocument(set, "ViewGroup_Layout");
LayoutParams lp = vg.generateLayoutParams(set);
assertNotNull(lp);
@@ -738,7 +739,10 @@
MockViewGroup vg = new MockViewGroup(mContext);
LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT);
- assertSame(p, vg.generateLayoutParams(p));
+ LayoutParams generatedParams = vg.generateLayoutParams(p);
+ assertEquals(generatedParams.getClass(), p.getClass());
+ assertEquals(p.width, generatedParams.width);
+ assertEquals(p.height, generatedParams.height);
}
public void testGetChildDrawingOrder() {
@@ -924,18 +928,18 @@
final int width = 100;
final int height = 200;
MockViewGroup vg = new MockViewGroup(mContext);
- MockView son = new MockView(mContext);
- son.setLayoutParams(new LayoutParams(width, height));
- son.forceLayout();
- vg.addView(son);
+ MockView child = new MockView(mContext);
+ child.setLayoutParams(new LayoutParams(width, height));
+ child.forceLayout();
+ vg.addView(child);
final int parentWidthMeasureSpec = 1;
final int parentHeightMeasureSpec = 2;
- vg.measureChild(son, parentWidthMeasureSpec, parentHeightMeasureSpec);
+ vg.measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec);
assertEquals(ViewGroup.getChildMeasureSpec(parentWidthMeasureSpec, 0, width),
- son.mWidthMeasureSpec);
+ child.mWidthMeasureSpec);
assertEquals(ViewGroup.getChildMeasureSpec(parentHeightMeasureSpec, 0, height),
- son.mHeightMeasureSpec);
+ child.mHeightMeasureSpec);
}
public void testMeasureChildren() {
@@ -966,24 +970,24 @@
final int parentHeightMeasureSpec = 3;
final int heightUsed = 4;
MockViewGroup vg = new MockViewGroup(mContext);
- MockView son = new MockView(mContext);
+ MockView child = new MockView(mContext);
- vg.addView(son);
- son.setLayoutParams(new ViewGroup.LayoutParams(width, height));
+ vg.addView(child);
+ child.setLayoutParams(new ViewGroup.LayoutParams(width, height));
try {
- vg.measureChildWithMargins(son, parentWidthMeasureSpec, widthUsed,
+ vg.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
parentHeightMeasureSpec, heightUsed);
fail("measureChildWithMargins should throw out class cast exception");
} catch (RuntimeException e) {
}
- son.setLayoutParams(new ViewGroup.MarginLayoutParams(width, height));
+ child.setLayoutParams(new ViewGroup.MarginLayoutParams(width, height));
- vg.measureChildWithMargins(son, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec,
+ vg.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec,
heightUsed);
assertEquals(ViewGroup.getChildMeasureSpec(parentWidthMeasureSpec, parentHeightMeasureSpec,
- width), son.mWidthMeasureSpec);
+ width), child.mWidthMeasureSpec);
assertEquals(ViewGroup.getChildMeasureSpec(widthUsed, heightUsed, height),
- son.mHeightMeasureSpec);
+ child.mHeightMeasureSpec);
}
public void testOffsetDescendantRectToMyCoords() {
@@ -1032,16 +1036,16 @@
public void testOnAnimationEnd() {
// this function is a call back function it should be tested in ViewGroup#drawChild.
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
- son.setAnimation(new MockAnimation());
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
+ child.setAnimation(new MockAnimation());
// this call will make mPrivateFlags |= ANIMATION_STARTED;
- son.onAnimationStart();
- father.addView(son);
+ child.onAnimationStart();
+ parent.addView(child);
MockCanvas canvas = new MockCanvas();
- assertFalse(father.drawChild(canvas, son, 100));
- assertTrue(son.isOnAnimationEndCalled);
+ assertFalse(parent.drawChild(canvas, child, 100));
+ assertTrue(child.isOnAnimationEndCalled);
}
private class MockAnimation extends Animation {
@@ -1062,22 +1066,22 @@
public void testOnAnimationStart() {
// This is a call back method. It should be tested in ViewGroup#drawChild.
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
- father.addView(son);
+ parent.addView(child);
MockCanvas canvas = new MockCanvas();
try {
- assertFalse(father.drawChild(canvas, son, 100));
- assertFalse(son.isOnAnimationStartCalled);
+ assertFalse(parent.drawChild(canvas, child, 100));
+ assertFalse(child.isOnAnimationStartCalled);
} catch (Exception e) {
// expected
}
- son.setAnimation(new MockAnimation());
- assertFalse(father.drawChild(canvas, son, 100));
- assertTrue(son.isOnAnimationStartCalled);
+ child.setAnimation(new MockAnimation());
+ assertFalse(parent.drawChild(canvas, child, 100));
+ assertTrue(child.isOnAnimationStartCalled);
}
public void testOnCreateDrawableState() {
@@ -1132,35 +1136,35 @@
}
public void testRemoveAllViewsInLayout() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
MockTextView textView = new MockTextView(mContext);
- assertEquals(0, father.getChildCount());
+ assertEquals(0, parent.getChildCount());
- son.addView(textView);
- father.addView(son);
- assertEquals(1, father.getChildCount());
+ child.addView(textView);
+ parent.addView(child);
+ assertEquals(1, parent.getChildCount());
- father.removeAllViewsInLayout();
- assertEquals(0, father.getChildCount());
- assertEquals(1, son.getChildCount());
- assertNull(son.getParent());
- assertSame(son, textView.getParent());
+ parent.removeAllViewsInLayout();
+ assertEquals(0, parent.getChildCount());
+ assertEquals(1, child.getChildCount());
+ assertNull(child.getParent());
+ assertSame(child, textView.getParent());
}
public void testRemoveDetachedView() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son1 = new MockViewGroup(mContext);
- MockViewGroup son2 = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child1 = new MockViewGroup(mContext);
+ MockViewGroup child2 = new MockViewGroup(mContext);
MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
- father.setOnHierarchyChangeListener(listener);
- father.addView(son1);
- father.addView(son2);
+ parent.setOnHierarchyChangeListener(listener);
+ parent.addView(child1);
+ parent.addView(child2);
- father.removeDetachedView(son1, false);
- assertSame(father, listener.sParent);
- assertSame(son1, listener.sChild);
+ parent.removeDetachedView(child1, false);
+ assertSame(parent, listener.sParent);
+ assertSame(child1, listener.sChild);
}
static class MockOnHierarchyChangeListener implements OnHierarchyChangeListener {
@@ -1178,93 +1182,123 @@
}
public void testRemoveView() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
- assertEquals(0, father.getChildCount());
+ assertEquals(0, parent.getChildCount());
- father.addView(son);
- assertEquals(1, father.getChildCount());
+ parent.addView(child);
+ assertEquals(1, parent.getChildCount());
- father.removeView(son);
- assertEquals(0, father.getChildCount());
- assertNull(son.getParent());
+ parent.removeView(child);
+ assertEquals(0, parent.getChildCount());
+ assertNull(child.getParent());
}
public void testRemoveViewAt() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
- assertEquals(0, father.getChildCount());
+ assertEquals(0, parent.getChildCount());
- father.addView(son);
- assertEquals(1, father.getChildCount());
+ parent.addView(child);
+ assertEquals(1, parent.getChildCount());
try {
- father.removeViewAt(2);
+ parent.removeViewAt(2);
fail("should throw out null pointer exception");
} catch (RuntimeException e) {
// expected
}
- assertEquals(1, father.getChildCount());
+ assertEquals(1, parent.getChildCount());
- father.removeViewAt(0);
- assertEquals(0, father.getChildCount());
- assertNull(son.getParent());
+ parent.removeViewAt(0);
+ assertEquals(0, parent.getChildCount());
+ assertNull(child.getParent());
}
public void testRemoveViewInLayout() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
- assertEquals(0, father.getChildCount());
+ assertEquals(0, parent.getChildCount());
- father.addView(son);
- assertEquals(1, father.getChildCount());
+ parent.addView(child);
+ assertEquals(1, parent.getChildCount());
- father.removeViewInLayout(son);
- assertEquals(0, father.getChildCount());
- assertNull(son.getParent());
+ parent.removeViewInLayout(child);
+ assertEquals(0, parent.getChildCount());
+ assertNull(child.getParent());
}
public void testRemoveViews() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son1 = new MockViewGroup(mContext);
- MockViewGroup son2 = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child1 = new MockViewGroup(mContext);
+ MockViewGroup child2 = new MockViewGroup(mContext);
- assertEquals(0, father.getChildCount());
+ assertEquals(0, parent.getChildCount());
+ parent.addView(child1);
+ parent.addView(child2);
+ assertEquals(2, parent.getChildCount());
- father.addView(son1);
- father.addView(son2);
- assertEquals(2, father.getChildCount());
+ try {
+ parent.removeViews(-1, 1); // negative begin
+ fail("should fail with IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {}
- father.removeViews(0, 1);
- assertEquals(1, father.getChildCount());
- assertNull(son1.getParent());
+ try {
+ parent.removeViews(0, -1); // negative count
+ fail("should fail with IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {}
- father.removeViews(0, 1);
- assertEquals(0, father.getChildCount());
- assertNull(son2.getParent());
+ try {
+ parent.removeViews(1, 2); // past end
+ fail("should fail with IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {}
+ assertEquals(2, parent.getChildCount()); // child list unmodified
+
+ parent.removeViews(0, 1);
+ assertEquals(1, parent.getChildCount());
+ assertNull(child1.getParent());
+
+ parent.removeViews(0, 1);
+ assertEquals(0, parent.getChildCount());
+ assertNull(child2.getParent());
}
public void testRemoveViewsInLayout() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son1 = new MockViewGroup(mContext);
- MockViewGroup son2 = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child1 = new MockViewGroup(mContext);
+ MockViewGroup child2 = new MockViewGroup(mContext);
- assertEquals(0, father.getChildCount());
+ assertEquals(0, parent.getChildCount());
+ parent.addView(child1);
+ parent.addView(child2);
+ assertEquals(2, parent.getChildCount());
- father.addView(son1);
- father.addView(son2);
- assertEquals(2, father.getChildCount());
+ try {
+ parent.removeViewsInLayout(-1, 1); // negative begin
+ fail("should fail with IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {}
- father.removeViewsInLayout(0, 1);
- assertEquals(1, father.getChildCount());
- assertNull(son1.getParent());
+ try {
+ parent.removeViewsInLayout(0, -1); // negative count
+ fail("should fail with IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {}
- father.removeViewsInLayout(0, 1);
- assertEquals(0, father.getChildCount());
- assertNull(son2.getParent());
+ try {
+ parent.removeViewsInLayout(1, 2); // past end
+ fail("should fail with IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {}
+ assertEquals(2, parent.getChildCount()); // child list unmodified
+
+ parent.removeViewsInLayout(0, 1);
+ assertEquals(1, parent.getChildCount());
+ assertNull(child1.getParent());
+
+ parent.removeViewsInLayout(0, 1);
+ assertEquals(0, parent.getChildCount());
+ assertNull(child2.getParent());
}
public void testRequestChildFocus() {
@@ -1286,13 +1320,13 @@
}
public void testRequestDisallowInterceptTouchEvent() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockView son = new MockView(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockView child = new MockView(mContext);
- father.addView(son);
- son.requestDisallowInterceptTouchEvent(true);
- son.requestDisallowInterceptTouchEvent(false);
- assertTrue(father.isRequestDisallowInterceptTouchEventCalled);
+ parent.addView(child);
+ child.requestDisallowInterceptTouchEvent(true);
+ child.requestDisallowInterceptTouchEvent(false);
+ assertTrue(parent.isRequestDisallowInterceptTouchEventCalled);
}
public void testRequestFocus() {
@@ -1303,13 +1337,13 @@
}
public void testRequestTransparentRegion() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockView son1 = new MockView(mContext);
- MockView son2 = new MockView(mContext);
- son1.addView(son2);
- father.addView(son1);
- son1.requestTransparentRegion(son2);
- assertTrue(father.isRequestTransparentRegionCalled);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockView child1 = new MockView(mContext);
+ MockView child2 = new MockView(mContext);
+ child1.addView(child2);
+ parent.addView(child1);
+ child1.requestTransparentRegion(child2);
+ assertTrue(parent.isRequestTransparentRegionCalled);
}
public void testScheduleLayoutAnimation() {
@@ -1476,15 +1510,15 @@
}
public void testSetOnHierarchyChangeListener() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
- father.setOnHierarchyChangeListener(listener);
- father.addView(son);
+ parent.setOnHierarchyChangeListener(listener);
+ parent.addView(child);
- father.removeDetachedView(son, false);
- assertSame(father, listener.sParent);
- assertSame(son, listener.sChild);
+ parent.removeDetachedView(child, false);
+ assertSame(parent, listener.sParent);
+ assertSame(child, listener.sChild);
}
public void testSetPadding() {
@@ -1595,12 +1629,12 @@
}
public void testShowContextMenuForChild() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
- father.addView(son);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
+ parent.addView(child);
- son.showContextMenuForChild(null);
- assertTrue(father.isShowContextMenuForChildCalled);
+ child.showContextMenuForChild(null);
+ assertTrue(parent.isShowContextMenuForChildCalled);
}
public void testStartLayoutAnimation() {
@@ -1616,24 +1650,24 @@
}
public void testUpdateViewLayout() {
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
- father.addView(son);
+ parent.addView(child);
LayoutParams param = new LayoutParams(100, 200);
- father.updateViewLayout(son, param);
- assertEquals(param.width, son.getLayoutParams().width);
- assertEquals(param.height, son.getLayoutParams().height);
+ parent.updateViewLayout(child, param);
+ assertEquals(param.width, child.getLayoutParams().width);
+ assertEquals(param.height, child.getLayoutParams().height);
}
public void testDebug() {
final int EXPECTED = 100;
- MockViewGroup father = new MockViewGroup(mContext);
- MockViewGroup son = new MockViewGroup(mContext);
- father.addView(son);
+ MockViewGroup parent = new MockViewGroup(mContext);
+ MockViewGroup child = new MockViewGroup(mContext);
+ parent.addView(child);
- father.debug(EXPECTED);
- assertEquals(EXPECTED + 1, son.debugDepth);
+ parent.debug(EXPECTED);
+ assertEquals(EXPECTED + 1, child.debugDepth);
}
public void testDispatchKeyEventPreIme() {
diff --git a/tests/tests/view/src/android/view/cts/ViewGroup_LayoutParamsTest.java b/tests/tests/view/src/android/view/cts/ViewGroup_LayoutParamsTest.java
index 5dadffd..7476ba6 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroup_LayoutParamsTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroup_LayoutParamsTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
index e53cba2..0420a4a 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.content.Context;
import android.content.res.XmlResourceParser;
diff --git a/tests/tests/view/src/android/view/cts/ViewLayoutPositionTestCtsActivity.java b/tests/tests/view/src/android/view/cts/ViewLayoutPositionTestCtsActivity.java
index 69dc70f..41f3e33 100644
--- a/tests/tests/view/src/android/view/cts/ViewLayoutPositionTestCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/ViewLayoutPositionTestCtsActivity.java
@@ -18,7 +18,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.view.R;
+import android.view.cts.R;
public class ViewLayoutPositionTestCtsActivity extends Activity {
@Override
diff --git a/tests/tests/view/src/android/view/cts/ViewStubCtsActivity.java b/tests/tests/view/src/android/view/cts/ViewStubCtsActivity.java
index d2f2a4f..4268837 100644
--- a/tests/tests/view/src/android/view/cts/ViewStubCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/ViewStubCtsActivity.java
@@ -18,7 +18,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.view.R;
+import android.view.cts.R;
public class ViewStubCtsActivity extends Activity {
@Override
diff --git a/tests/tests/view/src/android/view/cts/ViewStubTest.java b/tests/tests/view/src/android/view/cts/ViewStubTest.java
index c9cd44b..bdb988d 100644
--- a/tests/tests/view/src/android/view/cts/ViewStubTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewStubTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -40,7 +40,7 @@
private Activity mActivity;
public ViewStubTest() {
- super("com.android.cts.view", ViewStubCtsActivity.class);
+ super("android.view.cts", ViewStubCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 2c5b30a..0191072 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -16,7 +16,8 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.ViewTreeObserver;
+import android.view.cts.R;
import com.android.internal.view.menu.ContextMenuBuilder;
import android.content.Context;
@@ -45,6 +46,7 @@
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import android.util.Xml;
import android.view.ActionMode;
@@ -57,6 +59,7 @@
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.SoundEffectConstants;
import android.view.TouchDelegate;
import android.view.View;
@@ -84,9 +87,12 @@
import android.widget.LinearLayout;
import android.widget.ListView;
+import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Test {@link View}.
@@ -146,6 +152,37 @@
}
}
+ // Test that validates that Views can be constructed on a thread that
+ // does not have a Looper. Necessary for async inflation
+ private Pair<Class<?>, Throwable> sCtorException = null;
+ public void testConstructor2() throws Exception {
+ final Object[] args = new Object[] { mActivity, null };
+ final CountDownLatch latch = new CountDownLatch(1);
+ sCtorException = null;
+ new Thread() {
+ public void run() {
+ final Class<?>[] ctorSignature = new Class[] {
+ Context.class, AttributeSet.class};
+ for (Class<?> clazz : ASYNC_INFLATE_VIEWS) {
+ try {
+ Constructor<?> constructor = clazz.getConstructor(ctorSignature);
+ constructor.setAccessible(true);
+ constructor.newInstance(args);
+ } catch (Throwable t) {
+ sCtorException = new Pair<Class<?>, Throwable>(clazz, t);
+ break;
+ }
+ }
+ latch.countDown();
+ }
+ }.start();
+ latch.await();
+ if (sCtorException != null) {
+ throw new AssertionError("Failed to inflate "
+ + sCtorException.first.getName(), sCtorException.second);
+ }
+ }
+
public void testGetContext() {
View view = new View(mActivity);
assertSame(mActivity, view.getContext());
@@ -311,6 +348,29 @@
assertNull(view.getTouchDelegate());
}
+ public void testAccessPointerShape() {
+ View view = mActivity.findViewById(R.id.pointer_icon_layout);
+ MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE,
+ view.getX(), view.getY(), 0);
+
+ assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_HELP),
+ view.getPointerIcon(event, 0, 0));
+
+ event.setLocation(0, 21);
+ assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_CROSSHAIR),
+ view.getPointerIcon(event, 0, 21));
+ event.setLocation(0, 41);
+ assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_CROSSHAIR),
+ view.getPointerIcon(event, 0, 41));
+ event.setLocation(0, 51);
+ assertNull(view.getPointerIcon(event, 0, 51));
+
+ view.setPointerIcon(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_TEXT));
+ assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_TEXT),
+ view.getPointerIcon(event, 0, 51));
+ event.recycle();
+ }
+
@UiThreadTest
public void testAccessTag() {
ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
@@ -2230,6 +2290,71 @@
assertTrue(listener.hasOnClick());
}
+ private void checkBounds(final ViewGroup viewGroup, final View view,
+ final CountDownLatch countDownLatch, final int left, final int top,
+ final int width, final int height) {
+ viewGroup.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ assertEquals(left, view.getLeft());
+ assertEquals(top, view.getTop());
+ assertEquals(width, view.getWidth());
+ assertEquals(height, view.getHeight());
+ countDownLatch.countDown();
+ viewGroup.getViewTreeObserver().removeOnPreDrawListener(this);
+ return true;
+ }
+ });
+ }
+
+ public void testAddRemoveAffectsWrapContentLayout() throws Throwable {
+ final int childWidth = 100;
+ final int childHeight = 200;
+ final int parentHeight = 400;
+ final MockLinearLayout parent = new MockLinearLayout(mActivity);
+ ViewGroup.LayoutParams parentParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, parentHeight);
+ parent.setLayoutParams(parentParams);
+ final MockView child = new MockView(mActivity);
+ child.setBackgroundColor(Color.GREEN);
+ ViewGroup.LayoutParams childParams = new ViewGroup.LayoutParams(childWidth, childHeight);
+ child.setLayoutParams(childParams);
+ final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
+
+ // Idea:
+ // Add the wrap_content parent view to the hierarchy (removing other views as they
+ // are not needed), test that parent is 0xparentHeight
+ // Add the child view to the parent, test that parent has same width as child
+ // Remove the child view from the parent, test that parent is 0xparentHeight
+ final CountDownLatch countDownLatch1 = new CountDownLatch(1);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ viewGroup.removeAllViews();
+ viewGroup.addView(parent);
+ checkBounds(viewGroup, parent, countDownLatch1, 0, 0, 0, parentHeight);
+ }
+ });
+ countDownLatch1.await(500, TimeUnit.MILLISECONDS);
+
+ final CountDownLatch countDownLatch2 = new CountDownLatch(1);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ parent.addView(child);
+ checkBounds(viewGroup, parent, countDownLatch2, 0, 0, childWidth, parentHeight);
+ }
+ });
+ countDownLatch2.await(500, TimeUnit.MILLISECONDS);
+
+ final CountDownLatch countDownLatch3 = new CountDownLatch(1);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ parent.removeView(child);
+ checkBounds(viewGroup, parent, countDownLatch3, 0, 0, 0, parentHeight);
+ }
+ });
+ countDownLatch3.await(500, TimeUnit.MILLISECONDS);
+ }
+
@UiThreadTest
public void testDispatchKeyEvent() {
MockView view = (MockView) mActivity.findViewById(R.id.mock_view);
@@ -2537,7 +2662,7 @@
assertFalse(view.hasCalledOnWindowFocusChanged());
assertFalse(view.hasCalledDispatchWindowFocusChanged());
- CtsActivity activity = launchActivity("com.android.cts.view", CtsActivity.class, null);
+ CtsActivity activity = launchActivity("android.view.cts", CtsActivity.class, null);
// Wait until the window lost focus.
new PollingCheck(TIMEOUT_DELTA) {
@@ -3490,6 +3615,77 @@
assertNull(mode);
}
+ public void testPointerCapture() throws Throwable {
+ final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root);
+
+ long downTime = SystemClock.uptimeMillis();
+ int[] location = new int[2];
+ viewGroup.getLocationOnScreen(location);
+ float x = location[0] + viewGroup.getWidth() / 2;
+ float y = location[1] + viewGroup.getHeight() / 2;
+ final MotionEvent dummyMotion = MotionEvent.obtain(
+ downTime, downTime, MotionEvent.ACTION_HOVER_MOVE, x, y, 0);
+ dummyMotion.setSource(InputDevice.SOURCE_MOUSE);
+ final MockView view = (MockView)mActivity.findViewById(R.id.mock_view);
+
+ assertFalse(view.hasPointerCapture());
+
+ view.setPointerCapture();
+ assertTrue(view.hasPointerCapture());
+ getInstrumentation().sendPointerSync(dummyMotion);
+ getInstrumentation().waitForIdleSync();
+ assertTrue(view.hasCalledOnHoverEvent());
+ view.reset();
+
+ view.releasePointerCapture();
+ assertFalse(view.hasPointerCapture());
+
+ final MockView view2 = new MockView(mActivity);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ viewGroup.addView(view2);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ view.setPointerCapture();
+ assertTrue(view.hasPointerCapture());
+ assertFalse(view2.hasPointerCapture());
+
+ getInstrumentation().sendPointerSync(dummyMotion);
+ getInstrumentation().waitForIdleSync();
+ assertTrue(view.hasCalledOnHoverEvent());
+ assertFalse(view2.hasCalledOnHoverEvent());
+ view.reset();
+
+ view2.setPointerCapture();
+ assertFalse(view.hasPointerCapture());
+ assertTrue(view2.hasPointerCapture());
+
+ getInstrumentation().sendPointerSync(dummyMotion);
+ getInstrumentation().waitForIdleSync();
+ assertFalse(view.hasCalledOnHoverEvent());
+ assertTrue(view2.hasCalledOnHoverEvent());
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ viewGroup.removeView(view2);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ assertFalse(view.hasPointerCapture());
+ assertFalse(view2.hasPointerCapture());
+
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ viewGroup.addView(view2);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ assertFalse(view.hasPointerCapture());
+ assertFalse(view2.hasPointerCapture());
+ }
+
private static class MockViewGroup extends ViewGroup {
boolean isStartActionModeForChildCalled = false;
int startActionModeForChildType = ActionMode.TYPE_PRIMARY;
@@ -4095,4 +4291,75 @@
hasRun = true;
}
}
+
+ private static final Class<?> ASYNC_INFLATE_VIEWS[] = {
+ android.app.FragmentBreadCrumbs.class,
+// DISABLED because it doesn't have a AppWidgetHostView(Context, AttributeSet)
+// constructor, so it's not inflate-able
+// android.appwidget.AppWidgetHostView.class,
+ android.gesture.GestureOverlayView.class,
+ android.inputmethodservice.ExtractEditText.class,
+ android.inputmethodservice.KeyboardView.class,
+// android.media.tv.TvView.class,
+// android.opengl.GLSurfaceView.class,
+// android.view.SurfaceView.class,
+ android.view.TextureView.class,
+ android.view.ViewStub.class,
+// android.webkit.WebView.class,
+ android.widget.AbsoluteLayout.class,
+ android.widget.AdapterViewFlipper.class,
+ android.widget.AnalogClock.class,
+ android.widget.AutoCompleteTextView.class,
+ android.widget.Button.class,
+ android.widget.CalendarView.class,
+ android.widget.CheckBox.class,
+ android.widget.CheckedTextView.class,
+ android.widget.Chronometer.class,
+ android.widget.DatePicker.class,
+ android.widget.DialerFilter.class,
+ android.widget.DigitalClock.class,
+ android.widget.EditText.class,
+ android.widget.ExpandableListView.class,
+ android.widget.FrameLayout.class,
+ android.widget.Gallery.class,
+ android.widget.GridView.class,
+ android.widget.HorizontalScrollView.class,
+ android.widget.ImageButton.class,
+ android.widget.ImageSwitcher.class,
+ android.widget.ImageView.class,
+ android.widget.LinearLayout.class,
+ android.widget.ListView.class,
+ android.widget.MediaController.class,
+ android.widget.MultiAutoCompleteTextView.class,
+ android.widget.NumberPicker.class,
+ android.widget.ProgressBar.class,
+ android.widget.QuickContactBadge.class,
+ android.widget.RadioButton.class,
+ android.widget.RadioGroup.class,
+ android.widget.RatingBar.class,
+ android.widget.RelativeLayout.class,
+ android.widget.ScrollView.class,
+ android.widget.SeekBar.class,
+// DISABLED because it has required attributes
+// android.widget.SlidingDrawer.class,
+ android.widget.Spinner.class,
+ android.widget.StackView.class,
+ android.widget.Switch.class,
+ android.widget.TabHost.class,
+ android.widget.TabWidget.class,
+ android.widget.TableLayout.class,
+ android.widget.TableRow.class,
+ android.widget.TextClock.class,
+ android.widget.TextSwitcher.class,
+ android.widget.TextView.class,
+ android.widget.TimePicker.class,
+ android.widget.ToggleButton.class,
+ android.widget.TwoLineListItem.class,
+// android.widget.VideoView.class,
+ android.widget.ViewAnimator.class,
+ android.widget.ViewFlipper.class,
+ android.widget.ViewSwitcher.class,
+ android.widget.ZoomButton.class,
+ android.widget.ZoomControls.class,
+ };
}
diff --git a/tests/tests/view/src/android/view/cts/ViewTestCtsActivity.java b/tests/tests/view/src/android/view/cts/ViewTestCtsActivity.java
index 01215bc..bbe6ccc 100644
--- a/tests/tests/view/src/android/view/cts/ViewTestCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/ViewTestCtsActivity.java
@@ -20,7 +20,7 @@
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
-import com.android.cts.view.R;
+import android.view.cts.R;
public class ViewTestCtsActivity extends Activity {
private boolean mHasWindowFocus = false;
diff --git a/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java b/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java
index 7071808..b799e76 100644
--- a/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
import android.app.Instrumentation;
diff --git a/tests/tests/view/src/android/view/cts/View_AnimationTest.java b/tests/tests/view/src/android/view/cts/View_AnimationTest.java
index 64bb2f7..07abb6f 100644
--- a/tests/tests/view/src/android/view/cts/View_AnimationTest.java
+++ b/tests/tests/view/src/android/view/cts/View_AnimationTest.java
@@ -24,7 +24,7 @@
import android.view.animation.TranslateAnimation;
import android.view.animation.cts.AnimationTestUtils;
-import com.android.cts.view.R;
+import android.view.cts.R;
/**
@@ -40,7 +40,7 @@
private TranslateAnimation mAnimation;
public View_AnimationTest() {
- super("com.android.cts.view", ViewTestCtsActivity.class);
+ super("android.view.cts", ViewTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/View_FocusHandlingTest.java b/tests/tests/view/src/android/view/cts/View_FocusHandlingTest.java
index 97992ee..564620e 100644
--- a/tests/tests/view/src/android/view/cts/View_FocusHandlingTest.java
+++ b/tests/tests/view/src/android/view/cts/View_FocusHandlingTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
@@ -28,7 +28,7 @@
public class View_FocusHandlingTest
extends ActivityInstrumentationTestCase2<FocusHandlingCtsActivity> {
public View_FocusHandlingTest() {
- super("com.android.cts.view", FocusHandlingCtsActivity.class);
+ super("android.view.cts", FocusHandlingCtsActivity.class);
}
@UiThreadTest
diff --git a/tests/tests/view/src/android/view/cts/View_IdsTest.java b/tests/tests/view/src/android/view/cts/View_IdsTest.java
index e65ccf5..4dd00d6 100644
--- a/tests/tests/view/src/android/view/cts/View_IdsTest.java
+++ b/tests/tests/view/src/android/view/cts/View_IdsTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
@@ -29,7 +29,7 @@
public class View_IdsTest extends ActivityInstrumentationTestCase2<UsingViewsCtsActivity> {
public View_IdsTest() {
- super("com.android.cts.view", UsingViewsCtsActivity.class);
+ super("android.view.cts", UsingViewsCtsActivity.class);
}
@UiThreadTest
diff --git a/tests/tests/view/src/android/view/cts/View_LayoutPositionTest.java b/tests/tests/view/src/android/view/cts/View_LayoutPositionTest.java
index 3938607..53514dc 100644
--- a/tests/tests/view/src/android/view/cts/View_LayoutPositionTest.java
+++ b/tests/tests/view/src/android/view/cts/View_LayoutPositionTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
@@ -36,7 +36,7 @@
private Activity mActivity;
public View_LayoutPositionTest() {
- super("com.android.cts.view", ViewLayoutPositionTestCtsActivity.class);
+ super("android.view.cts", ViewLayoutPositionTestCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/View_UsingViewsTest.java b/tests/tests/view/src/android/view/cts/View_UsingViewsTest.java
index f6d067d..413c356 100644
--- a/tests/tests/view/src/android/view/cts/View_UsingViewsTest.java
+++ b/tests/tests/view/src/android/view/cts/View_UsingViewsTest.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
@@ -78,7 +78,7 @@
private TextView mWarningTextView;
public View_UsingViewsTest() {
- super("com.android.cts.view", UsingViewsCtsActivity.class);
+ super("android.view.cts", UsingViewsCtsActivity.class);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/WindowCtsActivity.java b/tests/tests/view/src/android/view/cts/WindowCtsActivity.java
index 8af808c..3cfcc96 100644
--- a/tests/tests/view/src/android/view/cts/WindowCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/WindowCtsActivity.java
@@ -16,7 +16,7 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/view/src/android/view/cts/WindowTest.java b/tests/tests/view/src/android/view/cts/WindowTest.java
index dcfcfb7..a897af4 100644
--- a/tests/tests/view/src/android/view/cts/WindowTest.java
+++ b/tests/tests/view/src/android/view/cts/WindowTest.java
@@ -16,7 +16,8 @@
package android.view.cts;
-import com.android.cts.view.R;
+import android.view.ContextThemeWrapper;
+import android.view.cts.R;
import android.app.Instrumentation;
import android.app.Presentation;
@@ -45,6 +46,7 @@
import android.view.InputDevice;
import android.view.InputQueue;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -61,6 +63,7 @@
import android.widget.Button;
import android.widget.TextView;
+import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -80,7 +83,7 @@
private VirtualDisplay mVirtualDisplay;
public WindowTest() {
- super("com.android.cts.view", WindowCtsActivity.class);
+ super("android.view.cts", WindowCtsActivity.class);
}
@Override
@@ -292,7 +295,7 @@
int screenHeight = dm.heightPixels;
assertTrue(decor.getWidth() >= screenWidth);
assertTrue(decor.getHeight() >= screenHeight);
- assertSame(mWindow.getContext(), decor.getContext());
+ assertTrue(decor.getContext() instanceof ContextThemeWrapper);
}
/**
@@ -868,6 +871,9 @@
public void addContentView(View view, ViewGroup.LayoutParams params) {
}
+ public void clearContentView() {
+ }
+
public View getCurrentFocus() {
return null;
}
@@ -1025,9 +1031,27 @@
}
@Override
+ public void setDecorCaptionShade(int decorCaptionShade) {
+
+ }
+
+ @Override
+ public void setResizingCaptionDrawable(Drawable drawable) {
+
+ }
+
+ @Override
public int getNavigationBarColor() {
return 0;
}
+
+ @Override
+ public void onMultiWindowModeChanged() {
+ }
+
+ @Override
+ public void reportActivityRelaunched() {
+ }
}
private class MockWindowCallback implements Window.Callback {
@@ -1131,5 +1155,8 @@
public void onWindowDismissed() {
}
+
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
+ }
}
}
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/BaseInputConnectionTest.java b/tests/tests/view/src/android/view/inputmethod/cts/BaseInputConnectionTest.java
index 30edecb..ee61446 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/BaseInputConnectionTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/BaseInputConnectionTest.java
@@ -16,15 +16,13 @@
package android.view.inputmethod.cts;
-import com.android.cts.view.R;
-
-
import android.app.Instrumentation;
import android.content.Context;
import android.cts.util.PollingCheck;
import android.os.Bundle;
import android.test.ActivityInstrumentationTestCase2;
import android.text.Editable;
+import android.text.Selection;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
@@ -32,10 +30,12 @@
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
+import android.view.cts.R;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.cts.util.InputConnectionTestUtils;
import android.widget.EditText;
public class BaseInputConnectionTest extends
@@ -48,7 +48,7 @@
private Instrumentation mInstrumentation;
public BaseInputConnectionTest() {
- super("com.android.cts.view", InputMethodCtsActivity.class);
+ super("android.view.cts", InputMethodCtsActivity.class);
}
@Override
@@ -163,7 +163,7 @@
}.run();
assertEquals(0, dummyConnection.getCursorCapsMode(TextUtils.CAP_MODE_WORDS));
- // Test deleteSurroudingText
+ // Test deleteSurroundingText
int end = text2.length();
mConnection.setSelection(end, end);
// Delete the ending space
@@ -254,6 +254,237 @@
mConnection.reportFullscreenMode(false);
assertFalse(imManager.isFullscreenMode());
mConnection.reportFullscreenMode(true);
- assertTrue(imManager.isFullscreenMode());
+ // Only IMEs are allowed to report full-screen mode. Calling this method from the
+ // application should have no effect.
+ assertFalse(imManager.isFullscreenMode());
+ }
+
+ /**
+ * An utility method to create an instance of {@link BaseInputConnection} in dummy mode with
+ * an initial text and selection range.
+ * @param view the {@link View} to be associated with the {@link BaseInputConnection}.
+ * @param source the initial text.
+ * @return {@link BaseInputConnection} instantiated in dummy mode with {@code source} and
+ * selection range from {@code selectionStart} to {@code selectionEnd}
+ */
+ private static BaseInputConnection createDummyConnectionWithSelection(
+ final View view, final CharSequence source) {
+ final int selectionStart = Selection.getSelectionStart(source);
+ final int selectionEnd = Selection.getSelectionEnd(source);
+ final Editable editable = Editable.Factory.getInstance().newEditable(source);
+ Selection.setSelection(editable, selectionStart, selectionEnd);
+ return new BaseInputConnection(view, false) {
+ @Override
+ public Editable getEditable() {
+ return editable;
+ }
+ };
+ }
+
+ private void testDeleteSurroundingTextMain(final String initialState,
+ final int deleteBefore, final int deleteAfter, final String expectedState) {
+ final CharSequence source = InputConnectionTestUtils.formatString(initialState);
+ final BaseInputConnection ic = createDummyConnectionWithSelection(mView, source);
+ ic.deleteSurroundingText(deleteBefore, deleteAfter);
+
+ final CharSequence expectedString = InputConnectionTestUtils.formatString(expectedState);
+ final int expectedSelectionStart = Selection.getSelectionStart(expectedString);
+ final int expectedSelectionEnd = Selection.getSelectionEnd(expectedString);
+
+ // It is sufficient to check the surrounding text up to source.length() characters, because
+ // InputConnection.deleteSurroundingText() is not supposed to increase the text length.
+ final int retrievalLength = source.length();
+ if (expectedSelectionStart == 0) {
+ assertTrue(TextUtils.isEmpty(ic.getTextBeforeCursor(retrievalLength, 0)));
+ } else {
+ assertEquals(expectedString.subSequence(0, expectedSelectionStart).toString(),
+ ic.getTextBeforeCursor(retrievalLength, 0).toString());
+ }
+ if (expectedSelectionStart == expectedSelectionEnd) {
+ assertTrue(TextUtils.isEmpty(ic.getSelectedText(0))); // null is allowed.
+ } else {
+ assertEquals(expectedString.subSequence(expectedSelectionStart,
+ expectedSelectionEnd).toString(), ic.getSelectedText(0).toString());
+ }
+ if (expectedSelectionEnd == expectedString.length()) {
+ assertTrue(TextUtils.isEmpty(ic.getTextAfterCursor(retrievalLength, 0)));
+ } else {
+ assertEquals(expectedString.subSequence(expectedSelectionEnd,
+ expectedString.length()).toString(),
+ ic.getTextAfterCursor(retrievalLength, 0).toString());
+ }
+ }
+
+ /**
+ * Tests {@link BaseInputConnection#deleteSurroundingText(int, int)} comprehensively.
+ */
+ public void testDeleteSurroundingText() throws Throwable {
+ testDeleteSurroundingTextMain("012[]3456789", 0, 0, "012[]3456789");
+ testDeleteSurroundingTextMain("012[]3456789", -1, -1, "012[]3456789");
+ testDeleteSurroundingTextMain("012[]3456789", 1, 2, "01[]56789");
+ testDeleteSurroundingTextMain("012[]3456789", 10, 1, "[]456789");
+ testDeleteSurroundingTextMain("012[]3456789", 1, 10, "01[]");
+ testDeleteSurroundingTextMain("[]0123456789", 3, 3, "[]3456789");
+ testDeleteSurroundingTextMain("0123456789[]", 3, 3, "0123456[]");
+ testDeleteSurroundingTextMain("012[345]6789", 0, 0, "012[345]6789");
+ testDeleteSurroundingTextMain("012[345]6789", -1, -1, "012[345]6789");
+ testDeleteSurroundingTextMain("012[345]6789", 1, 2, "01[345]89");
+ testDeleteSurroundingTextMain("012[345]6789", 10, 1, "[345]789");
+ testDeleteSurroundingTextMain("012[345]6789", 1, 10, "01[345]");
+ testDeleteSurroundingTextMain("[012]3456789", 3, 3, "[012]6789");
+ testDeleteSurroundingTextMain("0123456[789]", 3, 3, "0123[789]");
+ testDeleteSurroundingTextMain("[0123456789]", 0, 0, "[0123456789]");
+ testDeleteSurroundingTextMain("[0123456789]", 1, 1, "[0123456789]");
+
+ // Surrogate characters do not have any special meanings. Validating the character sequence
+ // is beyond the goal of this API.
+ testDeleteSurroundingTextMain("0<>[]3456789", 1, 0, "0<[]3456789");
+ testDeleteSurroundingTextMain("0<>[]3456789", 2, 0, "0[]3456789");
+ testDeleteSurroundingTextMain("0<>[]3456789", 3, 0, "[]3456789");
+ testDeleteSurroundingTextMain("012[]<>56789", 0, 1, "012[]>56789");
+ testDeleteSurroundingTextMain("012[]<>56789", 0, 2, "012[]56789");
+ testDeleteSurroundingTextMain("012[]<>56789", 0, 3, "012[]6789");
+ testDeleteSurroundingTextMain("0<<[]3456789", 1, 0, "0<[]3456789");
+ testDeleteSurroundingTextMain("0<<[]3456789", 2, 0, "0[]3456789");
+ testDeleteSurroundingTextMain("0<<[]3456789", 3, 0, "[]3456789");
+ testDeleteSurroundingTextMain("012[]<<56789", 0, 1, "012[]<56789");
+ testDeleteSurroundingTextMain("012[]<<56789", 0, 2, "012[]56789");
+ testDeleteSurroundingTextMain("012[]<<56789", 0, 3, "012[]6789");
+ testDeleteSurroundingTextMain("0>>[]3456789", 1, 0, "0>[]3456789");
+ testDeleteSurroundingTextMain("0>>[]3456789", 2, 0, "0[]3456789");
+ testDeleteSurroundingTextMain("0>>[]3456789", 3, 0, "[]3456789");
+ testDeleteSurroundingTextMain("012[]>>56789", 0, 1, "012[]>56789");
+ testDeleteSurroundingTextMain("012[]>>56789", 0, 2, "012[]56789");
+ testDeleteSurroundingTextMain("012[]>>56789", 0, 3, "012[]6789");
+ }
+
+ private void testDeleteSurroundingTextInCodePointsMain(final String initialState,
+ final int deleteBeforeInCodePoints, final int deleteAfterInCodePoints,
+ final String expectedState) {
+ final CharSequence source = InputConnectionTestUtils.formatString(initialState);
+ final BaseInputConnection ic = createDummyConnectionWithSelection(mView, source);
+ ic.deleteSurroundingTextInCodePoints(deleteBeforeInCodePoints, deleteAfterInCodePoints);
+
+ final CharSequence expectedString = InputConnectionTestUtils.formatString(expectedState);
+ final int expectedSelectionStart = Selection.getSelectionStart(expectedString);
+ final int expectedSelectionEnd = Selection.getSelectionEnd(expectedString);
+
+ // It is sufficient to check the surrounding text up to source.length() characters, because
+ // InputConnection.deleteSurroundingTextInCodePoints() is not supposed to increase the text
+ // length.
+ final int retrievalLength = source.length();
+ if (expectedSelectionStart == 0) {
+ assertTrue(TextUtils.isEmpty(ic.getTextBeforeCursor(retrievalLength, 0)));
+ } else {
+ assertEquals(expectedString.subSequence(0, expectedSelectionStart).toString(),
+ ic.getTextBeforeCursor(retrievalLength, 0).toString());
+ }
+ if (expectedSelectionStart == expectedSelectionEnd) {
+ assertTrue(TextUtils.isEmpty(ic.getSelectedText(0))); // null is allowed.
+ } else {
+ assertEquals(expectedString.subSequence(expectedSelectionStart,
+ expectedSelectionEnd).toString(), ic.getSelectedText(0).toString());
+ }
+ if (expectedSelectionEnd == expectedString.length()) {
+ assertTrue(TextUtils.isEmpty(ic.getTextAfterCursor(retrievalLength, 0)));
+ } else {
+ assertEquals(expectedString.subSequence(expectedSelectionEnd,
+ expectedString.length()).toString(),
+ ic.getTextAfterCursor(retrievalLength, 0).toString());
+ }
+ }
+
+ /**
+ * Tests {@link BaseInputConnection#deleteSurroundingTextInCodePoints(int, int)}
+ * comprehensively.
+ */
+ public void testDeleteSurroundingTextInCodePoints() throws Throwable {
+ testDeleteSurroundingTextInCodePointsMain("012[]3456789", 0, 0, "012[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("012[]3456789", -1, -1, "012[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("012[]3456789", 1, 2, "01[]56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]3456789", 10, 1, "[]456789");
+ testDeleteSurroundingTextInCodePointsMain("012[]3456789", 1, 10, "01[]");
+ testDeleteSurroundingTextInCodePointsMain("[]0123456789", 3, 3, "[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0123456789[]", 3, 3, "0123456[]");
+ testDeleteSurroundingTextInCodePointsMain("012[345]6789", 0, 0, "012[345]6789");
+ testDeleteSurroundingTextInCodePointsMain("012[345]6789", -1, -1, "012[345]6789");
+ testDeleteSurroundingTextInCodePointsMain("012[345]6789", 1, 2, "01[345]89");
+ testDeleteSurroundingTextInCodePointsMain("012[345]6789", 10, 1, "[345]789");
+ testDeleteSurroundingTextInCodePointsMain("012[345]6789", 1, 10, "01[345]");
+ testDeleteSurroundingTextInCodePointsMain("[012]3456789", 3, 3, "[012]6789");
+ testDeleteSurroundingTextInCodePointsMain("0123456[789]", 3, 3, "0123[789]");
+ testDeleteSurroundingTextInCodePointsMain("[0123456789]", 0, 0, "[0123456789]");
+ testDeleteSurroundingTextInCodePointsMain("[0123456789]", 1, 1, "[0123456789]");
+
+ testDeleteSurroundingTextInCodePointsMain("0<>[]3456789", 1, 0, "0[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0<>[]3456789", 2, 0, "[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0<>[]3456789", 3, 0, "[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<>56789", 0, 1, "012[]56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<>56789", 0, 2, "012[]6789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<>56789", 0, 3, "012[]789");
+
+ testDeleteSurroundingTextInCodePointsMain("[]<><><><><>", 0, 0, "[]<><><><><>");
+ testDeleteSurroundingTextInCodePointsMain("[]<><><><><>", 0, 1, "[]<><><><>");
+ testDeleteSurroundingTextInCodePointsMain("[]<><><><><>", 0, 2, "[]<><><>");
+ testDeleteSurroundingTextInCodePointsMain("[]<><><><><>", 0, 3, "[]<><>");
+ testDeleteSurroundingTextInCodePointsMain("[]<><><><><>", 0, 4, "[]<>");
+ testDeleteSurroundingTextInCodePointsMain("[]<><><><><>", 0, 5, "[]");
+ testDeleteSurroundingTextInCodePointsMain("[]<><><><><>", 0, 6, "[]");
+ testDeleteSurroundingTextInCodePointsMain("[]<><><><><>", 0, 1000, "[]");
+ testDeleteSurroundingTextInCodePointsMain("<><><><><>[]", 0, 0, "<><><><><>[]");
+ testDeleteSurroundingTextInCodePointsMain("<><><><><>[]", 1, 0, "<><><><>[]");
+ testDeleteSurroundingTextInCodePointsMain("<><><><><>[]", 2, 0, "<><><>[]");
+ testDeleteSurroundingTextInCodePointsMain("<><><><><>[]", 3, 0, "<><>[]");
+ testDeleteSurroundingTextInCodePointsMain("<><><><><>[]", 4, 0, "<>[]");
+ testDeleteSurroundingTextInCodePointsMain("<><><><><>[]", 5, 0, "[]");
+ testDeleteSurroundingTextInCodePointsMain("<><><><><>[]", 6, 0, "[]");
+ testDeleteSurroundingTextInCodePointsMain("<><><><><>[]", 1000, 0, "[]");
+
+ testDeleteSurroundingTextInCodePointsMain("0<<[]3456789", 1, 0, "0<<[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0<<[]3456789", 2, 0, "0<<[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0<<[]3456789", 3, 0, "0<<[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<<56789", 0, 1, "012[]<<56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<<56789", 0, 2, "012[]<<56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<<56789", 0, 3, "012[]<<56789");
+ testDeleteSurroundingTextInCodePointsMain("0>>[]3456789", 1, 0, "0>>[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0>>[]3456789", 2, 0, "0>>[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0>>[]3456789", 3, 0, "0>>[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("012[]>>56789", 0, 1, "012[]>>56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]>>56789", 0, 2, "012[]>>56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]>>56789", 0, 3, "012[]>>56789");
+ testDeleteSurroundingTextInCodePointsMain("01<[]>456789", 1, 0, "01<[]>456789");
+ testDeleteSurroundingTextInCodePointsMain("01<[]>456789", 0, 1, "01<[]>456789");
+ testDeleteSurroundingTextInCodePointsMain("<12[]3456789", 1, 0, "<1[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("<12[]3456789", 2, 0, "<[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("<12[]3456789", 3, 0, "<12[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("<<>[]3456789", 1, 0, "<[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("<<>[]3456789", 2, 0, "<<>[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("<<>[]3456789", 3, 0, "<<>[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("012[]34>6789", 0, 1, "012[]4>6789");
+ testDeleteSurroundingTextInCodePointsMain("012[]34>6789", 0, 2, "012[]>6789");
+ testDeleteSurroundingTextInCodePointsMain("012[]34>6789", 0, 3, "012[]34>6789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<>>6789", 0, 1, "012[]>6789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<>>6789", 0, 2, "012[]<>>6789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<>>6789", 0, 3, "012[]<>>6789");
+
+ // Atomicity test.
+ testDeleteSurroundingTextInCodePointsMain("0<<[]3456789", 1, 1, "0<<[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0<<[]3456789", 2, 1, "0<<[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0<<[]3456789", 3, 1, "0<<[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<<56789", 1, 1, "012[]<<56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<<56789", 1, 2, "012[]<<56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]<<56789", 1, 3, "012[]<<56789");
+ testDeleteSurroundingTextInCodePointsMain("0>>[]3456789", 1, 1, "0>>[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0>>[]3456789", 2, 1, "0>>[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("0>>[]3456789", 3, 1, "0>>[]3456789");
+ testDeleteSurroundingTextInCodePointsMain("012[]>>56789", 1, 1, "012[]>>56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]>>56789", 1, 2, "012[]>>56789");
+ testDeleteSurroundingTextInCodePointsMain("012[]>>56789", 1, 3, "012[]>>56789");
+ testDeleteSurroundingTextInCodePointsMain("01<[]>456789", 1, 1, "01<[]>456789");
+
+ // Do not verify the character sequences in the selected region.
+ testDeleteSurroundingTextInCodePointsMain("01[><]456789", 1, 0, "0[><]456789");
+ testDeleteSurroundingTextInCodePointsMain("01[><]456789", 0, 1, "01[><]56789");
+ testDeleteSurroundingTextInCodePointsMain("01[><]456789", 1, 1, "0[><]56789");
}
}
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/EditorInfoTest.java b/tests/tests/view/src/android/view/inputmethod/cts/EditorInfoTest.java
index 1981d6f..9184881 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/EditorInfoTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/EditorInfoTest.java
@@ -21,6 +21,7 @@
import android.os.Parcel;
import android.test.AndroidTestCase;
import android.text.TextUtils;
+import android.util.LocaleList;
import android.util.Printer;
import android.view.inputmethod.EditorInfo;
@@ -41,13 +42,14 @@
info.initialSelStart = 0;
info.inputType = EditorInfo.TYPE_MASK_CLASS;
info.label = "label";
- info.packageName = "com.android.cts.view";
+ info.packageName = "android.view.cts";
info.privateImeOptions = "privateIme";
Bundle b = new Bundle();
String key = "bundleKey";
String value = "bundleValue";
b.putString(key, value);
info.extras = b;
+ info.locales = LocaleList.forLanguageTags("en-PH,en-US");
assertEquals(0, info.describeContents());
@@ -70,6 +72,7 @@
assertEquals(info.actionLabel.toString(), targetInfo.actionLabel.toString());
assertEquals(info.label.toString(), targetInfo.label.toString());
assertEquals(info.extras.getString(key), targetInfo.extras.getString(key));
+ assertEquals(info.locales, targetInfo.locales);
TestPrinter printer = new TestPrinter();
String prefix = "TestEditorInfo";
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
index 8913d6e..432fa20 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
@@ -54,6 +54,8 @@
assertTrue(inputConnection.isCommitTextCalled);
wrapper.deleteSurroundingText(10, 100);
assertTrue(inputConnection.isDeleteSurroundingTextCalled);
+ wrapper.deleteSurroundingTextInCodePoints(10, 100);
+ assertTrue(inputConnection.isDeleteSurroundingTextInCodePointsCalled);
wrapper.endBatchEdit();
assertTrue(inputConnection.isEndBatchEditCalled);
wrapper.finishComposingText();
@@ -95,6 +97,7 @@
public boolean isCommitCorrectionCalled;
public boolean isCommitTextCalled;
public boolean isDeleteSurroundingTextCalled;
+ public boolean isDeleteSurroundingTextInCodePointsCalled;
public boolean isEndBatchEditCalled;
public boolean isFinishComposingTextCalled;
public boolean isGetCursorCapsModeCalled;
@@ -142,6 +145,11 @@
return false;
}
+ public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
+ isDeleteSurroundingTextInCodePointsCalled = true;
+ return false;
+ }
+
public boolean endBatchEdit() {
isEndBatchEditCalled = true;
return false;
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodCtsActivity.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodCtsActivity.java
index 45e5ff2..acbe8a1 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodCtsActivity.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodCtsActivity.java
@@ -17,7 +17,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.view.R;
+import android.view.cts.R;
public class InputMethodCtsActivity extends Activity {
@Override
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
index b84292f..d03bab5 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
@@ -15,7 +15,7 @@
*/
package android.view.inputmethod.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.app.Instrumentation;
import android.content.Context;
@@ -38,7 +38,7 @@
extends ActivityInstrumentationTestCase2<InputMethodCtsActivity> {
public InputMethodManagerTest() {
- super("com.android.cts.view", InputMethodCtsActivity.class);
+ super("android.view.cts", InputMethodCtsActivity.class);
}
private InputMethodCtsActivity mActivity;
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/KeyboardTest.java b/tests/tests/view/src/android/view/inputmethod/cts/KeyboardTest.java
index ce7f9d7..f56ad0e 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/KeyboardTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/KeyboardTest.java
@@ -16,7 +16,7 @@
package android.view.inputmethod.cts;
-import com.android.cts.view.R;
+import android.view.cts.R;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java b/tests/tests/view/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java
new file mode 100644
index 0000000..3735c33
--- /dev/null
+++ b/tests/tests/view/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.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.view.inputmethod.cts.util;
+
+import android.text.Selection;
+import android.text.SpannableStringBuilder;
+
+public final class InputConnectionTestUtils {
+
+ /**
+ * A utility function to generate test string for input method APIs. There are several
+ * pre-defined meta characters that are useful for unit tests.
+ *
+ * <p>Pre-defined meta characters:</p>
+ * <dl>
+ * <dl>{@code [}</dl><dd>The text selection starts from here.</dd>
+ * <dl>{@code ]}</dl><dd>The text selection ends at here.</dd>
+ * <dl>{@code <}</dl><dd>Represents a high surrogate character.</dd>
+ * <dl>{@code >}</dl><dd>Represents a low surrogate character.</dd>
+ * </ul>
+ *
+ * <p>Examples: {@code "012[3<>67]89"} will be converted to {@ode "0123HL6789"}, where
+ * {@code "H"} and {@code "L"} indicate certain high and low surrogate characters, respectively,
+ * with selecting {@code "3HL67"}.</p>
+ *
+ * @param formatString
+ * @return A {@link CharSequence} object with text selection specified by the meta characters.
+ */
+ public static CharSequence formatString(final String formatString) {
+ final String U1F427 = "\uD83D\uDC27";
+ final SpannableStringBuilder builder = new SpannableStringBuilder();
+ int selectionStart = -1;
+ int selectionEnd = -1;
+ for (int i = 0; i < formatString.length(); ++i) {
+ final Character c = formatString.charAt(i);
+ switch (c) {
+ case '[':
+ selectionStart = builder.length();
+ break;
+ case ']':
+ selectionEnd = builder.length();
+ break;
+ case '<':
+ builder.append(U1F427.charAt(0)); // High surrogate
+ break;
+ case '>':
+ builder.append(U1F427.charAt(1)); // Low surrogate
+ break;
+ default:
+ builder.append(c);
+ break;
+ }
+ }
+ if (selectionStart < 0) {
+ throw new UnsupportedOperationException("Selection marker '[' must be specified.");
+ }
+ if (selectionEnd < 0) {
+ throw new UnsupportedOperationException("Selection marker ']' must be specified.");
+ }
+ Selection.setSelection(builder, selectionStart, selectionEnd);
+ return builder;
+ }
+}
diff --git a/tests/tests/voiceinteraction/Android.mk b/tests/tests/voiceinteraction/Android.mk
index b8f95e3..2d0666f 100644
--- a/tests/tests/voiceinteraction/Android.mk
+++ b/tests/tests/voiceinteraction/Android.mk
@@ -27,6 +27,11 @@
LOCAL_PACKAGE_NAME := CtsVoiceInteractionTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/voiceinteraction/AndroidTest.xml b/tests/tests/voiceinteraction/AndroidTest.xml
index fa1ab70..2aba101 100644
--- a/tests/tests/voiceinteraction/AndroidTest.xml
+++ b/tests/tests/voiceinteraction/AndroidTest.xml
@@ -13,11 +13,14 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Test module config for VoiceInteraction">
- <include name="common-config" />
- <option name="cts-apk-installer:test-file-name" value="CtsVoiceInteractionService.apk" />
- <option name="cts-apk-installer:test-file-name" value="CtsVoiceInteractionApp.apk" />
- <option name="run-command:run-command"
- value="settings put secure voice_interaction_service android.voiceinteraction.service/.MainInteractionService" />
- <option name="cts-apk-installer:test-file-name" value="CtsVoiceInteractionTestCases.apk" />
+<configuration description="Config for CTS Voice Interaction test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsVoiceInteractionService.apk" />
+ <option name="test-file-name" value="CtsVoiceInteractionApp.apk" />
+ <option name="test-file-name" value="CtsVoiceInteractionTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.voiceinteraction.cts" />
+ </test>
</configuration>
diff --git a/tests/tests/voiceinteraction/OldAndroidTest.xml b/tests/tests/voiceinteraction/OldAndroidTest.xml
new file mode 100644
index 0000000..fa1ab70
--- /dev/null
+++ b/tests/tests/voiceinteraction/OldAndroidTest.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+<configuration description="Test module config for VoiceInteraction">
+ <include name="common-config" />
+ <option name="cts-apk-installer:test-file-name" value="CtsVoiceInteractionService.apk" />
+ <option name="cts-apk-installer:test-file-name" value="CtsVoiceInteractionApp.apk" />
+ <option name="run-command:run-command"
+ value="settings put secure voice_interaction_service android.voiceinteraction.service/.MainInteractionService" />
+ <option name="cts-apk-installer:test-file-name" value="CtsVoiceInteractionTestCases.apk" />
+</configuration>
diff --git a/tests/tests/voiceinteraction/service/Android.mk b/tests/tests/voiceinteraction/service/Android.mk
index 4338f13..705ef5b 100644
--- a/tests/tests/voiceinteraction/service/Android.mk
+++ b/tests/tests/voiceinteraction/service/Android.mk
@@ -27,6 +27,9 @@
LOCAL_PACKAGE_NAME := CtsVoiceInteractionService
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/voiceinteraction/testapp/Android.mk b/tests/tests/voiceinteraction/testapp/Android.mk
index 7453880..ae42d34 100644
--- a/tests/tests/voiceinteraction/testapp/Android.mk
+++ b/tests/tests/voiceinteraction/testapp/Android.mk
@@ -29,4 +29,7 @@
LOCAL_SDK_VERSION := current
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/voicesettings/Android.mk b/tests/tests/voicesettings/Android.mk
index 71fead6..91d013d 100644
--- a/tests/tests/voicesettings/Android.mk
+++ b/tests/tests/voicesettings/Android.mk
@@ -27,6 +27,11 @@
LOCAL_PACKAGE_NAME := CtsVoiceSettingsTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/voicesettings/AndroidTest.xml b/tests/tests/voicesettings/AndroidTest.xml
index e3be691..64f5335 100644
--- a/tests/tests/voicesettings/AndroidTest.xml
+++ b/tests/tests/voicesettings/AndroidTest.xml
@@ -1,3 +1,4 @@
+<?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");
@@ -12,10 +13,16 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Test module config for VoiceInteraction">
- <include name="common-config" />
- <option name="cts-apk-installer:test-file-name" value="CtsVoiceSettingsService.apk" />
- <option name="run-command:run-command"
- value="settings put secure voice_interaction_service android.voicesettings.service/.MainInteractionService" />
- <option name="cts-apk-installer:test-file-name" value="CtsVoiceSettingsTestCases.apk" />
+<configuration description="Config for CTS Voice Settings test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsVoiceSettingsService.apk" />
+ <option name="test-file-name" value="CtsVoiceSettingsTestCases.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="settings put secure voice_interaction_service android.voicesettings.service/.MainInteractionService" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.voicesettings.cts" />
+ </test>
</configuration>
diff --git a/tests/tests/voicesettings/OldAndroidTest.xml b/tests/tests/voicesettings/OldAndroidTest.xml
new file mode 100644
index 0000000..246bf06
--- /dev/null
+++ b/tests/tests/voicesettings/OldAndroidTest.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+<configuration description="Test module config for VoiceSettings">
+ <include name="common-config" />
+ <option name="cts-apk-installer:test-file-name" value="CtsVoiceSettingsService.apk" />
+ <option name="run-command:run-command"
+ value="settings put secure voice_interaction_service android.voicesettings.service/.MainInteractionService" />
+</configuration>
diff --git a/tests/tests/voicesettings/service/Android.mk b/tests/tests/voicesettings/service/Android.mk
index 97866d5..f23a136 100644
--- a/tests/tests/voicesettings/service/Android.mk
+++ b/tests/tests/voicesettings/service/Android.mk
@@ -27,6 +27,9 @@
LOCAL_PACKAGE_NAME := CtsVoiceSettingsService
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/webkit/Android.mk b/tests/tests/webkit/Android.mk
index 17a1f27..85377ae 100644
--- a/tests/tests/webkit/Android.mk
+++ b/tests/tests/webkit/Android.mk
@@ -29,6 +29,9 @@
LOCAL_PACKAGE_NAME := CtsWebkitTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
# uncomment when dalvik.annotation.Test* are removed or part of SDK
#LOCAL_SDK_VERSION := current
diff --git a/tests/tests/webkit/AndroidManifest.xml b/tests/tests/webkit/AndroidManifest.xml
index fa25824..44df7c4 100644
--- a/tests/tests/webkit/AndroidManifest.xml
+++ b/tests/tests/webkit/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.webkit">
+ package="android.webkit.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
@@ -59,7 +59,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.webkit"
+ android:targetPackage="android.webkit.cts"
android:label="CTS tests of android.webkit">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/webkit/AndroidTest.xml b/tests/tests/webkit/AndroidTest.xml
new file mode 100644
index 0000000..e6649e1
--- /dev/null
+++ b/tests/tests/webkit/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+<configuration description="Config for CTS Webkit test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsWebkitTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.webkit.cts" />
+ <option name="runtime-hint" value="6m39s" />
+ </test>
+
+</configuration>
diff --git a/tests/tests/webkit/assets/webkit/test_loginForm.html b/tests/tests/webkit/assets/webkit/test_loginForm.html
new file mode 100644
index 0000000..0935cf1
--- /dev/null
+++ b/tests/tests/webkit/assets/webkit/test_loginForm.html
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+
+<html>
+ <body>
+ <form>
+ <input type='text' name='username' value='Cts Test'/>
+ <input type='submit' name='submit' value='Submit'/>
+ </form>
+ </body>
+</html>
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
index 856b4aa..ffde739 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
@@ -42,7 +42,7 @@
private WebViewOnUiThread mOnUiThread;
public CookieManagerTest() {
- super("com.android.cts.webkit", CookieSyncManagerCtsActivity.class);
+ super("android.webkit.cts", CookieSyncManagerCtsActivity.class);
}
@Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
index 555266b..cca7e35 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
@@ -30,7 +30,7 @@
private static final long WAIT_TIME = 50;
public CookieTest() {
- super("com.android.cts.webkit", CookieSyncManagerCtsActivity.class);
+ super("android.webkit.cts", CookieSyncManagerCtsActivity.class);
}
@Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
index 32b6167..83330d4 100644
--- a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
@@ -110,7 +110,7 @@
private List<String> mProviders;
public GeolocationTest() throws Exception {
- super("com.android.cts.webkit", WebViewCtsActivity.class);
+ super("android.webkit.cts", WebViewCtsActivity.class);
}
// Both this test and WebViewOnUiThread need to override some of the methods on WebViewClient,
diff --git a/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java b/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
index 5c86987..10bf6d8 100644
--- a/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
@@ -38,7 +38,7 @@
private WebViewOnUiThread mOnUiThread;
public HttpAuthHandlerTest() {
- super("com.android.cts.webkit", WebViewCtsActivity.class);
+ super("android.webkit.cts", WebViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java b/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java
index 2a6af6e..6ffe69c 100644
--- a/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java
@@ -38,7 +38,7 @@
private static final String BASE_URI = "http://www.example.com";
public PostMessageTest() {
- super("com.android.cts.webkit", WebViewCtsActivity.class);
+ super("android.webkit.cts", WebViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
index 1ab5e5a..68d944b 100644
--- a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
+++ b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
@@ -55,6 +55,8 @@
public static final String BLANK_PAGE_URL = "webkit/test_blankPage.html";
public static final String ADD_JAVA_SCRIPT_INTERFACE_URL = "webkit/test_jsInterface.html";
+ public static final String LOGIN_FORM_URL = "webkit/test_loginForm.html";
+
public static final String EXT_WEB_URL1 = "http://www.example.com/";
public static final String LOCAL_FILESYSTEM_URL = "file:///etc/hosts";
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java b/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
index 7d25b84..e7d6211 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
@@ -31,7 +31,7 @@
private WebViewOnUiThread mOnUiThread;
public WebBackForwardListTest() {
- super("com.android.cts.webkit", WebViewCtsActivity.class);
+ super("android.webkit.cts", WebViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
index a6b647df..dc9e615 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
@@ -48,7 +48,7 @@
};
public WebHistoryItemTest() {
- super("com.android.cts.webkit", WebViewCtsActivity.class);
+ super("android.webkit.cts", WebViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index 592e308..7729baf 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -64,7 +64,7 @@
private Context mContext;
public WebSettingsTest() {
- super("com.android.cts.webkit", WebViewCtsActivity.class);
+ super("android.webkit.cts", WebViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index 0697429..1267ccb 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -34,11 +34,14 @@
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.cts.WebViewOnUiThread.WaitForLoadedClient;
+import android.util.Pair;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
public class WebViewClientTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
private static final long TEST_TIMEOUT = 5000;
@@ -48,7 +51,7 @@
private CtsTestServer mWebServer;
public WebViewClientTest() {
- super("com.android.cts.webkit", WebViewCtsActivity.class);
+ super("android.webkit.cts", WebViewCtsActivity.class);
}
@Override
@@ -85,7 +88,7 @@
return;
}
final WebViewClient webViewClient = new WebViewClient();
- assertFalse(webViewClient.shouldOverrideUrlLoading(mOnUiThread.getWebView(), null));
+ assertFalse(webViewClient.shouldOverrideUrlLoading(mOnUiThread.getWebView(), new String()));
}
// Verify shouldoverrideurlloading called on top level navigation
@@ -210,6 +213,40 @@
}.run();
}
+ public void testOnReceivedLoginRequest() throws Exception {
+ if (!NullWebViewUtils.isWebViewAvailable()) {
+ return;
+ }
+ final MockWebViewClient webViewClient = new MockWebViewClient();
+ mOnUiThread.setWebViewClient(webViewClient);
+ TestWebServer testServer = null;
+ //set the url and html
+ final String path = "/main";
+ final String page = "<head></head><body>test onReceivedLoginRequest</body>";
+ final String headerName = "x-auto-login";
+ final String headerValue = "realm=com.google&account=foo%40bar.com&args=random_string";
+ List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
+ headers.add(Pair.create(headerName, headerValue));
+
+ try {
+ testServer = new TestWebServer(false);
+ String url = testServer.setResponse(path, page, headers);
+ assertFalse(webViewClient.hasOnReceivedLoginRequest());
+ mOnUiThread.loadUrlAndWaitForCompletion(url);
+ assertTrue(webViewClient.hasOnReceivedLoginRequest());
+ new PollingCheck(TEST_TIMEOUT) {
+ @Override
+ protected boolean check() {
+ return webViewClient.hasOnReceivedLoginRequest();
+ }
+ }.run();
+ assertEquals("com.google", webViewClient.getLoginRequestRealm());
+ assertEquals("foo@bar.com", webViewClient.getLoginRequestAccount());
+ assertEquals("random_string", webViewClient.getLoginRequestArgs());
+ } finally {
+ testServer.shutdown();
+ }
+ }
public void testOnReceivedError() throws Exception {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
@@ -541,6 +578,10 @@
private boolean mOnFormResubmissionCalled;
private boolean mDoUpdateVisitedHistoryCalled;
private boolean mOnReceivedHttpAuthRequestCalled;
+ private boolean mOnReceivedLoginRequest;
+ private String mOnReceivedLoginAccount;
+ private String mOnReceivedLoginArgs;
+ private String mOnReceivedLoginRealm;
private boolean mOnUnhandledKeyEventCalled;
private boolean mOnScaleChangedCalled;
private int mShouldOverrideUrlLoadingCallCount;
@@ -566,6 +607,10 @@
return mOnReceivedErrorCode;
}
+ public boolean hasOnReceivedLoginRequest() {
+ return mOnReceivedLoginRequest;
+ }
+
public WebResourceError hasOnReceivedResourceError() {
return mOnReceivedResourceError;
}
@@ -602,6 +647,18 @@
return mLastShouldOverrideUrl;
}
+ public String getLoginRequestRealm() {
+ return mOnReceivedLoginRealm;
+ }
+
+ public String getLoginRequestAccount() {
+ return mOnReceivedLoginAccount;
+ }
+
+ public String getLoginRequestArgs() {
+ return mOnReceivedLoginArgs;
+ }
+
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
@@ -645,6 +702,16 @@
}
@Override
+ public void onReceivedLoginRequest(WebView view, String realm, String account,
+ String args) {
+ super.onReceivedLoginRequest(view, realm, account, args);
+ mOnReceivedLoginRequest = true;
+ mOnReceivedLoginRealm = realm;
+ mOnReceivedLoginAccount = account;
+ mOnReceivedLoginArgs = args;
+ }
+
+ @Override
public void onFormResubmission(WebView view, Message dontResend, Message resend) {
mOnFormResubmissionCalled = true;
dontResend.sendToTarget();
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java b/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java
index 9af7266..1b05154 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.webkit.cts;
-import com.android.cts.webkit.R;
+import android.webkit.cts.R;
import android.app.Activity;
import android.cts.util.NullWebViewUtils;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java
index 6555731..e07267f 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java
@@ -430,7 +430,7 @@
private WebViewOnUiThread mOnUiThread;
public WebViewSslTest() {
- super("com.android.cts.webkit", WebViewCtsActivity.class);
+ super("android.webkit.cts", WebViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
index 776cfab..6768b6f 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
@@ -39,7 +39,7 @@
private WebViewStartupCtsActivity mActivity;
public WebViewStartupTest() {
- super("com.android.cts.webkit", WebViewStartupCtsActivity.class);
+ super("android.webkit.cts", WebViewStartupCtsActivity.class);
}
@Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 23c8dba..3f4fd92 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -1126,6 +1126,39 @@
}.run();
}
+ public void testClearFormData() throws Throwable {
+ if (!NullWebViewUtils.isWebViewAvailable()) {
+ return;
+ }
+ try {
+ startWebServer(false);
+ WebSettings settings = mOnUiThread.getSettings();
+ settings.setDatabaseEnabled(true);
+ WebViewDatabase webViewDatabase = WebViewDatabase.getInstance(getActivity());
+ webViewDatabase.clearFormData();
+ final String url = mWebServer.getAssetUrl(TestHtmlConstants.LOGIN_FORM_URL);
+ mOnUiThread.loadUrlAndWaitForCompletion(url);
+ new PollingCheck(TEST_TIMEOUT) {
+ @Override
+ public boolean check() {
+ return !WebViewDatabase.getInstance(getActivity()).hasFormData();
+ }
+ }.run();
+
+ // click submit
+ moveFocusDown();
+ getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
+ new PollingCheck(TEST_TIMEOUT) {
+ @Override
+ public boolean check() {
+ return WebViewDatabase.getInstance(getActivity()).hasFormData();
+ }
+ }.run();
+ } finally {
+ WebViewDatabase.getInstance(getActivity()).clearFormData();
+ }
+ }
+
@UiThreadTest
public void testAccessHttpAuthUsernamePassword() {
if (!NullWebViewUtils.isWebViewAvailable()) {
@@ -1592,7 +1625,7 @@
} while (mOnUiThread.pageDown(false));
waitForFlingDone(mOnUiThread);
- int bottomScrollY = mOnUiThread.getScrollY();
+ final int bottomScrollY = mOnUiThread.getScrollY();
assertTrue(mOnUiThread.pageUp(false));
@@ -1601,17 +1634,25 @@
} while (mOnUiThread.pageUp(false));
waitForFlingDone(mOnUiThread);
- int topScrollY = mOnUiThread.getScrollY();
+ final int topScrollY = mOnUiThread.getScrollY();
// jump to the bottom
assertTrue(mOnUiThread.pageDown(true));
- waitForFlingDone(mOnUiThread);
- assertEquals(bottomScrollY, mOnUiThread.getScrollY());
+ new PollingCheck() {
+ @Override
+ protected boolean check() {
+ return bottomScrollY == mOnUiThread.getScrollY();
+ }
+ }.run();
// jump to the top
assertTrue(mOnUiThread.pageUp(true));
- waitForFlingDone(mOnUiThread);
- assertEquals(topScrollY, mOnUiThread.getScrollY());
+ new PollingCheck() {
+ @Override
+ protected boolean check() {
+ return topScrollY == mOnUiThread.getScrollY();
+ }
+ }.run();
}
public void testGetContentHeight() throws Throwable {
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
index 1db7fca..4fa9b4f 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
@@ -27,7 +27,7 @@
extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
public WebView_WebViewTransportTest() {
- super("com.android.cts.webkit", WebViewCtsActivity.class);
+ super("android.webkit.cts", WebViewCtsActivity.class);
}
@UiThreadTest
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index 505f82c..fa2b60a 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/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 += android-common ctsdeviceutil ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES += mockito-target android-common ctsdeviceutil ctstestrunner
LOCAL_JAVA_LIBRARIES := android.test.runner
@@ -29,4 +29,7 @@
LOCAL_PACKAGE_NAME := CtsWidgetTestCases
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index bc43106..576e751 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.widget">
+ package="android.widget.cts">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application android:label="Android TestCase"
@@ -355,7 +355,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.widget"
+ android:targetPackage="android.widget.cts"
android:label="CTS tests of android.widget">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/widget/AndroidTest.xml b/tests/tests/widget/AndroidTest.xml
new file mode 100644
index 0000000..d943b85
--- /dev/null
+++ b/tests/tests/widget/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<configuration description="Config for CTS Widget test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsWidgetTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.widget.cts" />
+ <option name="runtime-hint" value="3m" />
+ </test>
+</configuration>
diff --git a/tests/tests/widget/res/layout/digitalclock_layout.xml b/tests/tests/widget/res/layout/digitalclock_layout.xml
index d405af2..618dbea 100644
--- a/tests/tests/widget/res/layout/digitalclock_layout.xml
+++ b/tests/tests/widget/res/layout/digitalclock_layout.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<com.android.cts.widget.alarmclock.DigitalClock android:id="@+id/digitalClock"
+<android.widget.cts.alarmclock.DigitalClock android:id="@+id/digitalClock"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="208dip"
@@ -45,4 +45,4 @@
android:text="@string/pm"
android:textSize="28sp"/>
</LinearLayout>
-</com.android.cts.widget.alarmclock.DigitalClock>
+</android.widget.cts.alarmclock.DigitalClock>
diff --git a/tests/tests/widget/res/layout/linearlayout_layout.xml b/tests/tests/widget/res/layout/linearlayout_layout.xml
index c70937d..8881552 100644
--- a/tests/tests/widget/res/layout/linearlayout_layout.xml
+++ b/tests/tests/widget/res/layout/linearlayout_layout.xml
@@ -15,6 +15,7 @@
* 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">
diff --git a/tests/tests/widget/res/layout/seekbar_layout.xml b/tests/tests/widget/res/layout/seekbar_layout.xml
index 5c311fd..4b4a6b7 100644
--- a/tests/tests/widget/res/layout/seekbar_layout.xml
+++ b/tests/tests/widget/res/layout/seekbar_layout.xml
@@ -32,4 +32,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
+ <SeekBar
+ android:id="@+id/tick_mark_tint"
+ android:tickMarkTint="@android:color/white"
+ android:tickMarkTintMode="src_over"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
</LinearLayout>
diff --git a/tests/tests/widget/res/layout/toolbar_layout.xml b/tests/tests/widget/res/layout/toolbar_layout.xml
new file mode 100644
index 0000000..42e661b
--- /dev/null
+++ b/tests/tests/widget/res/layout/toolbar_layout.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+
+<Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/toolbar"
+ android:titleMargin="5px"
+ android:titleMarginTop="10px"
+ android:titleMarginEnd="15px"
+ android:titleMarginBottom="20px" />
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
index 2b38827..89a3448 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -73,7 +73,7 @@
private static final float DELTA = 0.001f;
public AbsListViewTest() {
- super("com.android.cts.widget", ListViewCtsActivity.class);
+ super("android.widget.cts", ListViewCtsActivity.class);
}
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java
index 305a9e2..7e88a19 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
index dfad3bbb..1eb34c8 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
@@ -16,22 +16,19 @@
package android.widget.cts;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.test.UiThreadTest;
-
-import com.android.cts.widget.R;
-
+import android.widget.cts.R;
import android.app.Activity;
import android.content.Context;
-import android.content.res.Resources;
+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.Drawable;
import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.AbsSeekBar;
@@ -42,17 +39,16 @@
*/
public class AbsSeekBarTest extends ActivityInstrumentationTestCase2<ProgressBarCtsActivity> {
public AbsSeekBarTest() {
- super("com.android.cts.widget", ProgressBarCtsActivity.class);
+ super("android.widget.cts", ProgressBarCtsActivity.class);
}
private Activity mActivity;
- private Resources mResources;
@Override
protected void setUp() throws Exception {
super.setUp();
+
mActivity = getActivity();
- mResources = mActivity.getResources();
}
public void testConstructor() {
@@ -81,17 +77,38 @@
public void testSetThumb() {
MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
- Drawable drawable1 = mResources.getDrawable(R.drawable.scenery);
- Drawable drawable2 = mResources.getDrawable(R.drawable.pass);
+ 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());
assertTrue(myAbsSeekBar.verifyDrawable(drawable1));
assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
myAbsSeekBar.setThumb(drawable2);
+ assertSame(drawable2, myAbsSeekBar.getThumb());
+ assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
+ assertTrue(myAbsSeekBar.verifyDrawable(drawable2));
+ }
+
+ public void testSetTickMark() {
+ MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
+ 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());
+ assertTrue(myAbsSeekBar.verifyDrawable(drawable1));
+ assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
+
+ myAbsSeekBar.setTickMark(drawable2);
+ assertSame(drawable2, myAbsSeekBar.getTickMark());
assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
assertTrue(myAbsSeekBar.verifyDrawable(drawable2));
}
@@ -112,10 +129,10 @@
public void testVerifyDrawable() {
MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
- Drawable drawable1 = mResources.getDrawable(R.drawable.scenery);
- Drawable drawable2 = mResources.getDrawable(R.drawable.pass);
- Drawable drawable3 = mResources.getDrawable(R.drawable.blue);
- Drawable drawable4 = mResources.getDrawable(R.drawable.black);
+ Drawable drawable1 = mActivity.getDrawable(R.drawable.scenery);
+ Drawable drawable2 = mActivity.getDrawable(R.drawable.pass);
+ Drawable drawable3 = mActivity.getDrawable(R.drawable.blue);
+ Drawable drawable4 = mActivity.getDrawable(R.drawable.black);
assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
@@ -239,10 +256,32 @@
thumb.hasCalledSetTint());
}
- 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
+ @UiThreadTest
+ public void testTickMarkTint() {
+ mActivity.setContentView(R.layout.seekbar_layout);
+
+ SeekBar inflatedView = (SeekBar) 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);
+
+ view.setTickMark(tickMark);
+ assertFalse("No tickMark tint applied by default", tickMark.hasCalledSetTint());
+
+ view.setTickMarkTintList(ColorStateList.valueOf(Color.WHITE));
+ assertTrue("TickMark tint applied when setTickMarkTintList() called after setTickMark()",
+ tickMark.hasCalledSetTint());
+
+ tickMark.reset();
+ view.setTickMark(null);
+ view.setTickMark(tickMark);
+ assertTrue("TickMark tint applied when setTickMarkTintList() called before setTickMark()",
+ tickMark.hasCalledSetTint());
}
private static class MyAbsSeekBar extends AbsSeekBar {
@@ -275,13 +314,7 @@
private boolean mCalledSetTint = false;
@Override
- public void draw(Canvas canvas) {
- mCalledDraw = true;
- }
-
- public boolean hasCalledDraw() {
- return mCalledDraw;
- }
+ public void draw(Canvas canvas) { }
public void reset() {
mCalledDraw = false;
diff --git a/tests/tests/widget/src/android/widget/cts/AbsSpinnerTest.java b/tests/tests/widget/src/android/widget/cts/AbsSpinnerTest.java
index 9669c7c..e07e8b1 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsSpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsSpinnerTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -43,7 +43,7 @@
private Context mContext;
public AbsSpinnerTest() {
- super("com.android.cts.widget", RelativeLayoutCtsActivity.class);
+ super("android.widget.cts", RelativeLayoutCtsActivity.class);
}
@Override
@@ -78,7 +78,7 @@
public void testSetSelectionIntBoolean() {
AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext,
- com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
+ android.widget.cts.R.array.string, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
absSpinner.setAdapter(adapter);
assertEquals(0, absSpinner.getSelectedItemPosition());
@@ -101,7 +101,7 @@
public void testSetSelectionInt() {
AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext,
- com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
+ android.widget.cts.R.array.string, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
absSpinner.setAdapter(adapter);
assertEquals(0, absSpinner.getSelectedItemPosition());
@@ -123,7 +123,7 @@
public void testAccessAdapter() {
AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext,
- com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
+ android.widget.cts.R.array.string, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
absSpinner.setAdapter(adapter);
@@ -159,7 +159,7 @@
AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter1 = ArrayAdapter.createFromResource(mContext,
- com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
+ android.widget.cts.R.array.string, android.R.layout.simple_spinner_item);
absSpinner.setAdapter(adapter1);
assertEquals(adapter1.getCount(), absSpinner.getCount());
@@ -236,7 +236,7 @@
public void testOnSaveAndRestoreInstanceState() {
AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext,
- com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
+ android.widget.cts.R.array.string, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
absSpinner.setAdapter(adapter);
assertEquals(0, absSpinner.getSelectedItemPosition());
diff --git a/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java b/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java
index bac2479..a838f65 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -46,7 +46,7 @@
private LayoutParams mAbsoluteLayoutParams;
public AbsoluteLayoutTest() {
- super("com.android.cts.widget", CtsActivity.class);
+ super("android.widget.cts", CtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java
index ebc4e74..2723581 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/AdapterViewCtsActivity.java
index 956ff9a..a85e365 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewCtsActivity.java
@@ -25,7 +25,7 @@
import android.widget.ArrayAdapter;
import android.widget.ListView;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* A minimal application for AdapterView test.
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
index ccbdd56..1b9137f 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
@@ -39,7 +39,7 @@
import android.widget.AdapterView.OnItemSelectedListener;
import android.provider.Settings;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
public class AdapterViewTest extends ActivityInstrumentationTestCase2<AdapterViewCtsActivity> {
@@ -55,7 +55,7 @@
private AdapterView<ListAdapter> mAdapterView;
public AdapterViewTest() {
- super("com.android.cts.widget", AdapterViewCtsActivity.class);
+ super("android.widget.cts", AdapterViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterView_AdapterContextMenuInfoTest.java b/tests/tests/widget/src/android/widget/cts/AdapterView_AdapterContextMenuInfoTest.java
index fde6095..17c7a1e 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterView_AdapterContextMenuInfoTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterView_AdapterContextMenuInfoTest.java
@@ -16,7 +16,6 @@
package android.widget.cts;
-
import android.test.AndroidTestCase;
import android.view.View;
import android.widget.AdapterView;
diff --git a/tests/tests/widget/src/android/widget/cts/AnalogClockTest.java b/tests/tests/widget/src/android/widget/cts/AnalogClockTest.java
index ef1a45d..fae6516 100644
--- a/tests/tests/widget/src/android/widget/cts/AnalogClockTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AnalogClockTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -33,7 +33,7 @@
private Activity mActivity;
public AnalogClockTest() {
- super("com.android.cts.widget", FrameLayoutCtsActivity.class);
+ super("android.widget.cts", FrameLayoutCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java b/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
index fdca64c..03677f2 100644
--- a/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
@@ -29,7 +29,7 @@
import android.widget.Filter;
import android.widget.TextView;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
public class ArrayAdapterTest extends InstrumentationTestCase {
diff --git a/tests/tests/widget/src/android/widget/cts/AutoCompleteCtsActivity.java b/tests/tests/widget/src/android/widget/cts/AutoCompleteCtsActivity.java
index 3d68f3e..1a12d66 100644
--- a/tests/tests/widget/src/android/widget/cts/AutoCompleteCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/AutoCompleteCtsActivity.java
@@ -19,7 +19,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* A minimal application for AutoCompleteTextView test.
diff --git a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
index c08abbc..eb22d6b 100644
--- a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -53,7 +53,7 @@
* Instantiates a new text view test.
*/
public AutoCompleteTextViewTest() {
- super("com.android.cts.widget", AutoCompleteCtsActivity.class);
+ super("android.widget.cts", AutoCompleteCtsActivity.class);
}
/** The m activity. */
diff --git a/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java b/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java
index 0369259..7659c1e 100644
--- a/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java
@@ -16,7 +16,6 @@
package android.widget.cts;
-
import android.database.DataSetObserver;
import android.test.AndroidTestCase;
import android.view.View;
diff --git a/tests/tests/widget/src/android/widget/cts/ButtonTest.java b/tests/tests/widget/src/android/widget/cts/ButtonTest.java
index 47d7108..9da2ecf 100644
--- a/tests/tests/widget/src/android/widget/cts/ButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ButtonTest.java
@@ -24,7 +24,7 @@
import android.util.Xml;
import android.widget.Button;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
public class ButtonTest extends AndroidTestCase {
diff --git a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
index 21e463f..b3a6e67 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
index a0ed498..52bef54 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
index c5d3bd1..039ca70 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
@@ -16,7 +16,8 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.os.Parcelable;
+import android.widget.cts.R;
import android.app.Activity;
@@ -44,7 +45,7 @@
private Instrumentation mInstrumentation;
public CheckedTextViewTest() {
- super("com.android.cts.widget", CheckedTextViewCtsActivity.class);
+ super("android.widget.cts", CheckedTextViewCtsActivity.class);
}
@Override
@@ -266,6 +267,35 @@
assertFalse(checkedTextView.isLayoutRequested());
}
+ public void testSetCheckMarkByMixedTypes() {
+ CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
+ cleanUpForceLayoutFlags(checkedTextView);
+
+ // Specifically test for b/22626247 (AOSP issue 180455).
+ checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
+ checkedTextView.setCheckMarkDrawable(null);
+ checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
+ assertNotNull(checkedTextView.getCheckMarkDrawable());
+ }
+
+ public void testAccessInstanceState() {
+ CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
+ Parcelable state;
+
+ assertFalse(checkedTextView.isChecked());
+ assertFalse(checkedTextView.getFreezesText());
+
+ state = checkedTextView.onSaveInstanceState();
+ assertNotNull(state);
+ assertFalse(checkedTextView.getFreezesText());
+
+ checkedTextView.setChecked(true);
+
+ checkedTextView.onRestoreInstanceState(state);
+ assertFalse(checkedTextView.isChecked());
+ assertTrue(checkedTextView.isLayoutRequested());
+ }
+
public void testOnDraw() {
// Do not test. Implementation details.
}
diff --git a/tests/tests/widget/src/android/widget/cts/ChronometerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ChronometerCtsActivity.java
index 3a7833d..7925b49 100644
--- a/tests/tests/widget/src/android/widget/cts/ChronometerCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ChronometerCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup;
diff --git a/tests/tests/widget/src/android/widget/cts/ChronometerTest.java b/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
index 7910274..ff1435f 100644
--- a/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
@@ -28,7 +28,7 @@
public class ChronometerTest extends ActivityInstrumentationTestCase2<ChronometerCtsActivity> {
private ChronometerCtsActivity mActivity;
public ChronometerTest() {
- super("com.android.cts.widget", ChronometerCtsActivity.class);
+ super("android.widget.cts", ChronometerCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java b/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
index 98bf047..4b32eff 100644
--- a/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
@@ -22,7 +22,7 @@
import android.graphics.PorterDuff;
import android.view.LayoutInflater;
import android.widget.ToggleButton;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java b/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java
index 730083e..b590199 100644
--- a/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java
@@ -37,7 +37,7 @@
import android.widget.FilterQueryProvider;
import android.widget.TextView;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* Test {@link CursorAdapter}.
diff --git a/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java b/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
index f74b9972..5295730 100644
--- a/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
@@ -32,7 +32,7 @@
import android.widget.FilterQueryProvider;
import android.widget.TextView;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
index 3fa238e..c48f684 100644
--- a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
import android.content.res.XmlResourceParser;
diff --git a/tests/tests/widget/src/android/widget/cts/DialerFilterCtsActivity.java b/tests/tests/widget/src/android/widget/cts/DialerFilterCtsActivity.java
index 572d3fb..406a49a 100644
--- a/tests/tests/widget/src/android/widget/cts/DialerFilterCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/DialerFilterCtsActivity.java
@@ -18,7 +18,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* A minimal application for DialerFilter test.
diff --git a/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java b/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
index 68a17e7..a99f56a 100644
--- a/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -45,7 +45,7 @@
private DialerFilter mDialerFilter;
public DialerFilterTest() {
- super("com.android.cts.widget", DialerFilterCtsActivity.class);
+ super("android.widget.cts", DialerFilterCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/DigitalClockCtsActivity.java b/tests/tests/widget/src/android/widget/cts/DigitalClockCtsActivity.java
index 68cb3f0..d92651e 100644
--- a/tests/tests/widget/src/android/widget/cts/DigitalClockCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/DigitalClockCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/DigitalClockTest.java b/tests/tests/widget/src/android/widget/cts/DigitalClockTest.java
index 86a9672..2bfcc59 100644
--- a/tests/tests/widget/src/android/widget/cts/DigitalClockTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DigitalClockTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParserException;
@@ -42,7 +42,7 @@
private Context mContext;
public DigitalClockTest() {
- super("com.android.cts.widget", DigitalClockCtsActivity.class);
+ super("android.widget.cts", DigitalClockCtsActivity.class);
}
@Override
@@ -114,7 +114,7 @@
private AttributeSet getAttributeSet(int resourceId) {
XmlResourceParser parser = mActivity.getResources().getXml(resourceId);
try {
- XmlUtils.beginDocument(parser, "com.android.cts.widget.alarmclock.DigitalClock");
+ XmlUtils.beginDocument(parser, "android.widget.cts.alarmclock.DigitalClock");
} catch (XmlPullParserException e) {
fail("unexpected XmlPullParserException.");
} catch (IOException e) {
diff --git a/tests/tests/widget/src/android/widget/cts/EditTextTest.java b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
index 7a71a58..88fa2e0 100644
--- a/tests/tests/widget/src/android/widget/cts/EditTextTest.java
+++ b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
@@ -28,7 +28,7 @@
import android.widget.EditText;
import android.widget.TextView.BufferType;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
public class EditTextTest extends AndroidTestCase {
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
index ac48ed8..e773ebf 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/FilterTest.java b/tests/tests/widget/src/android/widget/cts/FilterTest.java
index 2c598dd..7a1d111 100644
--- a/tests/tests/widget/src/android/widget/cts/FilterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FilterTest.java
@@ -32,7 +32,7 @@
private MockFilter mMockFilter;
public FilterTest() {
- super("com.android.cts.widget", CtsActivity.class);
+ super("android.widget.cts", CtsActivity.class);
}
public void testConstructor() throws Throwable {
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayoutCtsActivity.java b/tests/tests/widget/src/android/widget/cts/FrameLayoutCtsActivity.java
index c638313..1f97af4 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayoutCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayoutCtsActivity.java
@@ -18,7 +18,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* A minimal application for frame layout test.
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
index 31d9fff..1fc0cef 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
@@ -23,7 +23,7 @@
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -56,7 +56,7 @@
private FrameLayout mFrameLayout;
public FrameLayoutTest() {
- super("com.android.cts.widget", FrameLayoutCtsActivity.class);
+ super("android.widget.cts", FrameLayoutCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java
index 1e7082f..5774b53 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java
@@ -16,7 +16,8 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.view.Gravity;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -75,4 +76,47 @@
// expected, test success.
}
}
+
+ public void testCopyConstructor() {
+ FrameLayout.LayoutParams copy;
+
+ final FrameLayout.LayoutParams fllp = new FrameLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ fllp.gravity = Gravity.BOTTOM;
+ fllp.leftMargin = 5;
+ fllp.topMargin = 10;
+ fllp.rightMargin = 15;
+ fllp.bottomMargin = 20;
+
+ copy = new FrameLayout.LayoutParams(fllp);
+ assertEquals("Width", fllp.width, copy.width);
+ assertEquals("Height", fllp.height, copy.height);
+ assertEquals("Gravity", fllp.gravity, copy.gravity);
+ assertEquals("Left margin", fllp.leftMargin, copy.leftMargin);
+ assertEquals("Top margin", fllp.topMargin, copy.topMargin);
+ assertEquals("Right margin", fllp.rightMargin, copy.rightMargin);
+ assertEquals("Bottom margin", fllp.bottomMargin, copy.bottomMargin);
+
+ final MarginLayoutParams mlp = new MarginLayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ mlp.leftMargin = 5;
+ mlp.topMargin = 10;
+ mlp.rightMargin = 15;
+ mlp.bottomMargin = 20;
+
+ copy = new FrameLayout.LayoutParams(mlp);
+ assertEquals("Width", mlp.width, copy.width);
+ assertEquals("Height", mlp.height, copy.height);
+ assertEquals("Left margin", fllp.leftMargin, copy.leftMargin);
+ assertEquals("Top margin", fllp.topMargin, copy.topMargin);
+ assertEquals("Right margin", fllp.rightMargin, copy.rightMargin);
+ assertEquals("Bottom margin", fllp.bottomMargin, copy.bottomMargin);
+
+ final ViewGroup.LayoutParams vglp = new ViewGroup.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+
+ copy = new FrameLayout.LayoutParams(vglp);
+ assertEquals("Width", vglp.width, copy.width);
+ assertEquals("Height", vglp.height, copy.height);
+ }
}
diff --git a/tests/tests/widget/src/android/widget/cts/GalleryCtsActivity.java b/tests/tests/widget/src/android/widget/cts/GalleryCtsActivity.java
index 8d32717..8039f47 100644
--- a/tests/tests/widget/src/android/widget/cts/GalleryCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/GalleryCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.content.Context;
diff --git a/tests/tests/widget/src/android/widget/cts/GalleryTest.java b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
index 581107c..dd39461 100644
--- a/tests/tests/widget/src/android/widget/cts/GalleryTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -64,7 +64,7 @@
private final static float DELTA = 0.01f;
public GalleryTest() {
- super("com.android.cts.widget", GalleryCtsActivity.class);
+ super("android.widget.cts", GalleryCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java
index 0502e38..eacb676 100644
--- a/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/widget/src/android/widget/cts/GridLayoutCtsActivity.java b/tests/tests/widget/src/android/widget/cts/GridLayoutCtsActivity.java
index 3277ee8..bfbde22 100644
--- a/tests/tests/widget/src/android/widget/cts/GridLayoutCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/GridLayoutCtsActivity.java
@@ -18,7 +18,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* A minimal application for {@link android.widget.GridLayout} test.
diff --git a/tests/tests/widget/src/android/widget/cts/GridLayoutTest.java b/tests/tests/widget/src/android/widget/cts/GridLayoutTest.java
index d701623..adbb285 100644
--- a/tests/tests/widget/src/android/widget/cts/GridLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GridLayoutTest.java
@@ -27,7 +27,7 @@
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.TextView;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
import static android.view.ViewGroup.LAYOUT_MODE_OPTICAL_BOUNDS;
@@ -117,7 +117,7 @@
private Context mContext;
public GridLayoutTest() {
- super("com.android.cts.widget", GridLayoutCtsActivity.class);
+ super("android.widget.cts", GridLayoutCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
index 7a1182d..7b2e7a3 100644
--- a/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewTest.java b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
index 3c615bd..8698280 100644
--- a/tests/tests/widget/src/android/widget/cts/GridViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -57,7 +57,7 @@
private Instrumentation mInstrumentation;
public GridViewTest() {
- super("com.android.cts.widget", GridViewCtsActivity.class);
+ super("android.widget.cts", GridViewCtsActivity.class);
}
private GridView findGridViewById(int id) {
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java
index 312111a..a10e63a 100644
--- a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
index 36398c3..1149d3b 100644
--- a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -54,7 +54,7 @@
private Activity mActivity;
public HorizontalScrollViewTest() {
- super("com.android.cts.widget", HorizontalScrollViewCtsActivity.class);
+ super("android.widget.cts", HorizontalScrollViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
index 374c9c2..05c0e3f 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java b/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java
index 95f8d0c..a7bca5c 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/ImageViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ImageViewCtsActivity.java
index 295f3da..e68c986 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
index 8b50e2c..e0d821d 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
@@ -49,7 +49,7 @@
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
@@ -60,7 +60,7 @@
private Activity mActivity;
public ImageViewTest() {
- super("com.android.cts.widget", ImageViewCtsActivity.class);
+ super("android.widget.cts", ImageViewCtsActivity.class);
}
/**
diff --git a/tests/tests/widget/src/android/widget/cts/LayoutDirectionCtsActivity.java b/tests/tests/widget/src/android/widget/cts/LayoutDirectionCtsActivity.java
index 093f554..755091d 100644
--- a/tests/tests/widget/src/android/widget/cts/LayoutDirectionCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/LayoutDirectionCtsActivity.java
@@ -18,7 +18,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* A minimal application for layout direction test.
diff --git a/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java b/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java
index c393e95..2369c5a 100644
--- a/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java
@@ -20,7 +20,7 @@
import android.test.UiThreadTest;
import android.view.ViewGroup;
import android.widget.*;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import static android.view.View.LAYOUT_DIRECTION_LTR;
import static android.view.View.LAYOUT_DIRECTION_RTL;
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayoutCtsActivity.java b/tests/tests/widget/src/android/widget/cts/LinearLayoutCtsActivity.java
index 0cb5bc0..4a04b52 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayoutCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayoutCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
index 5815f9a..76fa782 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
@@ -16,6 +16,9 @@
package android.widget.cts;
+import android.graphics.Color;
+import android.view.View;
+import android.view.ViewTreeObserver;
import org.xmlpull.v1.XmlPullParser;
import android.app.Activity;
@@ -31,7 +34,10 @@
import android.widget.ListView;
import android.widget.TextView;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Test {@link LinearLayout}.
@@ -41,7 +47,7 @@
private Activity mActivity;
public LinearLayoutTest() {
- super("com.android.cts.widget", LinearLayoutCtsActivity.class);
+ super("android.widget.cts", LinearLayoutCtsActivity.class);
}
@Override
@@ -327,6 +333,78 @@
assertEquals(parent.getWidth(), rightView.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) {
+ viewGroup.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ assertEquals(left, view.getLeft());
+ assertEquals(top, view.getTop());
+ assertEquals(width, view.getWidth());
+ assertEquals(height, view.getHeight());
+ countDownLatch.countDown();
+ viewGroup.getViewTreeObserver().removeOnPreDrawListener(this);
+ return true;
+ }
+ });
+ }
+
+ public void testVisibilityAffectsLayout() throws Throwable {
+ // Toggling view visibility between GONE/VISIBLE can affect the position of
+ // other children in that container. This test verifies that these changes
+ // on the first child of a LinearLayout affects the position of a second child
+ final int childWidth = 100;
+ final int childHeight = 200;
+ final LinearLayout parent = new LinearLayout(mActivity);
+ ViewGroup.LayoutParams parentParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ parent.setLayoutParams(parentParams);
+ final View child1 = new View(mActivity);
+ child1.setBackgroundColor(Color.GREEN);
+ ViewGroup.LayoutParams childParams = new ViewGroup.LayoutParams(childWidth, childHeight);
+ child1.setLayoutParams(childParams);
+ final View child2 = new View(mActivity);
+ child2.setBackgroundColor(Color.RED);
+ childParams = new ViewGroup.LayoutParams(childWidth, childHeight);
+ child2.setLayoutParams(childParams);
+ final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.linearlayout_root);
+
+ final CountDownLatch countDownLatch1 = new CountDownLatch(1);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ viewGroup.removeAllViews();
+ viewGroup.addView(parent);
+ parent.addView(child1);
+ parent.addView(child2);
+ checkBounds(viewGroup, child1, countDownLatch1, 0, 0, childWidth, childHeight);
+ checkBounds(viewGroup, child2, countDownLatch1,
+ childWidth, 0, childWidth, childHeight);
+ }
+ });
+ countDownLatch1.await(500, TimeUnit.MILLISECONDS);
+
+ final CountDownLatch countDownLatch2 = new CountDownLatch(1);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ child1.setVisibility(View.GONE);
+ checkBounds(viewGroup, child2, countDownLatch2, 0, 0, childWidth, childHeight);
+ }
+ });
+ countDownLatch2.await(500, TimeUnit.MILLISECONDS);
+
+ final CountDownLatch countDownLatch3 = new CountDownLatch(2);
+ runTestOnUiThread(new Runnable() {
+ public void run() {
+ child1.setVisibility(View.VISIBLE);
+ checkBounds(viewGroup, child1, countDownLatch3, 0, 0, childWidth, childHeight);
+ checkBounds(viewGroup, child2, countDownLatch3,
+ childWidth, 0, childWidth, childHeight);
+ }
+ });
+ countDownLatch3.await(500, TimeUnit.MILLISECONDS);
+ }
+
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 31be765..4f36e94 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
index c4636fc..5856910 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.app.Instrumentation;
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ListViewCtsActivity.java
index 186e47b..ce198b3 100644
--- a/tests/tests/widget/src/android/widget/cts/ListViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ListViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewTest.java b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
index 838f7a8..e311cc7 100644
--- a/tests/tests/widget/src/android/widget/cts/ListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -37,6 +37,7 @@
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnDrawListener;
import android.view.animation.LayoutAnimationController;
import android.widget.AbsListView;
import android.widget.AdapterView;
@@ -69,7 +70,7 @@
private ArrayAdapter<String> mAdapter_empty;
public ListViewTest() {
- super("com.android.cts.widget", ListViewCtsActivity.class);
+ super("android.widget.cts", ListViewCtsActivity.class);
}
protected void setUp() throws Exception {
@@ -137,8 +138,11 @@
}
public void testAccessDividerHeight() {
+ final HasDrawnListener drawListener = new HasDrawnListener();
+
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
+ mListView.getViewTreeObserver().addOnDrawListener(drawListener);
mListView.setAdapter(mAdapter_countries);
}
});
@@ -155,23 +159,44 @@
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
+ drawListener.reset();
mListView.setDividerHeight(20);
}
});
mInstrumentation.waitForIdleSync();
+ assertTrue(drawListener.hasDrawn());
assertEquals(20, mListView.getDividerHeight());
assertEquals(20, r.bottom - r.top);
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
+ drawListener.reset();
mListView.setDividerHeight(10);
}
});
mInstrumentation.waitForIdleSync();
+ assertTrue(drawListener.hasDrawn());
assertEquals(10, mListView.getDividerHeight());
assertEquals(10, r.bottom - r.top);
}
+ static class HasDrawnListener implements OnDrawListener {
+ private boolean mHasDrawn;
+
+ @Override
+ public void onDraw() {
+ mHasDrawn = true;
+ }
+
+ public boolean hasDrawn() {
+ return mHasDrawn;
+ }
+
+ public void reset() {
+ mHasDrawn = false;
+ }
+ }
+
public void testAccessItemsCanFocus() {
mListView.setItemsCanFocus(true);
assertTrue(mListView.getItemsCanFocus());
diff --git a/tests/tests/widget/src/android/widget/cts/MediaControllerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/MediaControllerCtsActivity.java
index 5dfcc59..ac8f100 100644
--- a/tests/tests/widget/src/android/widget/cts/MediaControllerCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/MediaControllerCtsActivity.java
@@ -20,7 +20,7 @@
import android.os.Bundle;
import android.widget.MediaController;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* A minimal application for {@link MediaController} test.
diff --git a/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java b/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
index 9f3aa55..713604d 100644
--- a/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -50,7 +50,7 @@
private static final long DEFAULT_TIMEOUT = 3000;
public MediaControllerTest() {
- super("com.android.cts.widget", MediaControllerCtsActivity.class);
+ super("android.widget.cts", MediaControllerCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/MockPopupWindowCtsActivity.java b/tests/tests/widget/src/android/widget/cts/MockPopupWindowCtsActivity.java
index 9589fec..5d22fe5 100755
--- a/tests/tests/widget/src/android/widget/cts/MockPopupWindowCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/MockPopupWindowCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/MockURLSpanTestActivity.java b/tests/tests/widget/src/android/widget/cts/MockURLSpanTestActivity.java
index ab4940c..3d27f9a 100644
--- a/tests/tests/widget/src/android/widget/cts/MockURLSpanTestActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/MockURLSpanTestActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewCtsActivity.java
index 1379150..b5de67b 100644
--- a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
index 4afdb80..5c18030 100644
--- a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -44,7 +44,7 @@
private Activity mActivity;
public MultiAutoCompleteTextViewTest() {
- super("com.android.cts.widget", MultiAutoCompleteTextViewCtsActivity.class);
+ super("android.widget.cts", MultiAutoCompleteTextViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
index 2dff4cb..206b794 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import static org.mockito.Mockito.*;
import android.app.Activity;
import android.app.Instrumentation;
@@ -24,6 +24,7 @@
import android.view.Gravity;
import android.widget.PopupMenu;
+import android.widget.cts.R;
public class PopupMenuTest extends
ActivityInstrumentationTestCase2<MockPopupWindowCtsActivity> {
@@ -31,7 +32,7 @@
private Activity mActivity;
public PopupMenuTest() {
- super("com.android.cts.widget", MockPopupWindowCtsActivity.class);
+ super("android.widget.cts", MockPopupWindowCtsActivity.class);
}
@Override
@@ -45,6 +46,7 @@
PopupMenu popupMenu = new PopupMenu(mActivity,
mActivity.findViewById(R.id.anchor_middle_left));
assertEquals(Gravity.NO_GRAVITY, popupMenu.getGravity());
+
popupMenu.setGravity(Gravity.TOP);
assertEquals(Gravity.TOP, popupMenu.getGravity());
}
@@ -52,7 +54,7 @@
public void testOnDismissListener() {
final PopupMenu popupMenu = new PopupMenu(mActivity,
mActivity.findViewById(R.id.anchor_middle_left));
- TestPopupDismissListener listener = new TestPopupDismissListener();
+ PopupMenu.OnDismissListener listener = mock(PopupMenu.OnDismissListener.class);
popupMenu.setOnDismissListener(listener);
mInstrumentation.runOnMainSync(new Runnable() {
@@ -61,7 +63,7 @@
}
});
mInstrumentation.waitForIdleSync();
- assertEquals(0, listener.getDismissCount());
+ verify(listener, never()).onDismiss(popupMenu);
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
@@ -69,7 +71,7 @@
}
});
mInstrumentation.waitForIdleSync();
- assertEquals(1, listener.getDismissCount());
+ verify(listener, times(1)).onDismiss(popupMenu);
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
@@ -77,19 +79,6 @@
}
});
mInstrumentation.waitForIdleSync();
- assertEquals(1, listener.getDismissCount());
- }
-
- private class TestPopupDismissListener implements PopupMenu.OnDismissListener {
- int mDismissCount;
-
- @Override
- public void onDismiss(PopupMenu menu) {
- mDismissCount++;
- }
-
- int getDismissCount() {
- return mDismissCount;
- }
+ verify(listener, times(1)).onDismiss(popupMenu);
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index bb638e4..ff580e3 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -16,8 +16,9 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import static org.mockito.Mockito.*;
+import org.mockito.InOrder;
import android.app.Activity;
import android.app.Instrumentation;
@@ -25,24 +26,26 @@
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.os.Debug;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.transition.Transition;
+import android.transition.Transition.TransitionListener;
import android.transition.TransitionValues;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.WindowManager;
import android.widget.ImageView;
+import android.widget.PopupWindow.OnDismissListener;
import android.widget.PopupWindow;
import android.widget.TextView;
-import android.widget.PopupWindow.OnDismissListener;
+
+import android.widget.cts.R;
public class PopupWindowTest extends
ActivityInstrumentationTestCase2<MockPopupWindowCtsActivity> {
@@ -55,7 +58,7 @@
* Instantiates a new popup window test.
*/
public PopupWindowTest() {
- super("com.android.cts.widget", MockPopupWindowCtsActivity.class);
+ super("android.widget.cts", MockPopupWindowCtsActivity.class);
}
/*
@@ -425,20 +428,20 @@
mPopupWindow = new PopupWindow(new TextView(mActivity));
mPopupWindow.setOnDismissListener(null);
- MockOnDismissListener onDismissListener = new MockOnDismissListener();
+ OnDismissListener onDismissListener = mock(OnDismissListener.class);
mPopupWindow.setOnDismissListener(onDismissListener);
showPopup();
dismissPopup();
- assertEquals(1, onDismissListener.getOnDismissCalledCount());
+ verify(onDismissListener, times(1)).onDismiss();
showPopup();
dismissPopup();
- assertEquals(2, onDismissListener.getOnDismissCalledCount());
+ verify(onDismissListener, times(2)).onDismiss();
mPopupWindow.setOnDismissListener(null);
showPopup();
dismissPopup();
- assertEquals(2, onDismissListener.getOnDismissCalledCount());
+ verify(onDismissListener, times(2)).onDismiss();
}
public void testUpdate() {
@@ -485,23 +488,34 @@
}
public void testEnterExitTransition() {
- mPopupWindow = createPopupWindow(createPopupContent());
- final View anchorView = mActivity.findViewById(R.id.anchor_upper);
+ TransitionListener enterListener = mock(TransitionListener.class);
+ Transition enterTransition = new BaseTransition();
+ enterTransition.addListener(enterListener);
- final MockTransition enterTransition = new MockTransition();
- final MockTransition exitTransition = new MockTransition();
+ TransitionListener exitListener = mock(TransitionListener.class);
+ Transition exitTransition = new BaseTransition();
+ enterTransition.addListener(enterListener);
+
+ OnDismissListener dismissListener = mock(OnDismissListener.class);
+
+ mPopupWindow = createPopupWindow(createPopupContent());
mPopupWindow.setEnterTransition(enterTransition);
mPopupWindow.setExitTransition(exitTransition);
+ mPopupWindow.setOnDismissListener(dismissListener);
+ verify(enterListener, never()).onTransitionStart(any(Transition.class));
+ verify(exitListener, never()).onTransitionStart(any(Transition.class));
+ verify(dismissListener, never()).onDismiss();
+ final View anchorView = mActivity.findViewById(R.id.anchor_upper);
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
mPopupWindow.showAsDropDown(anchorView, 0, 0);
}
});
mInstrumentation.waitForIdleSync();
-
- assertEquals(1, enterTransition.getTransitionCount());
- assertEquals(0, exitTransition.getTransitionCount());
+ verify(enterListener, times(1)).onTransitionStart(enterTransition);
+ verify(exitListener, never()).onTransitionStart(any(Transition.class));
+ verify(dismissListener, never()).onDismiss();
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
@@ -509,9 +523,13 @@
}
});
mInstrumentation.waitForIdleSync();
+ verify(enterListener, times(1)).onTransitionStart(enterTransition);
+ verify(exitListener, times(1)).onTransitionStart(exitTransition);
+ verify(dismissListener, times(1)).onDismiss();
- assertEquals(1, enterTransition.getTransitionCount());
- assertEquals(1, exitTransition.getTransitionCount());
+ InOrder inOrder = inOrder(exitListener, dismissListener);
+ inOrder.verify(exitListener).onTransitionEnd(exitTransition);
+ inOrder.verify(dismissListener).onDismiss();
}
public void testUpdatePositionAndDimension() {
@@ -774,7 +792,9 @@
public void testSetTouchInterceptor() {
mPopupWindow = new PopupWindow(new TextView(mActivity));
- MockOnTouchListener onTouchListener = new MockOnTouchListener();
+ OnTouchListener onTouchListener = mock(OnTouchListener.class);
+ when(onTouchListener.onTouch(any(View.class), any(MotionEvent.class))).thenReturn(true);
+
mPopupWindow.setTouchInterceptor(onTouchListener);
mPopupWindow.setFocusable(true);
mPopupWindow.setOutsideTouchable(true);
@@ -794,20 +814,20 @@
MotionEvent event = MotionEvent.obtain(downTime, eventTime,
MotionEvent.ACTION_DOWN, x, y, 0);
getInstrumentation().sendPointerSync(event);
- assertEquals(1, onTouchListener.getOnTouchCalledCount());
+ verify(onTouchListener, times(1)).onTouch(any(View.class), any(MotionEvent.class));
downTime = SystemClock.uptimeMillis();
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
getInstrumentation().sendPointerSync(event);
- assertEquals(2, onTouchListener.getOnTouchCalledCount());
+ verify(onTouchListener, times(2)).onTouch(any(View.class), any(MotionEvent.class));
mPopupWindow.setTouchInterceptor(null);
downTime = SystemClock.uptimeMillis();
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
getInstrumentation().sendPointerSync(event);
- assertEquals(2, onTouchListener.getOnTouchCalledCount());
+ verify(onTouchListener, times(2)).onTouch(any(View.class), any(MotionEvent.class));
}
public void testSetWindowLayoutMode() {
@@ -829,107 +849,12 @@
assertEquals(LayoutParams.MATCH_PARENT, p.height);
}
- /**
- * The listener interface for receiving OnDismiss events. The class that is
- * interested in processing a OnDismiss event implements this interface, and
- * the object created with that class is registered with a component using
- * the component's <code>setOnDismissListener<code> method. When
- * the OnDismiss event occurs, that object's appropriate
- * method is invoked.
- */
- private static class MockOnDismissListener implements OnDismissListener {
+ private static class BaseTransition extends Transition {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {}
- /** The Ondismiss called count. */
- private int mOnDismissCalledCount;
-
- /**
- * Gets the onDismiss() called count.
- *
- * @return the on dismiss called count
- */
- public int getOnDismissCalledCount() {
- return mOnDismissCalledCount;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.widget.PopupWindow.OnDismissListener#onDismiss()
- */
- public void onDismiss() {
- mOnDismissCalledCount++;
- }
-
- }
-
- /**
- * The listener interface for receiving touch events.
- */
- private static class MockOnTouchListener implements OnTouchListener {
-
- /** The onTouch called count. */
- private int mOnTouchCalledCount;
-
- /**
- * Gets the onTouch() called count.
- *
- * @return the onTouch() called count
- */
- public int getOnTouchCalledCount() {
- return mOnTouchCalledCount;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.widget.PopupWindow.OnTouchListener#onDismiss()
- */
- public boolean onTouch(View v, MotionEvent event) {
- mOnTouchCalledCount++;
- return true;
- }
- }
-
- private static class MockTransition extends Transition {
- private int mTransitionCount;
-
- private MockTransition() {
- addListener(new Transition.TransitionListener() {
- @Override
- public void onTransitionStart(Transition transition) {
-
- }
-
- public void onTransitionEnd(Transition transition) {
- mTransitionCount++;
- }
-
- @Override
- public void onTransitionCancel(Transition transition) {
-
- }
-
- @Override
- public void onTransitionPause(Transition transition) {
-
- }
-
- @Override
- public void onTransitionResume(Transition transition) {
-
- }
- });
- }
-
- public void captureStartValues(TransitionValues transitionValues) {
- }
-
- public void captureEndValues(TransitionValues transitionValues) {
- }
-
- int getTransitionCount() {
- return mTransitionCount;
- }
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {}
}
private View createPopupContent() {
@@ -953,11 +878,6 @@
return window;
}
- /**
- * Show PopupWindow.
- */
- // FIXME: logcat info complains that there is window leakage due to that mPopupWindow is not
- // clean up. Need to fix it.
private void showPopup() {
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
@@ -972,14 +892,12 @@
mInstrumentation.waitForIdleSync();
}
- /**
- * Dismiss PopupWindow.
- */
private void dismissPopup() {
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
- if (mPopupWindow == null || !mPopupWindow.isShowing())
+ if (mPopupWindow == null || !mPopupWindow.isShowing()) {
return;
+ }
mPopupWindow.dismiss();
}
});
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
index e57d298..fd19191 100644
--- a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
@@ -21,7 +21,7 @@
import android.graphics.PorterDuff;
import android.view.LayoutInflater;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
index 4ec4eb5..eb9387b 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
diff --git a/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java b/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
index a172ecb..b2154e2 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/RadioGroup_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/RadioGroup_LayoutParamsTest.java
index b14c0e8..37cd632 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioGroup_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioGroup_LayoutParamsTest.java
@@ -114,7 +114,7 @@
}
mLayoutParams = new LayoutParams(getContext(),
- getAttributeSet(com.android.cts.widget.R.layout.radiogroup_1));
+ getAttributeSet(android.widget.cts.R.layout.radiogroup_1));
assertNotNull(mLayoutParams);
assertEquals(0.5, mLayoutParams.weight, 0);
assertEquals(Gravity.BOTTOM, mLayoutParams.gravity);
@@ -131,7 +131,7 @@
try {
new RadioGroup.LayoutParams(null,
- getAttributeSet(com.android.cts.widget.R.layout.radiogroup_1));
+ getAttributeSet(android.widget.cts.R.layout.radiogroup_1));
fail("The constructor should throw NullPointerException when param Context is null.");
} catch (NullPointerException e) {
}
@@ -143,7 +143,7 @@
assertEquals(LayoutParams.WRAP_CONTENT, layoutParams.width);
assertEquals(LayoutParams.WRAP_CONTENT, layoutParams.height);
- AttributeSet attrs = getAttributeSet(com.android.cts.widget.R.layout.radiogroup_1);
+ AttributeSet attrs = getAttributeSet(android.widget.cts.R.layout.radiogroup_1);
TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout);
layoutParams.setBaseAttributes(a,
R.styleable.ViewGroup_MarginLayout_layout_width,
diff --git a/tests/tests/widget/src/android/widget/cts/RatingBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RatingBarCtsActivity.java
index 7d4e232..1a9cb40 100644
--- a/tests/tests/widget/src/android/widget/cts/RatingBarCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/RatingBarCtsActivity.java
@@ -19,7 +19,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* An application for ProgressBar test
diff --git a/tests/tests/widget/src/android/widget/cts/RatingBarTest.java b/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
index 211d7fe..669e7a1 100644
--- a/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
import android.test.ActivityInstrumentationTestCase2;
@@ -32,7 +32,7 @@
private RatingBarCtsActivity mActivity;
public RatingBarTest() {
- super("com.android.cts.widget", RatingBarCtsActivity.class);
+ super("android.widget.cts", RatingBarCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayoutCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RelativeLayoutCtsActivity.java
index df83f54..c394ca4 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayoutCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayoutCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
index b228ca6..cd3cb09 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -46,7 +46,7 @@
private Activity mActivity;
public RelativeLayoutTest() {
- super("com.android.cts.widget", RelativeLayoutCtsActivity.class);
+ super("android.widget.cts", RelativeLayoutCtsActivity.class);
}
@Override
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 07c7b77..5706781 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
@@ -16,10 +16,11 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.test.ActivityInstrumentationTestCase2;
import android.test.ViewAsserts;
+import android.util.LayoutDirection;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.RelativeLayout;
@@ -31,7 +32,7 @@
ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
public RelativeLayout_LayoutParamsTest() {
- super("com.android.cts.widget", RelativeLayoutCtsActivity.class);
+ super("android.widget.cts", RelativeLayoutCtsActivity.class);
}
public void testConstructor() {
@@ -415,6 +416,29 @@
assertEquals(Integer.MIN_VALUE, rules[RelativeLayout.ALIGN_LEFT]);
}
+ public void testRemoveRule() {
+ RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(200, 300);
+
+ layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START, RelativeLayout.TRUE);
+ layoutParams.resolveLayoutDirection(LayoutDirection.LTR);
+ assertEquals(0, layoutParams.getRule(RelativeLayout.ALIGN_PARENT_START));
+ assertEquals(RelativeLayout.TRUE, layoutParams.getRule(RelativeLayout.ALIGN_PARENT_LEFT));
+ assertEquals(0, layoutParams.getRule(RelativeLayout.CENTER_HORIZONTAL));
+
+ layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
+ layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
+ layoutParams.resolveLayoutDirection(LayoutDirection.LTR);
+ assertEquals(0, layoutParams.getRule(RelativeLayout.ALIGN_PARENT_START));
+ assertEquals(0, layoutParams.getRule(RelativeLayout.ALIGN_PARENT_LEFT));
+ assertEquals(RelativeLayout.TRUE, layoutParams.getRule(RelativeLayout.CENTER_HORIZONTAL));
+
+ layoutParams.removeRule(RelativeLayout.CENTER_HORIZONTAL);
+ layoutParams.resolveLayoutDirection(LayoutDirection.LTR);
+ assertEquals(0, layoutParams.getRule(RelativeLayout.ALIGN_PARENT_START));
+ assertEquals(0, layoutParams.getRule(RelativeLayout.ALIGN_PARENT_LEFT));
+ assertEquals(0, layoutParams.getRule(RelativeLayout.CENTER_HORIZONTAL));
+ }
+
public void testDebug() {
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(200, 300);
assertNotNull(layoutParams.debug("test: "));
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
index ab109b1..369d7aa 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
@@ -26,11 +26,11 @@
import android.view.ViewGroup;
import android.widget.RemoteViews;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
public class RemoteViewsActivityTest
extends ActivityInstrumentationTestCase2<RemoteViewsCtsActivity> {
- private static final String PACKAGE_NAME = "com.android.cts.widget";
+ private static final String PACKAGE_NAME = "android.widget.cts";
private Activity mActivity;
public RemoteViewsActivityTest() {
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java
index 4da5aa2..64001dc 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.cts.util.NullWebViewUtils;
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
index 18bac7e..605dbb6 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
@@ -18,7 +18,7 @@
import android.graphics.drawable.Icon;
import android.test.UiThreadTest;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
@@ -59,7 +59,7 @@
* Test {@link RemoteViews}.
*/
public class RemoteViewsTest extends ActivityInstrumentationTestCase2<RemoteViewsCtsActivity> {
- private static final String PACKAGE_NAME = "com.android.cts.widget";
+ private static final String PACKAGE_NAME = "android.widget.cts";
private static final int INVALD_ID = -1;
diff --git a/tests/tests/widget/src/android/widget/cts/ResourceCursorAdapterTest.java b/tests/tests/widget/src/android/widget/cts/ResourceCursorAdapterTest.java
index 580be27..aefca0f 100644
--- a/tests/tests/widget/src/android/widget/cts/ResourceCursorAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ResourceCursorAdapterTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
diff --git a/tests/tests/widget/src/android/widget/cts/ResourceCursorTreeAdapterTest.java b/tests/tests/widget/src/android/widget/cts/ResourceCursorTreeAdapterTest.java
index 760f7e4..e801e93 100644
--- a/tests/tests/widget/src/android/widget/cts/ResourceCursorTreeAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ResourceCursorTreeAdapterTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
diff --git a/tests/tests/widget/src/android/widget/cts/ScrollViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ScrollViewCtsActivity.java
index 8965610..b2b51c6 100644
--- a/tests/tests/widget/src/android/widget/cts/ScrollViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ScrollViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
index a8fb224..0119cc0 100644
--- a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -61,7 +61,7 @@
private Activity mActivity;
public ScrollViewTest() {
- super("com.android.cts.widget", ScrollViewCtsActivity.class);
+ super("android.widget.cts", ScrollViewCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
index e7842c2..e22b910 100644
--- a/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/SeekBarTest.java b/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
index 43aada2..b9ad733 100644
--- a/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
@@ -38,7 +38,7 @@
private Instrumentation mInstrumentation;
public SeekBarTest() {
- super("com.android.cts.widget", SeekBarCtsActivity.class);
+ super("android.widget.cts", SeekBarCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java
index 28ff15e..5a9af25 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java
@@ -92,7 +92,7 @@
mContext = getInstrumentation().getTargetContext();
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mAdapterHost = (LinearLayout) mInflater.inflate(
- com.android.cts.widget.R.layout.cursoradapter_host, null);
+ android.widget.cts.R.layout.cursoradapter_host, null);
// new the SimpleAdapter instance
mSimpleAdapter = new SimpleAdapter(mContext,
@@ -289,9 +289,9 @@
// String represents resId
ImageView view = new ImageView(mContext);
assertNull(view.getDrawable());
- mSimpleAdapter.setViewImage(view, String.valueOf(com.android.cts.widget.R.drawable.scenery));
+ mSimpleAdapter.setViewImage(view, String.valueOf(android.widget.cts.R.drawable.scenery));
BitmapDrawable d = (BitmapDrawable) mContext.getResources().getDrawable(
- com.android.cts.widget.R.drawable.scenery);
+ android.widget.cts.R.drawable.scenery);
WidgetTestUtils.assertEquals(d.getBitmap(),
((BitmapDrawable) view.getDrawable()).getBitmap());
@@ -314,9 +314,9 @@
// resId
view = new ImageView(mContext);
assertNull(view.getDrawable());
- mSimpleAdapter.setViewImage(view, com.android.cts.widget.R.drawable.scenery);
+ mSimpleAdapter.setViewImage(view, android.widget.cts.R.drawable.scenery);
d = (BitmapDrawable) mContext.getResources()
- .getDrawable(com.android.cts.widget.R.drawable.scenery);
+ .getDrawable(android.widget.cts.R.drawable.scenery);
WidgetTestUtils.assertEquals(d.getBitmap(),
((BitmapDrawable) view.getDrawable()).getBitmap());
@@ -331,11 +331,11 @@
assertNull(view.getDrawable());
try {
mSimpleAdapter.setViewImage(view, SimpleCursorAdapterTest.createTestImage(mContext,
- "testimage", com.android.cts.widget.R.raw.testimage));
+ "testimage", android.widget.cts.R.raw.testimage));
assertNotNull(view.getDrawable());
Bitmap actualBitmap = ((BitmapDrawable) view.getDrawable()).getBitmap();
Bitmap testBitmap = WidgetTestUtils.getUnscaledAndDitheredBitmap(mContext.getResources(),
- com.android.cts.widget.R.raw.testimage, actualBitmap.getConfig());
+ android.widget.cts.R.raw.testimage, actualBitmap.getConfig());
WidgetTestUtils.assertEquals(testBitmap, actualBitmap);
} finally {
SimpleCursorAdapterTest.destroyTestImage(mContext,"testimage");
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java
index 13184de..f7f24da 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
@@ -185,7 +185,7 @@
public void testSetViewImage() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
// resId
- int sceneryImgResId = com.android.cts.widget.R.drawable.scenery;
+ int sceneryImgResId = android.widget.cts.R.drawable.scenery;
ImageView view = new ImageView(mContext);
assertNull(view.getDrawable());
simpleCursorAdapter.setViewImage(view, String.valueOf(sceneryImgResId));
@@ -216,7 +216,7 @@
view = new ImageView(mContext);
assertNull(view.getDrawable());
try {
- int testimgRawId = com.android.cts.widget.R.raw.testimage;
+ int testimgRawId = android.widget.cts.R.raw.testimage;
simpleCursorAdapter.setViewImage(view,
createTestImage(mContext, SAMPLE_IMAGE_NAME, testimgRawId));
assertNotNull(view.getDrawable());
@@ -327,7 +327,7 @@
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
- com.android.cts.widget.R.layout.cursoradapter_host, null);
+ android.widget.cts.R.layout.cursoradapter_host, null);
View result = simpleCursorAdapter.newView(mContext, null, viewGroup);
assertNotNull(result);
assertEquals(R.id.cursorAdapter_item0, result.getId());
@@ -343,7 +343,7 @@
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
- com.android.cts.widget.R.layout.cursoradapter_host, null);
+ android.widget.cts.R.layout.cursoradapter_host, null);
View result = simpleCursorAdapter.newDropDownView(null, null, viewGroup);
assertNotNull(result);
assertEquals(R.id.cursorAdapter_item0, result.getId());
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java
index c9fdbc3..02941fa 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
@@ -136,9 +136,9 @@
ImageView view = new ImageView(mContext);
assertNull(view.getDrawable());
mSimpleCursorTreeAdapter.setViewImage(view,
- String.valueOf(com.android.cts.widget.R.drawable.scenery));
+ String.valueOf(android.widget.cts.R.drawable.scenery));
BitmapDrawable d = (BitmapDrawable) mContext.getResources().getDrawable(
- com.android.cts.widget.R.drawable.scenery);
+ android.widget.cts.R.drawable.scenery);
WidgetTestUtils.assertEquals(d.getBitmap(),
((BitmapDrawable) view.getDrawable()).getBitmap());
@@ -164,10 +164,10 @@
try {
mSimpleCursorTreeAdapter.setViewImage(view,
SimpleCursorAdapterTest.createTestImage(mContext, SAMPLE_IMAGE_NAME,
- com.android.cts.widget.R.raw.testimage));
+ android.widget.cts.R.raw.testimage));
Bitmap actualBitmap = ((BitmapDrawable) view.getDrawable()).getBitmap();
Bitmap test = WidgetTestUtils.getUnscaledAndDitheredBitmap(mContext.getResources(),
- com.android.cts.widget.R.raw.testimage, actualBitmap.getConfig());
+ android.widget.cts.R.raw.testimage, actualBitmap.getConfig());
WidgetTestUtils.assertEquals(test, actualBitmap);
} finally {
SimpleCursorAdapterTest.destroyTestImage(mContext, SAMPLE_IMAGE_NAME);
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleExpandableListAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleExpandableListAdapterTest.java
index d1c63c0..674f427 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleExpandableListAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleExpandableListAdapterTest.java
@@ -98,7 +98,7 @@
mAdapterHost = (LinearLayout) ((LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
- com.android.cts.widget.R.layout.cursoradapter_host, null);
+ android.widget.cts.R.layout.cursoradapter_host, null);
}
public void testConstructor() {
diff --git a/tests/tests/widget/src/android/widget/cts/SlidingDrawerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SlidingDrawerCtsActivity.java
index 8b55e63..d1362c1 100644
--- a/tests/tests/widget/src/android/widget/cts/SlidingDrawerCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/SlidingDrawerCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java b/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
index 862fccf..2af1b06 100644
--- a/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -51,7 +51,7 @@
private Object mLock;
public SlidingDrawerTest() {
- super("com.android.cts.widget", SlidingDrawerCtsActivity.class);
+ super("android.widget.cts", SlidingDrawerCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
index ea37470..eea1e3e 100644
--- a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.AlertDialog;
@@ -37,7 +37,7 @@
private Context mTargetContext;
public SpinnerTest() {
- super("com.android.cts.widget", RelativeLayoutCtsActivity.class);
+ super("android.widget.cts", RelativeLayoutCtsActivity.class);
}
@Override
@@ -77,7 +77,7 @@
spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mTargetContext,
- com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
+ android.widget.cts.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);
diff --git a/tests/tests/widget/src/android/widget/cts/SwitchTest.java b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
index 164e7bf..e1124f3 100644
--- a/tests/tests/widget/src/android/widget/cts/SwitchTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
import android.content.res.ColorStateList;
diff --git a/tests/tests/widget/src/android/widget/cts/TabHostCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TabHostCtsActivity.java
index 9703dd7..189dbee 100644
--- a/tests/tests/widget/src/android/widget/cts/TabHostCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/TabHostCtsActivity.java
@@ -22,7 +22,7 @@
import android.widget.TabHost;
import android.widget.TextView;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* A minimal application for TabHost test.
diff --git a/tests/tests/widget/src/android/widget/cts/TabHostTest.java b/tests/tests/widget/src/android/widget/cts/TabHostTest.java
index 00ecd40..0544c24 100644
--- a/tests/tests/widget/src/android/widget/cts/TabHostTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TabHostTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
@@ -43,7 +43,7 @@
private TabHostCtsActivity mActivity;
public TabHostTest() {
- super("com.android.cts.widget", TabHostCtsActivity.class);
+ super("android.widget.cts", TabHostCtsActivity.class);
}
@Override
@@ -72,7 +72,7 @@
* 2. no exception occurs when doing normal operation after setup().
*/
public void testSetup1() throws Throwable {
- final Activity activity = launchActivity("com.android.cts.widget", CtsActivity.class, null);
+ final Activity activity = launchActivity("android.widget.cts", CtsActivity.class, null);
runTestOnUiThread(new Runnable() {
public void run() {
@@ -103,7 +103,7 @@
* 2. no exception occurs when uses TabSpec.setContent(android.content.Intent) after setup().
*/
public void testSetup2() throws Throwable {
- final ActivityGroup activity = launchActivity("com.android.cts.widget",
+ final ActivityGroup activity = launchActivity("android.widget.cts",
ActivityGroup.class, null);
diff --git a/tests/tests/widget/src/android/widget/cts/TabHost_TabSpecTest.java b/tests/tests/widget/src/android/widget/cts/TabHost_TabSpecTest.java
index 5745808..e8825c7 100644
--- a/tests/tests/widget/src/android/widget/cts/TabHost_TabSpecTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TabHost_TabSpecTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
@@ -46,7 +46,7 @@
private TabHostCtsActivity mActivity;
public TabHost_TabSpecTest() {
- super("com.android.cts.widget", TabHostCtsActivity.class);
+ super("android.widget.cts", TabHostCtsActivity.class);
}
@Override
@@ -137,7 +137,7 @@
TabSpec tabSpec2 = mTabHost.newTabSpec("tab spec 2");
tabSpec2.setIndicator("tab 2");
// TabContentFactory to create a TextView as the content of the tab.
- tabSpec2.setContent(com.android.cts.widget.R.id.tabhost_textview);
+ tabSpec2.setContent(android.widget.cts.R.id.tabhost_textview);
mTabHost.addTab(tabSpec2);
mTabHost.setCurrentTab(1);
TextView currentView = (TextView) mTabHost.getCurrentView();
@@ -147,7 +147,7 @@
TabSpec tabSpec3 = mTabHost.newTabSpec("tab spec 3");
tabSpec3.setIndicator("tab 3");
// TabContentFactory to create a ListView as the content of the tab.
- tabSpec3.setContent(com.android.cts.widget.R.id.tabhost_listview);
+ tabSpec3.setContent(android.widget.cts.R.id.tabhost_listview);
mTabHost.addTab(tabSpec3);
mTabHost.setCurrentTab(2);
assertTrue(mTabHost.getCurrentView() instanceof ListView);
diff --git a/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java b/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java
index 1f2e66c..f44117a 100644
--- a/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java
@@ -36,7 +36,7 @@
private Activity mActivity;
public TabWidgetTest() {
- super("com.android.cts.widget", TabHostCtsActivity.class);
+ super("android.widget.cts", TabHostCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/TableCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TableCtsActivity.java
index f76caed..490d261 100644
--- a/tests/tests/widget/src/android/widget/cts/TableCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/TableCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java b/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
index b9f0d1f..ccf22d9 100644
--- a/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.content.Context;
import android.content.res.XmlResourceParser;
@@ -42,7 +42,7 @@
private Context mContext;
public TableLayoutTest() {
- super("com.android.cts.widget", TableCtsActivity.class);
+ super("android.widget.cts", TableCtsActivity.class);
}
@Override
@@ -58,14 +58,14 @@
new TableLayout(mContext, null);
TableCtsActivity activity = getActivity();
- activity.setContentView(com.android.cts.widget.R.layout.table_layout_1);
+ activity.setContentView(android.widget.cts.R.layout.table_layout_1);
TableLayout tableLayout = (TableLayout) activity
- .findViewById(com.android.cts.widget.R.id.table1);
+ .findViewById(android.widget.cts.R.id.table1);
assertTrue(tableLayout.isColumnCollapsed(0));
assertTrue(tableLayout.isColumnStretchable(2));
- activity.setContentView(com.android.cts.widget.R.layout.table_layout_2);
- tableLayout = (TableLayout) activity.findViewById(com.android.cts.widget.R.id.table2);
+ activity.setContentView(android.widget.cts.R.layout.table_layout_2);
+ tableLayout = (TableLayout) activity.findViewById(android.widget.cts.R.id.table2);
assertTrue(tableLayout.isColumnShrinkable(1));
}
@@ -205,12 +205,12 @@
final TableCtsActivity activity = getActivity();
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
- activity.setContentView(com.android.cts.widget.R.layout.table_layout_1);
+ activity.setContentView(android.widget.cts.R.layout.table_layout_1);
}
});
getInstrumentation().waitForIdleSync();
final TableLayout tableLayout =
- (TableLayout) activity.findViewById(com.android.cts.widget.R.id.table1);
+ (TableLayout) activity.findViewById(android.widget.cts.R.id.table1);
// Preparation: remove Collapsed mark for column 0.
getInstrumentation().runOnMainSync(new Runnable() {
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 cbc41ce..fbd9f97 100644
--- a/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/TableRowTest.java b/tests/tests/widget/src/android/widget/cts/TableRowTest.java
index 6012f59..2e917f8 100644
--- a/tests/tests/widget/src/android/widget/cts/TableRowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableRowTest.java
@@ -33,7 +33,7 @@
import android.widget.TableRow;
import android.widget.TextView;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
@@ -44,7 +44,7 @@
Context mTargetContext;
public TableRowTest() {
- super("com.android.cts.widget", TableCtsActivity.class);
+ super("android.widget.cts", TableCtsActivity.class);
}
@Override
@@ -83,9 +83,9 @@
@UiThreadTest
public void testGetVirtualChildAt() {
TableCtsActivity activity = getActivity();
- activity.setContentView(com.android.cts.widget.R.layout.table_layout_1);
+ activity.setContentView(android.widget.cts.R.layout.table_layout_1);
TableLayout tableLayout = (TableLayout) activity
- .findViewById(com.android.cts.widget.R.id.table1);
+ .findViewById(android.widget.cts.R.id.table1);
TableRow tableRow = (TableRow) tableLayout.getChildAt(0);
Resources resources = activity.getResources();
@@ -96,8 +96,8 @@
assertEquals(resources.getString(R.string.table_layout_third),
((TextView) tableRow.getVirtualChildAt(2)).getText().toString());
- activity.setContentView(com.android.cts.widget.R.layout.table_layout_2);
- tableLayout = (TableLayout) activity.findViewById(com.android.cts.widget.R.id.table2);
+ activity.setContentView(android.widget.cts.R.layout.table_layout_2);
+ tableLayout = (TableLayout) activity.findViewById(android.widget.cts.R.id.table2);
tableRow = (TableRow) tableLayout.getChildAt(0);
assertNull(tableRow.getVirtualChildAt(0));
@@ -114,15 +114,15 @@
@UiThreadTest
public void testGetVirtualChildCount() {
TableCtsActivity activity = getActivity();
- activity.setContentView(com.android.cts.widget.R.layout.table_layout_1);
+ activity.setContentView(android.widget.cts.R.layout.table_layout_1);
TableLayout tableLayout = (TableLayout) activity
- .findViewById(com.android.cts.widget.R.id.table1);
+ .findViewById(android.widget.cts.R.id.table1);
TableRow tableRow = (TableRow) tableLayout.getChildAt(0);
assertEquals(3, tableRow.getVirtualChildCount());
- activity.setContentView(com.android.cts.widget.R.layout.table_layout_2);
- tableLayout = (TableLayout) activity.findViewById(com.android.cts.widget.R.id.table2);
+ activity.setContentView(android.widget.cts.R.layout.table_layout_2);
+ tableLayout = (TableLayout) activity.findViewById(android.widget.cts.R.id.table2);
tableRow = (TableRow) tableLayout.getChildAt(0);
assertEquals(5, tableRow.getVirtualChildCount());
diff --git a/tests/tests/widget/src/android/widget/cts/TableRow_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/TableRow_LayoutParamsTest.java
index 8308414..ce3be70 100644
--- a/tests/tests/widget/src/android/widget/cts/TableRow_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableRow_LayoutParamsTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -42,7 +42,7 @@
Context mTargetContext;
public TableRow_LayoutParamsTest() {
- super("com.android.cts.widget", TableCtsActivity.class);
+ super("android.widget.cts", TableCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
index 888f215..31fc486 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 829171c..6a36c7e 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -16,7 +16,9 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.text.Html;
+import android.text.Spanned;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParserException;
@@ -75,6 +77,7 @@
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.util.DisplayMetrics;
+import android.util.LocaleList;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@@ -121,7 +124,7 @@
private CharSequence mTransformedText;
public TextViewTest() {
- super("com.android.cts.widget", TextViewCtsActivity.class);
+ super("android.widget.cts", TextViewCtsActivity.class);
}
@Override
@@ -1266,6 +1269,50 @@
}
}
+ @UiThreadTest
+ public void testSetText_setsMovementMethodWhenLinksClickableAndTextContainsClickableSpans() {
+ Spanned text = Html.fromHtml("<a href='http://android.com'>link</a>");
+ mTextView = new TextView(mActivity);
+
+ mTextView.setLinksClickable(false);
+ mTextView.setText(text);
+ assertNull("TextView.setText should not set movement method if linksClickable is false",
+ mTextView.getMovementMethod());
+
+ mTextView.setLinksClickable(true);
+ mTextView.setText(text);
+ assertNotNull("TextView.setText should set movement method if linksClickable is true " +
+ "and text contains clickable spans", mTextView.getMovementMethod());
+ }
+
+ public void testRemoveSelectionWithSelectionHandles() {
+ initTextViewForTyping();
+
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTextView.setTextIsSelectable(true);
+ mTextView.setText("abcd", BufferType.EDITABLE);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ // 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());
+ }
+ });
+
+ // Make sure that a crash doesn't happen with {@link Selection#removeSelection}.
+ mInstrumentation.waitForIdleSync();
+ }
+
public void testUndo_insert() {
initTextViewForTyping();
@@ -1699,6 +1746,64 @@
mInstrumentation.waitForIdleSync();
}
+ public void testCopyAndPaste_byKey() {
+ initTextViewForTyping();
+
+ // Type "abc".
+ mInstrumentation.sendStringSync("abc");
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ // Select "bc"
+ Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ // Copy "bc"
+ sendKeys(KeyEvent.KEYCODE_COPY);
+
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ // Set cursor between 'b' and 'c'.
+ Selection.setSelection((Spannable) mTextView.getText(), 2, 2);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ // Paste "bc"
+ sendKeys(KeyEvent.KEYCODE_PASTE);
+ assertEquals("abbcc", mTextView.getText().toString());
+
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ Selection.selectAll((Spannable) mTextView.getText());
+ KeyEvent copyWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_COPY, 0, KeyEvent.META_SHIFT_LEFT_ON);
+ // Shift + copy doesn't perform copy.
+ mTextView.onKeyDown(KeyEvent.KEYCODE_COPY, copyWithMeta);
+ Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
+ mTextView.onTextContextMenuItem(android.R.id.paste);
+ assertEquals("bcabbcc", mTextView.getText().toString());
+
+ Selection.selectAll((Spannable) mTextView.getText());
+ copyWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_COPY, 0,
+ KeyEvent.META_CTRL_LEFT_ON);
+ // Control + copy doesn't perform copy.
+ mTextView.onKeyDown(KeyEvent.KEYCODE_COPY, copyWithMeta);
+ Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
+ mTextView.onTextContextMenuItem(android.R.id.paste);
+ assertEquals("bcbcabbcc", mTextView.getText().toString());
+
+ Selection.selectAll((Spannable) mTextView.getText());
+ copyWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_COPY, 0,
+ KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_CTRL_LEFT_ON);
+ // Control + Shift + copy doesn't perform copy.
+ mTextView.onKeyDown(KeyEvent.KEYCODE_COPY, copyWithMeta);
+ Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
+ mTextView.onTextContextMenuItem(android.R.id.paste);
+ assertEquals("bcbcbcabbcc", mTextView.getText().toString());
+ }
+ });
+ }
+
public void testCutAndPaste() {
initTextViewForTyping();
mActivity.runOnUiThread(new Runnable() {
@@ -1724,6 +1829,57 @@
mInstrumentation.waitForIdleSync();
}
+ public void testCutAndPaste_byKey() {
+ initTextViewForTyping();
+
+ // Type "abc".
+ mInstrumentation.sendStringSync("abc");
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ // Select "bc"
+ Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ // Cut "bc"
+ sendKeys(KeyEvent.KEYCODE_CUT);
+
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ assertEquals("a", mTextView.getText().toString());
+ // Move cursor to the head
+ Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ // Paste "bc"
+ sendKeys(KeyEvent.KEYCODE_PASTE);
+ assertEquals("bca", mTextView.getText().toString());
+
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ Selection.selectAll((Spannable) mTextView.getText());
+ KeyEvent cutWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_CUT, 0, KeyEvent.META_SHIFT_LEFT_ON);
+ // Shift + cut doesn't perform cut.
+ mTextView.onKeyDown(KeyEvent.KEYCODE_CUT, cutWithMeta);
+ assertEquals("bca", mTextView.getText().toString());
+
+ cutWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_CUT, 0,
+ KeyEvent.META_CTRL_LEFT_ON);
+ // Control + cut doesn't perform cut.
+ mTextView.onKeyDown(KeyEvent.KEYCODE_CUT, cutWithMeta);
+ assertEquals("bca", mTextView.getText().toString());
+
+ cutWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_CUT, 0,
+ KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_CTRL_LEFT_ON);
+ // Control + Shift + cut doesn't perform cut.
+ mTextView.onKeyDown(KeyEvent.KEYCODE_CUT, cutWithMeta);
+ assertEquals("bca", mTextView.getText().toString());
+ }
+ });
+ }
+
private static boolean hasSpansAtMiddleOfText(final TextView textView, final Class<?> type) {
final Spannable spannable = (Spannable)textView.getText();
final int at = spannable.length() / 2;
@@ -2427,6 +2583,160 @@
}
}
+ @UiThreadTest
+ public void testAppend_doesNotAddLinksWhenAppendedTextDoesNotContainLinks() {
+ mTextView = new TextView(mActivity);
+ mTextView.setAutoLinkMask(Linkify.ALL);
+ mTextView.setText("text without URL");
+
+ mTextView.append(" another text without URL");
+
+ Spannable text = (Spannable) mTextView.getText();
+ URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
+ assertEquals("URLSpan count should be zero", 0, urlSpans.length);
+ assertEquals("text without URL another text without URL", text.toString());
+ }
+
+ @UiThreadTest
+ public void testAppend_doesNotAddLinksWhenAutoLinkIsNotEnabled() {
+ mTextView = new TextView(mActivity);
+ mTextView.setText("text without URL");
+
+ mTextView.append(" text with URL http://android.com");
+
+ Spannable text = (Spannable) mTextView.getText();
+ URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
+ assertEquals("URLSpan count should be zero", 0, urlSpans.length);
+ assertEquals("text without URL text with URL http://android.com", text.toString());
+ }
+
+ @UiThreadTest
+ public void testAppend_addsLinksWhenAutoLinkIsEnabled() {
+ mTextView = new TextView(mActivity);
+ mTextView.setAutoLinkMask(Linkify.ALL);
+ mTextView.setText("text without URL");
+
+ mTextView.append(" text with URL http://android.com");
+
+ Spannable text = (Spannable) mTextView.getText();
+ URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
+ assertEquals("URLSpan count should be one after appending a URL", 1, urlSpans.length);
+ assertEquals("URLSpan URL should be same as the appended URL",
+ urlSpans[0].getURL(), "http://android.com");
+ assertEquals("text without URL text with URL http://android.com", text.toString());
+ }
+
+ @UiThreadTest
+ public void testAppend_addsLinksEvenWhenThereAreUrlsSetBefore() {
+ mTextView = new TextView(mActivity);
+ mTextView.setAutoLinkMask(Linkify.ALL);
+ mTextView.setText("text with URL http://android.com/before");
+
+ mTextView.append(" text with URL http://android.com");
+
+ Spannable text = (Spannable) mTextView.getText();
+ URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
+ assertEquals("URLSpan count should be two after appending another URL", 2, urlSpans.length);
+ assertEquals("First URLSpan URL should be same",
+ urlSpans[0].getURL(), "http://android.com/before");
+ assertEquals("URLSpan URL should be same as the appended URL",
+ urlSpans[1].getURL(), "http://android.com");
+ assertEquals("text with URL http://android.com/before text with URL http://android.com",
+ text.toString());
+ }
+
+ @UiThreadTest
+ public void testAppend_setsMovementMethodWhenTextContainsUrlAndAutoLinkIsEnabled() {
+ mTextView = new TextView(mActivity);
+ mTextView.setAutoLinkMask(Linkify.ALL);
+ mTextView.setText("text without a URL");
+
+ mTextView.append(" text with a url: http://android.com");
+
+ assertNotNull("MovementMethod should not be null when text contains url",
+ mTextView.getMovementMethod());
+ assertTrue("MovementMethod should be instance of LinkMovementMethod when text contains url",
+ mTextView.getMovementMethod() instanceof LinkMovementMethod);
+ }
+
+ @UiThreadTest
+ public void testAppend_setsMovementMethodWhenLinksClickableAndTextContainsClickableSpans() {
+ Spanned text = Html.fromHtml("<a href='http://android.com'>link</a>");
+ mTextView = new TextView(mActivity);
+
+ mTextView.setLinksClickable(false);
+ mTextView.append(text);
+ assertNull("TextView.append should not set movement method if linksClickable is false",
+ mTextView.getMovementMethod());
+
+ mTextView.setText("");
+ mTextView.setLinksClickable(true);
+ mTextView.append(text);
+ assertNotNull("TextView.append should set movement method if linksClickable is true " +
+ "and text contains clickable spans", mTextView.getMovementMethod());
+ }
+
+ @UiThreadTest
+ public void testAppend_setMovementMethodForExistingTextWhenLinksClickableIsTrueDuringAppend() {
+ Spanned text = Html.fromHtml("<a href='http://android.com'>link</a>");
+ mTextView = new TextView(mActivity);
+ mTextView.setLinksClickable(false);
+ mTextView.setText(text);
+
+ mTextView.setLinksClickable(true);
+ mTextView.append("");
+
+ assertNotNull("TextView.append should set movement method if existing text contains " +
+ "links but new text does not", mTextView.getMovementMethod());
+ }
+
+ @UiThreadTest
+ public void testAppend_addsLinksWhenTextIsSpannableAndContainsUrlAndAutoLinkIsEnabled() {
+ mTextView = new TextView(mActivity);
+ mTextView.setAutoLinkMask(Linkify.ALL);
+ mTextView.setText("text without a URL");
+
+ mTextView.append(new SpannableString(" text with a url: http://android.com"));
+
+ Spannable text = (Spannable) mTextView.getText();
+ URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
+ assertEquals("URLSpan count should be one after appending a URL", 1, urlSpans.length);
+ assertEquals("URLSpan URL should be same as the appended URL",
+ urlSpans[0].getURL(), "http://android.com");
+ }
+
+ @UiThreadTest
+ public void testAppend_addsLinkIfAppendedTextCompletesPartialUrlAtTheEndOfExistingText() {
+ mTextView = new TextView(mActivity);
+ mTextView.setAutoLinkMask(Linkify.ALL);
+ mTextView.setText("text with a partial url android.");
+
+ mTextView.append("com");
+
+ Spannable text = (Spannable) mTextView.getText();
+ URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
+ assertEquals("URLSpan count should be one after appending to partial URL",
+ 1, urlSpans.length);
+ assertEquals("URLSpan URL should be same as the appended URL",
+ urlSpans[0].getURL(), "http://android.com");
+ }
+
+ @UiThreadTest
+ public void testAppend_addsLinkIfAppendedTextUpdatesUrlAtTheEndOfExistingText() {
+ mTextView = new TextView(mActivity);
+ mTextView.setAutoLinkMask(Linkify.ALL);
+ mTextView.setText("text with a url http://android.com");
+
+ mTextView.append("/textview");
+
+ Spannable text = (Spannable) mTextView.getText();
+ URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
+ assertEquals("URLSpan count should still be one after extending a URL", 1, urlSpans.length);
+ assertEquals("URLSpan URL should be same as the new URL",
+ urlSpans[0].getURL(), "http://android.com/textview");
+ }
+
+
public void testAccessTransformationMethod() {
// check the password attribute in xml
mTextView = findTextView(R.id.textview_password);
@@ -4026,6 +4336,41 @@
}
}
+ public void testTextLocales() {
+ TextView tv = new TextView(mActivity);
+ assertEquals(Locale.getDefault(), tv.getTextLocale());
+ assertEquals(LocaleList.getDefault(), tv.getTextLocales());
+
+ tv.setTextLocale(Locale.CHINESE);
+ assertEquals(Locale.CHINESE, tv.getTextLocale());
+ assertEquals(new LocaleList(Locale.CHINESE), tv.getTextLocales());
+
+ tv.setTextLocales(LocaleList.forLanguageTags("en,ja"));
+ assertEquals(Locale.forLanguageTag("en"), tv.getTextLocale());
+ assertEquals(LocaleList.forLanguageTags("en,ja"), tv.getTextLocales());
+
+ try {
+ tv.setTextLocale(null);
+ fail("Setting the text locale to null should throw");
+ } catch (Throwable e) {
+ assertEquals(IllegalArgumentException.class, e.getClass());
+ }
+
+ try {
+ tv.setTextLocales(null);
+ fail("Setting the text locales to null should throw");
+ } catch (Throwable e) {
+ assertEquals(IllegalArgumentException.class, e.getClass());
+ }
+
+ try {
+ tv.setTextLocales(new LocaleList());
+ fail("Setting the text locale to an empty list should throw");
+ } catch (Throwable e) {
+ assertEquals(IllegalArgumentException.class, e.getClass());
+ }
+ }
+
public void testAllCapsLocalization() {
String testString = "abcdefghijklmnopqrstuvwxyz";
diff --git a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
index 1ce2844..39554bb 100644
--- a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
@@ -39,7 +39,7 @@
private Instrumentation mInstrumentation;
public TimePickerTest() {
- super("com.android.cts.widget", CtsActivity.class);
+ super("android.widget.cts", CtsActivity.class);
}
@Override
@@ -52,7 +52,7 @@
public void testConstructors() {
AttributeSet attrs =
- mContext.getResources().getLayout(com.android.cts.widget.R.layout.timepicker);
+ mContext.getResources().getLayout(android.widget.cts.R.layout.timepicker);
assertNotNull(attrs);
new TimePicker(mContext);
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 90a161e..854247e 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
@@ -44,7 +44,7 @@
private ViewTreeObserver.OnGlobalLayoutListener mLayoutListener;
public ToastTest() {
- super("com.android.cts.widget", CtsActivity.class);
+ super("android.widget.cts", CtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java b/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
index b3bc31e..d335c13 100644
--- a/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
@@ -21,13 +21,14 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
import android.test.InstrumentationTestCase;
import android.test.UiThreadTest;
import android.util.AttributeSet;
import android.util.Xml;
import android.widget.ToggleButton;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
@@ -96,9 +97,13 @@
// drawableStateChanged without any drawable.
toggleButton.drawableStateChanged();
+ StateListDrawable drawable = new StateListDrawable();
+ drawable.addState(new int[] { android.R.attr.state_pressed },
+ mContext.getDrawable(R.drawable.scenery));
+ drawable.addState(new int[] {},
+ mContext.getDrawable(R.drawable.scenery));
+
// drawableStateChanged when CheckMarkDrawable is not null.
- Resources resources = mContext.getResources();
- Drawable drawable = resources.getDrawable(R.drawable.scenery);
toggleButton.setButtonDrawable(drawable);
drawable.setState(null);
assertNull(drawable.getState());
diff --git a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
new file mode 100644
index 0000000..6bbcd4c
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package android.widget.cts;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.UiThreadTest;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Toolbar;
+
+public class ToolbarTest extends AndroidTestCase {
+ private Context mContext;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mContext = getContext();
+ }
+
+ @UiThreadTest
+ public void testGetTitleMargins() {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ View layout = inflater.inflate(R.layout.toolbar_layout, null);
+ Toolbar toolbar = (Toolbar) layout.findViewById(R.id.toolbar);
+
+ assertEquals(5, toolbar.getTitleMarginStart());
+ assertEquals(10, toolbar.getTitleMarginTop());
+ assertEquals(15, toolbar.getTitleMarginEnd());
+ assertEquals(20, toolbar.getTitleMarginBottom());
+ }
+
+ @UiThreadTest
+ public void testSetTitleMargins() {
+ Toolbar toolbar = new Toolbar(mContext);
+ assertEquals(0, toolbar.getTitleMarginStart());
+ assertEquals(0, toolbar.getTitleMarginTop());
+ assertEquals(0, toolbar.getTitleMarginEnd());
+ assertEquals(0, toolbar.getTitleMarginBottom());
+
+ toolbar.setTitleMargin(5, 10, 15, 20);
+ assertEquals(5, toolbar.getTitleMarginStart());
+ assertEquals(10, toolbar.getTitleMarginTop());
+ assertEquals(15, toolbar.getTitleMarginEnd());
+ assertEquals(20, toolbar.getTitleMarginBottom());
+
+ toolbar.setTitleMarginStart(25);
+ toolbar.setTitleMarginTop(30);
+ toolbar.setTitleMarginEnd(35);
+ toolbar.setTitleMarginBottom(40);
+ assertEquals(25, toolbar.getTitleMarginStart());
+ assertEquals(30, toolbar.getTitleMarginTop());
+ assertEquals(35, toolbar.getTitleMarginEnd());
+ assertEquals(40, toolbar.getTitleMarginBottom());
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/TwoLineListItemCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TwoLineListItemCtsActivity.java
index bd2c36d..68413ff 100644
--- a/tests/tests/widget/src/android/widget/cts/TwoLineListItemCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/TwoLineListItemCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/TwoLineListItemTest.java b/tests/tests/widget/src/android/widget/cts/TwoLineListItemTest.java
index 18dd407..4ee22a1 100644
--- a/tests/tests/widget/src/android/widget/cts/TwoLineListItemTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TwoLineListItemTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
@@ -36,7 +36,7 @@
private Activity mActivity;
public TwoLineListItemTest() {
- super("com.android.cts.widget", TwoLineListItemCtsActivity.class);
+ super("android.widget.cts", TwoLineListItemCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/VideoViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/VideoViewCtsActivity.java
index ad0d6eb..e831f04 100644
--- a/tests/tests/widget/src/android/widget/cts/VideoViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/VideoViewCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
index d9af514..157bad8 100644
--- a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.app.Instrumentation;
@@ -108,7 +108,7 @@
* Instantiates a new video view test.
*/
public VideoViewTest() {
- super("com.android.cts.widget", VideoViewCtsActivity.class);
+ super("android.widget.cts", VideoViewCtsActivity.class);
}
/**
diff --git a/tests/tests/widget/src/android/widget/cts/ViewAnimatorCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ViewAnimatorCtsActivity.java
index 21deef7..ec3e59e 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewAnimatorCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewAnimatorCtsActivity.java
@@ -18,7 +18,7 @@
import android.app.Activity;
import android.os.Bundle;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
* A minimal application for ViewAnimator test.
diff --git a/tests/tests/widget/src/android/widget/cts/ViewAnimatorTest.java b/tests/tests/widget/src/android/widget/cts/ViewAnimatorTest.java
index 024e3ee..696761b 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewAnimatorTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewAnimatorTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -43,7 +43,7 @@
private AttributeSet mAttributeSet;
public ViewAnimatorTest() {
- super("com.android.cts.widget", ViewAnimatorCtsActivity.class);
+ super("android.widget.cts", ViewAnimatorCtsActivity.class);
}
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/ViewFlipperCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ViewFlipperCtsActivity.java
index 7f13f6c..ba90590 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewFlipperCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewFlipperCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/ViewFlipperTest.java b/tests/tests/widget/src/android/widget/cts/ViewFlipperTest.java
index 025fae4..5ec242e 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewFlipperTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewFlipperTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -37,7 +37,7 @@
private Activity mActivity;
public ViewFlipperTest() {
- super("com.android.cts.widget", ViewFlipperCtsActivity.class);
+ super("android.widget.cts", ViewFlipperCtsActivity.class);
}
protected void setUp() throws Exception {
diff --git a/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java
index 4e14fc2..f3b3a3e 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java
@@ -35,8 +35,8 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(com.android.cts.widget.R.layout.viewgrouptest_stub);
- TextView textView = (TextView)findViewById(com.android.cts.widget.R.id.viewgrouptest_stub);
+ setContentView(android.widget.cts.R.layout.viewgrouptest_stub);
+ TextView textView = (TextView)findViewById(android.widget.cts.R.id.viewgrouptest_stub);
textView.setText("test");
}
@@ -49,7 +49,7 @@
mHandler.postDelayed(new Runnable() {
public void run() {
MockLinearLayout mll =
- (MockLinearLayout) findViewById(com.android.cts.widget.R.id.
+ (MockLinearLayout) findViewById(android.widget.cts.R.id.
mocklinearlayout);
if (!mll.mIsInvalidateChildInParentCalled) {
fail();
diff --git a/tests/tests/widget/src/android/widget/cts/ViewSwitcherTest.java b/tests/tests/widget/src/android/widget/cts/ViewSwitcherTest.java
index ce18267..7828570 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewSwitcherTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewSwitcherTest.java
@@ -28,7 +28,7 @@
import android.widget.ViewSwitcher;
import android.widget.ViewSwitcher.ViewFactory;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
/**
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ZoomButtonCtsActivity.java
index e371b3f..28563f5 100644
--- a/tests/tests/widget/src/android/widget/cts/ZoomButtonCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ZoomButtonCtsActivity.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
index 3d906db..493c484 100644
--- a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-import com.android.cts.widget.R;
+import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -37,7 +37,7 @@
private Activity mActivity;
public ZoomButtonTest() {
- super("com.android.cts.widget", ZoomButtonCtsActivity.class);
+ super("android.widget.cts", ZoomButtonCtsActivity.class);
}
@Override
diff --git a/tests/tvprovider/Android.mk b/tests/tvprovider/Android.mk
new file mode 100644
index 0000000..acf4bb9
--- /dev/null
+++ b/tests/tvprovider/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsTvProviderTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/tests/tvprovider/AndroidManifest.xml b/tests/tvprovider/AndroidManifest.xml
new file mode 100644
index 0000000..fcf0ec5
--- /dev/null
+++ b/tests/tvprovider/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.tvprovider.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
+ <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.tvprovider.cts"
+ android:label="CTS tests for TV Provider" />
+</manifest>
diff --git a/tests/tvprovider/AndroidTest.xml b/tests/tvprovider/AndroidTest.xml
new file mode 100644
index 0000000..f92b37d
--- /dev/null
+++ b/tests/tvprovider/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS TV Provider test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTvProviderTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.tvprovider.cts" />
+ </test>
+</configuration>
diff --git a/tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java b/tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java
new file mode 100644
index 0000000..b5fa019
--- /dev/null
+++ b/tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2014 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.tvprovider.cts;
+
+import android.content.ComponentName;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.OperationApplicationException;
+import android.content.pm.PackageManager;
+import android.cts.util.CtsAndroidTestCase;
+import android.database.Cursor;
+import android.media.tv.TvContract;
+import android.media.tv.TvContract.Channels;
+import android.media.tv.TvContract.Programs;
+import android.net.Uri;
+import android.os.RemoteException;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.MeasureRun;
+import com.android.compatibility.common.util.MeasureTime;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+import com.android.cts.util.TimeoutReq;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test performance of TvProvider on a device. TvProvider typically handles hundreds of
+ * thousands of records periodically, so it is desirable to have performance under a reasonable
+ * bar.
+ */
+public class TvProviderPerfTest extends CtsAndroidTestCase {
+ private static final int TRANSACTION_RUNS = 100;
+ private static final int QUERY_RUNS = 10;
+
+ private ContentResolver mContentResolver;
+ private String mInputId;
+ private boolean mHasTvInputFramework;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mHasTvInputFramework = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_LIVE_TV);
+ if (!mHasTvInputFramework) return;
+ mContentResolver = getContext().getContentResolver();
+ mInputId = TvContract.buildInputId(new ComponentName(getContext(), getClass()));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ if (!mHasTvInputFramework) return;
+ mContentResolver.delete(Programs.CONTENT_URI, null, null);
+ mContentResolver.delete(Channels.CONTENT_URI, null, null);
+ } finally {
+ super.tearDown();
+ }
+ }
+
+ @TimeoutReq(minutes = 8)
+ public void testChannels() throws Exception {
+ if (!mHasTvInputFramework) return;
+ double[] averages = new double[5];
+
+ // Insert
+ final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
+ final int TRANSACTION_SIZE = 1000;
+ double[] applyBatchTimes = MeasureTime.measure(TRANSACTION_RUNS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ operations.clear();
+ for (int j = 0; j < TRANSACTION_SIZE; ++j) {
+ ContentValues values = new ContentValues();
+ values.put(Channels.COLUMN_INPUT_ID, mInputId);
+ values.put(Channels.COLUMN_SERVICE_TYPE,
+ Channels.SERVICE_TYPE_AUDIO_VIDEO);
+ values.put(Channels.COLUMN_TYPE, Channels.TYPE_OTHER);
+ operations.add(
+ ContentProviderOperation.newInsert(Channels.CONTENT_URI)
+ .withValues(values).build());
+ }
+ try {
+ mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
+ } catch (OperationApplicationException | RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValues("Elapsed time for insert: ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[0] = Stat.getAverage(applyBatchTimes);
+
+ // Update
+ final String[] projection = { Channels._ID };
+ try (final Cursor cursor = mContentResolver.query(Channels.CONTENT_URI,
+ projection, null, null, null)) {
+ applyBatchTimes = MeasureTime.measure(TRANSACTION_RUNS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ operations.clear();
+ for (int j = 0; j < TRANSACTION_SIZE && cursor.moveToNext(); ++j) {
+ Uri channelUri = TvContract.buildChannelUri(cursor.getLong(0));
+ String number = Integer.toString(i * TRANSACTION_SIZE + j);
+ operations.add(
+ ContentProviderOperation.newUpdate(channelUri)
+ .withValue(Channels.COLUMN_DISPLAY_NUMBER, number)
+ .build());
+ }
+ try {
+ mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
+ } catch (OperationApplicationException | RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ report.addValues("Elapsed time for update: ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[1] = Stat.getAverage(applyBatchTimes);
+
+ // Query channels
+ applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ try (Cursor cursor = mContentResolver.query(Channels.CONTENT_URI, null, null,
+ null, null)) {
+ while (cursor.moveToNext()) {
+ // Do nothing. Just iterate all the items.
+ }
+ }
+ }
+ });
+ report.addValues("Elapsed time for query (channels): ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[2] = Stat.getAverage(applyBatchTimes);
+
+ // Query a channel
+ try (final Cursor cursor = mContentResolver.query(Channels.CONTENT_URI,
+ projection, null, null, null)) {
+ applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ assertTrue(cursor.moveToNext());
+ try (Cursor c = mContentResolver.query(TvContract.buildChannelUri(
+ cursor.getLong(0)), null, null, null, null)) {
+ while (c.moveToNext()) {
+ // Do nothing. Just iterate all the items.
+ }
+ }
+ }
+ });
+ }
+ report.addValues("Elapsed time for query (a channel): ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[3] = Stat.getAverage(applyBatchTimes);
+
+ // Delete
+ applyBatchTimes = MeasureTime.measure(1, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ mContentResolver.delete(TvContract.buildChannelsUriForInput(mInputId), null, null);
+ }
+ });
+ report.addValues("Elapsed time for delete: ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[4] = Stat.getAverage(applyBatchTimes);
+
+ report.addValues("Average elapsed time for insert, update, query (channels), "
+ + "query (a channel), delete: ",
+ averages, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.submit(getInstrumentation());
+ }
+
+ @TimeoutReq(minutes = 12)
+ public void testPrograms() throws Exception {
+ if (!mHasTvInputFramework) return;
+ double[] averages = new double[7];
+
+ // Prepare (insert channels)
+ final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
+ final int TRANSACTION_SIZE = 1000;
+ final int NUM_CHANNELS = 100;
+ final List<Uri> channelUris = new ArrayList<>();
+
+ operations.clear();
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ ContentValues values = new ContentValues();
+ values.put(Channels.COLUMN_INPUT_ID, mInputId);
+ values.put(Channels.COLUMN_SERVICE_TYPE,
+ Channels.SERVICE_TYPE_AUDIO_VIDEO);
+ values.put(Channels.COLUMN_TYPE, Channels.TYPE_OTHER);
+ operations.add(
+ ContentProviderOperation.newInsert(Channels.CONTENT_URI)
+ .withValues(values).build());
+ }
+ try {
+ ContentProviderResult[] results =
+ mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
+ for (ContentProviderResult result : results) {
+ channelUris.add(result.uri);
+ }
+ } catch (OperationApplicationException | RemoteException e) {
+ throw new RuntimeException(e);
+ }
+
+ // Insert
+ double[] applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ operations.clear();
+ Uri channelUri = channelUris.get(i);
+ long channelId = ContentUris.parseId(channelUri);
+ for (int j = 0; j < TRANSACTION_SIZE; ++j) {
+ ContentValues values = new ContentValues();
+ values.put(Programs.COLUMN_CHANNEL_ID, channelId);
+ operations.add(
+ ContentProviderOperation.newInsert(Programs.CONTENT_URI)
+ .withValues(values).build());
+ }
+ try {
+ mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
+ } catch (OperationApplicationException | RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValues("Elapsed time for insert: ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[0] = Stat.getAverage(applyBatchTimes);
+
+ // Update
+ final long PROGRAM_DURATION_MS = 60 * 1000;
+ final String[] projection = { Programs._ID };
+ applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ Uri channelUri = channelUris.get(i);
+ operations.clear();
+ try (Cursor cursor = mContentResolver.query(
+ TvContract.buildProgramsUriForChannel(channelUri),
+ projection, null, null, null)) {
+ long startTimeMs = 0;
+ long endTimeMs = 0;
+ while (cursor.moveToNext()) {
+ Uri programUri = TvContract.buildProgramUri(cursor.getLong(0));
+ endTimeMs += PROGRAM_DURATION_MS;
+ operations.add(
+ ContentProviderOperation.newUpdate(programUri)
+ .withValue(Programs.COLUMN_START_TIME_UTC_MILLIS, startTimeMs)
+ .withValue(Programs.COLUMN_END_TIME_UTC_MILLIS, endTimeMs)
+ .build());
+ startTimeMs = endTimeMs;
+ }
+ }
+ try {
+ mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
+ } catch (OperationApplicationException | RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ report.addValues("Elapsed time for update: ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[1] = Stat.getAverage(applyBatchTimes);
+
+ // Query programs
+ applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ try (Cursor cursor = mContentResolver.query(Programs.CONTENT_URI, null, null,
+ null, null)) {
+ while (cursor.moveToNext()) {
+ // Do nothing. Just iterate all the items.
+ }
+ }
+ }
+ });
+ report.addValues("Elapsed time for query (programs): ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[2] = Stat.getAverage(applyBatchTimes);
+
+ // Query programs with selection
+ applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ Uri channelUri = channelUris.get(i);
+ try (Cursor cursor = mContentResolver.query(
+ TvContract.buildProgramsUriForChannel(
+ channelUri, 0,
+ PROGRAM_DURATION_MS * TRANSACTION_SIZE / 2),
+ null, null, null, null)) {
+ while (cursor.moveToNext()) {
+ // Do nothing. Just iterate all the items.
+ }
+ }
+ }
+ });
+ report.addValues("Elapsed time for query (programs with selection): ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[3] = Stat.getAverage(applyBatchTimes);
+
+ // Query a program
+ try (final Cursor cursor = mContentResolver.query(Programs.CONTENT_URI,
+ projection, null, null, null)) {
+ applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ assertTrue(cursor.moveToNext());
+ try (Cursor c = mContentResolver.query(TvContract.buildProgramUri(
+ cursor.getLong(0)), null, null, null, null)) {
+ while (c.moveToNext()) {
+ // Do nothing. Just iterate all the items.
+ }
+ }
+ }
+ });
+ }
+ report.addValues("Elapsed time for query (a program): ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[4] = Stat.getAverage(applyBatchTimes);
+
+ // Delete programs
+ applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ Uri channelUri = channelUris.get(i);
+ mContentResolver.delete(
+ TvContract.buildProgramsUriForChannel(
+ channelUri,
+ PROGRAM_DURATION_MS * TRANSACTION_SIZE / 2,
+ PROGRAM_DURATION_MS * TRANSACTION_SIZE),
+ null, null);
+ }
+ });
+ report.addValues("Elapsed time for delete programs: ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[5] = Stat.getAverage(applyBatchTimes);
+
+ // Delete channels
+ applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
+ @Override
+ public void run(int i) {
+ Uri channelUri = channelUris.get(i);
+ mContentResolver.delete(channelUri, null, null);
+ }
+ });
+ report.addValues("Elapsed time for delete channels: ",
+ applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ averages[6] = Stat.getAverage(applyBatchTimes);
+
+ report.addValues("Average elapsed time for insert, update, query (programs), "
+ + "query (programs with selection), query (a channel), delete (channels), "
+ + "delete (programs): ",
+ averages, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.submit(getInstrumentation());
+ }
+}
diff --git a/tests/ui/Android.mk b/tests/ui/Android.mk
new file mode 100644
index 0000000..e77f035
--- /dev/null
+++ b/tests/ui/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsUiDeviceTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_CTS_PACKAGE)
+
+
diff --git a/tests/ui/AndroidManifest.xml b/tests/ui/AndroidManifest.xml
new file mode 100644
index 0000000..5ed06b4
--- /dev/null
+++ b/tests/ui/AndroidManifest.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.ui.cts" >
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+
+ <activity
+ android:name=".ScrollingActivity"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:label="UI Latency measurement"
+ android:targetPackage="android.ui.cts" >
+ <meta-data
+ android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
diff --git a/tests/ui/AndroidTest.xml b/tests/ui/AndroidTest.xml
new file mode 100644
index 0000000..de75d28
--- /dev/null
+++ b/tests/ui/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<configuration description="Config for CTS UI test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsUiDeviceTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.ui.cts" />
+ <option name="runtime-hint" value="5m" />
+ </test>
+</configuration>
diff --git a/tests/ui/src/android/ui/cts/ScrollingActivity.java b/tests/ui/src/android/ui/cts/ScrollingActivity.java
new file mode 100644
index 0000000..d5fc4b0
--- /dev/null
+++ b/tests/ui/src/android/ui/cts/ScrollingActivity.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2012 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.ui.cts;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Activity for measuring scrolling time of long list.
+ */
+public class ScrollingActivity extends ListActivity implements OnScrollListener {
+ static final String TAG = "ScrollingActivity";
+ private static final String NUM_ELEMENTS_EXTRA = "num_elements";
+ private static final int NUM_ELEMENTS_DEFAULT = 10000;
+ private static final int SCROLL_TIME_IN_MS = 1;
+ private static final int WAIT_TIMEOUT_IN_SECS = 5 * 60;
+ private String[] mItems;
+ private CountDownLatch mLatchStop = null;
+ private int mTargetLoc;
+ private int mNumElements;
+
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mNumElements = getIntent().getIntExtra(NUM_ELEMENTS_EXTRA, NUM_ELEMENTS_DEFAULT);
+ mItems = new String[mNumElements];
+ for (int i = 0; i < mNumElements; i++) {
+ mItems[i] = Integer.toString(i);
+ }
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, mItems));
+ ListView view = getListView();
+ view.setOnScrollListener(this);
+ }
+
+ public boolean scrollToTop() {
+ return doScroll(0);
+ }
+ public boolean scrollToBottom() {
+ return doScroll(mNumElements - 1);
+ }
+
+ private boolean doScroll(final int loc) {
+ mLatchStop = new CountDownLatch(1);
+ mTargetLoc = loc;
+ final ListView view = getListView();
+ runOnUiThread( new Runnable() {
+ @Override
+ public void run() {
+ view.smoothScrollToPositionFromTop(loc, 0, SCROLL_TIME_IN_MS);
+ }
+ });
+ boolean result = false;
+ try {
+ result = mLatchStop.await(WAIT_TIMEOUT_IN_SECS, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ mLatchStop = null;
+ return result;
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+
+ }
+
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem,
+ int visibleItemCount, int totalItemCount) {
+ //Log.i(TAG, "onScroll " + firstVisibleItem + " " + visibleItemCount);
+ if ((mTargetLoc >= firstVisibleItem) &&
+ (mTargetLoc <= (firstVisibleItem + visibleItemCount))) {
+ if (mLatchStop != null) {
+ mLatchStop.countDown();
+ }
+ }
+ }
+}
diff --git a/tests/ui/src/android/ui/cts/ScrollingTest.java b/tests/ui/src/android/ui/cts/ScrollingTest.java
new file mode 100644
index 0000000..4902807
--- /dev/null
+++ b/tests/ui/src/android/ui/cts/ScrollingTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 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.ui.cts;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.MeasureRun;
+import com.android.compatibility.common.util.MeasureTime;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+import com.android.cts.util.TimeoutReq;
+
+import java.io.IOException;
+
+public class ScrollingTest extends ActivityInstrumentationTestCase2<ScrollingActivity> {
+ private ScrollingActivity mActivity;
+
+ public ScrollingTest() {
+ super(ScrollingActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ getInstrumentation().waitForIdleSync();
+ try {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ }
+ });
+ } catch (Throwable e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mActivity = null;
+ super.tearDown();
+ }
+
+ @TimeoutReq(minutes = 30)
+ public void testFullScrolling() throws Exception {
+ final int NUMBER_REPEAT = 10;
+ final ScrollingActivity activity = mActivity;
+ double[] results = MeasureTime.measure(NUMBER_REPEAT, new MeasureRun() {
+
+ @Override
+ public void run(int i) throws IOException {
+ assertTrue(activity.scrollToBottom());
+ assertTrue(activity.scrollToTop());
+ }
+ });
+ DeviceReportLog report = new DeviceReportLog();
+ report.addValues("scrolling time", results, ResultType.LOWER_BETTER,ResultUnit.MS);
+ Stat.StatResult stat = Stat.getStat(results);
+ report.setSummary("scrolling time", stat.mAverage, ResultType.LOWER_BETTER,ResultUnit.MS);
+ report.submit(getInstrumentation());
+ }
+}
diff --git a/tests/uiautomator/Android.mk b/tests/uiautomator/Android.mk
index d0d4b8e..a3094f9 100644
--- a/tests/uiautomator/Android.mk
+++ b/tests/uiautomator/Android.mk
@@ -21,12 +21,15 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE := CtsUiAutomatorTests
-LOCAL_JAVA_LIBRARIES := uiautomator.core
+LOCAL_MODULE := CtsUiAutomatorTestCases
+LOCAL_STATIC_JAVA_LIBRARIES := uiautomator.core
LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_CTS_TEST_APK := CtsUiAutomatorApp
-LOCAL_CTS_TEST_APP_PACKAGE := com.android.cts.uiautomator
-LOCAL_CTS_TEST_PACKAGE := android.uiautomator
+LOCAL_CTS_TEST_APK := CtsUiAutomatorTestApp
+LOCAL_CTS_TEST_APP_PACKAGE := com.android.uiautomator.app
+LOCAL_CTS_TEST_PACKAGE := com.android.uiautomator.cts
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
include $(BUILD_CTS_UI_JAVA_LIBRARY)
diff --git a/tests/uiautomator/AndroidTest.xml b/tests/uiautomator/AndroidTest.xml
new file mode 100644
index 0000000..c931f59
--- /dev/null
+++ b/tests/uiautomator/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<configuration description="Config for CTS UI Automator test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsUiAutomatorTestApp.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="CtsUiAutomatorTestCases.jar->/data/local/tmp/CtsUiAutomatorTestCases.jar" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.UiAutomatorTest" >
+ <option name="jar-path" value="CtsUiAutomatorTestCases.jar" />
+ <option name="capture-logs" value="OFF" />
+ </test>
+</configuration>
diff --git a/tests/uiautomator/app/Android.mk b/tests/uiautomator/app/Android.mk
new file mode 100644
index 0000000..0bde598
--- /dev/null
+++ b/tests/uiautomator/app/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := CtsUiAutomatorTestApp
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/uiautomator/app/AndroidManifest.xml b/tests/uiautomator/app/AndroidManifest.xml
new file mode 100644
index 0000000..25f746b
--- /dev/null
+++ b/tests/uiautomator/app/AndroidManifest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2011 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.uiautomator.app"
+ android:versionCode="1"
+ android:versionName="1.0" >
+ <uses-sdk
+ android:minSdkVersion="14"
+ android:targetSdkVersion="15" />
+
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/title_test_list" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".SinglePaneDetailActivity"
+ android:label="@string/title_test_detail" >
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value="FragmentActivity" />
+ </activity>
+ </application>
+
+</manifest>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_action_search.png b/tests/uiautomator/app/res/drawable-hdpi/ic_action_search.png
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_action_search.png
rename to tests/uiautomator/app/res/drawable-hdpi/ic_action_search.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_launcher.png b/tests/uiautomator/app/res/drawable-hdpi/ic_launcher.png
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_launcher.png
rename to tests/uiautomator/app/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-ldpi/ic_launcher.png b/tests/uiautomator/app/res/drawable-ldpi/ic_launcher.png
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-ldpi/ic_launcher.png
rename to tests/uiautomator/app/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_action_search.png b/tests/uiautomator/app/res/drawable-mdpi/ic_action_search.png
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_action_search.png
rename to tests/uiautomator/app/res/drawable-mdpi/ic_action_search.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_launcher.png b/tests/uiautomator/app/res/drawable-mdpi/ic_launcher.png
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_launcher.png
rename to tests/uiautomator/app/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_action_search.png b/tests/uiautomator/app/res/drawable-xhdpi/ic_action_search.png
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_action_search.png
rename to tests/uiautomator/app/res/drawable-xhdpi/ic_action_search.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_launcher.png b/tests/uiautomator/app/res/drawable-xhdpi/ic_launcher.png
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_launcher.png
rename to tests/uiautomator/app/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout-land/test5_detail_fragment.xml b/tests/uiautomator/app/res/layout-land/test5_detail_fragment.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout-land/test5_detail_fragment.xml
rename to tests/uiautomator/app/res/layout-land/test5_detail_fragment.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/activity_main.xml b/tests/uiautomator/app/res/layout/activity_main.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/activity_main.xml
rename to tests/uiautomator/app/res/layout/activity_main.xml
diff --git a/tests/uiautomator/app/res/layout/list_activity.xml b/tests/uiautomator/app/res/layout/list_activity.xml
new file mode 100644
index 0000000..faedc91
--- /dev/null
+++ b/tests/uiautomator/app/res/layout/list_activity.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:name="com.android.uiautomator.app.TestListFragment"
+ android:id="@+id/item_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ tools:context=".MainActivity" />
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/simple_list_item_selected.xml b/tests/uiautomator/app/res/layout/simple_list_item_selected.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/simple_list_item_selected.xml
rename to tests/uiautomator/app/res/layout/simple_list_item_selected.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/singlepane_activity.xml b/tests/uiautomator/app/res/layout/singlepane_activity.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/singlepane_activity.xml
rename to tests/uiautomator/app/res/layout/singlepane_activity.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test1_detail_fragment.xml b/tests/uiautomator/app/res/layout/test1_detail_fragment.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test1_detail_fragment.xml
rename to tests/uiautomator/app/res/layout/test1_detail_fragment.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test2_detail_fragment.xml b/tests/uiautomator/app/res/layout/test2_detail_fragment.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test2_detail_fragment.xml
rename to tests/uiautomator/app/res/layout/test2_detail_fragment.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test3_detail_fragment.xml b/tests/uiautomator/app/res/layout/test3_detail_fragment.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test3_detail_fragment.xml
rename to tests/uiautomator/app/res/layout/test3_detail_fragment.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test4_detail_fragment.xml b/tests/uiautomator/app/res/layout/test4_detail_fragment.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test4_detail_fragment.xml
rename to tests/uiautomator/app/res/layout/test4_detail_fragment.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test5_detail_fragment.xml b/tests/uiautomator/app/res/layout/test5_detail_fragment.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test5_detail_fragment.xml
rename to tests/uiautomator/app/res/layout/test5_detail_fragment.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test6_detail_fragment.xml b/tests/uiautomator/app/res/layout/test6_detail_fragment.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test6_detail_fragment.xml
rename to tests/uiautomator/app/res/layout/test6_detail_fragment.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test_results_detail_fragment.xml b/tests/uiautomator/app/res/layout/test_results_detail_fragment.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test_results_detail_fragment.xml
rename to tests/uiautomator/app/res/layout/test_results_detail_fragment.xml
diff --git a/tests/uiautomator/app/res/layout/twopane_activity.xml b/tests/uiautomator/app/res/layout/twopane_activity.xml
new file mode 100644
index 0000000..a787368
--- /dev/null
+++ b/tests/uiautomator/app/res/layout/twopane_activity.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:divider="?android:attr/dividerHorizontal"
+ android:showDividers="middle"
+ tools:context=".TestListActivity">
+
+ <fragment
+ android:id="@+id/item_list"
+ android:name="com.android.uiautomator.app.TestListFragment"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+
+ <FrameLayout android:id="@+id/test_detail_container"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="3" />
+
+</LinearLayout>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/activity_main.xml b/tests/uiautomator/app/res/menu/activity_main.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/activity_main.xml
rename to tests/uiautomator/app/res/menu/activity_main.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test1_detail_activity.xml b/tests/uiautomator/app/res/menu/test1_detail_activity.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test1_detail_activity.xml
rename to tests/uiautomator/app/res/menu/test1_detail_activity.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test2_detail_activity.xml b/tests/uiautomator/app/res/menu/test2_detail_activity.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test2_detail_activity.xml
rename to tests/uiautomator/app/res/menu/test2_detail_activity.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test3_detail_activity.xml b/tests/uiautomator/app/res/menu/test3_detail_activity.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test3_detail_activity.xml
rename to tests/uiautomator/app/res/menu/test3_detail_activity.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test4_detail_activity.xml b/tests/uiautomator/app/res/menu/test4_detail_activity.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test4_detail_activity.xml
rename to tests/uiautomator/app/res/menu/test4_detail_activity.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test5_detail_activity.xml b/tests/uiautomator/app/res/menu/test5_detail_activity.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test5_detail_activity.xml
rename to tests/uiautomator/app/res/menu/test5_detail_activity.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test6_detail_activity.xml b/tests/uiautomator/app/res/menu/test6_detail_activity.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test6_detail_activity.xml
rename to tests/uiautomator/app/res/menu/test6_detail_activity.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test_results_detail_activity.xml b/tests/uiautomator/app/res/menu/test_results_detail_activity.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test_results_detail_activity.xml
rename to tests/uiautomator/app/res/menu/test_results_detail_activity.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/dimens.xml b/tests/uiautomator/app/res/values-large/dimens.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/dimens.xml
rename to tests/uiautomator/app/res/values-large/dimens.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/refs.xml b/tests/uiautomator/app/res/values-large/refs.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/refs.xml
rename to tests/uiautomator/app/res/values-large/refs.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-sw600dp/refs.xml b/tests/uiautomator/app/res/values-sw600dp/refs.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-sw600dp/refs.xml
rename to tests/uiautomator/app/res/values-sw600dp/refs.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v11/styles.xml b/tests/uiautomator/app/res/values-v11/styles.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v11/styles.xml
rename to tests/uiautomator/app/res/values-v11/styles.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v14/styles.xml b/tests/uiautomator/app/res/values-v14/styles.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v14/styles.xml
rename to tests/uiautomator/app/res/values-v14/styles.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-watch/styles.xml b/tests/uiautomator/app/res/values-watch/styles.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-watch/styles.xml
rename to tests/uiautomator/app/res/values-watch/styles.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/dimens.xml b/tests/uiautomator/app/res/values/dimens.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/dimens.xml
rename to tests/uiautomator/app/res/values/dimens.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml b/tests/uiautomator/app/res/values/strings.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml
rename to tests/uiautomator/app/res/values/strings.xml
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/styles.xml b/tests/uiautomator/app/res/values/styles.xml
similarity index 100%
rename from tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/styles.xml
rename to tests/uiautomator/app/res/values/styles.xml
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/MainActivity.java b/tests/uiautomator/app/src/com/android/uiautomator/app/MainActivity.java
new file mode 100644
index 0000000..feb6767
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/MainActivity.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.view.WindowManager;
+
+public class MainActivity extends FragmentActivity implements TestListFragment.Callbacks {
+
+ private boolean mTwoPane;
+ public static final String LOG_TAG = "UiAutomatorApp";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // If the device is locked, this attempts to dismiss the KeyGuard
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
+ WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
+ WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ setContentView(R.layout.list_activity);
+
+ if (findViewById(R.id.test_detail_container) != null) {
+ mTwoPane = true;
+ ((TestListFragment) getSupportFragmentManager().findFragmentById(R.id.item_list))
+ .setActivateOnItemClick(true);
+ }
+ }
+
+ @Override
+ public void onItemSelected(String id) {
+ if (mTwoPane) {
+ Fragment fragment = TestItems.getFragment(id);
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.test_detail_container, fragment).commit();
+ } else {
+ Intent detailIntent = new Intent(this, SinglePaneDetailActivity.class);
+ detailIntent.putExtra("item_id", id);
+ startActivity(detailIntent);
+ }
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/SinglePaneDetailActivity.java b/tests/uiautomator/app/src/com/android/uiautomator/app/SinglePaneDetailActivity.java
new file mode 100644
index 0000000..553557e
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/SinglePaneDetailActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.NavUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+
+public class SinglePaneDetailActivity extends FragmentActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.singlepane_activity);
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+
+ if (savedInstanceState == null) {
+ Fragment fragment = TestItems.getFragment(getIntent().getStringExtra("item_id"));
+ getSupportFragmentManager().beginTransaction()
+ .add(R.id.test_results_detail_container, fragment).commit();
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.test_results_detail_activity, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ NavUtils.navigateUpFromSameTask(this);
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test1DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test1DetailFragment.java
new file mode 100644
index 0000000..f7dccb3
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/Test1DetailFragment.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+
+public class Test1DetailFragment extends Fragment {
+
+ public static final String ARG_ITEM_ID = "item_id";
+ private Button mSubmitButton;
+ private EditText mEditText;
+ TestItems.TestItem mItem;
+
+ public Test1DetailFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments().containsKey(ARG_ITEM_ID)) {
+ mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID));
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ View rootView = inflater.inflate(R.layout.test1_detail_fragment, container, false);
+ if (mItem != null) {
+ ((EditText) rootView.findViewById(R.id.test1TextField)).setText(mItem.mName);
+
+ mSubmitButton = (Button) rootView.findViewById(R.id.test1SubmitButton);
+ mEditText = (EditText) rootView.findViewById(R.id.test1TextField);
+ mEditText.setText("");
+ mSubmitButton.setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final String savedInput = mEditText.getText().toString();
+ // clear so we won't be confused by the input text in
+ // validation
+ mEditText.setText("");
+ // close soft keyboard
+ InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
+ // display the submitted text
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.item1_dialog_title);
+ builder.setPositiveButton(R.string.OK, null);
+ builder.setMessage(savedInput);
+ AlertDialog diag = builder.create();
+ diag.show();
+ }
+ });
+ }
+ return rootView;
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test2DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test2DetailFragment.java
new file mode 100644
index 0000000..1cb3a69
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/Test2DetailFragment.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.app.AlertDialog;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+public class Test2DetailFragment extends Fragment {
+ public static final String ARG_ITEM_ID = "item_id";
+ private Button mButton1, mButton2, mButton3, mDynaButton;
+
+ public Test2DetailFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.test2_detail_activity, menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_title_result);
+ builder.setMessage(item.getTitle());
+ builder.setPositiveButton(R.string.OK, null);
+ AlertDialog diag = builder.create();
+ diag.show();
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ View rootView = inflater.inflate(R.layout.test2_detail_fragment, container, false);
+
+ mButton1 = (Button) rootView.findViewById(R.id.test2button1);
+ mButton2 = (Button) rootView.findViewById(R.id.test2button2);
+ mButton3 = (Button) rootView.findViewById(R.id.test2button3);
+ mDynaButton = (Button) rootView.findViewById(R.id.test2dynaButton);
+
+ mButton1.setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_title_result);
+ builder.setPositiveButton(R.string.OK, null);
+ builder.setMessage(R.string.button1);
+ AlertDialog diag = builder.create();
+ diag.show();
+ }
+ });
+
+ mButton1.setOnLongClickListener(new Button.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_title_result);
+ builder.setPositiveButton(R.string.OK, null);
+ builder.setMessage(R.string.button1long);
+ AlertDialog diag = builder.create();
+ diag.show();
+ return true;
+ }
+ });
+
+ mButton2.setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_title_result);
+ builder.setPositiveButton(R.string.OK, null);
+ builder.setMessage(R.string.button2);
+ AlertDialog diag = builder.create();
+ diag.show();
+ }
+ });
+
+ mButton2.setOnLongClickListener(new Button.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_title_result);
+ builder.setPositiveButton(R.string.OK, null);
+ builder.setMessage(R.string.button2long);
+ AlertDialog diag = builder.create();
+ diag.show();
+ return true;
+ }
+ });
+
+ mButton3.setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_title_result);
+ builder.setPositiveButton(R.string.OK, null);
+ builder.setMessage(R.string.button3);
+ AlertDialog diag = builder.create();
+ diag.show();
+ }
+ });
+
+ mButton3.setOnLongClickListener(new Button.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_title_result);
+ builder.setPositiveButton(R.string.OK, null);
+ builder.setMessage(R.string.button3long);
+ AlertDialog diag = builder.create();
+ diag.show();
+ return true;
+ }
+ });
+
+ mDynaButton.setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mDynaButton.setText(R.string.buttonAfter);
+ mDynaButton.setContentDescription(getString(R.string.buttonAfter));
+ }
+ });
+
+ return rootView;
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test3DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test3DetailFragment.java
new file mode 100644
index 0000000..cc76401
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/Test3DetailFragment.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+public class Test3DetailFragment extends Fragment {
+
+ public static final String ARG_ITEM_ID = "item_id";
+ private TextView mTextClock;
+ private Button mSubmitButton;
+ private EditText mEditText;
+ private long mCurrentTime;
+ private final Object sync = new Object();
+ private boolean mRunCounter = true;
+
+ public Test3DetailFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.test2_detail_activity, menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_title_result);
+ builder.setMessage(item.getTitle());
+ builder.setPositiveButton(R.string.OK, null);
+ AlertDialog diag = builder.create();
+ diag.show();
+ return super.onOptionsItemSelected(item);
+ }
+
+ private final Handler mHandler = new Handler();
+
+ final Runnable mClockRunnable = new Runnable() {
+ @Override
+ public void run() {
+ // call the activity method that updates the UI
+ updateClockOnUi();
+ }
+ };
+
+ private void updateClockOnUi() {
+ synchronized (sync) {
+ mTextClock.setText("" + mCurrentTime);
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ View rootView = inflater.inflate(R.layout.test3_detail_fragment, container, false);
+ mTextClock = (TextView) rootView.findViewById(R.id.test3ClockTextView);
+ mSubmitButton = (Button) rootView.findViewById(R.id.test3SubmitButton);
+ mEditText = (EditText) rootView.findViewById(R.id.test3TextField);
+ mSubmitButton.setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // close soft keyboard
+ InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
+
+ // display the submitted text
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.test3_dialog_title);
+ builder.setPositiveButton(R.string.OK, null);
+ CharSequence inputText = mEditText.getText();
+ if (inputText != null && !inputText.toString().isEmpty()) {
+ long inputTime = Long.parseLong(inputText.toString());
+ builder.setMessage("" + (mCurrentTime - inputTime));
+ } else {
+ builder.setMessage("<NO DATA>");
+ }
+ AlertDialog diag = builder.create();
+ diag.show();
+ mEditText.setText("");
+ mRunCounter = false;
+ }
+ });
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ while (mRunCounter) {
+ synchronized (sync) {
+ mCurrentTime = SystemClock.elapsedRealtime();
+ }
+ mHandler.post(mClockRunnable);
+ SystemClock.sleep(100);
+ }
+ }
+ }).start();
+
+ return rootView;
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test4DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test4DetailFragment.java
new file mode 100644
index 0000000..cc7b9f8
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/Test4DetailFragment.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.app.ActionBar;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class Test4DetailFragment extends Fragment implements ActionBar.TabListener {
+ public static final String ARG_ITEM_ID = "item_id";
+
+ /**
+ * The {@link android.support.v4.view.PagerAdapter} that will provide
+ * fragments for each of the sections. We use a
+ * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
+ * will keep every loaded fragment in memory. If this becomes too memory
+ * intensive, it may be best to switch to a
+ * {@link android.support.v4.app.FragmentStatePagerAdapter}.
+ */
+ SectionsPagerAdapter mSectionsPagerAdapter;
+
+ /**
+ * The {@link ViewPager} that will host the section contents.
+ */
+ ViewPager mViewPager;
+
+ public Test4DetailFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onDestroyView() {
+ getActivity().getActionBar().removeAllTabs();
+ super.onDestroyView();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+
+ View rootView = inflater.inflate(R.layout.test4_detail_fragment, container, false);
+
+ // Set up the action bar.
+ final ActionBar actionBar = getActivity().getActionBar();
+ if (actionBar.getTabCount() > 0) {
+ return rootView;
+ }
+ actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+
+ // Create the adapter that will return a fragment for each of the three
+ // primary sections of the app.
+ mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity().getSupportFragmentManager());
+
+ // Set up the ViewPager with the sections adapter.
+ mViewPager = (ViewPager) rootView.findViewById(R.id.test_4_detail_container);
+ mViewPager.setAdapter(mSectionsPagerAdapter);
+
+ // When swiping between different sections, select the corresponding
+ // tab. We can also use ActionBar.Tab#select() to do this if we have a
+ // reference to the Tab.
+ mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
+ @Override
+ public void onPageSelected(int position) {
+ actionBar.setSelectedNavigationItem(position);
+ }
+ });
+
+ // For each of the sections in the app, add a tab to the action bar.
+ for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
+ // Create a tab with text corresponding to the page title defined by
+ // the adapter. Also specify this Activity object, which implements
+ // the TabListener interface, as the listener for when this tab is
+ // selected.
+ actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i))
+ .setTabListener(this));
+ }
+ return rootView;
+ }
+
+ @Override
+ public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
+ }
+
+ @Override
+ public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
+ }
+
+ @Override
+ public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
+ }
+
+ /**
+ * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
+ * one of the primary sections of the app.
+ */
+ public class SectionsPagerAdapter extends FragmentPagerAdapter {
+
+ public SectionsPagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ @Override
+ public Fragment getItem(int i) {
+ Fragment fragment = new DummySectionFragment();
+ Bundle args = new Bundle();
+ args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public int getCount() {
+ return 4;
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ switch (position) {
+ case 0:
+ return getString(R.string.title_section1).toUpperCase();
+ case 1:
+ return getString(R.string.title_section2).toUpperCase();
+ case 2:
+ return getString(R.string.title_section3).toUpperCase();
+ case 3:
+ return getString(R.string.title_section4).toUpperCase();
+ }
+ return null;
+ }
+ }
+
+ /**
+ * A dummy fragment representing a section of the app, but that simply
+ * displays dummy text.
+ */
+ public static class DummySectionFragment extends Fragment {
+ public DummySectionFragment() {
+ }
+
+ public static final String ARG_SECTION_NUMBER = "section_number";
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ TextView textView = new TextView(getActivity());
+ textView.setGravity(Gravity.CENTER);
+ Bundle args = getArguments();
+ textView.setText("[ " + Integer.toString(args.getInt(ARG_SECTION_NUMBER)) + " ]");
+ return textView;
+ }
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test5DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test5DetailFragment.java
new file mode 100644
index 0000000..0e3eec4
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/Test5DetailFragment.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.app.AlertDialog;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ImageButton;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+
+public class Test5DetailFragment extends Fragment {
+
+ public static final String ARG_ITEM_ID = "item_id";
+
+ class PointerEvent {
+ int startX;
+ int startY;
+ int endX;
+ int endY;
+ }
+
+ private final PointerEvent mPointerEvent = new PointerEvent();
+
+ public Test5DetailFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ View rootView = inflater.inflate(R.layout.test5_detail_fragment, container, false);
+
+ // Set the content description for the following
+ Spinner spinner = (Spinner) rootView.findViewById(R.id.test_5_spinner);
+ spinner.setContentDescription("Spinner");
+ ImageButton imageButton = (ImageButton) rootView.findViewById(R.id.test_5_imageButton);
+ imageButton.setContentDescription("Image button");
+
+ // Each time this view is displayed, reset the following states
+ SeekBar seekBar = (SeekBar) rootView.findViewById(R.id.test_5_seekBar);
+ seekBar.setProgress(50);
+ seekBar.setContentDescription("Progress is 50 %");
+ CheckBox checkbox = (CheckBox) rootView.findViewById(R.id.test_5_checkBox);
+ checkbox.setChecked(false);
+
+ // Register click event handlers for the following
+ Button button = (Button) rootView.findViewById(R.id.test_5_button1);
+ button.setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // we want an artificial crash
+ throw new RuntimeException("Artificial crash to test UiWatcher");
+ }
+ });
+
+ imageButton.setOnTouchListener(new ImageButton.OnTouchListener() {
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ resetTouchResults();
+ collectStartAction(event, v);
+ } else if (event.getAction() == MotionEvent.ACTION_UP) {
+ collectEndAction(event, v);
+ displayTouchResults();
+ }
+ return false;
+ }
+ });
+
+ return rootView;
+ }
+
+ private void displayTouchResults() {
+ StringBuilder output = new StringBuilder();
+
+ output.append(String.format("%d,%d:%d,%d\n",
+ mPointerEvent.startX, mPointerEvent.startY, mPointerEvent.endX,
+ mPointerEvent.endY));
+
+ // display the submitted text
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.drag_item_touch_dialog_title);
+ builder.setPositiveButton(R.string.OK, null);
+ builder.setMessage(output.toString());
+ AlertDialog diag = builder.create();
+ diag.show();
+ }
+
+ /**
+ * Clears all collected pointer results
+ */
+ private void resetTouchResults() {
+ mPointerEvent.startX = mPointerEvent.startY =
+ mPointerEvent.endX = mPointerEvent.endY = -1;
+ }
+
+ /**
+ * Collects pointer touch information converting from relative to absolute before
+ * storing it as starting touch coordinates.
+ *
+ * @param event
+ * @param view
+ * @param pointerIndex
+ */
+ private void collectStartAction(MotionEvent event, View view) {
+ int offsetInScreen[] = new int[2];
+ view.getLocationOnScreen(offsetInScreen);
+ mPointerEvent.startX = (int)(event.getX() + offsetInScreen[0]);
+ mPointerEvent.startY = (int)(event.getY() + offsetInScreen[1]);
+ }
+
+ /**
+ * Collects pointer touch information converting from relative to absolute before
+ * storing it as ending touch coordinates.
+ *
+ * @param event
+ * @param view
+ * @param pointerIndex
+ */
+ private void collectEndAction(MotionEvent event, View view) {
+ int offsetInScreen[] = new int[2];
+ view.getLocationOnScreen(offsetInScreen);
+ mPointerEvent.endX = (int)(event.getX() + offsetInScreen[0]);
+ mPointerEvent.endY = (int)(event.getY() + offsetInScreen[1]);
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test6DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test6DetailFragment.java
new file mode 100644
index 0000000..d1149a6
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/Test6DetailFragment.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebView;
+
+public class Test6DetailFragment extends Fragment {
+ public static final String ARG_ITEM_ID = "item_id";
+ private final static String PAGE = "<html><body>"
+ + "This is test <b>6</b> for WebView text traversal test."
+ + "<p/><a href=\"http://google.com\">This is a link to google</a><br/>"
+ + "<h5>This is h5 text</h5>"
+ + "<a href=\"http://yahoo.com\">This is a link to yahoo</a>"
+ + "<p/><h4>This is h4 text</h4>" + "</body></html>";
+
+ public Test6DetailFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ View rootView = inflater.inflate(R.layout.test6_detail_fragment, container, false);
+ WebView wv = (WebView) rootView.findViewById(R.id.test6WebView);
+ wv.loadData(PAGE, "text/html", null);
+ return rootView;
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/TestGenericDetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/TestGenericDetailFragment.java
new file mode 100644
index 0000000..d87a849
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/TestGenericDetailFragment.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.app.AlertDialog;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class TestGenericDetailFragment extends Fragment {
+ public static final String ARG_ITEM_ID = "item_id";
+ TestItems.TestItem mItem;
+
+ private class PointerEvent {
+ int startX;
+ int startY;
+ int endX;
+ int endY;
+ }
+
+ private final PointerEvent[] mPointerEvents = new PointerEvent[10];
+
+ public TestGenericDetailFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments().containsKey(ARG_ITEM_ID)) {
+ mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID));
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ View rootView = inflater.inflate(R.layout.test_results_detail_fragment, container, false);
+ if (mItem != null) {
+ ((TextView) rootView.findViewById(R.id.testResultsTextView)).setText(mItem.mName);
+ }
+
+ // listen to touch events to verify the multiPointerGesture APIs
+ // Since API Level 18
+ rootView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+
+ switch(event.getAction() & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN:
+ // Reset any collected touch coordinate results on the primary touch down
+ resetTouchResults();
+ // collect this event
+ collectStartAction(event, v, 0);
+ break;
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ // collect this event
+ collectStartAction(event, v, getPointerIndex(event));
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ // collect this event
+ collectEndAction(event, v, getPointerIndex(event));
+ break;
+
+ case MotionEvent.ACTION_UP:
+ // collect this event
+ collectEndAction(event, v, 0);
+ // on the primary touch up display results collected for all pointers
+ displayTouchResults();
+ break;
+ }
+ return true;
+ }
+ });
+
+ return rootView;
+ }
+
+ /**
+ * Displays collected results from all pointers into a dialog view in the following
+ * format: "startX,startY:endX,endY" where each line represent data for a pointer if
+ * multiple pointers (fingers) were detected.
+ */
+ private void displayTouchResults() {
+ StringBuilder output = new StringBuilder();
+ for (int x = 0; x < mPointerEvents.length; x++) {
+ if (mPointerEvents[x].startX == -1)
+ break;
+
+ output.append(String.format("%d,%d:%d,%d\n",
+ mPointerEvents[x].startX, mPointerEvents[x].startY, mPointerEvents[x].endX,
+ mPointerEvents[x].endY));
+ }
+
+ // display the submitted text
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.generic_item_touch_dialog_title);
+ builder.setPositiveButton(R.string.OK, null);
+ builder.setMessage(output.toString());
+ AlertDialog diag = builder.create();
+ diag.show();
+ }
+
+ /**
+ * Clears all collected pointer results
+ */
+ private void resetTouchResults() {
+ for (int x = 0; x < mPointerEvents.length; x++) {
+ if (mPointerEvents[x] == null)
+ mPointerEvents[x] = new PointerEvent();
+ mPointerEvents[x].startX = mPointerEvents[x].startY =
+ mPointerEvents[x].endX = mPointerEvents[x].endY = -1;
+ }
+ }
+
+ /**
+ * Collects pointer touch information converting from relative to absolute before
+ * storing it as starting touch coordinates.
+ *
+ * @param event
+ * @param view
+ * @param pointerIndex
+ */
+ private void collectStartAction(MotionEvent event, View view, int pointerIndex) {
+ int offsetInScreen[] = new int[2];
+ view.getLocationOnScreen(offsetInScreen);
+ mPointerEvents[getPointerId(event)].startX =
+ (int)(event.getX(pointerIndex) + offsetInScreen[0]);
+ mPointerEvents[getPointerId(event)].startY =
+ (int)(event.getY(pointerIndex) + offsetInScreen[1]);
+ }
+
+ /**
+ * Collects pointer touch information converting from relative to absolute before
+ * storing it as ending touch coordinates.
+ *
+ * @param event
+ * @param view
+ * @param pointerIndex
+ */
+ private void collectEndAction(MotionEvent event, View view, int pointerIndex) {
+ int offsetInScreen[] = new int[2];
+ view.getLocationOnScreen(offsetInScreen);
+ mPointerEvents[getPointerId(event)].endX =
+ (int)(event.getX(pointerIndex) + offsetInScreen[0]);
+ mPointerEvents[getPointerId(event)].endY =
+ (int)(event.getY(pointerIndex) + offsetInScreen[1]);
+ }
+
+ private int getPointerId(MotionEvent event) {
+ return event.getPointerId(getPointerIndex(event));
+ }
+
+ private int getPointerIndex(MotionEvent event) {
+ return ((event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
+ >> MotionEvent.ACTION_POINTER_INDEX_SHIFT);
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/TestItems.java b/tests/uiautomator/app/src/com/android/uiautomator/app/TestItems.java
new file mode 100644
index 0000000..89886fe
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/TestItems.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TestItems {
+ private static String LOG_TAG = TestItems.class.getSimpleName();
+ private static List<TestItem> ITEMS = new ArrayList<TestItem>();
+ private static Map<String, TestItem> ITEM_MAP = new HashMap<String, TestItem>();
+
+ public static class TestItem {
+ public String mId;
+ public String mName;
+ private final Class<Fragment> mClassFragment;
+ public String mTestDescription;
+
+ @SuppressWarnings("unchecked")
+ public TestItem(String id, String name, Class<?> clsf) {
+ mId = id;
+ mName = name;
+ mClassFragment = (Class<Fragment>) clsf;
+ }
+
+ @Override
+ public String toString() {
+ return mName;
+ }
+ }
+
+ static {
+ addTestItem(new TestItem("1", "Test 1", Test1DetailFragment.class));
+ addTestItem(new TestItem("2", "Test 2", Test2DetailFragment.class));
+ addTestItem(new TestItem("3", "Test 3", Test3DetailFragment.class));
+ addTestItem(new TestItem("4", "Test 4", Test4DetailFragment.class));
+ addTestItem(new TestItem("5", "Test 5", Test5DetailFragment.class));
+ addTestItem(new TestItem("6", "Test 6", Test6DetailFragment.class));
+ addTestItem(new TestItem("7", "Test 7", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("8", "Test 8", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("9", "Test 9", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("10", "Test 10", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("11", "Test 11", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("12", "Test 12", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("13", "Test 13", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("14", "Test 14", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("15", "Test 15", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("16", "Test 16", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("17", "Test 17", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("18", "Test 18", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("19", "Test 19", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("20", "Test 20", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("21", "Test 21", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("22", "Test 22", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("23", "Test 23", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("24", "Test 24", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("25", "Test 25", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("26", "Test 26", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("27", "Test 27", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("28", "Test 28", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("29", "Test 29", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("30", "Test 30", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("31", "Test 31", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("32", "Test 32", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("33", "Test 33", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("34", "Test 34", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("35", "Test 35", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("36", "Test 36", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("37", "Test 37", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("38", "Test 38", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("39", "Test 39", TestGenericDetailFragment.class));
+ addTestItem(new TestItem("40", "Test 40", TestGenericDetailFragment.class));
+ }
+
+ private static void addTestItem(TestItem item) {
+ ITEMS.add(item);
+ ITEM_MAP.put(item.mId, item);
+ }
+
+ public static List<TestItem> getTests() {
+ return ITEMS;
+ }
+
+ public static TestItem getTest(String id) {
+ return ITEM_MAP.get(id);
+ }
+
+ public static TestItem getTest(int pos) {
+ return ITEMS.get(pos);
+ }
+
+ public static Fragment getFragment(String id) {
+ try {
+ Fragment fragment = getTest(id).mClassFragment.newInstance();
+ Bundle arguments = new Bundle();
+ arguments.putString("item_id", id);
+ fragment.setArguments(arguments);
+ return fragment;
+ } catch (InstantiationException e) {
+ Log.e(LOG_TAG, "Exception", e);
+ return null;
+ } catch (IllegalAccessException e) {
+ Log.e(LOG_TAG, "Exception", e);
+ return null;
+ }
+ }
+}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/TestListFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/TestListFragment.java
new file mode 100644
index 0000000..ba981cb
--- /dev/null
+++ b/tests/uiautomator/app/src/com/android/uiautomator/app/TestListFragment.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public class TestListFragment extends ListFragment {
+
+ private static final String STATE_ACTIVATED_POSITION = "activated_position";
+
+ private Callbacks mCallbacks = sDummyCallbacks;
+ private int mActivatedPosition = ListView.INVALID_POSITION;
+
+ public interface Callbacks {
+
+ public void onItemSelected(String id);
+ }
+
+ private static Callbacks sDummyCallbacks = new Callbacks() {
+ @Override
+ public void onItemSelected(String id) {
+ }
+ };
+
+ public TestListFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setListAdapter(new ArrayAdapter<TestItems.TestItem>(getActivity(),
+ R.layout.simple_list_item_selected, R.id.label, TestItems.getTests()));
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedState) {
+ super.onViewCreated(view, savedState);
+ if (savedState != null && savedState.containsKey(STATE_ACTIVATED_POSITION)) {
+ setActivatedPosition(savedState.getInt(STATE_ACTIVATED_POSITION));
+ }
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ if (!(activity instanceof Callbacks)) {
+ throw new IllegalStateException("Activity must implement fragment's callbacks.");
+ }
+
+ mCallbacks = (Callbacks) activity;
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mCallbacks = sDummyCallbacks;
+ }
+
+ @Override
+ public void onListItemClick(ListView listView, View view, int position, long id) {
+ super.onListItemClick(listView, view, position, id);
+ mCallbacks.onItemSelected(TestItems.getTest(position).mId);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ if (mActivatedPosition != ListView.INVALID_POSITION) {
+ outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
+ }
+ }
+
+ public void setActivateOnItemClick(boolean activateOnItemClick) {
+ getListView().setChoiceMode(
+ activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
+ }
+
+ public void setActivatedPosition(int position) {
+ if (position == ListView.INVALID_POSITION) {
+ getListView().setItemChecked(mActivatedPosition, false);
+ } else {
+ getListView().setItemChecked(position, true);
+ }
+
+ mActivatedPosition = position;
+ }
+}
diff --git a/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java b/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java
deleted file mode 100644
index 7e4c367..0000000
--- a/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java
+++ /dev/null
@@ -1,1072 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomatortest;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.util.Log;
-
-import com.android.uiautomator.core.UiCollection;
-import com.android.uiautomator.core.UiDevice;
-import com.android.uiautomator.core.UiObject;
-import com.android.uiautomator.core.UiObjectNotFoundException;
-import com.android.uiautomator.core.UiScrollable;
-import com.android.uiautomator.core.UiSelector;
-import com.android.uiautomator.core.UiWatcher;
-import com.android.uiautomator.testrunner.UiAutomatorTestCase;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Sanity test uiautomator functionality on target device.
- */
-public class CtsUiAutomatorTest extends UiAutomatorTestCase {
- private static final String LOG_TAG = CtsUiAutomatorTest.class.getSimpleName();
- private static final String[] LIST_SCROLL_TESTS = new String[] {
- "Test 17", "Test 11", "Test 20", "Test 35"
- };
- private static final String LAUNCH_APP = "am start -a android.intent.action.MAIN"
- + " -n com.android.cts.uiautomator/.MainActivity -W";
- private static final String PKG_NAME = "com.android.cts.uiautomator";
-
- // Maximum wait for key object to become visible
- private static final int WAIT_EXIST_TIMEOUT = 5 * 1000;
-
- private static final String SCREEN_SHOT_FILE_PATH_NAME = "/data/local/tmp/ctsScreenShot";
-
- // Should match the value defined in UiObject
- private static final int FINGER_TOUCH_HALF_WIDTH = 20;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // Make sure the test app is always running
- UiDevice.getInstance().waitForIdle();
- if (!new UiObject(new UiSelector().packageName(PKG_NAME)).exists())
- runShellCommand(LAUNCH_APP);
- }
-
- /**
- * Helper to execute a command on the shell
- *
- * @throws IOException
- * @throws InterruptedException
- */
- private void runShellCommand(String command) throws IOException, InterruptedException {
- Process p = null;
- BufferedReader resultReader = null;
- try {
- p = Runtime.getRuntime().exec(command);
- int status = p.waitFor();
- if (status != 0) {
- throw new RuntimeException(String.format("Run shell command: %s, status: %s",
- command, status));
- }
- } finally {
- if (resultReader != null) {
- resultReader.close();
- }
- if (p != null) {
- p.destroy();
- }
- }
- }
-
- /*
- * Items in the listScrollTests array should be spread out such that a
- * scroll is required to reach each item at each of the far ends.
- */
- public void testListScrollAndSelect() throws UiObjectNotFoundException {
- UiScrollable listView = new UiScrollable(
- new UiSelector().className(android.widget.ListView.class.getName()));
-
- // on single fragment display
- if (!listView.exists())
- UiDevice.getInstance().pressBack();
-
- for (String test : LIST_SCROLL_TESTS) {
- openTest(test);
- verifyTestDetailsExists(test);
- }
- }
-
- /**
- * Test erasing of multi word text in edit field and input of new text. Test
- * verifying input text using a complex UiSelector
- *
- * @throws UiObjectNotFoundException
- */
- public void testTextEraseAndInput() throws UiObjectNotFoundException {
- String testText = "Android Ui Automator Input Text";
- openTest("Test 1");
-
- UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
- .getName()));
- editText.setText(testText);
-
- UiObject submitButton = new UiObject(new UiSelector()
- .className(android.widget.Button.class.getName()).clickable(true)
- .textStartsWith("Submit"));
- submitButton.click();
-
- UiObject result = new UiObject(new UiSelector().className(
- android.widget.LinearLayout.class.getName()).childSelector(
- (new UiSelector().className(android.widget.ScrollView.class.getName())
- .childSelector(new UiSelector().className(android.widget.TextView.class
- .getName())))));
-
- if (!testText.equals(result.getText())) {
- throw new UiObjectNotFoundException("Test text: " + testText);
- }
-
- getObjectByText("OK").click();
- }
-
- /**
- * Select each of the buttons by using only the content description property
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectByContentDescription() throws UiObjectNotFoundException {
- openTest("Test 2");
- getObjectByDescription("Button 1").click();
- verifyDialogActionResults("Button 1");
- getObjectByDescription("Button 2").click();
- verifyDialogActionResults("Button 2");
- getObjectByDescription("Button 3").click();
- verifyDialogActionResults("Button 3");
- }
-
- /**
- * Select each of the buttons by using only the text property
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectByText() throws UiObjectNotFoundException {
- openTest("Test 2");
- getObjectByText("Button 1").click();
- verifyDialogActionResults("Button 1");
- getObjectByText("Button 2").click();
- verifyDialogActionResults("Button 2");
- getObjectByText("Button 3").click();
- verifyDialogActionResults("Button 3");
- }
-
- /**
- * Select each of the buttons by using only the index property
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectByIndex() throws UiObjectNotFoundException {
- openTest("Test 2");
- getObjectByIndex(android.widget.Button.class.getName(), 0).click();
- verifyDialogActionResults("Button 1");
- getObjectByIndex(android.widget.Button.class.getName(), 1).click();
- verifyDialogActionResults("Button 2");
- getObjectByIndex(android.widget.Button.class.getName(), 2).click();
- verifyDialogActionResults("Button 3");
- }
-
- /**
- * Select each of the buttons by using only the instance number
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectByInstance() throws UiObjectNotFoundException {
- openTest("Test 2");
- getObjectByInstance(android.widget.Button.class.getName(), 0).click();
- verifyDialogActionResults("Button 1");
- getObjectByInstance(android.widget.Button.class.getName(), 1).click();
- verifyDialogActionResults("Button 2");
- getObjectByInstance(android.widget.Button.class.getName(), 2).click();
- verifyDialogActionResults("Button 3");
- }
-
- /**
- * Test when a node's state is changed due to an action, it is updated in the accessibility
- * hierarchy.
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectAfterContentChanged() throws UiObjectNotFoundException {
- openTest("Test 2");
- UiObject dynaButton = getObjectByText("Before");
- dynaButton.click();
- assertTrue("Button state change is not refreshed in accessibility hierarchy",
- getObjectByText("After").exists());
- }
-
- /**
- * Test opening the options menu using the soft buttons
- *
- * @throws UiObjectNotFoundException
- * @throws InterruptedException
- * @throws IOException
- */
- public void testDeviceSoftKeys() throws UiObjectNotFoundException, IOException,
- InterruptedException {
- openTest("Test 2");
- UiDevice device = UiDevice.getInstance();
- device.pressMenu();
- getObjectByText("Finish").click();
- verifyDialogActionResults("Finish");
-
- // Back button
- openTest("Test 1");
- UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
- .getName()));
- editText.setText("Android Geppetto Test Application");
-
- UiObject submitButton = new UiObject(new UiSelector()
- .className(android.widget.Button.class.getName()).clickable(true)
- .textStartsWith("Submit"));
- submitButton.click();
-
- // Text from the popup dialog
- UiObject result = new UiObject(new UiSelector().textContains("geppetto"));
-
- // Back button test to dismiss the dialog
- assertTrue("Wait for exist must return true", result.waitForExists(2000));
- device.pressBack();
- result.waitUntilGone(1000);
- assertFalse("Wait for exist must return false after press back", result.exists());
-
- // Home button test
- openTest("Test 5");
- String pkgName = device.getCurrentPackageName();
- assertTrue("CTS test app must be running", pkgName.equals(PKG_NAME));
- device.pressHome();
- boolean gone = new UiObject(new UiSelector().packageName(PKG_NAME)).waitUntilGone(5000);
- assertTrue("CTS test app still visble after pressing home", gone);
- }
-
- /**
- * This view is in constant update generating window content changed events.
- * The test will read the time displayed and exhaust each wait for idle
- * timeout until it read and sets the text back into the edit field and
- * presses submit. A dialog box should pop up with the time it took since
- * reading the value until pressing submit.
- *
- * @throws UiObjectNotFoundException
- */
- public void testWaitForIdleTimeout() throws UiObjectNotFoundException {
- openTest("Test 3");
- UiObject clk = new UiObject(new UiSelector().descriptionStartsWith("Performance "));
-
- // First default wait for idle timeout assumed to be 10 seconds
- String txtTime = clk.getText();
- UiObject edit = new UiObject(new UiSelector().className(android.widget.EditText.class
- .getName()));
-
- // Second default wait for idle timeout assumed to be 10 seconds.
- // Total ~20.
- edit.setText(txtTime);
-
- // Third default wait for idle timeout assumed to be 10 seconds.
- // Total ~30.
- getObjectByText("Submit").click();
-
- // The value read should have value between 30 and 60 seconds indicating
- // that the internal default timeouts for wait-for-idle is in acceptable
- // range.
- UiObject readTime = new UiObject(new UiSelector().className(
- android.widget.TextView.class.getName()).instance(1));
- String timeDiff = readTime.getText();
- Log.i(LOG_TAG, "Sync time: " + timeDiff);
-
- getObjectByText("OK").click();
-
- int totalDelay = Integer.parseInt(timeDiff);
-
- // Cumulative waits in this test should add up to at minimum 30 seconds
- assertFalse("Timeout for wait-for-idle is too short. Expecting minimum 30 seconds",
- totalDelay < 30 * 1000);
-
- // allow for tolerance in time measurements due to differences between
- // device speeds
- assertFalse("Timeout for wait-for-idle is too long. Expecting maximum 60 seconds",
- totalDelay > 60 * 1000);
- }
-
- /**
- * This view is in constant update generating window content changed events.
- * This test uses the soft key presses and clicks while the background
- * screen is constantly updating causing a constant busy state.
- *
- * @throws UiObjectNotFoundException
- */
- public void testVerifyMenuClicks() throws UiObjectNotFoundException {
- openTest("Test 3");
- UiDevice.getInstance().pressMenu();
- new UiObject(new UiSelector().text("Submit")).click();
- verifyDialogActionResults("Submit");
- UiDevice.getInstance().pressMenu();
- new UiObject(new UiSelector().text("Exit")).click();
- verifyDialogActionResults("Exit");
- }
-
- /**
- * Verifies swipeRight, swipeLeft and raw swipe APIs perform as expected.
- *
- * @throws UiObjectNotFoundException
- */
- public void testSwipes() throws UiObjectNotFoundException {
- openTest("Test 4");
- UiObject textView = new UiObject(new UiSelector().textContains("["));
-
- textView.swipeLeft(10);
- assertTrue("UiObject swipe left 1->2", "[ 2 ]".equals(textView.getText()));
-
- textView.swipeLeft(10);
- assertTrue("UiObject swipe left 2->3", "[ 3 ]".equals(textView.getText()));
-
- textView.swipeLeft(10);
- assertTrue("UiObject swipe left 3->4", "[ 4 ]".equals(textView.getText()));
-
- textView.swipeRight(10);
- assertTrue("UiObject swipe right 3<-4", "[ 3 ]".equals(textView.getText()));
-
- textView.swipeRight(10);
- assertTrue("UiObject swipe right 2<-3", "[ 2 ]".equals(textView.getText()));
-
- textView.swipeRight(10);
- assertTrue("UiObject swipe right 1<-2", "[ 1 ]".equals(textView.getText()));
-
- Rect tb = textView.getBounds();
- UiDevice.getInstance().swipe(tb.right - 20, tb.centerY(), tb.left + 20, tb.centerY(), 50);
-
- SystemClock.sleep(100);
- assertTrue("UiDevice raw swipe 1->2", "[ 2 ]".equals(textView.getText()));
- }
-
- /**
- * Creates a complex selector
- *
- * @throws UiObjectNotFoundException
- */
- public void testComplexSelectors() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiSelector frameLayout = new UiSelector().className(android.widget.FrameLayout.class
- .getName());
- UiSelector gridLayout = new UiSelector().className(android.widget.GridLayout.class
- .getName());
- UiSelector toggleButton = new UiSelector().className(android.widget.ToggleButton.class
- .getName());
- UiObject button = new UiObject(frameLayout.childSelector(gridLayout).childSelector(
- toggleButton));
-
- assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
- button.click();
- assertTrue("Toggle button value should be ON", "ON".equals(button.getText()));
- button.click();
- assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
- }
-
- /**
- * Test when an object does not exist, an exception is thrown
- * @throws UiObjectNotFoundException
- */
- public void testExceptionObjectNotFound() throws UiObjectNotFoundException {
- UiSelector selector = new UiSelector().text("Nothing should be found");
- UiSelector child = new UiSelector().className("Nothing");
- UiObject obj = new UiObject(selector.childSelector(child));
-
- assertFalse("Object is reported as existing", obj.exists());
-
- try {
- obj.click();
- } catch (UiObjectNotFoundException e) {
- return;
- }
- assertTrue("Exception not thrown for Object not found", false);
- }
-
- /**
- * Verifies the UiWatcher registration and trigger function
- *
- * @throws UiObjectNotFoundException
- */
- public void testUiWatcher() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiDevice device = UiDevice.getInstance();
- device.registerWatcher("Artificial crash", new UiWatcher() {
-
- @Override
- public boolean checkForCondition() {
- if (new UiObject(new UiSelector().packageName("android")).exists()) {
- try {
- // Expecting a localized OK button
- new UiObject(new UiSelector().className(
- android.widget.Button.class.getName()).enabled(true)).click();
- } catch (UiObjectNotFoundException e) {
- }
- return true;
- }
- return false;
- }
- });
-
- // Causes a runtime exception to be thrown
- getObjectByText("Button").click();
-
- // Fake doing something while the exception is being displayed
- SystemClock.sleep(2000);
- device.runWatchers();
- assertTrue("UiWatcher not triggered", device.hasAnyWatcherTriggered());
- }
-
- /**
- * Verifies the 'checked' property of both UiSelector and UiObject
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectorChecked() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiObject checkboxChecked = new UiObject(new UiSelector().className(
- android.widget.CheckBox.class.getName()).checked(true));
- UiObject checkboxNotChecked = new UiObject(new UiSelector().className(
- android.widget.CheckBox.class.getName()).checked(false));
-
- checkboxNotChecked.click();
- assertTrue("Checkbox should be checked", checkboxChecked.isChecked());
- checkboxChecked.click();
- assertFalse("Checkbox should be unchecked", checkboxNotChecked.isChecked());
- }
-
- /**
- * Verifies the 'Clickable' property of both the UiSelector and UiObject
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectorClickable() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiSelector clickableCheckbox = new UiSelector().clickable(true).className(
- android.widget.CheckBox.class.getName());
- UiSelector notClickableProgress = new UiSelector().clickable(false).className(
- android.widget.ProgressBar.class.getName());
-
- assertTrue("Selector clickable", new UiObject(clickableCheckbox).isClickable());
- assertFalse("Selector not clickable", new UiObject(notClickableProgress).isClickable());
- }
-
- /**
- * Verifies the 'focusable' property of both UiSelector and UiObject
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectorFocusable() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiSelector mainLayout = new UiSelector().description("Widgets Collection");
- UiSelector focusableCheckbox = mainLayout.childSelector(new UiSelector().className(
- android.widget.CheckBox.class.getName()).focusable(true));
- UiSelector notFocusableSpinner = mainLayout.childSelector(new UiSelector().className(
- android.widget.Spinner.class.getName()).focusable(false));
-
- assertTrue("Selector focusable", new UiObject(focusableCheckbox).isFocusable());
- assertFalse("Selector not focusable", new UiObject(notFocusableSpinner).isFocusable());
- }
-
- /**
- * Verifies the 'DescriptionContains' property of UiSelector
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectorDescriptionContains() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiSelector progressDescriptionContains = new UiSelector().descriptionContains("%");
- assertTrue("Selector descriptionContains", "Progress is 50 %".equals(new UiObject(
- progressDescriptionContains).getContentDescription()));
- }
-
- /**
- * Verifies the 'DescriptionStarts' property of UiSelector
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectorDescriptionStarts() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiSelector progressDescriptionStart = new UiSelector().descriptionStartsWith("progress");
- assertTrue("Selector descriptionStart", "Progress is 50 %".equals(new UiObject(
- progressDescriptionStart).getContentDescription()));
- }
-
- /**
- * Verifies the 'Enabled' property of both UiSelector and UiObject
- *
- * @throws UiObjectNotFoundException
- */
- public void testSelectorEnabled() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiSelector mainLayout = new UiSelector().description("Widgets Collection");
- UiSelector buttonDisabled = mainLayout.childSelector(new UiSelector().className(
- android.widget.Button.class.getName()).enabled(false));
- UiSelector buttonEnabled = mainLayout.childSelector(new UiSelector().className(
- android.widget.Button.class.getName()).enabled(true));
-
- assertFalse("Selector enabled false", new UiObject(buttonDisabled).isEnabled());
- assertTrue("Selector enabled true", new UiObject(buttonEnabled).isEnabled());
- }
-
- /**
- * Verifies the UiCollection object child counting by object pattern
- *
- * @throws UiObjectNotFoundException
- */
- public void testCollectionCount() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiCollection collection = new UiCollection(
- new UiSelector().description("Widgets Collection"));
- assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
-
- assertTrue("Collection count",
- collection.getChildCount(new UiSelector().clickable(true)) == 6);
- }
-
- /**
- * Verifies the UiCollection can find an object by text and returning by
- * pattern
- *
- * @throws UiObjectNotFoundException
- */
- public void testCollectionGetChildByText() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiCollection collection = new UiCollection(
- new UiSelector().description("Widgets Collection"));
- assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
-
- UiObject item = collection.getChildByText(
- new UiSelector().className(android.widget.Button.class.getName()), "Button");
-
- assertTrue("Collection get child by text", "Button".equals(item.getText()));
- }
-
- /**
- * Verifies the UiCollection can find an object by instance and returning by
- * pattern
- *
- * @throws UiObjectNotFoundException
- */
- public void testCollectionGetChildByInstance() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiCollection collection = new UiCollection(
- new UiSelector().description("Widgets Collection"));
- assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
-
- // find the second button
- UiObject item = collection.getChildByInstance(
- new UiSelector().className(android.widget.Button.class.getName()), 1);
-
- assertTrue("Collection get child by instance", "Button".equals(item.getText()));
- }
-
- /**
- * Verifies the UiCollection can find an object by description and returning
- * by pattern
- *
- * @throws UiObjectNotFoundException
- */
- public void testCollectionGetChildByDescription() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiCollection collection = new UiCollection(
- new UiSelector().description("Widgets Collection"));
- assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
-
- UiObject item = collection.getChildByDescription(
- new UiSelector().className(android.widget.Button.class.getName()),
- "Description for Button");
-
- assertTrue("Collection get child by description", "Button".equals(item.getText()));
- }
-
- /**
- * Test Orientation APIs by causing rotations and verifying current state
- *
- * @throws RemoteException
- * @throws UiObjectNotFoundException
- * @since API Level 17
- */
- public void testRotation() throws RemoteException, UiObjectNotFoundException {
- openTest("Test 5");
- UiDevice device = UiDevice.getInstance();
-
- device.setOrientationLeft();
- device.waitForIdle(); // isNaturalOrientation is not waiting for idle
- SystemClock.sleep(1000);
- assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
-
- device.setOrientationNatural();
- device.waitForIdle(); // isNaturalOrientation is not waiting for idle
- SystemClock.sleep(1000);
- assertTrue("Device orientation should be natural", device.isNaturalOrientation());
-
- device.setOrientationRight();
- device.waitForIdle(); // isNaturalOrientation is not waiting for idle
- SystemClock.sleep(1000);
- assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
-
- device.setOrientationNatural();
- }
-
- /**
- * Reads the current device's product name. Since it is not possible to predetermine the
- * would be value, the check verifies that the value is not null and not empty.
- *
- * @since API Level 17
- */
- public void testGetProductName() {
- String name = UiDevice.getInstance().getProductName();
- assertFalse("Product name check returned empty string", name.isEmpty());
- }
-
- /**
- * Select each of the buttons by using only regex text
- *
- * @throws UiObjectNotFoundException
- * @since API Level 17
- */
- public void testSelectByTextMatch() throws UiObjectNotFoundException {
- openTest("Test 2");
- getObjectByTextMatch(".*n\\s1$").click();
- verifyDialogActionResults("Button 1");
- getObjectByTextMatch(".*n\\s2$").click();
- verifyDialogActionResults("Button 2");
- getObjectByTextMatch(".*n\\s3$").click();
- verifyDialogActionResults("Button 3");
- }
-
- /**
- * Select each of the buttons by using only regex content-description
- *
- * @throws UiObjectNotFoundException
- * @since API Level 17
- */
- public void testSelectByDescriptionMatch() throws UiObjectNotFoundException {
- openTest("Test 2");
- getObjectByDescriptionMatch(".*n\\s1$").click();
- verifyDialogActionResults("Button 1");
- getObjectByDescriptionMatch(".*n\\s2$").click();
- verifyDialogActionResults("Button 2");
- getObjectByDescriptionMatch(".*n\\s3$").click();
- verifyDialogActionResults("Button 3");
- }
-
- /**
- * Select each of the buttons by using only regex class name
- *
- * @throws UiObjectNotFoundException
- * @since API Level 17
- */
- public void testSelectByClassMatch() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiObject tgl = getObjectByClassMatch(".*ToggleButton$", 0);
- String tglValue = tgl.getText();
- tgl.click();
-
- assertFalse("Matching class by Regex failed", tglValue.equals(tgl.getText()));
- }
-
- /**
- * Select each of the buttons by using only class type
- *
- * @throws UiObjectNotFoundException
- * @since API Level 17
- */
- public void testSelectByClassType() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiObject tgl = getObjectByClass(android.widget.ToggleButton.class, 0);
- String tglValue = tgl.getText();
- tgl.click();
-
- assertFalse("Matching class by class type failed", tglValue.equals(tgl.getText()));
- }
-
- /**
- * Test the coordinates of 3 buttons side by side verifying vertical and
- * horizontal coordinates.
- *
- * @throws UiObjectNotFoundException
- * @since API Level 17
- */
- public void testGetVisibleBounds() throws UiObjectNotFoundException {
- openTest("Test 2");
- Rect rect1 = getObjectByText("Button 1").getVisibleBounds();
- Rect rect2 = getObjectByText("Button 2").getVisibleBounds();
- Rect rect3 = getObjectByText("Button 3").getVisibleBounds();
-
- assertTrue("X coordinate check failed",
- rect1.left < rect2.left && rect2.right < rect3.right);
- assertTrue("Y coordinate check failed",
- rect1.top == rect2.top && rect2.bottom == rect3.bottom);
- }
-
- /**
- * Tests the LongClick functionality in the API
- *
- * @throws UiObjectNotFoundException
- * @since API Level 17
- */
- public void testSelectorLongClickable() throws UiObjectNotFoundException {
- openTest("Test 2");
- getObjectByText("Button 1").longClick();
- verifyDialogActionResults("Longclick Button 1");
- }
-
- /**
- * Test the UiSelector's long-clickable property
- *
- * @throws UiObjectNotFoundException
- * @since API Level 17
- */
- public void testSelectorLongClickableProperty() throws UiObjectNotFoundException {
- openTest("Test 2");
- UiObject button3 = new UiObject(new UiSelector().className(
- android.widget.Button.class).longClickable(true).instance(2));
- button3.longClick();
- verifyDialogActionResults("Longclick Button 3");
- }
-
- /**
- * Takes a screen shot of the current display and checks if the file is
- * created and is not zero size.
- *
- * @since API Level 17
- */
- public void testTakeScreenShots() {
- File storePath = new File(SCREEN_SHOT_FILE_PATH_NAME);
- getUiDevice().takeScreenshot(storePath);
-
- assertTrue("Screenshot file not detected in store", storePath.exists());
- assertTrue("Zero size for screenshot file", storePath.length() > 0);
- }
-
- /**
- * Verifies the 'Resource-Id' property of UiSelector
- *
- * @throws UiObjectNotFoundException
- * @since API Level 18
- */
- public void testSelectorResourceId() throws UiObjectNotFoundException {
- openTest("Test 5");
- UiSelector toggleSelector =
- new UiSelector().resourceId("com.android.cts.uiautomator:id/test_5_toggleButton");
- UiObject toggleButton = new UiObject(toggleSelector);
- assertTrue("Object with selector resource-id not found", toggleButton.exists());
- assertTrue("Incorrect object for selector resource-id returned",
- "OFF".equals(toggleButton.getText()) || "ON".equals(toggleButton.getText()));
- }
-
- /**
- * Verify the UiSelector property resourceIdMatches
- *
- * @throws UiObjectNotFoundException
- * @since API Level 18
- */
- public void testSelectorResourceIdMatches() throws UiObjectNotFoundException {
- openTest("Test 2");
- new UiObject(new UiSelector().resourceIdMatches("(?i).*button.*").instance(2)).click();
- verifyDialogActionResults("Button 3");
- new UiObject(new UiSelector().resourceIdMatches("(?i).*button1.*")).click();
- verifyDialogActionResults("Button 1");
- }
-
- /**
- * Performs a pinch out from the center of a view to its edges and listens to
- * the motion events to make sure the starting and ending points of both pointers
- * are correct.
- *
- * @throws UiObjectNotFoundException
- * @since API Level 18
- */
- public void testPinchOut() throws UiObjectNotFoundException {
- openTest("Test 12");
-
- UiObject screen = new UiObject(
- new UiSelector().description("Details View"));
-
- // get the current view dimensions
- Rect screenRect = screen.getBounds();
-
- // perform the pinch for 100% of the view dimensions starting form
- // the center out to the edges.
- screen.pinchOut(100, 30);
-
- // dialog with the detected pointers motion coordinates is displayed.
- UiObject results = new UiObject(new UiSelector().className(
- android.widget.ScrollView.class).childSelector(new UiSelector().className(
- android.widget.TextView.class)));
- String allPointers = results.getText();
- new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
-
- // parse pointer 1
- Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
- Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
- // parse pointer 2
- Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
- Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
-
- assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
- assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
- assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
- assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
-
- assertTrue("Touch-down X coordinate for pointer 1 is invalid",
- withinMarginOfError(0.125f, screenRect.centerX(), p1s.x));
-
- assertTrue("Touch-down X coordinate for pointer 2 is invalid",
- withinMarginOfError(0.125f, screenRect.centerX(), p2s.x));
-
- assertTrue("Touch-up X coordinate for pointer 1 is invalid",
- withinMarginOfError(0.125f, screenRect.centerX() - screenRect.left,
- screenRect.centerX() - p1e.x));
-
- assertTrue("Touch-up X coordinate for pointer 2 is invalid",
- withinMarginOfError(0.125f, screenRect.right, p2e.x));
- }
-
- /**
- * Performs a pinch in from the edges of a view to its center and listens to
- * the motion events to make sure the starting and ending points of both pointers
- * are correct.
- *
- * @throws UiObjectNotFoundException
- * @since API Level 18
- */
- public void testPinchIn() throws UiObjectNotFoundException {
- openTest("Test 12");
-
- UiObject screen = new UiObject(
- new UiSelector().description("Details View"));
-
- // get the current view dimensions
- Rect screenRect = screen.getBounds();
-
- // perform the pinch for 100% of the view dimensions starting form
- // the edges in towards the center.
- screen.pinchIn(100, 30);
-
- // dialog with the detected pointers motion coordinates is displayed.
- UiObject results = new UiObject(new UiSelector().className(
- android.widget.ScrollView.class).childSelector(new UiSelector().className(
- android.widget.TextView.class)));
- String allPointers = results.getText();
- new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
-
- // parse pointer 1
- Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
- Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
- // parse pointer 2
- Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
- Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
-
- assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
- assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
- assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
- assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
-
- assertTrue("Touch-down X coordinate for pointer 1 is invalid",
- withinMarginOfError(0.125f, screenRect.centerX() - screenRect.left,
- screenRect.centerX() - p1s.x));
-
- assertTrue("Touch-down X coordinate for pointer 2 is invalid",
- withinMarginOfError(0.125f, screenRect.right, p2s.x));
-
- assertTrue("Touch-up X coordinate for pointer 1 is invalid",
- withinMarginOfError(0.125f, screenRect.centerX() - FINGER_TOUCH_HALF_WIDTH, p1e.x));
-
- assertTrue("Touch-up X coordinate for pointer 2 is invalid",
- withinMarginOfError(0.125f, screenRect.centerX() + FINGER_TOUCH_HALF_WIDTH, p2e.x));
- }
-
- /**
- * Performs a drag and drop operation from one UiObject to another UiObject
- *
- * @throws UiObjectNotFoundException
- * @since API Level 18
- */
- public void testDragToObject() throws UiObjectNotFoundException {
- openTest("Test 5");
-
- UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
- UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
-
- Rect starsBarRect = starsBar.getBounds();
- Rect imageButtonRect = imageButton.getBounds();
- imageButton.dragTo(starsBar, 30);
-
- // dialog with the detected pointers motion coordinates is displayed.
- UiObject results = new UiObject(new UiSelector().className(
- android.widget.ScrollView.class).childSelector(new UiSelector().className(
- android.widget.TextView.class)));
- String allPointers = results.getText();
- new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
-
- // parse pointer 1
- Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
- Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
-
- assertTrue("Invalid touch starting.X reported",
- withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
- assertTrue("Invalid touch starting.Y reported",
- withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
- assertTrue("Invalid touch ending.X reported",
- withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
- assertTrue("Invalid touch ending.Y reported",
- withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
- }
-
- /**
- * Performs a drag and drop operation from one UiObject to a specified coordinates
- *
- * @throws UiObjectNotFoundException
- * @since API Level 18
- */
- public void testDragToCoordinates() throws UiObjectNotFoundException {
- openTest("Test 5");
-
- UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
- UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
-
- Rect starsBarRect = starsBar.getBounds();
- Rect imageButtonRect = imageButton.getBounds();
- imageButton.dragTo(starsBarRect.centerX(), starsBarRect.centerY(), 30);
-
- // dialog with the detected pointers motion coordinates is displayed.
- UiObject results = new UiObject(new UiSelector().className(
- android.widget.ScrollView.class).childSelector(new UiSelector().className(
- android.widget.TextView.class)));
- String allPointers = results.getText();
- new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
-
- // parse pointer 1
- Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
- Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
-
- assertTrue("Invalid touch starting.X reported",
- withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
- assertTrue("Invalid touch starting.Y reported",
- withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
- assertTrue("Invalid touch ending.X reported",
- withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
- assertTrue("Invalid touch ending.Y reported",
- withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
- }
-
- /**
- * Detect if actual value is within the allowable margin of error of the expected value.
- *
- * Used essentially with actual values that may vary from the expected values such in the
- * cases of touch and pinch and touch and swipe where the starting or ending points may
- * not exactly match the expected value.
- *
- * @param marginPrecent is values between 0 and 1
- * @param expected
- * @param actual
- * @return true if actual is within the allowed range from expected
- */
- private boolean withinMarginOfError(float marginPrecent, int expected, int actual) {
- int m = (int) (marginPrecent * expected);
- return actual >= expected - m && actual <= expected + m;
- }
-
- /**
- * Parses a string containing starting to ending coordinates of one or more pointers.
- *
- * @param allPointers is a raw string with coordinates from all detected pointers
- * @param pointerNumber is the desired pointer to be parsed
- * @param edge is the 0 for the start or 1 for the end of the swipe
- * @return Point containing the start or end coordinates of the specified pointer number
- */
- private Point parsePointerCoordinates(String allPointers, int pointerNumber, int edge) {
- String pointers[] = allPointers.split("\n");
- String coordinates = pointers[pointerNumber].split(":")[edge];
- String xy[] = coordinates.split(",");
- return new Point(Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
- }
-
- /**
- * Private helper to open test views. Also covers UiScrollable tests
- *
- * @param name
- * @throws UiObjectNotFoundException
- */
- private void openTest(String name) throws UiObjectNotFoundException {
- try {
- UiDevice.getInstance().setOrientationNatural();
- } catch (RemoteException e) {
- // will catch it in its own test. For now try to put the device
- // in its natural orientation prior to each test
- }
- UiScrollable listView = new UiScrollable(
- new UiSelector().className(android.widget.ListView.class.getName()));
-
- // on single fragment display
- if (!listView.exists())
- UiDevice.getInstance().pressBack();
-
- UiObject testItem = listView.getChildByText(
- new UiSelector().className(android.widget.TextView.class.getName()), name);
-
- testItem.click();
- }
-
- private void verifyTestDetailsExists(String name) throws UiObjectNotFoundException {
- // verify that we're at the right test
- new UiObject(new UiSelector().description("Details").text(name)).getText();
- }
-
- private UiObject getObjectByText(String txt) {
- return new UiObject(new UiSelector().text(txt));
- }
-
- private UiObject getObjectByTextMatch(String regex) {
- return new UiObject(new UiSelector().textMatches(regex));
- }
-
- private UiObject getObjectByDescriptionMatch(String regex) {
- return new UiObject(new UiSelector().descriptionMatches(regex));
- }
-
- private UiObject getObjectByDescription(String txt) {
- return new UiObject(new UiSelector().description(txt));
- }
-
- private UiObject getObjectByClassMatch(String regex, int instance) {
- return new UiObject(new UiSelector().classNameMatches(regex).instance(instance));
- }
-
- private <T> UiObject getObjectByClass(Class<T> type, int instance) {
- return new UiObject(new UiSelector().className(type).instance(instance));
- }
-
- private UiObject getObjectByIndex(String className, int index) {
- return new UiObject(new UiSelector().className(className).index(index));
- }
-
- private UiObject getObjectByInstance(String className, int instance) {
- return new UiObject(new UiSelector().className(className).instance(instance));
- }
-
- private void verifyDialogActionResults(String txt) throws UiObjectNotFoundException {
- if (!getObjectByText("Action results").exists() || !getObjectByText(txt).exists()) {
- throw new UiObjectNotFoundException(txt);
- }
- getObjectByText("OK").click();
- }
-}
diff --git a/tests/uiautomator/src/com/android/uiautomator/cts/UiAutomatorTest.java b/tests/uiautomator/src/com/android/uiautomator/cts/UiAutomatorTest.java
new file mode 100644
index 0000000..9873d1f
--- /dev/null
+++ b/tests/uiautomator/src/com/android/uiautomator/cts/UiAutomatorTest.java
@@ -0,0 +1,1072 @@
+/*
+ * Copyright (C) 2012 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 com.android.uiautomator.cts;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.uiautomator.core.UiCollection;
+import com.android.uiautomator.core.UiDevice;
+import com.android.uiautomator.core.UiObject;
+import com.android.uiautomator.core.UiObjectNotFoundException;
+import com.android.uiautomator.core.UiScrollable;
+import com.android.uiautomator.core.UiSelector;
+import com.android.uiautomator.core.UiWatcher;
+import com.android.uiautomator.testrunner.UiAutomatorTestCase;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Sanity test uiautomator functionality on target device.
+ */
+public class UiAutomatorTest extends UiAutomatorTestCase {
+ private static final String LOG_TAG = UiAutomatorTest.class.getSimpleName();
+ private static final String[] LIST_SCROLL_TESTS = new String[] {
+ "Test 17", "Test 11", "Test 20", "Test 35"
+ };
+ private static final String PKG_NAME = "com.android.uiautomator.app";
+ private static final String LAUNCH_APP = "am start -a android.intent.action.MAIN -n "
+ + PKG_NAME + "/.MainActivity -W";
+
+ // Maximum wait for key object to become visible
+ private static final int WAIT_EXIST_TIMEOUT = 5 * 1000;
+
+ private static final String SCREEN_SHOT_FILE_PATH_NAME = "/data/local/tmp/ctsScreenShot";
+
+ // Should match the value defined in UiObject
+ private static final int FINGER_TOUCH_HALF_WIDTH = 20;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Make sure the test app is always running
+ UiDevice.getInstance().waitForIdle();
+ if (!new UiObject(new UiSelector().packageName(PKG_NAME)).exists())
+ runShellCommand(LAUNCH_APP);
+ }
+
+ /**
+ * Helper to execute a command on the shell
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ private void runShellCommand(String command) throws IOException, InterruptedException {
+ Process p = null;
+ BufferedReader resultReader = null;
+ try {
+ p = Runtime.getRuntime().exec(command);
+ int status = p.waitFor();
+ if (status != 0) {
+ throw new RuntimeException(String.format("Run shell command: %s, status: %s",
+ command, status));
+ }
+ } finally {
+ if (resultReader != null) {
+ resultReader.close();
+ }
+ if (p != null) {
+ p.destroy();
+ }
+ }
+ }
+
+ /*
+ * Items in the listScrollTests array should be spread out such that a
+ * scroll is required to reach each item at each of the far ends.
+ */
+ public void testListScrollAndSelect() throws UiObjectNotFoundException {
+ UiScrollable listView = new UiScrollable(
+ new UiSelector().className(android.widget.ListView.class.getName()));
+
+ // on single fragment display
+ if (!listView.exists())
+ UiDevice.getInstance().pressBack();
+
+ for (String test : LIST_SCROLL_TESTS) {
+ openTest(test);
+ verifyTestDetailsExists(test);
+ }
+ }
+
+ /**
+ * Test erasing of multi word text in edit field and input of new text. Test
+ * verifying input text using a complex UiSelector
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testTextEraseAndInput() throws UiObjectNotFoundException {
+ String testText = "Android Ui Automator Input Text";
+ openTest("Test 1");
+
+ UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
+ .getName()));
+ editText.setText(testText);
+
+ UiObject submitButton = new UiObject(new UiSelector()
+ .className(android.widget.Button.class.getName()).clickable(true)
+ .textStartsWith("Submit"));
+ submitButton.click();
+
+ UiObject result = new UiObject(new UiSelector().className(
+ android.widget.LinearLayout.class.getName()).childSelector(
+ (new UiSelector().className(android.widget.ScrollView.class.getName())
+ .childSelector(new UiSelector().className(android.widget.TextView.class
+ .getName())))));
+
+ if (!testText.equals(result.getText())) {
+ throw new UiObjectNotFoundException("Test text: " + testText);
+ }
+
+ getObjectByText("OK").click();
+ }
+
+ /**
+ * Select each of the buttons by using only the content description property
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectByContentDescription() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ getObjectByDescription("Button 1").click();
+ verifyDialogActionResults("Button 1");
+ getObjectByDescription("Button 2").click();
+ verifyDialogActionResults("Button 2");
+ getObjectByDescription("Button 3").click();
+ verifyDialogActionResults("Button 3");
+ }
+
+ /**
+ * Select each of the buttons by using only the text property
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectByText() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ getObjectByText("Button 1").click();
+ verifyDialogActionResults("Button 1");
+ getObjectByText("Button 2").click();
+ verifyDialogActionResults("Button 2");
+ getObjectByText("Button 3").click();
+ verifyDialogActionResults("Button 3");
+ }
+
+ /**
+ * Select each of the buttons by using only the index property
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectByIndex() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ getObjectByIndex(android.widget.Button.class.getName(), 0).click();
+ verifyDialogActionResults("Button 1");
+ getObjectByIndex(android.widget.Button.class.getName(), 1).click();
+ verifyDialogActionResults("Button 2");
+ getObjectByIndex(android.widget.Button.class.getName(), 2).click();
+ verifyDialogActionResults("Button 3");
+ }
+
+ /**
+ * Select each of the buttons by using only the instance number
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectByInstance() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ getObjectByInstance(android.widget.Button.class.getName(), 0).click();
+ verifyDialogActionResults("Button 1");
+ getObjectByInstance(android.widget.Button.class.getName(), 1).click();
+ verifyDialogActionResults("Button 2");
+ getObjectByInstance(android.widget.Button.class.getName(), 2).click();
+ verifyDialogActionResults("Button 3");
+ }
+
+ /**
+ * Test when a node's state is changed due to an action, it is updated in the accessibility
+ * hierarchy.
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectAfterContentChanged() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ UiObject dynaButton = getObjectByText("Before");
+ dynaButton.click();
+ assertTrue("Button state change is not refreshed in accessibility hierarchy",
+ getObjectByText("After").exists());
+ }
+
+ /**
+ * Test opening the options menu using the soft buttons
+ *
+ * @throws UiObjectNotFoundException
+ * @throws InterruptedException
+ * @throws IOException
+ */
+ public void testDeviceSoftKeys() throws UiObjectNotFoundException, IOException,
+ InterruptedException {
+ openTest("Test 2");
+ UiDevice device = UiDevice.getInstance();
+ device.pressMenu();
+ getObjectByText("Finish").click();
+ verifyDialogActionResults("Finish");
+
+ // Back button
+ openTest("Test 1");
+ UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
+ .getName()));
+ editText.setText("Android Geppetto Test Application");
+
+ UiObject submitButton = new UiObject(new UiSelector()
+ .className(android.widget.Button.class.getName()).clickable(true)
+ .textStartsWith("Submit"));
+ submitButton.click();
+
+ // Text from the popup dialog
+ UiObject result = new UiObject(new UiSelector().textContains("geppetto"));
+
+ // Back button test to dismiss the dialog
+ assertTrue("Wait for exist must return true", result.waitForExists(2000));
+ device.pressBack();
+ result.waitUntilGone(1000);
+ assertFalse("Wait for exist must return false after press back", result.exists());
+
+ // Home button test
+ openTest("Test 5");
+ String pkgName = device.getCurrentPackageName();
+ assertTrue("CTS test app must be running", pkgName.equals(PKG_NAME));
+ device.pressHome();
+ boolean gone = new UiObject(new UiSelector().packageName(PKG_NAME)).waitUntilGone(5000);
+ assertTrue("CTS test app still visble after pressing home", gone);
+ }
+
+ /**
+ * This view is in constant update generating window content changed events.
+ * The test will read the time displayed and exhaust each wait for idle
+ * timeout until it read and sets the text back into the edit field and
+ * presses submit. A dialog box should pop up with the time it took since
+ * reading the value until pressing submit.
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testWaitForIdleTimeout() throws UiObjectNotFoundException {
+ openTest("Test 3");
+ UiObject clk = new UiObject(new UiSelector().descriptionStartsWith("Performance "));
+
+ // First default wait for idle timeout assumed to be 10 seconds
+ String txtTime = clk.getText();
+ UiObject edit = new UiObject(new UiSelector().className(android.widget.EditText.class
+ .getName()));
+
+ // Second default wait for idle timeout assumed to be 10 seconds.
+ // Total ~20.
+ edit.setText(txtTime);
+
+ // Third default wait for idle timeout assumed to be 10 seconds.
+ // Total ~30.
+ getObjectByText("Submit").click();
+
+ // The value read should have value between 30 and 60 seconds indicating
+ // that the internal default timeouts for wait-for-idle is in acceptable
+ // range.
+ UiObject readTime = new UiObject(new UiSelector().className(
+ android.widget.TextView.class.getName()).instance(1));
+ String timeDiff = readTime.getText();
+ Log.i(LOG_TAG, "Sync time: " + timeDiff);
+
+ getObjectByText("OK").click();
+
+ int totalDelay = Integer.parseInt(timeDiff);
+
+ // Cumulative waits in this test should add up to at minimum 30 seconds
+ assertFalse("Timeout for wait-for-idle is too short. Expecting minimum 30 seconds",
+ totalDelay < 30 * 1000);
+
+ // allow for tolerance in time measurements due to differences between
+ // device speeds
+ assertFalse("Timeout for wait-for-idle is too long. Expecting maximum 60 seconds",
+ totalDelay > 60 * 1000);
+ }
+
+ /**
+ * This view is in constant update generating window content changed events.
+ * This test uses the soft key presses and clicks while the background
+ * screen is constantly updating causing a constant busy state.
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testVerifyMenuClicks() throws UiObjectNotFoundException {
+ openTest("Test 3");
+ UiDevice.getInstance().pressMenu();
+ new UiObject(new UiSelector().text("Submit")).click();
+ verifyDialogActionResults("Submit");
+ UiDevice.getInstance().pressMenu();
+ new UiObject(new UiSelector().text("Exit")).click();
+ verifyDialogActionResults("Exit");
+ }
+
+ /**
+ * Verifies swipeRight, swipeLeft and raw swipe APIs perform as expected.
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSwipes() throws UiObjectNotFoundException {
+ openTest("Test 4");
+ UiObject textView = new UiObject(new UiSelector().textContains("["));
+
+ textView.swipeLeft(10);
+ assertTrue("UiObject swipe left 1->2", "[ 2 ]".equals(textView.getText()));
+
+ textView.swipeLeft(10);
+ assertTrue("UiObject swipe left 2->3", "[ 3 ]".equals(textView.getText()));
+
+ textView.swipeLeft(10);
+ assertTrue("UiObject swipe left 3->4", "[ 4 ]".equals(textView.getText()));
+
+ textView.swipeRight(10);
+ assertTrue("UiObject swipe right 3<-4", "[ 3 ]".equals(textView.getText()));
+
+ textView.swipeRight(10);
+ assertTrue("UiObject swipe right 2<-3", "[ 2 ]".equals(textView.getText()));
+
+ textView.swipeRight(10);
+ assertTrue("UiObject swipe right 1<-2", "[ 1 ]".equals(textView.getText()));
+
+ Rect tb = textView.getBounds();
+ UiDevice.getInstance().swipe(tb.right - 20, tb.centerY(), tb.left + 20, tb.centerY(), 50);
+
+ SystemClock.sleep(100);
+ assertTrue("UiDevice raw swipe 1->2", "[ 2 ]".equals(textView.getText()));
+ }
+
+ /**
+ * Creates a complex selector
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testComplexSelectors() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiSelector frameLayout = new UiSelector().className(android.widget.FrameLayout.class
+ .getName());
+ UiSelector gridLayout = new UiSelector().className(android.widget.GridLayout.class
+ .getName());
+ UiSelector toggleButton = new UiSelector().className(android.widget.ToggleButton.class
+ .getName());
+ UiObject button = new UiObject(frameLayout.childSelector(gridLayout).childSelector(
+ toggleButton));
+
+ assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
+ button.click();
+ assertTrue("Toggle button value should be ON", "ON".equals(button.getText()));
+ button.click();
+ assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
+ }
+
+ /**
+ * Test when an object does not exist, an exception is thrown
+ * @throws UiObjectNotFoundException
+ */
+ public void testExceptionObjectNotFound() throws UiObjectNotFoundException {
+ UiSelector selector = new UiSelector().text("Nothing should be found");
+ UiSelector child = new UiSelector().className("Nothing");
+ UiObject obj = new UiObject(selector.childSelector(child));
+
+ assertFalse("Object is reported as existing", obj.exists());
+
+ try {
+ obj.click();
+ } catch (UiObjectNotFoundException e) {
+ return;
+ }
+ assertTrue("Exception not thrown for Object not found", false);
+ }
+
+ /**
+ * Verifies the UiWatcher registration and trigger function
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testUiWatcher() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiDevice device = UiDevice.getInstance();
+ device.registerWatcher("Artificial crash", new UiWatcher() {
+
+ @Override
+ public boolean checkForCondition() {
+ if (new UiObject(new UiSelector().packageName("android")).exists()) {
+ try {
+ // Expecting a localized OK button
+ new UiObject(new UiSelector().className(
+ android.widget.Button.class.getName()).enabled(true)).click();
+ } catch (UiObjectNotFoundException e) {
+ }
+ return true;
+ }
+ return false;
+ }
+ });
+
+ // Causes a runtime exception to be thrown
+ getObjectByText("Button").click();
+
+ // Fake doing something while the exception is being displayed
+ SystemClock.sleep(2000);
+ device.runWatchers();
+ assertTrue("UiWatcher not triggered", device.hasAnyWatcherTriggered());
+ }
+
+ /**
+ * Verifies the 'checked' property of both UiSelector and UiObject
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectorChecked() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiObject checkboxChecked = new UiObject(new UiSelector().className(
+ android.widget.CheckBox.class.getName()).checked(true));
+ UiObject checkboxNotChecked = new UiObject(new UiSelector().className(
+ android.widget.CheckBox.class.getName()).checked(false));
+
+ checkboxNotChecked.click();
+ assertTrue("Checkbox should be checked", checkboxChecked.isChecked());
+ checkboxChecked.click();
+ assertFalse("Checkbox should be unchecked", checkboxNotChecked.isChecked());
+ }
+
+ /**
+ * Verifies the 'Clickable' property of both the UiSelector and UiObject
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectorClickable() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiSelector clickableCheckbox = new UiSelector().clickable(true).className(
+ android.widget.CheckBox.class.getName());
+ UiSelector notClickableProgress = new UiSelector().clickable(false).className(
+ android.widget.ProgressBar.class.getName());
+
+ assertTrue("Selector clickable", new UiObject(clickableCheckbox).isClickable());
+ assertFalse("Selector not clickable", new UiObject(notClickableProgress).isClickable());
+ }
+
+ /**
+ * Verifies the 'focusable' property of both UiSelector and UiObject
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectorFocusable() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiSelector mainLayout = new UiSelector().description("Widgets Collection");
+ UiSelector focusableCheckbox = mainLayout.childSelector(new UiSelector().className(
+ android.widget.CheckBox.class.getName()).focusable(true));
+ UiSelector notFocusableSpinner = mainLayout.childSelector(new UiSelector().className(
+ android.widget.Spinner.class.getName()).focusable(false));
+
+ assertTrue("Selector focusable", new UiObject(focusableCheckbox).isFocusable());
+ assertFalse("Selector not focusable", new UiObject(notFocusableSpinner).isFocusable());
+ }
+
+ /**
+ * Verifies the 'DescriptionContains' property of UiSelector
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectorDescriptionContains() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiSelector progressDescriptionContains = new UiSelector().descriptionContains("%");
+ assertTrue("Selector descriptionContains", "Progress is 50 %".equals(new UiObject(
+ progressDescriptionContains).getContentDescription()));
+ }
+
+ /**
+ * Verifies the 'DescriptionStarts' property of UiSelector
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectorDescriptionStarts() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiSelector progressDescriptionStart = new UiSelector().descriptionStartsWith("progress");
+ assertTrue("Selector descriptionStart", "Progress is 50 %".equals(new UiObject(
+ progressDescriptionStart).getContentDescription()));
+ }
+
+ /**
+ * Verifies the 'Enabled' property of both UiSelector and UiObject
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testSelectorEnabled() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiSelector mainLayout = new UiSelector().description("Widgets Collection");
+ UiSelector buttonDisabled = mainLayout.childSelector(new UiSelector().className(
+ android.widget.Button.class.getName()).enabled(false));
+ UiSelector buttonEnabled = mainLayout.childSelector(new UiSelector().className(
+ android.widget.Button.class.getName()).enabled(true));
+
+ assertFalse("Selector enabled false", new UiObject(buttonDisabled).isEnabled());
+ assertTrue("Selector enabled true", new UiObject(buttonEnabled).isEnabled());
+ }
+
+ /**
+ * Verifies the UiCollection object child counting by object pattern
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testCollectionCount() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiCollection collection = new UiCollection(
+ new UiSelector().description("Widgets Collection"));
+ assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
+
+ assertTrue("Collection count",
+ collection.getChildCount(new UiSelector().clickable(true)) == 6);
+ }
+
+ /**
+ * Verifies the UiCollection can find an object by text and returning by
+ * pattern
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testCollectionGetChildByText() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiCollection collection = new UiCollection(
+ new UiSelector().description("Widgets Collection"));
+ assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
+
+ UiObject item = collection.getChildByText(
+ new UiSelector().className(android.widget.Button.class.getName()), "Button");
+
+ assertTrue("Collection get child by text", "Button".equals(item.getText()));
+ }
+
+ /**
+ * Verifies the UiCollection can find an object by instance and returning by
+ * pattern
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testCollectionGetChildByInstance() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiCollection collection = new UiCollection(
+ new UiSelector().description("Widgets Collection"));
+ assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
+
+ // find the second button
+ UiObject item = collection.getChildByInstance(
+ new UiSelector().className(android.widget.Button.class.getName()), 1);
+
+ assertTrue("Collection get child by instance", "Button".equals(item.getText()));
+ }
+
+ /**
+ * Verifies the UiCollection can find an object by description and returning
+ * by pattern
+ *
+ * @throws UiObjectNotFoundException
+ */
+ public void testCollectionGetChildByDescription() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiCollection collection = new UiCollection(
+ new UiSelector().description("Widgets Collection"));
+ assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
+
+ UiObject item = collection.getChildByDescription(
+ new UiSelector().className(android.widget.Button.class.getName()),
+ "Description for Button");
+
+ assertTrue("Collection get child by description", "Button".equals(item.getText()));
+ }
+
+ /**
+ * Test Orientation APIs by causing rotations and verifying current state
+ *
+ * @throws RemoteException
+ * @throws UiObjectNotFoundException
+ * @since API Level 17
+ */
+ public void testRotation() throws RemoteException, UiObjectNotFoundException {
+ openTest("Test 5");
+ UiDevice device = UiDevice.getInstance();
+
+ device.setOrientationLeft();
+ device.waitForIdle(); // isNaturalOrientation is not waiting for idle
+ SystemClock.sleep(1000);
+ assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
+
+ device.setOrientationNatural();
+ device.waitForIdle(); // isNaturalOrientation is not waiting for idle
+ SystemClock.sleep(1000);
+ assertTrue("Device orientation should be natural", device.isNaturalOrientation());
+
+ device.setOrientationRight();
+ device.waitForIdle(); // isNaturalOrientation is not waiting for idle
+ SystemClock.sleep(1000);
+ assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
+
+ device.setOrientationNatural();
+ }
+
+ /**
+ * Reads the current device's product name. Since it is not possible to predetermine the
+ * would be value, the check verifies that the value is not null and not empty.
+ *
+ * @since API Level 17
+ */
+ public void testGetProductName() {
+ String name = UiDevice.getInstance().getProductName();
+ assertFalse("Product name check returned empty string", name.isEmpty());
+ }
+
+ /**
+ * Select each of the buttons by using only regex text
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 17
+ */
+ public void testSelectByTextMatch() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ getObjectByTextMatch(".*n\\s1$").click();
+ verifyDialogActionResults("Button 1");
+ getObjectByTextMatch(".*n\\s2$").click();
+ verifyDialogActionResults("Button 2");
+ getObjectByTextMatch(".*n\\s3$").click();
+ verifyDialogActionResults("Button 3");
+ }
+
+ /**
+ * Select each of the buttons by using only regex content-description
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 17
+ */
+ public void testSelectByDescriptionMatch() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ getObjectByDescriptionMatch(".*n\\s1$").click();
+ verifyDialogActionResults("Button 1");
+ getObjectByDescriptionMatch(".*n\\s2$").click();
+ verifyDialogActionResults("Button 2");
+ getObjectByDescriptionMatch(".*n\\s3$").click();
+ verifyDialogActionResults("Button 3");
+ }
+
+ /**
+ * Select each of the buttons by using only regex class name
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 17
+ */
+ public void testSelectByClassMatch() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiObject tgl = getObjectByClassMatch(".*ToggleButton$", 0);
+ String tglValue = tgl.getText();
+ tgl.click();
+
+ assertFalse("Matching class by Regex failed", tglValue.equals(tgl.getText()));
+ }
+
+ /**
+ * Select each of the buttons by using only class type
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 17
+ */
+ public void testSelectByClassType() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiObject tgl = getObjectByClass(android.widget.ToggleButton.class, 0);
+ String tglValue = tgl.getText();
+ tgl.click();
+
+ assertFalse("Matching class by class type failed", tglValue.equals(tgl.getText()));
+ }
+
+ /**
+ * Test the coordinates of 3 buttons side by side verifying vertical and
+ * horizontal coordinates.
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 17
+ */
+ public void testGetVisibleBounds() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ Rect rect1 = getObjectByText("Button 1").getVisibleBounds();
+ Rect rect2 = getObjectByText("Button 2").getVisibleBounds();
+ Rect rect3 = getObjectByText("Button 3").getVisibleBounds();
+
+ assertTrue("X coordinate check failed",
+ rect1.left < rect2.left && rect2.right < rect3.right);
+ assertTrue("Y coordinate check failed",
+ rect1.top == rect2.top && rect2.bottom == rect3.bottom);
+ }
+
+ /**
+ * Tests the LongClick functionality in the API
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 17
+ */
+ public void testSelectorLongClickable() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ getObjectByText("Button 1").longClick();
+ verifyDialogActionResults("Longclick Button 1");
+ }
+
+ /**
+ * Test the UiSelector's long-clickable property
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 17
+ */
+ public void testSelectorLongClickableProperty() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ UiObject button3 = new UiObject(new UiSelector().className(
+ android.widget.Button.class).longClickable(true).instance(2));
+ button3.longClick();
+ verifyDialogActionResults("Longclick Button 3");
+ }
+
+ /**
+ * Takes a screen shot of the current display and checks if the file is
+ * created and is not zero size.
+ *
+ * @since API Level 17
+ */
+ public void testTakeScreenShots() {
+ File storePath = new File(SCREEN_SHOT_FILE_PATH_NAME);
+ getUiDevice().takeScreenshot(storePath);
+
+ assertTrue("Screenshot file not detected in store", storePath.exists());
+ assertTrue("Zero size for screenshot file", storePath.length() > 0);
+ }
+
+ /**
+ * Verifies the 'Resource-Id' property of UiSelector
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 18
+ */
+ public void testSelectorResourceId() throws UiObjectNotFoundException {
+ openTest("Test 5");
+ UiSelector toggleSelector =
+ new UiSelector().resourceId("com.android.uiautomator.app:id/test_5_toggleButton");
+ UiObject toggleButton = new UiObject(toggleSelector);
+ assertTrue("Object with selector resource-id not found", toggleButton.exists());
+ assertTrue("Incorrect object for selector resource-id returned",
+ "OFF".equals(toggleButton.getText()) || "ON".equals(toggleButton.getText()));
+ }
+
+ /**
+ * Verify the UiSelector property resourceIdMatches
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 18
+ */
+ public void testSelectorResourceIdMatches() throws UiObjectNotFoundException {
+ openTest("Test 2");
+ new UiObject(new UiSelector().resourceIdMatches("(?i).*button.*").instance(2)).click();
+ verifyDialogActionResults("Button 3");
+ new UiObject(new UiSelector().resourceIdMatches("(?i).*button1.*")).click();
+ verifyDialogActionResults("Button 1");
+ }
+
+ /**
+ * Performs a pinch out from the center of a view to its edges and listens to
+ * the motion events to make sure the starting and ending points of both pointers
+ * are correct.
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 18
+ */
+ public void testPinchOut() throws UiObjectNotFoundException {
+ openTest("Test 12");
+
+ UiObject screen = new UiObject(
+ new UiSelector().description("Details View"));
+
+ // get the current view dimensions
+ Rect screenRect = screen.getBounds();
+
+ // perform the pinch for 100% of the view dimensions starting form
+ // the center out to the edges.
+ screen.pinchOut(100, 30);
+
+ // dialog with the detected pointers motion coordinates is displayed.
+ UiObject results = new UiObject(new UiSelector().className(
+ android.widget.ScrollView.class).childSelector(new UiSelector().className(
+ android.widget.TextView.class)));
+ String allPointers = results.getText();
+ new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
+
+ // parse pointer 1
+ Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
+ Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
+ // parse pointer 2
+ Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
+ Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
+
+ assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
+ assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
+ assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
+ assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
+
+ assertTrue("Touch-down X coordinate for pointer 1 is invalid",
+ withinMarginOfError(0.125f, screenRect.centerX(), p1s.x));
+
+ assertTrue("Touch-down X coordinate for pointer 2 is invalid",
+ withinMarginOfError(0.125f, screenRect.centerX(), p2s.x));
+
+ assertTrue("Touch-up X coordinate for pointer 1 is invalid",
+ withinMarginOfError(0.125f, screenRect.centerX() - screenRect.left,
+ screenRect.centerX() - p1e.x));
+
+ assertTrue("Touch-up X coordinate for pointer 2 is invalid",
+ withinMarginOfError(0.125f, screenRect.right, p2e.x));
+ }
+
+ /**
+ * Performs a pinch in from the edges of a view to its center and listens to
+ * the motion events to make sure the starting and ending points of both pointers
+ * are correct.
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 18
+ */
+ public void testPinchIn() throws UiObjectNotFoundException {
+ openTest("Test 12");
+
+ UiObject screen = new UiObject(
+ new UiSelector().description("Details View"));
+
+ // get the current view dimensions
+ Rect screenRect = screen.getBounds();
+
+ // perform the pinch for 100% of the view dimensions starting form
+ // the edges in towards the center.
+ screen.pinchIn(100, 30);
+
+ // dialog with the detected pointers motion coordinates is displayed.
+ UiObject results = new UiObject(new UiSelector().className(
+ android.widget.ScrollView.class).childSelector(new UiSelector().className(
+ android.widget.TextView.class)));
+ String allPointers = results.getText();
+ new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
+
+ // parse pointer 1
+ Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
+ Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
+ // parse pointer 2
+ Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
+ Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
+
+ assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
+ assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
+ assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
+ assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
+
+ assertTrue("Touch-down X coordinate for pointer 1 is invalid",
+ withinMarginOfError(0.125f, screenRect.centerX() - screenRect.left,
+ screenRect.centerX() - p1s.x));
+
+ assertTrue("Touch-down X coordinate for pointer 2 is invalid",
+ withinMarginOfError(0.125f, screenRect.right, p2s.x));
+
+ assertTrue("Touch-up X coordinate for pointer 1 is invalid",
+ withinMarginOfError(0.125f, screenRect.centerX() - FINGER_TOUCH_HALF_WIDTH, p1e.x));
+
+ assertTrue("Touch-up X coordinate for pointer 2 is invalid",
+ withinMarginOfError(0.125f, screenRect.centerX() + FINGER_TOUCH_HALF_WIDTH, p2e.x));
+ }
+
+ /**
+ * Performs a drag and drop operation from one UiObject to another UiObject
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 18
+ */
+ public void testDragToObject() throws UiObjectNotFoundException {
+ openTest("Test 5");
+
+ UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
+ UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
+
+ Rect starsBarRect = starsBar.getBounds();
+ Rect imageButtonRect = imageButton.getBounds();
+ imageButton.dragTo(starsBar, 30);
+
+ // dialog with the detected pointers motion coordinates is displayed.
+ UiObject results = new UiObject(new UiSelector().className(
+ android.widget.ScrollView.class).childSelector(new UiSelector().className(
+ android.widget.TextView.class)));
+ String allPointers = results.getText();
+ new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
+
+ // parse pointer 1
+ Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
+ Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
+
+ assertTrue("Invalid touch starting.X reported",
+ withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
+ assertTrue("Invalid touch starting.Y reported",
+ withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
+ assertTrue("Invalid touch ending.X reported",
+ withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
+ assertTrue("Invalid touch ending.Y reported",
+ withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
+ }
+
+ /**
+ * Performs a drag and drop operation from one UiObject to a specified coordinates
+ *
+ * @throws UiObjectNotFoundException
+ * @since API Level 18
+ */
+ public void testDragToCoordinates() throws UiObjectNotFoundException {
+ openTest("Test 5");
+
+ UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
+ UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
+
+ Rect starsBarRect = starsBar.getBounds();
+ Rect imageButtonRect = imageButton.getBounds();
+ imageButton.dragTo(starsBarRect.centerX(), starsBarRect.centerY(), 30);
+
+ // dialog with the detected pointers motion coordinates is displayed.
+ UiObject results = new UiObject(new UiSelector().className(
+ android.widget.ScrollView.class).childSelector(new UiSelector().className(
+ android.widget.TextView.class)));
+ String allPointers = results.getText();
+ new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
+
+ // parse pointer 1
+ Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
+ Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
+
+ assertTrue("Invalid touch starting.X reported",
+ withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
+ assertTrue("Invalid touch starting.Y reported",
+ withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
+ assertTrue("Invalid touch ending.X reported",
+ withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
+ assertTrue("Invalid touch ending.Y reported",
+ withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
+ }
+
+ /**
+ * Detect if actual value is within the allowable margin of error of the expected value.
+ *
+ * Used essentially with actual values that may vary from the expected values such in the
+ * cases of touch and pinch and touch and swipe where the starting or ending points may
+ * not exactly match the expected value.
+ *
+ * @param marginPrecent is values between 0 and 1
+ * @param expected
+ * @param actual
+ * @return true if actual is within the allowed range from expected
+ */
+ private boolean withinMarginOfError(float marginPrecent, int expected, int actual) {
+ int m = (int) (marginPrecent * expected);
+ return actual >= expected - m && actual <= expected + m;
+ }
+
+ /**
+ * Parses a string containing starting to ending coordinates of one or more pointers.
+ *
+ * @param allPointers is a raw string with coordinates from all detected pointers
+ * @param pointerNumber is the desired pointer to be parsed
+ * @param edge is the 0 for the start or 1 for the end of the swipe
+ * @return Point containing the start or end coordinates of the specified pointer number
+ */
+ private Point parsePointerCoordinates(String allPointers, int pointerNumber, int edge) {
+ String pointers[] = allPointers.split("\n");
+ String coordinates = pointers[pointerNumber].split(":")[edge];
+ String xy[] = coordinates.split(",");
+ return new Point(Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
+ }
+
+ /**
+ * Private helper to open test views. Also covers UiScrollable tests
+ *
+ * @param name
+ * @throws UiObjectNotFoundException
+ */
+ private void openTest(String name) throws UiObjectNotFoundException {
+ try {
+ UiDevice.getInstance().setOrientationNatural();
+ } catch (RemoteException e) {
+ // will catch it in its own test. For now try to put the device
+ // in its natural orientation prior to each test
+ }
+ UiScrollable listView = new UiScrollable(
+ new UiSelector().className(android.widget.ListView.class.getName()));
+
+ // on single fragment display
+ if (!listView.exists())
+ UiDevice.getInstance().pressBack();
+
+ UiObject testItem = listView.getChildByText(
+ new UiSelector().className(android.widget.TextView.class.getName()), name);
+
+ testItem.click();
+ }
+
+ private void verifyTestDetailsExists(String name) throws UiObjectNotFoundException {
+ // verify that we're at the right test
+ new UiObject(new UiSelector().description("Details").text(name)).getText();
+ }
+
+ private UiObject getObjectByText(String txt) {
+ return new UiObject(new UiSelector().text(txt));
+ }
+
+ private UiObject getObjectByTextMatch(String regex) {
+ return new UiObject(new UiSelector().textMatches(regex));
+ }
+
+ private UiObject getObjectByDescriptionMatch(String regex) {
+ return new UiObject(new UiSelector().descriptionMatches(regex));
+ }
+
+ private UiObject getObjectByDescription(String txt) {
+ return new UiObject(new UiSelector().description(txt));
+ }
+
+ private UiObject getObjectByClassMatch(String regex, int instance) {
+ return new UiObject(new UiSelector().classNameMatches(regex).instance(instance));
+ }
+
+ private <T> UiObject getObjectByClass(Class<T> type, int instance) {
+ return new UiObject(new UiSelector().className(type).instance(instance));
+ }
+
+ private UiObject getObjectByIndex(String className, int index) {
+ return new UiObject(new UiSelector().className(className).index(index));
+ }
+
+ private UiObject getObjectByInstance(String className, int instance) {
+ return new UiObject(new UiSelector().className(className).instance(instance));
+ }
+
+ private void verifyDialogActionResults(String txt) throws UiObjectNotFoundException {
+ if (!getObjectByText("Action results").exists() || !getObjectByText(txt).exists()) {
+ throw new UiObjectNotFoundException(txt);
+ }
+ getObjectByText("OK").click();
+ }
+}
diff --git a/tests/uiautomator/test-apps/Android.mk b/tests/uiautomator/test-apps/Android.mk
deleted file mode 100644
index e790e1e..0000000
--- a/tests/uiautomator/test-apps/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (C) 2012 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.
-
-include $(call all-subdir-makefiles)
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk b/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk
deleted file mode 100644
index 3827754..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2012 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_PACKAGE_NAME := CtsUiAutomatorApp
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/AndroidManifest.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/AndroidManifest.xml
deleted file mode 100644
index 87c2d82..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/AndroidManifest.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2011 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.uiautomator"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk
- android:minSdkVersion="14"
- android:targetSdkVersion="15" />
-
- <uses-permission android:name="android.permission.INTERNET"/>
- <application
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <activity
- android:name=".MainActivity"
- android:label="@string/title_test_list" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <activity
- android:name=".SinglePaneDetailActivity"
- android:label="@string/title_test_detail" >
- <meta-data
- android:name="android.support.PARENT_ACTIVITY"
- android:value="FragmentActivity" />
- </activity>
- </application>
-
-</manifest>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/list_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/list_activity.xml
deleted file mode 100644
index 25bca5d..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/list_activity.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2011 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.
- -->
-<fragment xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:name="com.android.cts.uiautomator.TestListFragment"
- android:id="@+id/item_list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- tools:context=".MainActivity" />
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/twopane_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/twopane_activity.xml
deleted file mode 100644
index 3777db6..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/twopane_activity.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2011 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"
- xmlns:tools="http://schemas.android.com/tools"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:divider="?android:attr/dividerHorizontal"
- android:showDividers="middle"
- tools:context=".TestListActivity">
-
- <fragment
- android:id="@+id/item_list"
- android:name="com.android.cts.uiautomator.TestListFragment"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1" />
-
- <FrameLayout android:id="@+id/test_detail_container"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="3" />
-
-</LinearLayout>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/MainActivity.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/MainActivity.java
deleted file mode 100644
index 81833b7..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/MainActivity.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.view.WindowManager;
-
-public class MainActivity extends FragmentActivity implements TestListFragment.Callbacks {
-
- private boolean mTwoPane;
- public static final String LOG_TAG = "UiAutomatorApp";
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // If the device is locked, this attempts to dismiss the KeyGuard
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
- WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
- WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-
- setContentView(R.layout.list_activity);
-
- if (findViewById(R.id.test_detail_container) != null) {
- mTwoPane = true;
- ((TestListFragment) getSupportFragmentManager().findFragmentById(R.id.item_list))
- .setActivateOnItemClick(true);
- }
- }
-
- @Override
- public void onItemSelected(String id) {
- if (mTwoPane) {
- Fragment fragment = TestItems.getFragment(id);
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.test_detail_container, fragment).commit();
- } else {
- Intent detailIntent = new Intent(this, SinglePaneDetailActivity.class);
- detailIntent.putExtra("item_id", id);
- startActivity(detailIntent);
- }
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/SinglePaneDetailActivity.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/SinglePaneDetailActivity.java
deleted file mode 100644
index 1c0ff8c..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/SinglePaneDetailActivity.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.NavUtils;
-import android.view.Menu;
-import android.view.MenuItem;
-
-public class SinglePaneDetailActivity extends FragmentActivity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.singlepane_activity);
- getActionBar().setDisplayHomeAsUpEnabled(true);
-
- if (savedInstanceState == null) {
- Fragment fragment = TestItems.getFragment(getIntent().getStringExtra("item_id"));
- getSupportFragmentManager().beginTransaction()
- .add(R.id.test_results_detail_container, fragment).commit();
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.test_results_detail_activity, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- NavUtils.navigateUpFromSameTask(this);
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test1DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test1DetailFragment.java
deleted file mode 100644
index e8eddba..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test1DetailFragment.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
-import android.widget.EditText;
-
-public class Test1DetailFragment extends Fragment {
-
- public static final String ARG_ITEM_ID = "item_id";
- private Button mSubmitButton;
- private EditText mEditText;
- TestItems.TestItem mItem;
-
- public Test1DetailFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getArguments().containsKey(ARG_ITEM_ID)) {
- mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID));
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- View rootView = inflater.inflate(R.layout.test1_detail_fragment, container, false);
- if (mItem != null) {
- ((EditText) rootView.findViewById(R.id.test1TextField)).setText(mItem.mName);
-
- mSubmitButton = (Button) rootView.findViewById(R.id.test1SubmitButton);
- mEditText = (EditText) rootView.findViewById(R.id.test1TextField);
- mEditText.setText("");
- mSubmitButton.setOnClickListener(new Button.OnClickListener() {
- @Override
- public void onClick(View v) {
- final String savedInput = mEditText.getText().toString();
- // clear so we won't be confused by the input text in
- // validation
- mEditText.setText("");
- // close soft keyboard
- InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
- Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
- // display the submitted text
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.item1_dialog_title);
- builder.setPositiveButton(R.string.OK, null);
- builder.setMessage(savedInput);
- AlertDialog diag = builder.create();
- diag.show();
- }
- });
- }
- return rootView;
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java
deleted file mode 100644
index 4fb322f..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-
-public class Test2DetailFragment extends Fragment {
- public static final String ARG_ITEM_ID = "item_id";
- private Button mButton1, mButton2, mButton3, mDynaButton;
-
- public Test2DetailFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- inflater.inflate(R.menu.test2_detail_activity, menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.dialog_title_result);
- builder.setMessage(item.getTitle());
- builder.setPositiveButton(R.string.OK, null);
- AlertDialog diag = builder.create();
- diag.show();
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- View rootView = inflater.inflate(R.layout.test2_detail_fragment, container, false);
-
- mButton1 = (Button) rootView.findViewById(R.id.test2button1);
- mButton2 = (Button) rootView.findViewById(R.id.test2button2);
- mButton3 = (Button) rootView.findViewById(R.id.test2button3);
- mDynaButton = (Button) rootView.findViewById(R.id.test2dynaButton);
-
- mButton1.setOnClickListener(new Button.OnClickListener() {
- @Override
- public void onClick(View v) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.dialog_title_result);
- builder.setPositiveButton(R.string.OK, null);
- builder.setMessage(R.string.button1);
- AlertDialog diag = builder.create();
- diag.show();
- }
- });
-
- mButton1.setOnLongClickListener(new Button.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.dialog_title_result);
- builder.setPositiveButton(R.string.OK, null);
- builder.setMessage(R.string.button1long);
- AlertDialog diag = builder.create();
- diag.show();
- return true;
- }
- });
-
- mButton2.setOnClickListener(new Button.OnClickListener() {
- @Override
- public void onClick(View v) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.dialog_title_result);
- builder.setPositiveButton(R.string.OK, null);
- builder.setMessage(R.string.button2);
- AlertDialog diag = builder.create();
- diag.show();
- }
- });
-
- mButton2.setOnLongClickListener(new Button.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.dialog_title_result);
- builder.setPositiveButton(R.string.OK, null);
- builder.setMessage(R.string.button2long);
- AlertDialog diag = builder.create();
- diag.show();
- return true;
- }
- });
-
- mButton3.setOnClickListener(new Button.OnClickListener() {
- @Override
- public void onClick(View v) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.dialog_title_result);
- builder.setPositiveButton(R.string.OK, null);
- builder.setMessage(R.string.button3);
- AlertDialog diag = builder.create();
- diag.show();
- }
- });
-
- mButton3.setOnLongClickListener(new Button.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.dialog_title_result);
- builder.setPositiveButton(R.string.OK, null);
- builder.setMessage(R.string.button3long);
- AlertDialog diag = builder.create();
- diag.show();
- return true;
- }
- });
-
- mDynaButton.setOnClickListener(new Button.OnClickListener() {
- @Override
- public void onClick(View v) {
- mDynaButton.setText(R.string.buttonAfter);
- mDynaButton.setContentDescription(getString(R.string.buttonAfter));
- }
- });
-
- return rootView;
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test3DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test3DetailFragment.java
deleted file mode 100644
index e0be0cf..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test3DetailFragment.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-
-public class Test3DetailFragment extends Fragment {
-
- public static final String ARG_ITEM_ID = "item_id";
- private TextView mTextClock;
- private Button mSubmitButton;
- private EditText mEditText;
- private long mCurrentTime;
- private final Object sync = new Object();
- private boolean mRunCounter = true;
-
- public Test3DetailFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- inflater.inflate(R.menu.test2_detail_activity, menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.dialog_title_result);
- builder.setMessage(item.getTitle());
- builder.setPositiveButton(R.string.OK, null);
- AlertDialog diag = builder.create();
- diag.show();
- return super.onOptionsItemSelected(item);
- }
-
- private final Handler mHandler = new Handler();
-
- final Runnable mClockRunnable = new Runnable() {
- @Override
- public void run() {
- // call the activity method that updates the UI
- updateClockOnUi();
- }
- };
-
- private void updateClockOnUi() {
- synchronized (sync) {
- mTextClock.setText("" + mCurrentTime);
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- View rootView = inflater.inflate(R.layout.test3_detail_fragment, container, false);
- mTextClock = (TextView) rootView.findViewById(R.id.test3ClockTextView);
- mSubmitButton = (Button) rootView.findViewById(R.id.test3SubmitButton);
- mEditText = (EditText) rootView.findViewById(R.id.test3TextField);
- mSubmitButton.setOnClickListener(new Button.OnClickListener() {
- @Override
- public void onClick(View v) {
- // close soft keyboard
- InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
- Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
-
- // display the submitted text
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.test3_dialog_title);
- builder.setPositiveButton(R.string.OK, null);
- CharSequence inputText = mEditText.getText();
- if (inputText != null && !inputText.toString().isEmpty()) {
- long inputTime = Long.parseLong(inputText.toString());
- builder.setMessage("" + (mCurrentTime - inputTime));
- } else {
- builder.setMessage("<NO DATA>");
- }
- AlertDialog diag = builder.create();
- diag.show();
- mEditText.setText("");
- mRunCounter = false;
- }
- });
-
- new Thread(new Runnable() {
- @Override
- public void run() {
- while (mRunCounter) {
- synchronized (sync) {
- mCurrentTime = SystemClock.elapsedRealtime();
- }
- mHandler.post(mClockRunnable);
- SystemClock.sleep(100);
- }
- }
- }).start();
-
- return rootView;
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test4DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test4DetailFragment.java
deleted file mode 100644
index 0c914dc..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test4DetailFragment.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.app.ActionBar;
-import android.app.FragmentTransaction;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentPagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-public class Test4DetailFragment extends Fragment implements ActionBar.TabListener {
- public static final String ARG_ITEM_ID = "item_id";
-
- /**
- * The {@link android.support.v4.view.PagerAdapter} that will provide
- * fragments for each of the sections. We use a
- * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
- * will keep every loaded fragment in memory. If this becomes too memory
- * intensive, it may be best to switch to a
- * {@link android.support.v4.app.FragmentStatePagerAdapter}.
- */
- SectionsPagerAdapter mSectionsPagerAdapter;
-
- /**
- * The {@link ViewPager} that will host the section contents.
- */
- ViewPager mViewPager;
-
- public Test4DetailFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- public void onDestroyView() {
- getActivity().getActionBar().removeAllTabs();
- super.onDestroyView();
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-
- View rootView = inflater.inflate(R.layout.test4_detail_fragment, container, false);
-
- // Set up the action bar.
- final ActionBar actionBar = getActivity().getActionBar();
- if (actionBar.getTabCount() > 0) {
- return rootView;
- }
- actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
-
- // Create the adapter that will return a fragment for each of the three
- // primary sections of the app.
- mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity().getSupportFragmentManager());
-
- // Set up the ViewPager with the sections adapter.
- mViewPager = (ViewPager) rootView.findViewById(R.id.test_4_detail_container);
- mViewPager.setAdapter(mSectionsPagerAdapter);
-
- // When swiping between different sections, select the corresponding
- // tab. We can also use ActionBar.Tab#select() to do this if we have a
- // reference to the Tab.
- mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
- @Override
- public void onPageSelected(int position) {
- actionBar.setSelectedNavigationItem(position);
- }
- });
-
- // For each of the sections in the app, add a tab to the action bar.
- for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
- // Create a tab with text corresponding to the page title defined by
- // the adapter. Also specify this Activity object, which implements
- // the TabListener interface, as the listener for when this tab is
- // selected.
- actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i))
- .setTabListener(this));
- }
- return rootView;
- }
-
- @Override
- public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
- }
-
- @Override
- public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
- }
-
- @Override
- public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
- }
-
- /**
- * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
- * one of the primary sections of the app.
- */
- public class SectionsPagerAdapter extends FragmentPagerAdapter {
-
- public SectionsPagerAdapter(FragmentManager fm) {
- super(fm);
- }
-
- @Override
- public Fragment getItem(int i) {
- Fragment fragment = new DummySectionFragment();
- Bundle args = new Bundle();
- args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1);
- fragment.setArguments(args);
- return fragment;
- }
-
- @Override
- public int getCount() {
- return 4;
- }
-
- @Override
- public CharSequence getPageTitle(int position) {
- switch (position) {
- case 0:
- return getString(R.string.title_section1).toUpperCase();
- case 1:
- return getString(R.string.title_section2).toUpperCase();
- case 2:
- return getString(R.string.title_section3).toUpperCase();
- case 3:
- return getString(R.string.title_section4).toUpperCase();
- }
- return null;
- }
- }
-
- /**
- * A dummy fragment representing a section of the app, but that simply
- * displays dummy text.
- */
- public static class DummySectionFragment extends Fragment {
- public DummySectionFragment() {
- }
-
- public static final String ARG_SECTION_NUMBER = "section_number";
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- TextView textView = new TextView(getActivity());
- textView.setGravity(Gravity.CENTER);
- Bundle args = getArguments();
- textView.setText("[ " + Integer.toString(args.getInt(ARG_SECTION_NUMBER)) + " ]");
- return textView;
- }
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test5DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test5DetailFragment.java
deleted file mode 100644
index e2dd156..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test5DetailFragment.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.ImageButton;
-import android.widget.SeekBar;
-import android.widget.Spinner;
-
-public class Test5DetailFragment extends Fragment {
-
- public static final String ARG_ITEM_ID = "item_id";
-
- class PointerEvent {
- int startX;
- int startY;
- int endX;
- int endY;
- }
-
- private final PointerEvent mPointerEvent = new PointerEvent();
-
- public Test5DetailFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- View rootView = inflater.inflate(R.layout.test5_detail_fragment, container, false);
-
- // Set the content description for the following
- Spinner spinner = (Spinner) rootView.findViewById(R.id.test_5_spinner);
- spinner.setContentDescription("Spinner");
- ImageButton imageButton = (ImageButton) rootView.findViewById(R.id.test_5_imageButton);
- imageButton.setContentDescription("Image button");
-
- // Each time this view is displayed, reset the following states
- SeekBar seekBar = (SeekBar) rootView.findViewById(R.id.test_5_seekBar);
- seekBar.setProgress(50);
- seekBar.setContentDescription("Progress is 50 %");
- CheckBox checkbox = (CheckBox) rootView.findViewById(R.id.test_5_checkBox);
- checkbox.setChecked(false);
-
- // Register click event handlers for the following
- Button button = (Button) rootView.findViewById(R.id.test_5_button1);
- button.setOnClickListener(new Button.OnClickListener() {
- @Override
- public void onClick(View v) {
- // we want an artificial crash
- throw new RuntimeException("Artificial crash to test UiWatcher");
- }
- });
-
- imageButton.setOnTouchListener(new ImageButton.OnTouchListener() {
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- resetTouchResults();
- collectStartAction(event, v);
- } else if (event.getAction() == MotionEvent.ACTION_UP) {
- collectEndAction(event, v);
- displayTouchResults();
- }
- return false;
- }
- });
-
- return rootView;
- }
-
- private void displayTouchResults() {
- StringBuilder output = new StringBuilder();
-
- output.append(String.format("%d,%d:%d,%d\n",
- mPointerEvent.startX, mPointerEvent.startY, mPointerEvent.endX,
- mPointerEvent.endY));
-
- // display the submitted text
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.drag_item_touch_dialog_title);
- builder.setPositiveButton(R.string.OK, null);
- builder.setMessage(output.toString());
- AlertDialog diag = builder.create();
- diag.show();
- }
-
- /**
- * Clears all collected pointer results
- */
- private void resetTouchResults() {
- mPointerEvent.startX = mPointerEvent.startY =
- mPointerEvent.endX = mPointerEvent.endY = -1;
- }
-
- /**
- * Collects pointer touch information converting from relative to absolute before
- * storing it as starting touch coordinates.
- *
- * @param event
- * @param view
- * @param pointerIndex
- */
- private void collectStartAction(MotionEvent event, View view) {
- int offsetInScreen[] = new int[2];
- view.getLocationOnScreen(offsetInScreen);
- mPointerEvent.startX = (int)(event.getX() + offsetInScreen[0]);
- mPointerEvent.startY = (int)(event.getY() + offsetInScreen[1]);
- }
-
- /**
- * Collects pointer touch information converting from relative to absolute before
- * storing it as ending touch coordinates.
- *
- * @param event
- * @param view
- * @param pointerIndex
- */
- private void collectEndAction(MotionEvent event, View view) {
- int offsetInScreen[] = new int[2];
- view.getLocationOnScreen(offsetInScreen);
- mPointerEvent.endX = (int)(event.getX() + offsetInScreen[0]);
- mPointerEvent.endY = (int)(event.getY() + offsetInScreen[1]);
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test6DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test6DetailFragment.java
deleted file mode 100644
index 90bcfcf..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test6DetailFragment.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.WebView;
-
-public class Test6DetailFragment extends Fragment {
- public static final String ARG_ITEM_ID = "item_id";
- private final static String PAGE = "<html><body>"
- + "This is test <b>6</b> for WebView text traversal test."
- + "<p/><a href=\"http://google.com\">This is a link to google</a><br/>"
- + "<h5>This is h5 text</h5>"
- + "<a href=\"http://yahoo.com\">This is a link to yahoo</a>"
- + "<p/><h4>This is h4 text</h4>" + "</body></html>";
-
- public Test6DetailFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- View rootView = inflater.inflate(R.layout.test6_detail_fragment, container, false);
- WebView wv = (WebView) rootView.findViewById(R.id.test6WebView);
- wv.loadData(PAGE, "text/html", null);
- return rootView;
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestGenericDetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestGenericDetailFragment.java
deleted file mode 100644
index a7215c3..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestGenericDetailFragment.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-public class TestGenericDetailFragment extends Fragment {
- public static final String ARG_ITEM_ID = "item_id";
- TestItems.TestItem mItem;
-
- private class PointerEvent {
- int startX;
- int startY;
- int endX;
- int endY;
- }
-
- private final PointerEvent[] mPointerEvents = new PointerEvent[10];
-
- public TestGenericDetailFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getArguments().containsKey(ARG_ITEM_ID)) {
- mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID));
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- View rootView = inflater.inflate(R.layout.test_results_detail_fragment, container, false);
- if (mItem != null) {
- ((TextView) rootView.findViewById(R.id.testResultsTextView)).setText(mItem.mName);
- }
-
- // listen to touch events to verify the multiPointerGesture APIs
- // Since API Level 18
- rootView.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
-
- switch(event.getAction() & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN:
- // Reset any collected touch coordinate results on the primary touch down
- resetTouchResults();
- // collect this event
- collectStartAction(event, v, 0);
- break;
-
- case MotionEvent.ACTION_POINTER_DOWN:
- // collect this event
- collectStartAction(event, v, getPointerIndex(event));
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- // collect this event
- collectEndAction(event, v, getPointerIndex(event));
- break;
-
- case MotionEvent.ACTION_UP:
- // collect this event
- collectEndAction(event, v, 0);
- // on the primary touch up display results collected for all pointers
- displayTouchResults();
- break;
- }
- return true;
- }
- });
-
- return rootView;
- }
-
- /**
- * Displays collected results from all pointers into a dialog view in the following
- * format: "startX,startY:endX,endY" where each line represent data for a pointer if
- * multiple pointers (fingers) were detected.
- */
- private void displayTouchResults() {
- StringBuilder output = new StringBuilder();
- for (int x = 0; x < mPointerEvents.length; x++) {
- if (mPointerEvents[x].startX == -1)
- break;
-
- output.append(String.format("%d,%d:%d,%d\n",
- mPointerEvents[x].startX, mPointerEvents[x].startY, mPointerEvents[x].endX,
- mPointerEvents[x].endY));
- }
-
- // display the submitted text
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.generic_item_touch_dialog_title);
- builder.setPositiveButton(R.string.OK, null);
- builder.setMessage(output.toString());
- AlertDialog diag = builder.create();
- diag.show();
- }
-
- /**
- * Clears all collected pointer results
- */
- private void resetTouchResults() {
- for (int x = 0; x < mPointerEvents.length; x++) {
- if (mPointerEvents[x] == null)
- mPointerEvents[x] = new PointerEvent();
- mPointerEvents[x].startX = mPointerEvents[x].startY =
- mPointerEvents[x].endX = mPointerEvents[x].endY = -1;
- }
- }
-
- /**
- * Collects pointer touch information converting from relative to absolute before
- * storing it as starting touch coordinates.
- *
- * @param event
- * @param view
- * @param pointerIndex
- */
- private void collectStartAction(MotionEvent event, View view, int pointerIndex) {
- int offsetInScreen[] = new int[2];
- view.getLocationOnScreen(offsetInScreen);
- mPointerEvents[getPointerId(event)].startX =
- (int)(event.getX(pointerIndex) + offsetInScreen[0]);
- mPointerEvents[getPointerId(event)].startY =
- (int)(event.getY(pointerIndex) + offsetInScreen[1]);
- }
-
- /**
- * Collects pointer touch information converting from relative to absolute before
- * storing it as ending touch coordinates.
- *
- * @param event
- * @param view
- * @param pointerIndex
- */
- private void collectEndAction(MotionEvent event, View view, int pointerIndex) {
- int offsetInScreen[] = new int[2];
- view.getLocationOnScreen(offsetInScreen);
- mPointerEvents[getPointerId(event)].endX =
- (int)(event.getX(pointerIndex) + offsetInScreen[0]);
- mPointerEvents[getPointerId(event)].endY =
- (int)(event.getY(pointerIndex) + offsetInScreen[1]);
- }
-
- private int getPointerId(MotionEvent event) {
- return event.getPointerId(getPointerIndex(event));
- }
-
- private int getPointerIndex(MotionEvent event) {
- return ((event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT);
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestItems.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestItems.java
deleted file mode 100644
index db6e693..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestItems.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class TestItems {
- private static String LOG_TAG = TestItems.class.getSimpleName();
- private static List<TestItem> ITEMS = new ArrayList<TestItem>();
- private static Map<String, TestItem> ITEM_MAP = new HashMap<String, TestItem>();
-
- public static class TestItem {
- public String mId;
- public String mName;
- private final Class<Fragment> mClassFragment;
- public String mTestDescription;
-
- @SuppressWarnings("unchecked")
- public TestItem(String id, String name, Class<?> clsf) {
- mId = id;
- mName = name;
- mClassFragment = (Class<Fragment>) clsf;
- }
-
- @Override
- public String toString() {
- return mName;
- }
- }
-
- static {
- addTestItem(new TestItem("1", "Test 1", Test1DetailFragment.class));
- addTestItem(new TestItem("2", "Test 2", Test2DetailFragment.class));
- addTestItem(new TestItem("3", "Test 3", Test3DetailFragment.class));
- addTestItem(new TestItem("4", "Test 4", Test4DetailFragment.class));
- addTestItem(new TestItem("5", "Test 5", Test5DetailFragment.class));
- addTestItem(new TestItem("6", "Test 6", Test6DetailFragment.class));
- addTestItem(new TestItem("7", "Test 7", TestGenericDetailFragment.class));
- addTestItem(new TestItem("8", "Test 8", TestGenericDetailFragment.class));
- addTestItem(new TestItem("9", "Test 9", TestGenericDetailFragment.class));
- addTestItem(new TestItem("10", "Test 10", TestGenericDetailFragment.class));
- addTestItem(new TestItem("11", "Test 11", TestGenericDetailFragment.class));
- addTestItem(new TestItem("12", "Test 12", TestGenericDetailFragment.class));
- addTestItem(new TestItem("13", "Test 13", TestGenericDetailFragment.class));
- addTestItem(new TestItem("14", "Test 14", TestGenericDetailFragment.class));
- addTestItem(new TestItem("15", "Test 15", TestGenericDetailFragment.class));
- addTestItem(new TestItem("16", "Test 16", TestGenericDetailFragment.class));
- addTestItem(new TestItem("17", "Test 17", TestGenericDetailFragment.class));
- addTestItem(new TestItem("18", "Test 18", TestGenericDetailFragment.class));
- addTestItem(new TestItem("19", "Test 19", TestGenericDetailFragment.class));
- addTestItem(new TestItem("20", "Test 20", TestGenericDetailFragment.class));
- addTestItem(new TestItem("21", "Test 21", TestGenericDetailFragment.class));
- addTestItem(new TestItem("22", "Test 22", TestGenericDetailFragment.class));
- addTestItem(new TestItem("23", "Test 23", TestGenericDetailFragment.class));
- addTestItem(new TestItem("24", "Test 24", TestGenericDetailFragment.class));
- addTestItem(new TestItem("25", "Test 25", TestGenericDetailFragment.class));
- addTestItem(new TestItem("26", "Test 26", TestGenericDetailFragment.class));
- addTestItem(new TestItem("27", "Test 27", TestGenericDetailFragment.class));
- addTestItem(new TestItem("28", "Test 28", TestGenericDetailFragment.class));
- addTestItem(new TestItem("29", "Test 29", TestGenericDetailFragment.class));
- addTestItem(new TestItem("30", "Test 30", TestGenericDetailFragment.class));
- addTestItem(new TestItem("31", "Test 31", TestGenericDetailFragment.class));
- addTestItem(new TestItem("32", "Test 32", TestGenericDetailFragment.class));
- addTestItem(new TestItem("33", "Test 33", TestGenericDetailFragment.class));
- addTestItem(new TestItem("34", "Test 34", TestGenericDetailFragment.class));
- addTestItem(new TestItem("35", "Test 35", TestGenericDetailFragment.class));
- addTestItem(new TestItem("36", "Test 36", TestGenericDetailFragment.class));
- addTestItem(new TestItem("37", "Test 37", TestGenericDetailFragment.class));
- addTestItem(new TestItem("38", "Test 38", TestGenericDetailFragment.class));
- addTestItem(new TestItem("39", "Test 39", TestGenericDetailFragment.class));
- addTestItem(new TestItem("40", "Test 40", TestGenericDetailFragment.class));
- }
-
- private static void addTestItem(TestItem item) {
- ITEMS.add(item);
- ITEM_MAP.put(item.mId, item);
- }
-
- public static List<TestItem> getTests() {
- return ITEMS;
- }
-
- public static TestItem getTest(String id) {
- return ITEM_MAP.get(id);
- }
-
- public static TestItem getTest(int pos) {
- return ITEMS.get(pos);
- }
-
- public static Fragment getFragment(String id) {
- try {
- Fragment fragment = getTest(id).mClassFragment.newInstance();
- Bundle arguments = new Bundle();
- arguments.putString("item_id", id);
- fragment.setArguments(arguments);
- return fragment;
- } catch (InstantiationException e) {
- Log.e(LOG_TAG, "Exception", e);
- return null;
- } catch (IllegalAccessException e) {
- Log.e(LOG_TAG, "Exception", e);
- return null;
- }
- }
-}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestListFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestListFragment.java
deleted file mode 100644
index 46f0f73..0000000
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestListFragment.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.uiautomator;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.ListFragment;
-import android.view.View;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-public class TestListFragment extends ListFragment {
-
- private static final String STATE_ACTIVATED_POSITION = "activated_position";
-
- private Callbacks mCallbacks = sDummyCallbacks;
- private int mActivatedPosition = ListView.INVALID_POSITION;
-
- public interface Callbacks {
-
- public void onItemSelected(String id);
- }
-
- private static Callbacks sDummyCallbacks = new Callbacks() {
- @Override
- public void onItemSelected(String id) {
- }
- };
-
- public TestListFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setListAdapter(new ArrayAdapter<TestItems.TestItem>(getActivity(),
- R.layout.simple_list_item_selected, R.id.label, TestItems.getTests()));
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedState) {
- super.onViewCreated(view, savedState);
- if (savedState != null && savedState.containsKey(STATE_ACTIVATED_POSITION)) {
- setActivatedPosition(savedState.getInt(STATE_ACTIVATED_POSITION));
- }
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- if (!(activity instanceof Callbacks)) {
- throw new IllegalStateException("Activity must implement fragment's callbacks.");
- }
-
- mCallbacks = (Callbacks) activity;
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- mCallbacks = sDummyCallbacks;
- }
-
- @Override
- public void onListItemClick(ListView listView, View view, int position, long id) {
- super.onListItemClick(listView, view, position, id);
- mCallbacks.onItemSelected(TestItems.getTest(position).mId);
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- if (mActivatedPosition != ListView.INVALID_POSITION) {
- outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
- }
- }
-
- public void setActivateOnItemClick(boolean activateOnItemClick) {
- getListView().setChoiceMode(
- activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
- }
-
- public void setActivatedPosition(int position) {
- if (position == ListView.INVALID_POSITION) {
- getListView().setItemChecked(mActivatedPosition, false);
- } else {
- getListView().setItemChecked(position, true);
- }
-
- mActivatedPosition = position;
- }
-}
diff --git a/tests/video/Android.mk b/tests/video/Android.mk
new file mode 100644
index 0000000..2d31e0f
--- /dev/null
+++ b/tests/video/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2013 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestrunner
+
+LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libnativehelper_compat_libc++
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsVideoTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/tests/video/AndroidManifest.xml b/tests/video/AndroidManifest.xml
new file mode 100644
index 0000000..22dad9e
--- /dev/null
+++ b/tests/video/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.video.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.video.cts"
+ android:label="CTS tests for Video" >
+ <meta-data
+ android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+</manifest>
diff --git a/tests/video/AndroidTest.xml b/tests/video/AndroidTest.xml
new file mode 100644
index 0000000..0c98c42
--- /dev/null
+++ b/tests/video/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS Video test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsVideoTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.video.cts" />
+ </test>
+</configuration>
diff --git a/tests/video/src/android/video/cts/CodecInfo.java b/tests/video/src/android/video/cts/CodecInfo.java
new file mode 100644
index 0000000..c1bf0a9
--- /dev/null
+++ b/tests/video/src/android/video/cts/CodecInfo.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 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.video.cts;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecInfo.CodecProfileLevel;
+import android.media.MediaCodecInfo.VideoCapabilities;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
+import android.util.Log;
+import android.util.Range;
+
+import java.io.IOException;
+
+/**
+ * Utility class for getting codec information like bit rate, fps, and etc.
+ * Uses public member variables instead of methods as this code is only for video benchmarking.
+ */
+public class CodecInfo {
+ /** bit rate in bps */
+ public int mBitRate = 0;
+ /** Frame rate */
+ public int mFps = 0;
+ /** if codec is supporting YUV semiplanar format */
+ public boolean mSupportSemiPlanar = false;
+ /** if codec is supporting YUV planar format */
+ public boolean mSupportPlanar = false;
+
+ private static final String TAG = "CodecInfo";
+ private static final String VIDEO_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
+ /**
+ * Check if given codec with given (w,h) is supported.
+ * @param codecName codec name
+ * @param mimeType codec type in mime format like MediaFormat.MIMETYPE_VIDEO_AVC
+ * @param w video width
+ * @param h video height
+ * @return null if the configuration is not supported.
+ */
+ public static CodecInfo getSupportedFormatInfo(
+ String codecName, String mimeType, int w, int h) {
+ MediaCodec codec;
+ try {
+ codec = MediaCodec.createByCodecName(codecName);
+ } catch (IOException e) {
+ return null;
+ }
+
+ CodecCapabilities cap = codec.getCodecInfo().getCapabilitiesForType(mimeType);
+ if (cap.colorFormats.length == 0) {
+ Log.w(TAG, "no supported color format");
+ codec.release();
+ return null;
+ }
+
+ CodecInfo info = new CodecInfo();
+ for (int color : cap.colorFormats) {
+ if (color == CodecCapabilities.COLOR_FormatYUV420SemiPlanar) {
+ info.mSupportSemiPlanar = true;
+ }
+ if (color == CodecCapabilities.COLOR_FormatYUV420Planar) {
+ info.mSupportPlanar = true;
+ }
+ }
+ printIntArray("supported colors", cap.colorFormats);
+
+ VideoCapabilities vidCap = cap.getVideoCapabilities();
+ try {
+ info.mFps = vidCap.getSupportedFrameRatesFor(w, h).getUpper().intValue();
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "unsupported size");
+ codec.release();
+ return null;
+ }
+ info.mBitRate = vidCap.getBitrateRange().getUpper();
+ Log.i(TAG, "test bit rate " + info.mBitRate + " fps " + info.mFps);
+ codec.release();
+ return info;
+ }
+
+ // for debugging
+ private static void printIntArray(String msg, int[] data) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(msg);
+ builder.append(":");
+ for (int e : data) {
+ builder.append(Integer.toHexString(e));
+ builder.append(",");
+ }
+ builder.deleteCharAt(builder.length() - 1);
+ Log.i(TAG, builder.toString());
+ }
+}
diff --git a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
new file mode 100644
index 0000000..d5db375
--- /dev/null
+++ b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
@@ -0,0 +1,1258 @@
+/*
+ * Copyright (C) 2013 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.video.cts;
+
+import android.cts.util.MediaUtils;
+import android.cts.util.DeviceReportLog;
+import android.graphics.ImageFormat;
+import android.graphics.Point;
+import android.media.Image;
+import android.media.Image.Plane;
+import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
+import android.media.cts.CodecImage;
+import android.media.cts.CodecUtils;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Range;
+
+import android.cts.util.CtsAndroidTestCase;
+import com.android.cts.util.ResultType;
+import com.android.cts.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+import com.android.cts.util.TimeoutReq;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.Random;
+
+/**
+ * This tries to test video encoder / decoder performance by running encoding / decoding
+ * without displaying the raw data. To make things simpler, encoder is used to encode synthetic
+ * data and decoder is used to decode the encoded video. This approach does not work where
+ * there is only decoder. Performance index is total time taken for encoding and decoding
+ * the whole frames.
+ * To prevent sacrificing quality for faster encoding / decoding, randomly selected pixels are
+ * compared with the original image. As the pixel comparison can slow down the decoding process,
+ * only some randomly selected pixels are compared. As there can be only one performance index,
+ * error above certain threshold in pixel value will be treated as an error.
+ */
+public class VideoEncoderDecoderTest extends CtsAndroidTestCase {
+ private static final String TAG = "VideoEncoderDecoderTest";
+ // this wait time affects fps as too big value will work as a blocker if device fps
+ // is not very high.
+ private static final long VIDEO_CODEC_WAIT_TIME_US = 5000;
+ private static final boolean VERBOSE = false;
+ private static final String VIDEO_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
+ private static final String VIDEO_VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
+ private static final String VIDEO_H263 = MediaFormat.MIMETYPE_VIDEO_H263;
+ private static final String VIDEO_MPEG4 = MediaFormat.MIMETYPE_VIDEO_MPEG4;
+ private int mCurrentTestRound = 0;
+ private double[][] mEncoderFrameTimeDiff = null;
+ private double[][] mDecoderFrameTimeDiff = null;
+ // i frame interval for encoder
+ private static final int KEY_I_FRAME_INTERVAL = 5;
+ private static final int MOVING_AVERAGE_NUM = 10;
+
+ private static final int Y_CLAMP_MIN = 16;
+ private static final int Y_CLAMP_MAX = 235;
+ private static final int YUV_PLANE_ADDITIONAL_LENGTH = 200;
+ private ByteBuffer mYBuffer, mYDirectBuffer;
+ private ByteBuffer mUVBuffer, mUVDirectBuffer;
+ private int mSrcColorFormat;
+ private int mDstColorFormat;
+ private int mBufferWidth;
+ private int mBufferHeight;
+ private int mVideoWidth;
+ private int mVideoHeight;
+ private int mFrameRate;
+
+ private MediaFormat mEncInputFormat;
+ private MediaFormat mEncOutputFormat;
+ private MediaFormat mDecOutputFormat;
+
+ private LinkedList<Pair<ByteBuffer, BufferInfo>> mEncodedOutputBuffer;
+ // check this many pixels per each decoded frame
+ // checking too many points decreases decoder frame rates a lot.
+ private static final int PIXEL_CHECK_PER_FRAME = 1000;
+ // RMS error in pixel values above this will be treated as error.
+ private static final double PIXEL_RMS_ERROR_MARGAIN = 20.0;
+ private double mRmsErrorMargain = PIXEL_RMS_ERROR_MARGAIN;
+ private Random mRandom;
+
+ private class TestConfig {
+ public boolean mTestPixels = true;
+ public boolean mTestResult = false;
+ public boolean mReportFrameTime = false;
+ public int mTotalFrames = 300;
+ public int mMaxTimeMs = 120000; // 2 minutes
+ public int mNumberOfRepeat = 10;
+ }
+
+ private TestConfig mTestConfig;
+
+ private DeviceReportLog mReportLog;
+
+ @Override
+ protected void setUp() throws Exception {
+ mEncodedOutputBuffer = new LinkedList<Pair<ByteBuffer, BufferInfo>>();
+ // Use time as a seed, hoping to prevent checking pixels in the same pattern
+ long now = System.currentTimeMillis();
+ mRandom = new Random(now);
+ mTestConfig = new TestConfig();
+ mReportLog = new DeviceReportLog();
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mEncodedOutputBuffer.clear();
+ mEncodedOutputBuffer = null;
+ mYBuffer = null;
+ mUVBuffer = null;
+ mYDirectBuffer = null;
+ mUVDirectBuffer = null;
+ mRandom = null;
+ mTestConfig = null;
+ mReportLog.deliverReportToHost(getInstrumentation());
+ super.tearDown();
+ }
+
+ private String getEncoderName(String mime) {
+ return getCodecName(mime, true /* isEncoder */);
+ }
+
+ private String getDecoderName(String mime) {
+ return getCodecName(mime, false /* isEncoder */);
+ }
+
+ private String getCodecName(String mime, boolean isEncoder) {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo info : mcl.getCodecInfos()) {
+ if (info.isEncoder() != isEncoder) {
+ continue;
+ }
+ CodecCapabilities caps = null;
+ try {
+ caps = info.getCapabilitiesForType(mime);
+ } catch (IllegalArgumentException e) { // mime is not supported
+ continue;
+ }
+ return info.getName();
+ }
+ return null;
+ }
+
+ private String[] getEncoderName(String mime, boolean isGoog) {
+ return getCodecName(mime, isGoog, true /* isEncoder */);
+ }
+
+ private String[] getDecoderName(String mime, boolean isGoog) {
+ return getCodecName(mime, isGoog, false /* isEncoder */);
+ }
+
+ private String[] getCodecName(String mime, boolean isGoog, boolean isEncoder) {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ ArrayList<String> result = new ArrayList<String>();
+ for (MediaCodecInfo info : mcl.getCodecInfos()) {
+ if (info.isEncoder() != isEncoder
+ || info.getName().toLowerCase().startsWith("omx.google.") != isGoog) {
+ continue;
+ }
+ CodecCapabilities caps = null;
+ try {
+ caps = info.getCapabilitiesForType(mime);
+ } catch (IllegalArgumentException e) { // mime is not supported
+ continue;
+ }
+ result.add(info.getName());
+ }
+ return result.toArray(new String[result.size()]);
+ }
+
+ public void testAvc0176x0144() throws Exception {
+ doTestDefault(VIDEO_AVC, 176, 144);
+ }
+
+ public void testAvc0352x0288() throws Exception {
+ doTestDefault(VIDEO_AVC, 352, 288);
+ }
+
+ public void testAvc0720x0480() throws Exception {
+ doTestDefault(VIDEO_AVC, 720, 480);
+ }
+
+ public void testAvc1280x0720() throws Exception {
+ doTestDefault(VIDEO_AVC, 1280, 720);
+ }
+
+ /**
+ * resolution intentionally set to 1072 not 1080
+ * as 1080 is not multiple of 16, and it requires additional setting like stride
+ * which is not specified in API documentation.
+ */
+ public void testAvc1920x1072() throws Exception {
+ doTestDefault(VIDEO_AVC, 1920, 1072);
+ }
+
+ // Avc tests
+ public void testAvc0320x0240Other() throws Exception {
+ doTestOther(VIDEO_AVC, 320, 240);
+ }
+
+ public void testAvc0320x0240Goog() throws Exception {
+ doTestGoog(VIDEO_AVC, 320, 240);
+ }
+
+ public void testAvc0720x0480Other() throws Exception {
+ doTestOther(VIDEO_AVC, 720, 480);
+ }
+
+ public void testAvc0720x0480Goog() throws Exception {
+ doTestGoog(VIDEO_AVC, 720, 480);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testAvc1280x0720Other() throws Exception {
+ doTestOther(VIDEO_AVC, 1280, 720);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testAvc1280x0720Goog() throws Exception {
+ doTestGoog(VIDEO_AVC, 1280, 720);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testAvc1920x1080Other() throws Exception {
+ doTestOther(VIDEO_AVC, 1920, 1080);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testAvc1920x1080Goog() throws Exception {
+ doTestGoog(VIDEO_AVC, 1920, 1080);
+ }
+
+ // Vp8 tests
+ public void testVp80320x0180Other() throws Exception {
+ doTestOther(VIDEO_VP8, 320, 180);
+ }
+
+ public void testVp80320x0180Goog() throws Exception {
+ doTestGoog(VIDEO_VP8, 320, 180);
+ }
+
+ public void testVp80640x0360Other() throws Exception {
+ doTestOther(VIDEO_VP8, 640, 360);
+ }
+
+ public void testVp80640x0360Goog() throws Exception {
+ doTestGoog(VIDEO_VP8, 640, 360);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testVp81280x0720Other() throws Exception {
+ doTestOther(VIDEO_VP8, 1280, 720);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testVp81280x0720Goog() throws Exception {
+ doTestGoog(VIDEO_VP8, 1280, 720);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testVp81920x1080Other() throws Exception {
+ doTestOther(VIDEO_VP8, 1920, 1080);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testVp81920x1080Goog() throws Exception {
+ doTestGoog(VIDEO_VP8, 1920, 1080);
+ }
+
+ // H263 tests
+ public void testH2630176x0144Other() throws Exception {
+ doTestOther(VIDEO_H263, 176, 144);
+ }
+
+ public void testH2630176x0144Goog() throws Exception {
+ doTestGoog(VIDEO_H263, 176, 144);
+ }
+
+ public void testH2630352x0288Other() throws Exception {
+ doTestOther(VIDEO_H263, 352, 288);
+ }
+
+ public void testH2630352x0288Goog() throws Exception {
+ doTestGoog(VIDEO_H263, 352, 288);
+ }
+
+ // Mpeg4 tests
+ public void testMpeg40176x0144Other() throws Exception {
+ doTestOther(VIDEO_MPEG4, 176, 144);
+ }
+
+ public void testMpeg40176x0144Goog() throws Exception {
+ doTestGoog(VIDEO_MPEG4, 176, 144);
+ }
+
+ public void testMpeg40352x0288Other() throws Exception {
+ doTestOther(VIDEO_MPEG4, 352, 288);
+ }
+
+ public void testMpeg40352x0288Goog() throws Exception {
+ doTestGoog(VIDEO_MPEG4, 352, 288);
+ }
+
+ public void testMpeg40640x0480Other() throws Exception {
+ doTestOther(VIDEO_MPEG4, 640, 480);
+ }
+
+ public void testMpeg40640x0480Goog() throws Exception {
+ doTestGoog(VIDEO_MPEG4, 640, 480);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testMpeg41280x0720Other() throws Exception {
+ doTestOther(VIDEO_MPEG4, 1280, 720);
+ }
+
+ @TimeoutReq(minutes = 10)
+ public void testMpeg41280x0720Goog() throws Exception {
+ doTestGoog(VIDEO_MPEG4, 1280, 720);
+ }
+
+ private boolean isSrcSemiPlanar() {
+ return mSrcColorFormat == CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
+ }
+
+ private boolean isSrcFlexYUV() {
+ return mSrcColorFormat == CodecCapabilities.COLOR_FormatYUV420Flexible;
+ }
+
+ private boolean isDstSemiPlanar() {
+ return mDstColorFormat == CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
+ }
+
+ private boolean isDstFlexYUV() {
+ return mDstColorFormat == CodecCapabilities.COLOR_FormatYUV420Flexible;
+ }
+
+ private static int getColorFormat(CodecInfo info) {
+ if (info.mSupportSemiPlanar) {
+ return CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
+ } else if (info.mSupportPlanar) {
+ return CodecCapabilities.COLOR_FormatYUV420Planar;
+ } else {
+ // FlexYUV must be supported
+ return CodecCapabilities.COLOR_FormatYUV420Flexible;
+ }
+ }
+
+ private void doTestGoog(String mimeType, int w, int h) throws Exception {
+ mTestConfig.mTestPixels = false;
+ mTestConfig.mTestResult = true;
+ mTestConfig.mTotalFrames = 3000;
+ mTestConfig.mNumberOfRepeat = 2;
+ doTest(true /* isGoog */, mimeType, w, h);
+ }
+
+ private void doTestOther(String mimeType, int w, int h) throws Exception {
+ mTestConfig.mTestPixels = false;
+ mTestConfig.mTestResult = true;
+ mTestConfig.mTotalFrames = 3000;
+ mTestConfig.mNumberOfRepeat = 2;
+ doTest(false /* isGoog */, mimeType, w, h);
+ }
+
+ private void doTestDefault(String mimeType, int w, int h) throws Exception {
+ String encoderName = getEncoderName(mimeType);
+ if (encoderName == null) {
+ Log.i(TAG, "Encoder for " + mimeType + " not found");
+ return;
+ }
+
+ String decoderName = getDecoderName(mimeType);
+ if (decoderName == null) {
+ Log.i(TAG, "Encoder for " + mimeType + " not found");
+ return;
+ }
+
+ doTestByName(encoderName, decoderName, mimeType, w, h);
+ }
+
+ /**
+ * Run encoding / decoding test for given mimeType of codec
+ * @param isGoog test google or non-google codec.
+ * @param mimeType like video/avc
+ * @param w video width
+ * @param h video height
+ */
+ private void doTest(boolean isGoog, String mimeType, int w, int h)
+ throws Exception {
+ String[] encoderNames = getEncoderName(mimeType, isGoog);
+ if (encoderNames.length == 0) {
+ Log.i(TAG, isGoog ? "Google " : "Non-google "
+ + "encoder for " + mimeType + " not found");
+ return;
+ }
+
+ String[] decoderNames = getDecoderName(mimeType, isGoog);
+ if (decoderNames.length == 0) {
+ Log.i(TAG, isGoog ? "Google " : "Non-google "
+ + "decoder for " + mimeType + " not found");
+ return;
+ }
+
+ for (String encoderName: encoderNames) {
+ for (String decoderName: decoderNames) {
+ doTestByName(encoderName, decoderName, mimeType, w, h);
+ }
+ }
+ }
+
+ private void doTestByName(
+ String encoderName, String decoderName, String mimeType, int w, int h)
+ throws Exception {
+ CodecInfo infoEnc = CodecInfo.getSupportedFormatInfo(encoderName, mimeType, w, h);
+ if (infoEnc == null) {
+ Log.i(TAG, "Encoder " + mimeType + " with " + w + "," + h + " not supported");
+ return;
+ }
+ CodecInfo infoDec = CodecInfo.getSupportedFormatInfo(decoderName, mimeType, w, h);
+ assertNotNull(infoDec);
+ mVideoWidth = w;
+ mVideoHeight = h;
+
+ mSrcColorFormat = getColorFormat(infoEnc);
+ mDstColorFormat = getColorFormat(infoDec);
+ Log.i(TAG, "Testing video resolution " + w + "x" + h +
+ ": enc format " + mSrcColorFormat +
+ ", dec format " + mDstColorFormat);
+
+ initYUVPlane(w + YUV_PLANE_ADDITIONAL_LENGTH, h + YUV_PLANE_ADDITIONAL_LENGTH);
+ mEncoderFrameTimeDiff =
+ new double[mTestConfig.mNumberOfRepeat][mTestConfig.mTotalFrames - 1];
+ mDecoderFrameTimeDiff =
+ new double[mTestConfig.mNumberOfRepeat][mTestConfig.mTotalFrames - 1];
+ double[] encoderFpsResults = new double[mTestConfig.mNumberOfRepeat];
+ double[] decoderFpsResults = new double[mTestConfig.mNumberOfRepeat];
+ double[] totalFpsResults = new double[mTestConfig.mNumberOfRepeat];
+ double[] decoderRmsErrorResults = new double[mTestConfig.mNumberOfRepeat];
+ boolean success = true;
+ for (int i = 0; i < mTestConfig.mNumberOfRepeat && success; i++) {
+ mCurrentTestRound = i;
+ MediaFormat format = new MediaFormat();
+ format.setString(MediaFormat.KEY_MIME, mimeType);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, infoEnc.mBitRate);
+ format.setInteger(MediaFormat.KEY_WIDTH, w);
+ format.setInteger(MediaFormat.KEY_HEIGHT, h);
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT, mSrcColorFormat);
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, infoEnc.mFps);
+ mFrameRate = infoEnc.mFps;
+ format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, KEY_I_FRAME_INTERVAL);
+
+ double encodingTime = runEncoder(encoderName, format, mTestConfig.mTotalFrames);
+ // re-initialize format for decoder
+ format = new MediaFormat();
+ format.setString(MediaFormat.KEY_MIME, mimeType);
+ format.setInteger(MediaFormat.KEY_WIDTH, w);
+ format.setInteger(MediaFormat.KEY_HEIGHT, h);
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT, mDstColorFormat);
+ double[] decoderResult = runDecoder(decoderName, format);
+ if (decoderResult == null) {
+ success = false;
+ } else {
+ double decodingTime = decoderResult[0];
+ decoderRmsErrorResults[i] = decoderResult[1];
+ encoderFpsResults[i] = (double)mTestConfig.mTotalFrames / encodingTime * 1000.0;
+ decoderFpsResults[i] = (double)mTestConfig.mTotalFrames / decodingTime * 1000.0;
+ totalFpsResults[i] =
+ (double)mTestConfig.mTotalFrames / (encodingTime + decodingTime) * 1000.0;
+ }
+
+ // clear things for re-start
+ mEncodedOutputBuffer.clear();
+ // it will be good to clean everything to make every run the same.
+ System.gc();
+ }
+ mReportLog.printArray("encoder", encoderFpsResults, ResultType.HIGHER_BETTER,
+ ResultUnit.FPS);
+ mReportLog.printArray("rms error", decoderRmsErrorResults, ResultType.LOWER_BETTER,
+ ResultUnit.NONE);
+ mReportLog.printArray("decoder", decoderFpsResults, ResultType.HIGHER_BETTER,
+ ResultUnit.FPS);
+ mReportLog.printArray("encoder decoder", totalFpsResults, ResultType.HIGHER_BETTER,
+ ResultUnit.FPS);
+ mReportLog.printValue(mimeType + " encoder average fps for " + w + "x" + h,
+ Stat.getAverage(encoderFpsResults), ResultType.HIGHER_BETTER, ResultUnit.FPS);
+ mReportLog.printValue(mimeType + " decoder average fps for " + w + "x" + h,
+ Stat.getAverage(decoderFpsResults), ResultType.HIGHER_BETTER, ResultUnit.FPS);
+ mReportLog.printSummary("encoder decoder", Stat.getAverage(totalFpsResults),
+ ResultType.HIGHER_BETTER, ResultUnit.FPS);
+
+ boolean encTestPassed = false;
+ boolean decTestPassed = false;
+ double[] measuredFps = new double[mTestConfig.mNumberOfRepeat];
+ String[] resultRawData = new String[mTestConfig.mNumberOfRepeat];
+ for (int i = 0; i < mTestConfig.mNumberOfRepeat; i++) {
+ // make sure that rms error is not too big.
+ if (decoderRmsErrorResults[i] >= mRmsErrorMargain) {
+ fail("rms error is bigger than the limit "
+ + decoderRmsErrorResults[i] + " vs " + mRmsErrorMargain);
+ }
+
+ if (mTestConfig.mReportFrameTime) {
+ mReportLog.printValue(
+ "encodertest#" + i + ": " + Arrays.toString(mEncoderFrameTimeDiff[i]),
+ 0, ResultType.NEUTRAL, ResultUnit.NONE);
+ mReportLog.printValue(
+ "decodertest#" + i + ": " + Arrays.toString(mDecoderFrameTimeDiff[i]),
+ 0, ResultType.NEUTRAL, ResultUnit.NONE);
+ }
+
+ if (mTestConfig.mTestResult) {
+ double[] avgs = MediaUtils.calculateMovingAverage(
+ mEncoderFrameTimeDiff[i], MOVING_AVERAGE_NUM);
+ double encMin = Stat.getMin(avgs);
+ double encMax = Stat.getMax(avgs);
+ double encAvg = MediaUtils.getAverage(mEncoderFrameTimeDiff[i]);
+ double encStdev = MediaUtils.getStdev(avgs);
+ String prefix = "codec=" + encoderName + " round=" + i +
+ " EncInputFormat=" + mEncInputFormat +
+ " EncOutputFormat=" + mEncOutputFormat;
+ String result =
+ MediaUtils.logResults(mReportLog, prefix, encMin, encMax, encAvg, encStdev);
+ double measuredEncFps = 1000000000 / encMin;
+ resultRawData[i] = result;
+ measuredFps[i] = measuredEncFps;
+ if (!encTestPassed) {
+ encTestPassed = MediaUtils.verifyResults(
+ encoderName, mimeType, w, h, measuredEncFps);
+ }
+
+ avgs = MediaUtils.calculateMovingAverage(
+ mDecoderFrameTimeDiff[i], MOVING_AVERAGE_NUM);
+ double decMin = Stat.getMin(avgs);
+ double decMax = Stat.getMax(avgs);
+ double decAvg = MediaUtils.getAverage(mDecoderFrameTimeDiff[i]);
+ double decStdev = MediaUtils.getStdev(avgs);
+ prefix = "codec=" + decoderName + " size=" + w + "x" + h + " round=" + i +
+ " DecOutputFormat=" + mDecOutputFormat;
+ MediaUtils.logResults(mReportLog, prefix, decMin, decMax, decAvg, decStdev);
+ double measuredDecFps = 1000000000 / decMin;
+ if (!decTestPassed) {
+ decTestPassed = MediaUtils.verifyResults(
+ decoderName, mimeType, w, h, measuredDecFps);
+ }
+ }
+ }
+
+ if (mTestConfig.mTestResult) {
+ if (!encTestPassed) {
+ Range<Double> reportedRange =
+ MediaUtils.getAchievableFrameRatesFor(encoderName, mimeType, w, h);
+ String failMessage =
+ MediaUtils.getErrorMessage(reportedRange, measuredFps, resultRawData);
+ fail(failMessage);
+ }
+ // Decoder result will be verified in VideoDecoderPerfTest
+ // if (!decTestPassed) {
+ // fail("Measured fps for " + decoderName +
+ // " doesn't match with reported achievable frame rates.");
+ // }
+ }
+ measuredFps = null;
+ resultRawData = null;
+ }
+
+ /**
+ * run encoder benchmarking
+ * @param encoderName encoder name
+ * @param format format of media to encode
+ * @param totalFrames total number of frames to encode
+ * @return time taken in ms to encode the frames. This does not include initialization time.
+ */
+ private double runEncoder(String encoderName, MediaFormat format, int totalFrames) {
+ MediaCodec codec = null;
+ try {
+ codec = MediaCodec.createByCodecName(encoderName);
+ codec.configure(
+ format,
+ null /* surface */,
+ null /* crypto */,
+ MediaCodec.CONFIGURE_FLAG_ENCODE);
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "codec '" + encoderName + "' failed configuration.");
+ codec.release();
+ assertTrue("codec '" + encoderName + "' failed configuration.", false);
+ } catch (IOException | NullPointerException e) {
+ Log.i(TAG, "could not find codec for " + format);
+ return Double.NaN;
+ }
+ codec.start();
+ mEncInputFormat = codec.getInputFormat();
+ ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
+
+ int numBytesSubmitted = 0;
+ int numBytesDequeued = 0;
+ int inFramesCount = 0;
+ long lastOutputTimeNs = 0;
+ long start = System.currentTimeMillis();
+ while (true) {
+ int index;
+
+ if (inFramesCount < totalFrames) {
+ index = codec.dequeueInputBuffer(VIDEO_CODEC_WAIT_TIME_US /* timeoutUs */);
+ if (index != MediaCodec.INFO_TRY_AGAIN_LATER) {
+ int size;
+ boolean eos = (inFramesCount == (totalFrames - 1));
+ if (!eos && ((System.currentTimeMillis() - start) > mTestConfig.mMaxTimeMs)) {
+ eos = true;
+ }
+ // when encoder only supports flexYUV, use Image only; otherwise,
+ // use ByteBuffer & Image each on half of the frames to test both
+ if (isSrcFlexYUV() || inFramesCount % 2 == 0) {
+ Image image = codec.getInputImage(index);
+ // image should always be available
+ assertTrue(image != null);
+ size = queueInputImageEncoder(
+ codec, image, index, inFramesCount,
+ eos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
+ } else {
+ ByteBuffer buffer = codec.getInputBuffer(index);
+ size = queueInputBufferEncoder(
+ codec, buffer, index, inFramesCount,
+ eos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
+ }
+ inFramesCount++;
+ numBytesSubmitted += size;
+ if (VERBOSE) {
+ Log.d(TAG, "queued " + size + " bytes of input data, frame " +
+ (inFramesCount - 1));
+ }
+
+ }
+ }
+ MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+ index = codec.dequeueOutputBuffer(info, VIDEO_CODEC_WAIT_TIME_US /* timeoutUs */);
+ if (index == MediaCodec.INFO_TRY_AGAIN_LATER) {
+ } else if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ mEncOutputFormat = codec.getOutputFormat();
+ } else if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+ codecOutputBuffers = codec.getOutputBuffers();
+ } else if (index >= 0) {
+ if (lastOutputTimeNs > 0) {
+ int pos = mEncodedOutputBuffer.size() - 1;
+ if (pos < mEncoderFrameTimeDiff[mCurrentTestRound].length) {
+ long diff = System.nanoTime() - lastOutputTimeNs;
+ mEncoderFrameTimeDiff[mCurrentTestRound][pos] = diff;
+ }
+ }
+ lastOutputTimeNs = System.nanoTime();
+
+ dequeueOutputBufferEncoder(codec, codecOutputBuffers, index, info);
+ numBytesDequeued += info.size;
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ if (VERBOSE) {
+ Log.d(TAG, "dequeued output EOS.");
+ }
+ break;
+ }
+ if (VERBOSE) {
+ Log.d(TAG, "dequeued " + info.size + " bytes of output data.");
+ }
+ }
+ }
+ long finish = System.currentTimeMillis();
+ int validDataNum = Math.min(mEncodedOutputBuffer.size() - 1,
+ mEncoderFrameTimeDiff[mCurrentTestRound].length);
+ mEncoderFrameTimeDiff[mCurrentTestRound] =
+ Arrays.copyOf(mEncoderFrameTimeDiff[mCurrentTestRound], validDataNum);
+ if (VERBOSE) {
+ Log.d(TAG, "queued a total of " + numBytesSubmitted + "bytes, "
+ + "dequeued " + numBytesDequeued + " bytes.");
+ }
+ codec.stop();
+ codec.release();
+ codec = null;
+ return (double)(finish - start);
+ }
+
+ /**
+ * Fills input buffer for encoder from YUV buffers.
+ * @return size of enqueued data.
+ */
+ private int queueInputBufferEncoder(
+ MediaCodec codec, ByteBuffer buffer, int index, int frameCount, int flags) {
+ buffer.clear();
+
+ Point origin = getOrigin(frameCount);
+ // Y color first
+ int srcOffsetY = origin.x + origin.y * mBufferWidth;
+ final byte[] yBuffer = mYBuffer.array();
+ for (int i = 0; i < mVideoHeight; i++) {
+ buffer.put(yBuffer, srcOffsetY, mVideoWidth);
+ srcOffsetY += mBufferWidth;
+ }
+ if (isSrcSemiPlanar()) {
+ int srcOffsetU = origin.y / 2 * mBufferWidth + origin.x / 2 * 2;
+ final byte[] uvBuffer = mUVBuffer.array();
+ for (int i = 0; i < mVideoHeight / 2; i++) {
+ buffer.put(uvBuffer, srcOffsetU, mVideoWidth);
+ srcOffsetU += mBufferWidth;
+ }
+ } else {
+ int srcOffsetU = origin.y / 2 * mBufferWidth / 2 + origin.x / 2;
+ int srcOffsetV = srcOffsetU + mBufferWidth / 2 * mBufferHeight / 2;
+ final byte[] uvBuffer = mUVBuffer.array();
+ for (int i = 0; i < mVideoHeight / 2; i++) { //U only
+ buffer.put(uvBuffer, srcOffsetU, mVideoWidth / 2);
+ srcOffsetU += mBufferWidth / 2;
+ }
+ for (int i = 0; i < mVideoHeight / 2; i++) { //V only
+ buffer.put(uvBuffer, srcOffsetV, mVideoWidth / 2);
+ srcOffsetV += mBufferWidth / 2;
+ }
+ }
+ int size = mVideoHeight * mVideoWidth * 3 / 2;
+ long ptsUsec = computePresentationTime(frameCount);
+
+ codec.queueInputBuffer(index, 0 /* offset */, size, ptsUsec /* timeUs */, flags);
+ if (VERBOSE && (frameCount == 0)) {
+ printByteArray("Y ", mYBuffer.array(), 0, 20);
+ printByteArray("UV ", mUVBuffer.array(), 0, 20);
+ printByteArray("UV ", mUVBuffer.array(), mBufferWidth * 60, 20);
+ }
+ return size;
+ }
+
+ class YUVImage extends CodecImage {
+ private final int mImageWidth;
+ private final int mImageHeight;
+ private final Plane[] mPlanes;
+
+ YUVImage(
+ Point origin,
+ int imageWidth, int imageHeight,
+ int arrayWidth, int arrayHeight,
+ boolean semiPlanar,
+ ByteBuffer bufferY, ByteBuffer bufferUV) {
+ mImageWidth = imageWidth;
+ mImageHeight = imageHeight;
+ ByteBuffer dupY = bufferY.duplicate();
+ ByteBuffer dupUV = bufferUV.duplicate();
+ mPlanes = new Plane[3];
+
+ int srcOffsetY = origin.x + origin.y * arrayWidth;
+
+ mPlanes[0] = new YUVPlane(
+ mImageWidth, mImageHeight, arrayWidth, 1,
+ dupY, srcOffsetY);
+
+ if (semiPlanar) {
+ int srcOffsetUV = origin.y / 2 * arrayWidth + origin.x / 2 * 2;
+
+ mPlanes[1] = new YUVPlane(
+ mImageWidth / 2, mImageHeight / 2, arrayWidth, 2,
+ dupUV, srcOffsetUV);
+ mPlanes[2] = new YUVPlane(
+ mImageWidth / 2, mImageHeight / 2, arrayWidth, 2,
+ dupUV, srcOffsetUV + 1);
+ } else {
+ int srcOffsetU = origin.y / 2 * arrayWidth / 2 + origin.x / 2;
+ int srcOffsetV = srcOffsetU + arrayWidth / 2 * arrayHeight / 2;
+
+ mPlanes[1] = new YUVPlane(
+ mImageWidth / 2, mImageHeight / 2, arrayWidth / 2, 1,
+ dupUV, srcOffsetU);
+ mPlanes[2] = new YUVPlane(
+ mImageWidth / 2, mImageHeight / 2, arrayWidth / 2, 1,
+ dupUV, srcOffsetV);
+ }
+ }
+
+ @Override
+ public int getFormat() {
+ return ImageFormat.YUV_420_888;
+ }
+
+ @Override
+ public int getWidth() {
+ return mImageWidth;
+ }
+
+ @Override
+ public int getHeight() {
+ return mImageHeight;
+ }
+
+ @Override
+ public long getTimestamp() {
+ return 0;
+ }
+
+ @Override
+ public Plane[] getPlanes() {
+ return mPlanes;
+ }
+
+ @Override
+ public void close() {
+ mPlanes[0] = null;
+ mPlanes[1] = null;
+ mPlanes[2] = null;
+ }
+
+ class YUVPlane extends CodecImage.Plane {
+ private final int mRowStride;
+ private final int mPixelStride;
+ private final ByteBuffer mByteBuffer;
+
+ YUVPlane(int w, int h, int rowStride, int pixelStride,
+ ByteBuffer buffer, int offset) {
+ mRowStride = rowStride;
+ mPixelStride = pixelStride;
+
+ // only safe to access length bytes starting from buffer[offset]
+ int length = (h - 1) * rowStride + (w - 1) * pixelStride + 1;
+
+ buffer.position(offset);
+ mByteBuffer = buffer.slice();
+ mByteBuffer.limit(length);
+ }
+
+ @Override
+ public int getRowStride() {
+ return mRowStride;
+ }
+
+ @Override
+ public int getPixelStride() {
+ return mPixelStride;
+ }
+
+ @Override
+ public ByteBuffer getBuffer() {
+ return mByteBuffer;
+ }
+ }
+ }
+
+ /**
+ * Fills input image for encoder from YUV buffers.
+ * @return size of enqueued data.
+ */
+ private int queueInputImageEncoder(
+ MediaCodec codec, Image image, int index, int frameCount, int flags) {
+ assertTrue(image.getFormat() == ImageFormat.YUV_420_888);
+
+
+ Point origin = getOrigin(frameCount);
+
+ // Y color first
+ CodecImage srcImage = new YUVImage(
+ origin,
+ mVideoWidth, mVideoHeight,
+ mBufferWidth, mBufferHeight,
+ isSrcSemiPlanar(),
+ mYDirectBuffer, mUVDirectBuffer);
+
+ CodecUtils.copyFlexYUVImage(image, srcImage);
+
+ int size = mVideoHeight * mVideoWidth * 3 / 2;
+ long ptsUsec = computePresentationTime(frameCount);
+
+ codec.queueInputBuffer(index, 0 /* offset */, size, ptsUsec /* timeUs */, flags);
+ if (VERBOSE && (frameCount == 0)) {
+ printByteArray("Y ", mYBuffer.array(), 0, 20);
+ printByteArray("UV ", mUVBuffer.array(), 0, 20);
+ printByteArray("UV ", mUVBuffer.array(), mBufferWidth * 60, 20);
+ }
+ return size;
+ }
+
+ /**
+ * Dequeue encoded data from output buffer and store for later usage.
+ */
+ private void dequeueOutputBufferEncoder(
+ MediaCodec codec, ByteBuffer[] outputBuffers,
+ int index, MediaCodec.BufferInfo info) {
+ ByteBuffer output = outputBuffers[index];
+ int l = info.size;
+ ByteBuffer copied = ByteBuffer.allocate(l);
+ output.get(copied.array(), 0, l);
+ BufferInfo savedInfo = new BufferInfo();
+ savedInfo.set(0, l, info.presentationTimeUs, info.flags);
+ mEncodedOutputBuffer.addLast(Pair.create(copied, savedInfo));
+ codec.releaseOutputBuffer(index, false /* render */);
+ }
+
+ /**
+ * run decoder benchmarking with encoded stream stored from encoding phase
+ * @param decoderName decoder name
+ * @param format format of media to decode
+ * @return returns length-2 array with 0: time for decoding, 1 : rms error of pixels
+ */
+ private double[] runDecoder(String decoderName, MediaFormat format) {
+ MediaCodec codec = null;
+ try {
+ codec = MediaCodec.createByCodecName(decoderName);
+ } catch (IOException | NullPointerException e) {
+ Log.i(TAG, "could not find decoder for " + format);
+ return null;
+ }
+ codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
+ codec.start();
+ ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
+
+ double totalErrorSquared = 0;
+
+ MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+ boolean sawOutputEOS = false;
+ int inputLeft = mEncodedOutputBuffer.size();
+ int inputBufferCount = 0;
+ int outFrameCount = 0;
+ YUVValue expected = new YUVValue();
+ YUVValue decoded = new YUVValue();
+ long lastOutputTimeNs = 0;
+ long start = System.currentTimeMillis();
+ while (!sawOutputEOS) {
+ if (inputLeft > 0) {
+ int inputBufIndex = codec.dequeueInputBuffer(VIDEO_CODEC_WAIT_TIME_US);
+
+ if (inputBufIndex >= 0) {
+ ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
+ dstBuf.clear();
+ ByteBuffer src = mEncodedOutputBuffer.get(inputBufferCount).first;
+ BufferInfo srcInfo = mEncodedOutputBuffer.get(inputBufferCount).second;
+ int writeSize = src.capacity();
+ dstBuf.put(src.array(), 0, writeSize);
+
+ int flags = srcInfo.flags;
+ if ((System.currentTimeMillis() - start) > mTestConfig.mMaxTimeMs) {
+ flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+ }
+
+ codec.queueInputBuffer(
+ inputBufIndex,
+ 0 /* offset */,
+ writeSize,
+ srcInfo.presentationTimeUs,
+ flags);
+ inputLeft --;
+ inputBufferCount ++;
+ }
+ }
+
+ int res = codec.dequeueOutputBuffer(info, VIDEO_CODEC_WAIT_TIME_US);
+ if (res >= 0) {
+ int outputBufIndex = res;
+
+ // only do YUV compare on EOS frame if the buffer size is none-zero
+ if (info.size > 0) {
+ if (lastOutputTimeNs > 0) {
+ int pos = outFrameCount - 1;
+ if (pos < mDecoderFrameTimeDiff[mCurrentTestRound].length) {
+ long diff = System.nanoTime() - lastOutputTimeNs;
+ mDecoderFrameTimeDiff[mCurrentTestRound][pos] = diff;
+ }
+ }
+ lastOutputTimeNs = System.nanoTime();
+
+ if (mTestConfig.mTestPixels) {
+ Point origin = getOrigin(outFrameCount);
+ int i;
+
+ // if decoder supports planar or semiplanar, check output with
+ // ByteBuffer & Image each on half of the points
+ int pixelCheckPerFrame = PIXEL_CHECK_PER_FRAME;
+ if (!isDstFlexYUV()) {
+ pixelCheckPerFrame /= 2;
+ ByteBuffer buf = codec.getOutputBuffer(outputBufIndex);
+ if (VERBOSE && (outFrameCount == 0)) {
+ printByteBuffer("Y ", buf, 0, 20);
+ printByteBuffer("UV ", buf, mVideoWidth * mVideoHeight, 20);
+ printByteBuffer("UV ", buf,
+ mVideoWidth * mVideoHeight + mVideoWidth * 60, 20);
+ }
+ for (i = 0; i < pixelCheckPerFrame; i++) {
+ int w = mRandom.nextInt(mVideoWidth);
+ int h = mRandom.nextInt(mVideoHeight);
+ getPixelValuesFromYUVBuffers(origin.x, origin.y, w, h, expected);
+ getPixelValuesFromOutputBuffer(buf, w, h, decoded);
+ if (VERBOSE) {
+ Log.i(TAG, outFrameCount + "-" + i + "- th round: ByteBuffer:"
+ + " expected "
+ + expected.mY + "," + expected.mU + "," + expected.mV
+ + " decoded "
+ + decoded.mY + "," + decoded.mU + "," + decoded.mV);
+ }
+ totalErrorSquared += expected.calcErrorSquared(decoded);
+ }
+ }
+
+ Image image = codec.getOutputImage(outputBufIndex);
+ assertTrue(image != null);
+ for (i = 0; i < pixelCheckPerFrame; i++) {
+ int w = mRandom.nextInt(mVideoWidth);
+ int h = mRandom.nextInt(mVideoHeight);
+ getPixelValuesFromYUVBuffers(origin.x, origin.y, w, h, expected);
+ getPixelValuesFromImage(image, w, h, decoded);
+ if (VERBOSE) {
+ Log.i(TAG, outFrameCount + "-" + i + "- th round: FlexYUV:"
+ + " expcted "
+ + expected.mY + "," + expected.mU + "," + expected.mV
+ + " decoded "
+ + decoded.mY + "," + decoded.mU + "," + decoded.mV);
+ }
+ totalErrorSquared += expected.calcErrorSquared(decoded);
+ }
+ }
+ outFrameCount++;
+ }
+ codec.releaseOutputBuffer(outputBufIndex, false /* render */);
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ Log.d(TAG, "saw output EOS.");
+ sawOutputEOS = true;
+ }
+ } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ mDecOutputFormat = codec.getOutputFormat();
+ Log.d(TAG, "output format has changed to " + mDecOutputFormat);
+ int colorFormat = mDecOutputFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+ if (colorFormat == CodecCapabilities.COLOR_FormatYUV420SemiPlanar
+ || colorFormat == CodecCapabilities.COLOR_FormatYUV420Planar) {
+ mDstColorFormat = colorFormat;
+ } else {
+ mDstColorFormat = CodecCapabilities.COLOR_FormatYUV420Flexible;
+ Log.w(TAG, "output format changed to unsupported one " +
+ Integer.toHexString(colorFormat) + ", using FlexYUV");
+ }
+ }
+ }
+ long finish = System.currentTimeMillis();
+ int validDataNum = Math.min(outFrameCount - 1,
+ mDecoderFrameTimeDiff[mCurrentTestRound].length);
+ mDecoderFrameTimeDiff[mCurrentTestRound] =
+ Arrays.copyOf(mDecoderFrameTimeDiff[mCurrentTestRound], validDataNum);
+ codec.stop();
+ codec.release();
+ codec = null;
+
+ // divide by 3 as sum is done for Y, U, V.
+ double errorRms = Math.sqrt(totalErrorSquared / PIXEL_CHECK_PER_FRAME / outFrameCount / 3);
+ double[] result = { (double) finish - start, errorRms };
+ return result;
+ }
+
+ /**
+ * returns origin in the absolute frame for given frame count.
+ * The video scene is moving by moving origin per each frame.
+ */
+ private Point getOrigin(int frameCount) {
+ if (frameCount < 100) {
+ return new Point(2 * frameCount, 0);
+ } else if (frameCount < 200) {
+ return new Point(200, (frameCount - 100) * 2);
+ } else {
+ if (frameCount > 300) { // for safety
+ frameCount = 300;
+ }
+ return new Point(600 - frameCount * 2, 600 - frameCount * 2);
+ }
+ }
+
+ /**
+ * initialize reference YUV plane
+ * @param w This should be YUV_PLANE_ADDITIONAL_LENGTH pixels bigger than video resolution
+ * to allow movements
+ * @param h This should be YUV_PLANE_ADDITIONAL_LENGTH pixels bigger than video resolution
+ * to allow movements
+ * @param semiPlanarEnc
+ * @param semiPlanarDec
+ */
+ private void initYUVPlane(int w, int h) {
+ int bufferSizeY = w * h;
+ mYBuffer = ByteBuffer.allocate(bufferSizeY);
+ mUVBuffer = ByteBuffer.allocate(bufferSizeY / 2);
+ mYDirectBuffer = ByteBuffer.allocateDirect(bufferSizeY);
+ mUVDirectBuffer = ByteBuffer.allocateDirect(bufferSizeY / 2);
+ mBufferWidth = w;
+ mBufferHeight = h;
+ final byte[] yArray = mYBuffer.array();
+ final byte[] uvArray = mUVBuffer.array();
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ yArray[i * w + j] = clampY((i + j) & 0xff);
+ }
+ }
+ if (isSrcSemiPlanar()) {
+ for (int i = 0; i < h/2; i++) {
+ for (int j = 0; j < w/2; j++) {
+ uvArray[i * w + 2 * j] = (byte) (i & 0xff);
+ uvArray[i * w + 2 * j + 1] = (byte) (j & 0xff);
+ }
+ }
+ } else { // planar, U first, then V
+ int vOffset = bufferSizeY / 4;
+ for (int i = 0; i < h/2; i++) {
+ for (int j = 0; j < w/2; j++) {
+ uvArray[i * w/2 + j] = (byte) (i & 0xff);
+ uvArray[i * w/2 + vOffset + j] = (byte) (j & 0xff);
+ }
+ }
+ }
+ mYDirectBuffer.put(yArray);
+ mUVDirectBuffer.put(uvArray);
+ mYDirectBuffer.rewind();
+ mUVDirectBuffer.rewind();
+ }
+
+ /**
+ * class to store pixel values in YUV
+ *
+ */
+ public class YUVValue {
+ public byte mY;
+ public byte mU;
+ public byte mV;
+ public YUVValue() {
+ }
+
+ public boolean equalTo(YUVValue other) {
+ return (mY == other.mY) && (mU == other.mU) && (mV == other.mV);
+ }
+
+ public double calcErrorSquared(YUVValue other) {
+ // Java's byte is signed but here we want to calculate difference in unsigned bytes.
+ double yDelta = (mY & 0xFF) - (other.mY & 0xFF);
+ double uDelta = (mU & 0xFF) - (other.mU & 0xFF);
+ double vDelta = (mV & 0xFF) - (other.mV & 0xFF);
+ return yDelta * yDelta + uDelta * uDelta + vDelta * vDelta;
+ }
+ }
+
+ /**
+ * Read YUV values from given position (x,y) for given origin (originX, originY)
+ * The whole data is already available from YBuffer and UVBuffer.
+ * @param result pass the result via this. This is for avoiding creating / destroying too many
+ * instances
+ */
+ private void getPixelValuesFromYUVBuffers(int originX, int originY, int x, int y,
+ YUVValue result) {
+ result.mY = mYBuffer.get((originY + y) * mBufferWidth + (originX + x));
+ if (isSrcSemiPlanar()) {
+ int index = (originY + y) / 2 * mBufferWidth + (originX + x) / 2 * 2;
+ //Log.d(TAG, "YUV " + originX + "," + originY + "," + x + "," + y + "," + index);
+ result.mU = mUVBuffer.get(index);
+ result.mV = mUVBuffer.get(index + 1);
+ } else {
+ int vOffset = mBufferWidth * mBufferHeight / 4;
+ int index = (originY + y) / 2 * mBufferWidth / 2 + (originX + x) / 2;
+ result.mU = mUVBuffer.get(index);
+ result.mV = mUVBuffer.get(vOffset + index);
+ }
+ }
+
+ /**
+ * Read YUV pixels from decoded output buffer for give (x, y) position
+ * Output buffer is composed of Y parts followed by U/V
+ * @param result pass the result via this. This is for avoiding creating / destroying too many
+ * instances
+ */
+ private void getPixelValuesFromOutputBuffer(ByteBuffer buffer, int x, int y, YUVValue result) {
+ result.mY = buffer.get(y * mVideoWidth + x);
+ if (isDstSemiPlanar()) {
+ int index = mVideoWidth * mVideoHeight + y / 2 * mVideoWidth + x / 2 * 2;
+ //Log.d(TAG, "Decoded " + x + "," + y + "," + index);
+ result.mU = buffer.get(index);
+ result.mV = buffer.get(index + 1);
+ } else {
+ int vOffset = mVideoWidth * mVideoHeight / 4;
+ int index = mVideoWidth * mVideoHeight + y / 2 * mVideoWidth / 2 + x / 2;
+ result.mU = buffer.get(index);
+ result.mV = buffer.get(index + vOffset);
+ }
+ }
+
+ private void getPixelValuesFromImage(Image image, int x, int y, YUVValue result) {
+ assertTrue(image.getFormat() == ImageFormat.YUV_420_888);
+
+ Plane[] planes = image.getPlanes();
+ assertTrue(planes.length == 3);
+
+ result.mY = getPixelFromPlane(planes[0], x, y);
+ result.mU = getPixelFromPlane(planes[1], x / 2, y / 2);
+ result.mV = getPixelFromPlane(planes[2], x / 2, y / 2);
+ }
+
+ private byte getPixelFromPlane(Plane plane, int x, int y) {
+ ByteBuffer buf = plane.getBuffer();
+ return buf.get(y * plane.getRowStride() + x * plane.getPixelStride());
+ }
+
+ /**
+ * Y cannot have full range. clamp it to prevent invalid value.
+ */
+ private byte clampY(int y) {
+ if (y < Y_CLAMP_MIN) {
+ y = Y_CLAMP_MIN;
+ } else if (y > Y_CLAMP_MAX) {
+ y = Y_CLAMP_MAX;
+ }
+ return (byte) (y & 0xff);
+ }
+
+ // for debugging
+ private void printByteArray(String msg, byte[] data, int offset, int len) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(msg);
+ builder.append(":");
+ for (int i = offset; i < offset + len; i++) {
+ builder.append(Integer.toHexString(data[i]));
+ builder.append(",");
+ }
+ builder.deleteCharAt(builder.length() - 1);
+ Log.i(TAG, builder.toString());
+ }
+
+ // for debugging
+ private void printByteBuffer(String msg, ByteBuffer data, int offset, int len) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(msg);
+ builder.append(":");
+ for (int i = offset; i < offset + len; i++) {
+ builder.append(Integer.toHexString(data.get(i)));
+ builder.append(",");
+ }
+ builder.deleteCharAt(builder.length() - 1);
+ Log.i(TAG, builder.toString());
+ }
+
+ /**
+ * Generates the presentation time for frame N, in microseconds.
+ */
+ private long computePresentationTime(int frameIndex) {
+ return 132 + frameIndex * 1000000L / mFrameRate;
+ }
+}
diff --git a/tests/vm/Android.mk b/tests/vm/Android.mk
new file mode 100755
index 0000000..13da75e
--- /dev/null
+++ b/tests/vm/Android.mk
@@ -0,0 +1,39 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsVmTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/vm/AndroidManifest.xml b/tests/vm/AndroidManifest.xml
new file mode 100755
index 0000000..cbd2c90
--- /dev/null
+++ b/tests/vm/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.vm.cts">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <!-- self-instrumenting test package. -->
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:label="CTS VM test cases"
+ android:targetPackage="android.vm.cts" >
+ </instrumentation>
+</manifest>
+
diff --git a/tests/vm/AndroidTest.xml b/tests/vm/AndroidTest.xml
new file mode 100644
index 0000000..2bac07b
--- /dev/null
+++ b/tests/vm/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<configuration description="Config for CTS VM test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsVmTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.vm.cts" />
+ </test>
+</configuration>
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_double/AddDoubleTest.java b/tests/vm/src/android/vm/cts/opcodes/add_double/AddDoubleTest.java
new file mode 100644
index 0000000..ba5a41d
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_double/AddDoubleTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+package android.vm.cts.opcodes.add_double;
+
+import junit.framework.TestCase;
+
+public class AddDoubleTest extends TestCase {
+
+ /**
+ * @title Arguments = 2.7d, 3.14d
+ */
+ public void testN1() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(5.84d, t.run(2.7d, 3.14d));
+ }
+
+ /**
+ * @title Arguments = 0, -3.14d
+ */
+ public void testN2() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(-3.14d, t.run(0, -3.14d));
+ }
+
+ /**
+ * @title Arguments = -3.14d, -2.7d
+ */
+ public void testN3() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(-5.84d, t.run(-3.14d, -2.7d));
+ }
+
+ /**
+ * @title Arguments = Double.MAX_VALUE, Double.NaN
+ */
+ public void testB1() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(Double.NaN, t.run(Double.MAX_VALUE, Double.NaN));
+ }
+
+ /**
+ * @title Arguments = Double.POSITIVE_INFINITY,
+ * Double.NEGATIVE_INFINITY
+ */
+ public void testB2() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(Double.NaN, t.run(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * @title Arguments = Double.POSITIVE_INFINITY,
+ * Double.POSITIVE_INFINITY
+ */
+ public void testB3() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(Double.POSITIVE_INFINITY, t.run(Double.POSITIVE_INFINITY,
+ Double.POSITIVE_INFINITY));
+ }
+
+ /**
+ * @title Arguments = Double.POSITIVE_INFINITY, -2.7d
+ */
+ public void testB4() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(Double.POSITIVE_INFINITY, t.run(Double.POSITIVE_INFINITY, -2.7d));
+ }
+
+ /**
+ * @title Arguments = +0, -0
+ */
+ public void testB5() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(+0d, t.run(+0d, -0d));
+ }
+
+ /**
+ * @title Arguments = -0d, -0d
+ */
+ public void testB6() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(-0d, t.run(-0d, -0d));
+ }
+
+ /**
+ * @title Arguments = -2.7d, 2.7d
+ */
+ public void testB7() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(+0d, t.run(-2.7d, 2.7d));
+ }
+
+ /**
+ * @title Arguments = Double.MAX_VALUE, Double.MAX_VALUE
+ */
+ public void testB8() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(Double.POSITIVE_INFINITY, t.run(Double.MAX_VALUE, Double.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Double.MIN_VALUE, -4.9E-324
+ */
+ public void testB9() {
+ AddDouble_1 t = new AddDouble_1();
+ assertEquals(0d, t.run(Double.MIN_VALUE, -4.9E-324));
+ }
+
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_double/AddDouble_1.java b/tests/vm/src/android/vm/cts/opcodes/add_double/AddDouble_1.java
new file mode 100644
index 0000000..d4ebed2
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_double/AddDouble_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_double;
+
+public class AddDouble_1 {
+
+ public double run(double a, double b) {
+ return a + b;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_double/AddDouble_3.java b/tests/vm/src/android/vm/cts/opcodes/add_double/AddDouble_3.java
new file mode 100644
index 0000000..587a68b
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_double/AddDouble_3.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_double;
+
+public class AddDouble_3 {
+
+ public double run(long a, double b) {
+ return 1;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_double_2addr/AddDouble2AddrTest.java b/tests/vm/src/android/vm/cts/opcodes/add_double_2addr/AddDouble2AddrTest.java
new file mode 100644
index 0000000..27de92c
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_double_2addr/AddDouble2AddrTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_double_2addr;
+
+import junit.framework.TestCase;
+
+public class AddDouble2AddrTest extends TestCase {
+ /**
+ * @title Arguments = 2.7d, 3.14d
+ */
+ public void testN1() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(5.84d, t.run(2.7d, 3.14d));
+ }
+
+ /**
+ * @title Arguments = 0, -3.14d
+ */
+ public void testN2() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(-3.14d, t.run(0, -3.14d));
+ }
+
+ /**
+ * @title Arguments = -3.14d, -2.7d
+ */
+ public void testN3() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(-5.84d, t.run(-3.14d, -2.7d));
+ }
+
+ /**
+ * @title Arguments = Double.MAX_VALUE, Double.NaN
+ */
+ public void testB1() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(Double.NaN, t.run(Double.MAX_VALUE, Double.NaN));
+ }
+
+ /**
+ * @title Arguments = Double.POSITIVE_INFINITY,
+ * Double.NEGATIVE_INFINITY
+ */
+ public void testB2() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(Double.NaN, t.run(Double.POSITIVE_INFINITY,
+ Double.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * @title Arguments = Double.POSITIVE_INFINITY,
+ * Double.POSITIVE_INFINITY
+ */
+ public void testB3() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(Double.POSITIVE_INFINITY, t.run(Double.POSITIVE_INFINITY,
+ Double.POSITIVE_INFINITY));
+ }
+
+ /**
+ * @title Arguments = Double.POSITIVE_INFINITY, -2.7d
+ */
+ public void testB4() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(Double.POSITIVE_INFINITY, t.run(Double.POSITIVE_INFINITY,
+ -2.7d));
+ }
+
+ /**
+ * @title Arguments = +0, -0
+ */
+ public void testB5() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(+0d, t.run(+0d, -0d));
+ }
+
+ /**
+ * @title Arguments = -0d, -0d
+ */
+ public void testB6() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(-0d, t.run(-0d, -0d));
+ }
+
+ /**
+ * @title Arguments = -2.7d, 2.7d
+ */
+ public void testB7() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(+0d, t.run(-2.7d, 2.7d));
+ }
+
+ /**
+ * @title Arguments = Double.MAX_VALUE, Double.MAX_VALUE
+ */
+ public void testB8() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(Double.POSITIVE_INFINITY, t.run(Double.MAX_VALUE,
+ Double.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Double.MIN_VALUE, -4.9E-324
+ */
+ public void testB9() {
+ AddDouble2Addr_1 t = new AddDouble2Addr_1();
+ assertEquals(0d, t.run(Double.MIN_VALUE, -4.9E-324));
+ }
+
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_double_2addr/AddDouble2Addr_1.java b/tests/vm/src/android/vm/cts/opcodes/add_double_2addr/AddDouble2Addr_1.java
new file mode 100644
index 0000000..2536113
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_double_2addr/AddDouble2Addr_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_double_2addr;
+
+public class AddDouble2Addr_1 {
+
+ public double run(double a, double b) {
+ return a + b;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_double_2addr/AddDouble2Addr_3.java b/tests/vm/src/android/vm/cts/opcodes/add_double_2addr/AddDouble2Addr_3.java
new file mode 100644
index 0000000..7ed1fe8
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_double_2addr/AddDouble2Addr_3.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_double_2addr;
+
+public class AddDouble2Addr_3 {
+
+ public double run(long a) {
+ return 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_float/AddFloatTest.java b/tests/vm/src/android/vm/cts/opcodes/add_float/AddFloatTest.java
new file mode 100644
index 0000000..76490b0
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_float/AddFloatTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_float;
+
+import junit.framework.TestCase;
+
+public class AddFloatTest extends TestCase {
+ /**
+ * @title Arguments = 2.7f, 3.14f
+ */
+ public void testN1() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(5.84f, t.run(2.7f, 3.14f));
+ }
+
+ /**
+ * @title Arguments = 0, -3.14f
+ */
+ public void testN2() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(-3.14f, t.run(0, -3.14f));
+ }
+
+ /**
+ * @title Arguments = -3.14f, -2.7f
+ */
+ public void testN3() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(-5.84f, t.run(-3.14f, -2.7f));
+ }
+
+ /**
+ * @title Arguments = Float.MAX_VALUE, Float.NaN
+ */
+ public void testB1() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(Float.POSITIVE_INFINITY, t.run(3.3028235E38f, 0.11E38f));
+ }
+
+ /**
+ * @title Arguments = Float.POSITIVE_INFINITY,
+ * Float.NEGATIVE_INFINITY
+ */
+ public void testB2() {
+ AddFloat_1 t = new AddFloat_1();
+ assertTrue(Float.isNaN(t.run(Float.POSITIVE_INFINITY,
+ Float.NEGATIVE_INFINITY)));
+ }
+
+ /**
+ * @title Arguments = Float.POSITIVE_INFINITY,
+ * Float.POSITIVE_INFINITY
+ */
+ public void testB3() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(Float.POSITIVE_INFINITY, t.run(Float.POSITIVE_INFINITY,
+ Float.POSITIVE_INFINITY));
+ }
+
+ /**
+ * @title Arguments = Float.POSITIVE_INFINITY, -2.7f
+ */
+ public void testB4() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(Float.POSITIVE_INFINITY, t.run(Float.POSITIVE_INFINITY,
+ -2.7f));
+ }
+
+ /**
+ * @title Arguments = +0, -0f
+ */
+ public void testB5() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(+0f, t.run(+0f, -0f));
+ }
+
+ /**
+ * @title Arguments = -0f, -0f
+ */
+ public void testB6() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(-0f, t.run(-0f, -0f));
+ }
+
+ /**
+ * @title Arguments = -2.7f, 2.7f
+ */
+ public void testB7() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(+0f, t.run(-2.7f, 2.7f));
+ }
+
+ /**
+ * @title Arguments = Float.MAX_VALUE, Float.MAX_VALUE
+ */
+ public void testB8() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(Float.POSITIVE_INFINITY, t.run(Float.MAX_VALUE,
+ Float.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Float.MIN_VALUE, -1.4E-45f
+ */
+ public void testB9() {
+ AddFloat_1 t = new AddFloat_1();
+ assertEquals(0f, t.run(Float.MIN_VALUE, -1.4E-45f));
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_float/AddFloat_1.java b/tests/vm/src/android/vm/cts/opcodes/add_float/AddFloat_1.java
new file mode 100644
index 0000000..aff5beb
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_float/AddFloat_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_float;
+
+public class AddFloat_1 {
+
+ public float run(float a, float b) {
+ return a + b;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_float/AddFloat_5.java b/tests/vm/src/android/vm/cts/opcodes/add_float/AddFloat_5.java
new file mode 100644
index 0000000..2eba052
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_float/AddFloat_5.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_float;
+
+public class AddFloat_5 {
+
+ public float run(int a, float b) {
+ return 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_float_2addr/AddFloat2AddrTest.java b/tests/vm/src/android/vm/cts/opcodes/add_float_2addr/AddFloat2AddrTest.java
new file mode 100644
index 0000000..177e564
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_float_2addr/AddFloat2AddrTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+package android.vm.cts.opcodes.add_float_2addr;
+
+import junit.framework.TestCase;
+
+public class AddFloat2AddrTest extends TestCase {
+ /**
+ * @title Arguments = 2.7f, 3.14f
+ */
+ public void testN1() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(5.84f, t.run(2.7f, 3.14f));
+ }
+
+ /**
+ * @title Arguments = 0, -3.14f
+ */
+ public void testN2() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(-3.14f, t.run(0, -3.14f));
+ }
+
+ /**
+ * @title Arguments = -3.14f, -2.7f
+ */
+ public void testN3() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(-5.84f, t.run(-3.14f, -2.7f));
+ }
+
+ /**
+ * @title Arguments = Float.MAX_VALUE, Float.NaN
+ */
+ public void testB1() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(Float.POSITIVE_INFINITY, t.run(3.3028235E38f, 0.11E38f));
+ }
+
+ /**
+ * @title Arguments = Float.POSITIVE_INFINITY,
+ * Float.NEGATIVE_INFINITY
+ */
+ public void testB2() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertTrue(Float.isNaN(t.run(Float.POSITIVE_INFINITY,
+ Float.NEGATIVE_INFINITY)));
+ }
+
+ /**
+ * @title Arguments = Float.POSITIVE_INFINITY,
+ * Float.POSITIVE_INFINITY
+ */
+ public void testB3() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(Float.POSITIVE_INFINITY, t.run(Float.POSITIVE_INFINITY,
+ Float.POSITIVE_INFINITY));
+ }
+
+ /**
+ * @title Arguments = Float.POSITIVE_INFINITY, -2.7f
+ */
+ public void testB4() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(Float.POSITIVE_INFINITY, t.run(Float.POSITIVE_INFINITY,
+ -2.7f));
+ }
+
+ /**
+ * @title Arguments = +0, -0f
+ */
+ public void testB5() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(+0f, t.run(+0f, -0f));
+ }
+
+ /**
+ * @title Arguments = -0f, -0f
+ */
+ public void testB6() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(-0f, t.run(-0f, -0f));
+ }
+
+ /**
+ * @title Arguments = -2.7f, 2.7f
+ */
+ public void testB7() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(+0f, t.run(-2.7f, 2.7f));
+ }
+
+ /**
+ * @title Arguments = Float.MAX_VALUE, Float.MAX_VALUE
+ */
+ public void testB8() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(Float.POSITIVE_INFINITY, t.run(Float.MAX_VALUE,
+ Float.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Float.MIN_VALUE, -1.4E-45f
+ */
+ public void testB9() {
+ AddFloat2Addr_1 t = new AddFloat2Addr_1();
+ assertEquals(0f, t.run(Float.MIN_VALUE, -1.4E-45f));
+ }
+
+
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_float_2addr/AddFloat2Addr_1.java b/tests/vm/src/android/vm/cts/opcodes/add_float_2addr/AddFloat2Addr_1.java
new file mode 100644
index 0000000..cabd4f9
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_float_2addr/AddFloat2Addr_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_float_2addr;
+
+public class AddFloat2Addr_1 {
+
+ public float run(float a, float b) {
+ return a + b;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_float_2addr/AddFloat2Addr_5.java b/tests/vm/src/android/vm/cts/opcodes/add_float_2addr/AddFloat2Addr_5.java
new file mode 100644
index 0000000..7fdd723
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_float_2addr/AddFloat2Addr_5.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_float_2addr;
+
+public class AddFloat2Addr_5 {
+
+ public float run(int a, float b) {
+ return 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int/AddIntTest.java b/tests/vm/src/android/vm/cts/opcodes/add_int/AddIntTest.java
new file mode 100644
index 0000000..7e67da6
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int/AddIntTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+package android.vm.cts.opcodes.add_int;
+
+import junit.framework.TestCase;
+
+public class AddIntTest extends TestCase {
+ /**
+ * @title Arguments = 8, 4
+ */
+ public void testN1() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(12, t.run(8, 4));
+ }
+
+ /**
+ * @title Arguments = 0, 255
+ */
+ public void testN2() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(255, t.run(0, 255));
+ }
+
+ /**
+ * @title Arguments = 0, -65536
+ */
+ public void testN3() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(-65536, t.run(0, -65536));
+ }
+
+ /**
+ * @title Arguments = 0, -2147483647
+ */
+ public void testN4() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(-2147483647, t.run(0, -2147483647));
+ }
+
+ /**
+ * @title Arguments = 0x7ffffffe, 2
+ */
+ public void testN5() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(-2147483648, t.run(0x7ffffffe, 2));
+ }
+
+ /**
+ * @title Arguments = -1, 1
+ */
+ public void testN6() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(0, t.run(-1, 1));
+ }
+
+
+ /**
+ * @title Arguments = 0, Integer.MAX_VALUE
+ */
+ public void testB1() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(Integer.MAX_VALUE, t.run(0, Integer.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Integer.MAX_VALUE, Integer.MAX_VALUE
+ */
+ public void testB2() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(-2, t.run(Integer.MAX_VALUE, Integer.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Integer.MAX_VALUE, 1
+ */
+ public void testB3() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(Integer.MIN_VALUE, t.run(Integer.MAX_VALUE, 1));
+ }
+
+ /**
+ * @title Arguments = Integer.MIN_VALUE, 1
+ */
+ public void testB4() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(-2147483647, t.run(Integer.MIN_VALUE, 1));
+ }
+
+ /**
+ * @title Arguments = 0, 0
+ */
+ public void testB5() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(0, t.run(0, 0));
+ }
+
+ /**
+ * @title Arguments = Integer.MIN_VALUE, Integer.MIN_VALUE
+ */
+ public void testB6() {
+ AddInt_1 t = new AddInt_1();
+ assertEquals(0, t.run(Integer.MIN_VALUE, Integer.MIN_VALUE));
+ }
+
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int/AddInt_1.java b/tests/vm/src/android/vm/cts/opcodes/add_int/AddInt_1.java
new file mode 100644
index 0000000..825821d
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int/AddInt_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int;
+
+public class AddInt_1 {
+
+ public int run(int a, int b) {
+ return a + b;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int/AddInt_5.java b/tests/vm/src/android/vm/cts/opcodes/add_int/AddInt_5.java
new file mode 100644
index 0000000..c17caaa
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int/AddInt_5.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int;
+
+public class AddInt_5 {
+
+ public int run(int a, float b) {
+ return 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_2addr/AddInt2AddrTest.java b/tests/vm/src/android/vm/cts/opcodes/add_int_2addr/AddInt2AddrTest.java
new file mode 100644
index 0000000..b2c4eb3
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_2addr/AddInt2AddrTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+package android.vm.cts.opcodes.add_int_2addr;
+
+import junit.framework.TestCase;
+
+public class AddInt2AddrTest extends TestCase {
+ /**
+ * @title Arguments = 8, 4
+ */
+ public void testN1() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(12, t.run(8, 4));
+ }
+
+ /**
+ * @title Arguments = 0, 255
+ */
+ public void testN2() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(255, t.run(0, 255));
+ }
+
+ /**
+ * @title Arguments = 0, -65536
+ */
+ public void testN3() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(-65536, t.run(0, -65536));
+ }
+
+ /**
+ * @title Arguments = 0, -2147483647
+ */
+ public void testN4() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(-2147483647, t.run(0, -2147483647));
+ }
+
+ /**
+ * @title Arguments = 0x7ffffffe, 2
+ */
+ public void testN5() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(-2147483648, t.run(0x7ffffffe, 2));
+ }
+
+ /**
+ * @title Arguments = -1, 1
+ */
+ public void testN6() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(0, t.run(-1, 1));
+ }
+
+ /**
+ * @title Arguments = 0, Integer.MAX_VALUE
+ */
+ public void testB1() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(Integer.MAX_VALUE, t.run(0, Integer.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Integer.MAX_VALUE, Integer.MAX_VALUE
+ */
+ public void testB2() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(-2, t.run(Integer.MAX_VALUE, Integer.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Integer.MAX_VALUE, 1
+ */
+ public void testB3() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(Integer.MIN_VALUE, t.run(Integer.MAX_VALUE, 1));
+ }
+
+ /**
+ * @title Arguments = Integer.MIN_VALUE, 1
+ */
+ public void testB4() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(-2147483647, t.run(Integer.MIN_VALUE, 1));
+ }
+
+ /**
+ * @title Arguments = 0, 0
+ */
+ public void testB5() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(0, t.run(0, 0));
+ }
+
+ /**
+ * @title Arguments = Integer.MIN_VALUE, Integer.MIN_VALUE
+ */
+ public void testB6() {
+ AddInt2Addr_1 t = new AddInt2Addr_1();
+ assertEquals(0, t.run(Integer.MIN_VALUE, Integer.MIN_VALUE));
+ }
+
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_2addr/AddInt2Addr_1.java b/tests/vm/src/android/vm/cts/opcodes/add_int_2addr/AddInt2Addr_1.java
new file mode 100644
index 0000000..ec0757b
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_2addr/AddInt2Addr_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_2addr;
+
+public class AddInt2Addr_1 {
+
+ public int run(int a, int b) {
+ return a+b;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_2addr/AddInt2Addr_5.java b/tests/vm/src/android/vm/cts/opcodes/add_int_2addr/AddInt2Addr_5.java
new file mode 100644
index 0000000..8b78444
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_2addr/AddInt2Addr_5.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_2addr;
+
+public class AddInt2Addr_5 {
+
+ public int run(int a, float b) {
+ return 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16Test.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16Test.java
new file mode 100644
index 0000000..cc378df
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16Test.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+package android.vm.cts.opcodes.add_int_lit16;
+
+import junit.framework.TestCase;
+
+public class AddIntLit16Test extends TestCase {
+ /**
+ * @title Arguments = 8 + 4
+ */
+ public void testN1() {
+ AddIntLit16_1 t = new AddIntLit16_1();
+ assertEquals(12, t.run());
+ }
+
+ /**
+ * @title Arguments = 0 + 255
+ */
+ public void testN2() {
+ AddIntLit16_2 t = new AddIntLit16_2();
+ assertEquals(255, t.run());
+ }
+
+ /**
+ * @title Arguments = 0 + (-32768)
+ */
+ public void testN3() {
+ AddIntLit16_3 t = new AddIntLit16_3();
+ assertEquals(-32768, t.run());
+ }
+
+ /**
+ * @title Arguments = (-2147483647) + 0
+ */
+ public void testN4() {
+ AddIntLit16_4 t = new AddIntLit16_4();
+ assertEquals(-2147483647, t.run());
+ }
+
+ /**
+ * @title Arguments = 0x7ffffffe + 2
+ */
+ public void testN5() {
+ AddIntLit16_5 t = new AddIntLit16_5();
+ assertEquals(-2147483648, t.run());
+ }
+
+ /**
+ * @title Arguments = -1 + 1
+ */
+ public void testN6() {
+ AddIntLit16_6 t = new AddIntLit16_6();
+ assertEquals(0, t.run());
+ }
+
+ /**
+ * @title Arguments = 0 + Short.MAX_VALUE
+ */
+ public void testB1() {
+ AddIntLit16_7 t = new AddIntLit16_7();
+ assertEquals(Short.MAX_VALUE, t.run());
+ }
+
+ /**
+ * @title Arguments = Integer.MAX_VALUE + Short.MAX_VALUE
+ */
+ public void testB2() {
+ AddIntLit16_8 t = new AddIntLit16_8();
+ assertEquals(-2147450882, t.run());
+ }
+
+ /**
+ * @title Arguments = Integer.MAX_VALUE + 1
+ */
+ public void testB3() {
+ AddIntLit16_9 t = new AddIntLit16_9();
+ assertEquals(Integer.MIN_VALUE, t.run());
+ }
+
+ /**
+ * @title Arguments = Integer.MIN_VALUE + 1
+ */
+ public void testB4() {
+ AddIntLit16_10 t = new AddIntLit16_10();
+ assertEquals(-2147483647, t.run());
+ }
+
+ /**
+ * @title Arguments = 0 + 0
+ */
+ public void testB5() {
+ AddIntLit16_11 t = new AddIntLit16_11();
+ assertEquals(0, t.run());
+ }
+
+ /**
+ * @title Arguments = Short.MIN_VALUE + Short.MIN_VALUE
+ */
+ public void testB6() {
+ AddIntLit16_12 t = new AddIntLit16_12();
+ assertEquals(-65536, t.run());
+ }
+
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_1.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_1.java
new file mode 100644
index 0000000..95313ee
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_1 {
+
+ public int run() {
+ return 8 + 4;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_10.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_10.java
new file mode 100644
index 0000000..e5fa9fa
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_10.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_10 {
+
+ public int run() {
+ return Integer.MIN_VALUE + 1;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_11.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_11.java
new file mode 100644
index 0000000..375cfff
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_11.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_11 {
+
+ public int run() {
+ return 0 + 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_12.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_12.java
new file mode 100644
index 0000000..3c30be0
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_12.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_12 {
+
+ public int run() {
+ return Short.MIN_VALUE + Short.MIN_VALUE;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_16.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_16.java
new file mode 100644
index 0000000..5f3d6f9
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_16.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_16 {
+
+ public int run(float f) {
+ return 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_2.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_2.java
new file mode 100644
index 0000000..69c6c8d
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_2.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_2 {
+
+ public int run() {
+ return 0 + 255;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_3.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_3.java
new file mode 100644
index 0000000..51e84ba
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_3.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_3 {
+
+ public int run() {
+ return 0 + (-32768);
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_4.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_4.java
new file mode 100644
index 0000000..0fa1146
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_4.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_4 {
+
+ public int run() {
+ return (-2147483647) + 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_5.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_5.java
new file mode 100644
index 0000000..2080b8b
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_5.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_5 {
+
+ public int run() {
+ return 0x7ffffffe + 2;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_6.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_6.java
new file mode 100644
index 0000000..4db27b0
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_6.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_6 {
+
+ public int run() {
+ return -1 + 1;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_7.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_7.java
new file mode 100644
index 0000000..b74ed5d
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_7.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_7 {
+
+ public int run() {
+ return 0 + Short.MAX_VALUE;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_8.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_8.java
new file mode 100644
index 0000000..c4900e0
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_8.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_8 {
+
+ public int run() {
+ return Integer.MAX_VALUE + Short.MAX_VALUE;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_9.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_9.java
new file mode 100644
index 0000000..3368cf9
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit16/AddIntLit16_9.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit16;
+
+public class AddIntLit16_9 {
+
+ public int run() {
+ return Integer.MAX_VALUE + 1;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8.java
new file mode 100644
index 0000000..fe3710b
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+package android.vm.cts.opcodes.add_int_lit8;
+
+import junit.framework.TestCase;
+
+public class AddIntLit8 extends TestCase {
+ /**
+ * @title Arguments = 8 + 4
+ */
+ public void testN1() {
+ AddIntLit8_1 t = new AddIntLit8_1();
+ assertEquals(12, t.run());
+ }
+
+ /**
+ * @title Arguments = Byte.MIN_VALUE + Byte.MAX_VALUE
+ */
+ public void testN2() {
+ AddIntLit8_2 t = new AddIntLit8_2();
+ assertEquals(-1, t.run());
+ }
+
+ /**
+ * @title Arguments = 0 + (-128)
+ */
+ public void testN3() {
+ AddIntLit8_3 t = new AddIntLit8_3();
+ assertEquals(-128, t.run());
+ }
+
+ /**
+ * @title Arguments = (-2147483647) + 0
+ */
+ public void testN4() {
+ AddIntLit8_4 t = new AddIntLit8_4();
+ assertEquals(-2147483647, t.run());
+ }
+
+ /**
+ * @title Arguments = 0x7ffffffe + 2
+ */
+ public void testN5() {
+ AddIntLit8_5 t = new AddIntLit8_5();
+ assertEquals(-2147483648, t.run());
+ }
+
+ /**
+ * @title Arguments = -1 + 1
+ */
+ public void testN6() {
+ AddIntLit8_6 t = new AddIntLit8_6();
+ assertEquals(0, t.run());
+ }
+
+ /**
+ * @title Arguments = 0 + Byte.MAX_VALUE
+ */
+ public void testB1() {
+ AddIntLit8_7 t = new AddIntLit8_7();
+ assertEquals(Byte.MAX_VALUE, t.run());
+ }
+
+ /**
+ * @title Arguments = Integer.MAX_VALUE + Byte.MAX_VALUE
+ */
+ public void testB2() {
+ AddIntLit8_8 t = new AddIntLit8_8();
+ assertEquals(-2147483522, t.run());
+ }
+
+ /**
+ * @title Arguments = Integer.MAX_VALUE + 1
+ */
+ public void testB3() {
+ AddIntLit8_9 t = new AddIntLit8_9();
+ assertEquals(Integer.MIN_VALUE, t.run());
+ }
+
+ /**
+ * @title Arguments = Integer.MIN_VALUE + 1
+ */
+ public void testB4() {
+ AddIntLit8_10 t = new AddIntLit8_10();
+ assertEquals(-2147483647, t.run());
+ }
+
+ /**
+ * @title Arguments = 0 + 0
+ */
+ public void testB5() {
+ AddIntLit8_11 t = new AddIntLit8_11();
+ assertEquals(0, t.run());
+ }
+
+ /**
+ * @title Arguments = Short.MIN_VALUE + Byte.MIN_VALUE
+ */
+ public void testB6() {
+ AddIntLit8_12 t = new AddIntLit8_12();
+ assertEquals(-32896, t.run());
+ }
+
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_1.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_1.java
new file mode 100644
index 0000000..2017b31
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_1 {
+
+ public int run() {
+ return 8 + 4;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_10.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_10.java
new file mode 100644
index 0000000..88fae83
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_10.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_10 {
+
+ public int run() {
+ return Integer.MIN_VALUE + 1;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_11.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_11.java
new file mode 100644
index 0000000..5c29a91
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_11.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_11 {
+
+ public int run() {
+ return 0 + 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_12.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_12.java
new file mode 100644
index 0000000..9fa0a8d
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_12.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_12 {
+
+ public int run() {
+ return Short.MIN_VALUE + Byte.MIN_VALUE;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_16.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_16.java
new file mode 100644
index 0000000..f8338e8
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_16.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_16 {
+
+ public int run(float f) {
+ return 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_2.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_2.java
new file mode 100644
index 0000000..eaa4f38
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_2.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_2 {
+
+ public int run() {
+ return Byte.MIN_VALUE + Byte.MAX_VALUE;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_3.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_3.java
new file mode 100644
index 0000000..e7b0534
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_3.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_3 {
+
+ public int run() {
+ return 0 + (-128);
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_4.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_4.java
new file mode 100644
index 0000000..7a22091
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_4.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_4 {
+
+ public int run() {
+ return (-2147483647) + 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_5.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_5.java
new file mode 100644
index 0000000..bfbd8c5
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_5.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_5 {
+
+ public int run() {
+ return 0x7ffffffe + 2;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_6.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_6.java
new file mode 100644
index 0000000..7c14c37
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_6.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_6 {
+
+ public int run() {
+ return -1 + 1;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_7.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_7.java
new file mode 100644
index 0000000..d5347d0
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_7.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_7 {
+
+ public int run() {
+ return 0 + Byte.MAX_VALUE;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_8.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_8.java
new file mode 100644
index 0000000..c7a8a9b
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_8.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_8 {
+
+ public int run() {
+ return Integer.MAX_VALUE + Byte.MAX_VALUE;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_9.java b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_9.java
new file mode 100644
index 0000000..c246375
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_int_lit8/AddIntLit8_9.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_int_lit8;
+
+public class AddIntLit8_9 {
+
+ public int run() {
+ return Integer.MAX_VALUE + 1;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_long/AddLongTest.java b/tests/vm/src/android/vm/cts/opcodes/add_long/AddLongTest.java
new file mode 100644
index 0000000..27c4536
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_long/AddLongTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_long;
+
+import junit.framework.TestCase;
+
+public class AddLongTest extends TestCase {
+ /**
+ * @title Arguments = 12345678l, 87654321l
+ */
+ public void testN1() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(99999999l, t.run(12345678l, 87654321l));
+ }
+
+ /**
+ * @title Arguments = 0l, 87654321l
+ */
+ public void testN2() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(87654321l, t.run(0l, 87654321l));
+ }
+
+ /**
+ * @title Arguments = -12345678l, 0l
+ */
+ public void testN3() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(-12345678l, t.run(-12345678l, 0l));
+ }
+
+ /**
+ * @title Arguments = 0 + Long.MAX_VALUE
+ */
+ public void testB1() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(9223372036854775807L, t.run(0l, Long.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = 0 + Long.MIN_VALUE
+ */
+ public void testB2() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(-9223372036854775808L, t.run(0l, Long.MIN_VALUE));
+ }
+
+ /**
+ * @title Arguments = 0 + 0
+ */
+ public void testB3() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(0l, t.run(0l, 0l));
+ }
+
+ /**
+ * @title Arguments = Long.MAX_VALUE + Long.MAX_VALUE
+ */
+ public void testB4() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(-2, t.run(Long.MAX_VALUE, Long.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Long.MAX_VALUE + Long.MIN_VALUE
+ */
+ public void testB5() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(-1l, t.run(Long.MAX_VALUE, Long.MIN_VALUE));
+ }
+
+ /**
+ * @title Arguments = Long.MIN_VALUE + Long.MIN_VALUE
+ */
+ public void testB6() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(0l, t.run(Long.MIN_VALUE, Long.MIN_VALUE));
+ }
+
+ /**
+ * @title Arguments = Long.MIN_VALUE + 1
+ */
+ public void testB7() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(-9223372036854775807l, t.run(Long.MIN_VALUE, 1l));
+ }
+
+ /**
+ * @title Arguments = Long.MAX_VALUE + 1
+ */
+ public void testB8() {
+ AddLong_1 t = new AddLong_1();
+ assertEquals(-9223372036854775808l, t.run(Long.MAX_VALUE, 1l));
+ }
+
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_long/AddLong_1.java b/tests/vm/src/android/vm/cts/opcodes/add_long/AddLong_1.java
new file mode 100644
index 0000000..285e4df
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_long/AddLong_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_long;
+
+public class AddLong_1 {
+
+ public long run(long a, long b) {
+ return a+b;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_long/AddLong_6.java b/tests/vm/src/android/vm/cts/opcodes/add_long/AddLong_6.java
new file mode 100644
index 0000000..ff7195e
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_long/AddLong_6.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_long;
+
+public class AddLong_6 {
+
+ public long run(long a, double b) {
+ return 0;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_long_2addr/AddLong2AddrTest.java b/tests/vm/src/android/vm/cts/opcodes/add_long_2addr/AddLong2AddrTest.java
new file mode 100644
index 0000000..5e97757
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_long_2addr/AddLong2AddrTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+package android.vm.cts.opcodes.add_long_2addr;
+
+import junit.framework.TestCase;
+
+public class AddLong2AddrTest extends TestCase {
+ /**
+ * @title Arguments = 12345678l, 87654321l
+ */
+ public void testN1() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(99999999l, t.run(12345678l, 87654321l));
+ }
+
+ /**
+ * @title Arguments = 0l, 87654321l
+ */
+ public void testN2() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(87654321l, t.run(0l, 87654321l));
+ }
+
+ /**
+ * @title Arguments = -12345678l, 0l
+ */
+ public void testN3() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(-12345678l, t.run(-12345678l, 0l));
+ }
+
+ /**
+ * @title Arguments = 0 + Long.MAX_VALUE
+ */
+ public void testB1() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(9223372036854775807L, t.run(0l, Long.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = 0 + Long.MIN_VALUE
+ */
+ public void testB2() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(-9223372036854775808L, t.run(0l, Long.MIN_VALUE));
+ }
+
+ /**
+ * @title Arguments = 0 + 0
+ */
+ public void testB3() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(0l, t.run(0l, 0l));
+ }
+
+ /**
+ * @title Arguments = Long.MAX_VALUE + Long.MAX_VALUE
+ */
+ public void testB4() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(-2, t.run(Long.MAX_VALUE, Long.MAX_VALUE));
+ }
+
+ /**
+ * @title Arguments = Long.MAX_VALUE + Long.MIN_VALUE
+ */
+ public void testB5() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(-1l, t.run(Long.MAX_VALUE, Long.MIN_VALUE));
+ }
+
+ /**
+ * @title Arguments = Long.MIN_VALUE + Long.MIN_VALUE
+ */
+ public void testB6() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(0l, t.run(Long.MIN_VALUE, Long.MIN_VALUE));
+ }
+
+ /**
+ * @title Arguments = Long.MIN_VALUE + 1
+ */
+ public void testB7() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(-9223372036854775807l, t.run(Long.MIN_VALUE, 1l));
+ }
+
+ /**
+ * @title Arguments = Long.MAX_VALUE + 1
+ */
+ public void testB8() {
+ AddLong2Addr_1 t = new AddLong2Addr_1();
+ assertEquals(-9223372036854775808l, t.run(Long.MAX_VALUE, 1l));
+ }
+
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_long_2addr/AddLong2Addr_1.java b/tests/vm/src/android/vm/cts/opcodes/add_long_2addr/AddLong2Addr_1.java
new file mode 100644
index 0000000..777a356
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_long_2addr/AddLong2Addr_1.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_long_2addr;
+
+public class AddLong2Addr_1 {
+
+ public long run(long a, long b) {
+ return a+b;
+ }
+}
diff --git a/tests/vm/src/android/vm/cts/opcodes/add_long_2addr/AddLong2Addr_6.java b/tests/vm/src/android/vm/cts/opcodes/add_long_2addr/AddLong2Addr_6.java
new file mode 100644
index 0000000..4c7dd18
--- /dev/null
+++ b/tests/vm/src/android/vm/cts/opcodes/add_long_2addr/AddLong2Addr_6.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.vm.cts.opcodes.add_long_2addr;
+
+public class AddLong2Addr_6 {
+
+ public long run(double a) {
+ return 0;
+ }
+}
diff --git a/tools/cts-device-info/Android.mk b/tools/cts-device-info/Android.mk
index 5f2b223..d479d9f 100644
--- a/tools/cts-device-info/Android.mk
+++ b/tools/cts-device-info/Android.mk
@@ -18,11 +18,17 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+DEVICE_INFO_MIN_SDK := 23
+DEVICE_INFO_TARGET_SDK := 23
+
DEVICE_INFO_PERMISSIONS :=
-DEVICE_INFO_ACTIVITIES :=
+DEVICE_INFO_ACTIVITIES := \
+ com.android.compatibility.common.deviceinfo.GlesStubActivity
LOCAL_PACKAGE_NAME := CtsDeviceInfo
-include $(BUILD_CTS_DEVICE_INFO_PACKAGE)
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+include $(BUILD_CTS_DEVICE_INFO_PACKAGE)
diff --git a/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java b/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java
index 886193c..a645585 100644
--- a/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java
+++ b/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java
@@ -17,17 +17,12 @@
import android.os.Bundle;
-import com.android.compatibility.common.deviceinfo.DeviceInfoActivity;
+import com.android.compatibility.common.deviceinfo.DeviceInfo;
/**
* Sample device info collector.
*/
-public class SampleDeviceInfo extends DeviceInfoActivity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
+public class SampleDeviceInfo extends DeviceInfo {
@Override
protected void collectDeviceInfo() {
@@ -60,4 +55,3 @@
endGroup(); // foo
}
}
-
diff --git a/tools/cts-java-scanner-doclet/src/com/android/cts/javascannerdoclet/CtsJavaScannerDoclet.java b/tools/cts-java-scanner-doclet/src/com/android/cts/javascannerdoclet/CtsJavaScannerDoclet.java
index 78d4249..1b48ddf 100644
--- a/tools/cts-java-scanner-doclet/src/com/android/cts/javascannerdoclet/CtsJavaScannerDoclet.java
+++ b/tools/cts-java-scanner-doclet/src/com/android/cts/javascannerdoclet/CtsJavaScannerDoclet.java
@@ -65,6 +65,10 @@
static final String JUNIT_TEST_CASE_CLASS_NAME = "junit.framework.testcase";
+ private static final String TIMEOUT_ANNOTATION = "com.android.cts.util.TimeoutReq";
+ private static final String SUPPRESS_ANNOTATION =
+ "android.test.suitebuilder.annotation.Suppress";
+
public static boolean start(RootDoc root) {
ClassDoc[] classes = root.classes();
if (classes == null) {
@@ -93,10 +97,11 @@
continue;
}
+ boolean suppressed = false;
AnnotationDesc[] annotations = method.annotations();
for (AnnotationDesc annot : annotations) {
String atype = annot.annotationType().toString();
- if (atype.equals("com.android.cts.util.TimeoutReq")) {
+ if (atype.equals(TIMEOUT_ANNOTATION)) {
ElementValuePair[] cpairs = annot.elementValues();
for (ElementValuePair pair : cpairs) {
AnnotationTypeElementDoc elem = pair.element();
@@ -105,8 +110,13 @@
timeout = ((Integer) value.value());
}
}
+ } else if (atype.equals(SUPPRESS_ANNOTATION)) {
+ suppressed = true;
}
}
+ if (suppressed) {
+ continue;
+ }
} else {
/* JUnit4 */
boolean isTest = false;
diff --git a/tools/cts-preconditions/Android.mk b/tools/cts-preconditions/Android.mk
new file mode 100644
index 0000000..daf35f4
--- /dev/null
+++ b/tools/cts-preconditions/Android.mk
@@ -0,0 +1,39 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-preconditions
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_PACKAGE_NAME := CtsPreconditions
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tools/cts-preconditions/AndroidManifest.xml b/tools/cts-preconditions/AndroidManifest.xml
new file mode 100644
index 0000000..a8eb827
--- /dev/null
+++ b/tools/cts-preconditions/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.preconditions.cts">
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <!-- self-instrumenting test package. -->
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:label="CTS preconditions test"
+ android:targetPackage="com.android.preconditions.cts" >
+ </instrumentation>
+</manifest>
diff --git a/tools/cts-preconditions/src/com/android/preconditions/cts/PreconditionsTest.java b/tools/cts-preconditions/src/com/android/preconditions/cts/PreconditionsTest.java
new file mode 100644
index 0000000..b3162b9
--- /dev/null
+++ b/tools/cts-preconditions/src/com/android/preconditions/cts/PreconditionsTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package com.android.preconditions.cts;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+import com.android.compatibility.common.preconditions.ExternalStorageHelper;
+import com.android.compatibility.common.preconditions.ScreenLockHelper;
+
+/**
+ * A test to verify that device-side preconditions are met for CTS
+ */
+public class PreconditionsTest extends AndroidTestCase {
+
+ /**
+ * Test if device has no screen lock
+ * @throws Exception
+ */
+ public void testScreenUnlocked() throws Exception {
+ assertFalse("Device must have screen lock disabled",
+ ScreenLockHelper.isDeviceSecure(this.getContext()));
+ }
+
+ /**
+ * Test if device has accessible external storage
+ * @throws Exception
+ */
+ public void testExternalStoragePresent() throws Exception {
+ assertTrue("Device must have external storage mounted in order to run CTS",
+ ExternalStorageHelper.isExternalStorageReadable());
+ assertTrue("Device external storage must be writable in order to run CTS",
+ ExternalStorageHelper.isExternalStorageWritable());
+ }
+
+}
diff --git a/tools/cts-tradefed/Android.mk b/tools/cts-tradefed/Android.mk
new file mode 100644
index 0000000..2f743e6
--- /dev/null
+++ b/tools/cts-tradefed/Android.mk
@@ -0,0 +1,34 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../../common/host-side/tradefed/src)
+
+LOCAL_JAVA_RESOURCE_DIRS := res
+LOCAL_JAVA_RESOURCE_DIRS += ../../common/host-side/tradefed/res
+
+LOCAL_SUITE_BUILD_NUMBER := $(BUILD_NUMBER)
+LOCAL_SUITE_NAME := CTS_V2
+LOCAL_SUITE_FULLNAME := "Compatibility Test Suite"
+LOCAL_SUITE_VERSION := 5.0
+
+LOCAL_MODULE := cts-tradefed_v2
+
+include $(BUILD_COMPATIBILITY_SUITE)
+
+# Build all sub-directories
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/cts-tradefed/DynamicConfig.xml b/tools/cts-tradefed/DynamicConfig.xml
new file mode 100644
index 0000000..6acffc0
--- /dev/null
+++ b/tools/cts-tradefed/DynamicConfig.xml
@@ -0,0 +1,18 @@
+<!-- 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.
+-->
+
+<DynamicConfig>
+ <Config key="MediaFilesUrl">https://dl.google.com/dl/android/cts/android-cts-media-1.1.zip</Config>
+</DynamicConfig>
diff --git a/tools/cts-tradefed/README b/tools/cts-tradefed/README
new file mode 100644
index 0000000..d1357aa
--- /dev/null
+++ b/tools/cts-tradefed/README
@@ -0,0 +1,83 @@
+CTS Trade Federation
+---------------------
+
+CTS Trade Federation, cts-tradefed for short, is the next
+generation test harness for CTS.
+
+cts-tradefed is built on top of the Android Trade Federation test harness.
+
+It works in a similar manner to the prior CTS harness, but supports some
+advanced features such as:
+
+ - modular, flexible extensible design. cts-tradefed can be extended to
+support running CTS in a continuous test environment.
+ - supports sharding a CTS test run across multiple devices in parallel
+ - automatically continue a CTS test run on another device if connection
+is lost
+
+Configuring cts-tradefed
+------------------------
+
+1. Ensure 'adb' is in your current PATH. adb can be found in the
+Android SDK available from http://developer.android.com
+
+Example:
+ PATH=$PATH:/home/myuser/android-sdk-linux_x86/platform-tools
+
+2. Follow the 'Setting up your device' steps documented in the
+CTS User Manual. The CTS User Manual can be downloaded at
+http://source.android.com/compatibility/downloads.html
+
+3. Connect the device to the host machine.
+
+4. Ensure device is visible via 'adb devices'
+
+Using cts-tradefed
+-------------------
+
+To run a test plan on a single device:
+
+1. Make sure you have at least one device connected
+2. Launch the cts-tradefed console by running the 'cts-tradefed'. If you've
+downloaded and extracted the CTS zip, the script can be found at
+ android-cts/tools/cts-tradefed
+Or else if you are working from the Android source tree and have run make cts,
+the script can be found at
+ out/host/linux-x86/cts/android-cts/tools/cts-tradefed
+3. Type:
+'run cts' to run the default CTS plan
+
+Some other useful commands are
+
+To run a test module:
+'run cts --module <module_name>'
+
+To run a specific test:
+'run cts --test <test_name>'
+
+To shard a plan test run on multiple devices
+'run cts --shards <number of shards>
+note: all connected devices must be running the same build
+
+For more options:
+'run cts --help'
+
+CTS Tradefed Development
+------------------------
+See http://source.android.com for instructions on obtaining the Android
+platform source code and setting up a build environment.
+
+The source for the CTS extensions for tradefed can be found at
+<android source root>/cts/tools/tradefed-host
+
+The source for the tradefed framework can be found on the 'tradefed' branch.
+
+Perform these steps to build and run cts-tradefed from the development
+environment:
+cd <path to android source root>
+make cts
+cts-tradefed
+
+More documentation and details on using and extending trade federation will
+be forthcoming in the near future.
+
diff --git a/tools/cts-tradefed/etc/Android.mk b/tools/cts-tradefed/etc/Android.mk
new file mode 100644
index 0000000..877f67c
--- /dev/null
+++ b/tools/cts-tradefed/etc/Android.mk
@@ -0,0 +1,22 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_PREBUILT_EXECUTABLES := cts-tradefed_v2
+include $(BUILD_HOST_PREBUILT)
+
diff --git a/tools/cts-tradefed/etc/cts-tradefed_v2 b/tools/cts-tradefed/etc/cts-tradefed_v2
new file mode 100755
index 0000000..d1cf0cc
--- /dev/null
+++ b/tools/cts-tradefed/etc/cts-tradefed_v2
@@ -0,0 +1,119 @@
+#!/bin/bash
+
+# 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.
+
+# launcher script for cts-tradefed harness
+# can be used from an Android build environment, or a standalone cts zip
+
+checkFile() {
+ if [ ! -f "$1" ]; then
+ echo "Unable to locate $1"
+ exit
+ fi;
+}
+
+checkPath() {
+ if ! type -P $1 &> /dev/null; then
+ echo "Unable to find $1 in path."
+ exit
+ fi;
+}
+
+checkPath adb
+checkPath java
+
+# check java version
+JAVA_VERSION=$(java -version 2>&1 | head -n 2 | grep '[ "]1\.[678][\. "$$]')
+if [ "${JAVA_VERSION}" == "" ]; then
+ echo "Wrong java version. 1.6, 1.7 or 1.8 is required."
+ exit
+fi
+
+# check debug flag and set up remote debugging
+if [ -n "${TF_DEBUG}" ]; then
+ if [ -z "${TF_DEBUG_PORT}" ]; then
+ TF_DEBUG_PORT=10088
+ fi
+ RDBG_FLAG=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=${TF_DEBUG_PORT}
+fi
+
+# get OS
+HOST=`uname`
+if [ "$HOST" == "Linux" ]; then
+ OS="linux-x86"
+elif [ "$HOST" == "Darwin" ]; then
+ OS="darwin-x86"
+else
+ echo "Unrecognized OS"
+ exit
+fi
+
+# check if in Android build env
+if [ ! -z "${ANDROID_BUILD_TOP}" ]; then
+ if [ ! -z "${ANDROID_HOST_OUT}" ]; then
+ CTS_V2_ROOT=${ANDROID_HOST_OUT}/cts_v2
+ else
+ CTS_V2_ROOT=${ANDROID_BUILD_TOP}/${OUT_DIR:-out}/host/${OS}/cts_v2
+ fi
+ if [ ! -d ${CTS_V2_ROOT} ]; then
+ echo "Could not find $CTS_V2_ROOT in Android build environment. Try 'make cts_v2'"
+ exit
+ fi;
+fi;
+
+if [ -z ${CTS_V2_ROOT} ]; then
+ # assume we're in an extracted cts install
+ CTS_V2_ROOT="$(dirname $0)/../.."
+fi;
+
+JAR_DIR=${CTS_V2_ROOT}/android-cts_v2/tools
+JARS="tradefed-prebuilt
+ hosttestlib
+ compatibility-host-util
+ cts-tradefed_v2"
+
+for JAR in $JARS; do
+ checkFile ${JAR_DIR}/${JAR}.jar
+ JAR_PATH=${JAR_PATH}:${JAR_DIR}/${JAR}.jar
+done
+
+OPTIONAL_JARS="
+ google-tradefed
+ google-tradefed-tests
+ google-tf-prod-tests"
+
+for JAR in $OPTIONAL_JARS; do
+ if [ -f "$JAR.jar" ]; then
+ JAR_PATH=${JAR_PATH}:${JAR_DIR}/${JAR}.jar
+ fi;
+done
+
+# load any shared libraries for host-side executables
+LIB_DIR=${CTS_V2_ROOT}/android-cts_v2/lib
+if [ "$HOST" == "Linux" ]; then
+ LD_LIBRARY_PATH=${LIB_DIR}:${LIB_DIR}64:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+elif [ "$HOST" == "Darwin" ]; then
+ DYLD_LIBRARY_PATH=${LIB_DIR}:${LIB_DIR}64:${DYLD_LIBRARY_PATH}
+ export DYLD_LIBRARY_PATH
+fi
+
+# include any host-side test jars
+for j in ${CTS_V2_ROOT}/android-cts_v2/testcases/*.jar; do
+ JAR_PATH=${JAR_PATH}:$j
+done
+
+java $RDBG_FLAG -cp ${JAR_PATH} -DCTS_V2_ROOT=${CTS_V2_ROOT} com.android.compatibility.common.tradefed.command.CompatibilityConsole "$@"
+
diff --git a/tools/cts-tradefed/res/config/cts-camera.xml b/tools/cts-tradefed/res/config/cts-camera.xml
new file mode 100644
index 0000000..5bc395d
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-camera.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<configuration description="Runs CTS-camera from a pre-existing CTS installation">
+
+ <include name="cts" />
+
+ <option name="compatibility:plan" value="cts-camera" />
+
+ <!-- All camera CTS tests -->
+ <option name="compatibility:include-filter" value="CtsCameraTestCases" />
+
+ <!-- Other camera related CTS tests -->
+ <option name="compatibility:include-filter"
+ value="CtsAppTestCases android.app.cts.SystemFeaturesTest#testCameraFeatures"/>
+ <option name="compatibility:include-filter"
+ value="CtsPermissionTestCases android.permission.cts.CameraPermissionTest"/>
+ <option name="compatibility:include-filter"
+ value="CtsPermissionTestCases android.permission.cts.Camera2PermissionTest"/>
+
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-filtered-sample.xml b/tools/cts-tradefed/res/config/cts-filtered-sample.xml
new file mode 100644
index 0000000..73b98c5
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-filtered-sample.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+<configuration description="Runs CTS from a pre-existing CTS installation">
+
+ <include name="common-compatibility-config" />
+
+ <option name="compatibility:plan" value="cts-filtered-sample" />
+
+ <!-- Tell all AndroidJUnitTests to only run the medium sized tests -->
+ <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:size:medium" />
+
+ <!-- Tell 64bit CtsContentTestCases which timeout to use -->
+ <option name="compatibility:module-arg" value="arm64-v8a CtsContentTestCases:test-timeout:600" />
+
+ <!-- Include CtsGestureTestCases but only run the tests on arm32 -->
+ <option name="compatibility:include-filter" value="armeabi-v7a CtsGestureTestCases" />
+
+ <!-- Exclude CtsMediaStressTestCases -->
+ <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases" />
+
+ <!-- Include CtsUtilTestCases but only run the small tests -->
+ <option name="compatibility:module-arg" value="CtsUtilTestCases:size:small" />
+
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts.xml b/tools/cts-tradefed/res/config/cts.xml
new file mode 100644
index 0000000..e6a75a0
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts.xml
@@ -0,0 +1,66 @@
+<?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.
+-->
+<configuration description="Runs CTS from a pre-existing CTS installation">
+
+ <include name="everything" />
+
+ <option name="compatibility:plan" value="cts" />
+
+ <option name="enable-root" value="false" />
+
+ <!-- Exclude sample test cases -->
+ <option name="compatibility:exclude-filter" value="CtsSampleDeviceTestCases" />
+ <option name="compatibility:exclude-filter" value="CtsSampleHostTestCases" />
+ <!-- Exclude automotive only test cases for now -->
+ <option name="compatibility:exclude-filter" value="CtsAutomotiveTestCases" />
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="module-name" value="cts_v2"/>
+ <option name="version-name" value="1.0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.StayAwakePreparer" />
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.PropertyCheck">
+ <option name="property-name" value="ro.build.type" />
+ <option name="expected-value" value="user"/> <!-- Device should have user build -->
+ <option name="throw-error" value="false"/> <!-- Only print warning if not user build -->
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.PropertyCheck">
+ <option name="property-name" value="ro.product.locale" />
+ <option name="expected-value" value="en-US"/> <!-- Device locale should be US English -->
+ <option name="throw-error" value="false"/> <!-- Only print warning if not en-US -->
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkPreconditionCheck">
+ <option name="apk" value="CtsPreconditions.apk"/>
+ <option name="package" value="com.android.preconditions.cts"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="rm -rf /sdcard/device-info-files" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceInfoCollector">
+ <option name="apk" value="CtsDeviceInfo.apk"/>
+ <option name="package" value="com.android.compatibility.common.deviceinfo"/>
+ <option name="src-dir" value="/sdcard/device-info-files/"/>
+ <option name="dest-dir" value="device-info-files/"/>
+ </target_preparer>
+
+</configuration>
diff --git a/tools/cts-tradefed/tests/Android.mk b/tools/cts-tradefed/tests/Android.mk
new file mode 100644
index 0000000..7314fdb
--- /dev/null
+++ b/tools/cts-tradefed/tests/Android.mk
@@ -0,0 +1,25 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := cts-tradefed-tests_v2
+LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt cts-tradefed_v2
+
+include $(BUILD_HOST_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/tools/cts-tradefed/tests/run_tests.sh b/tools/cts-tradefed/tests/run_tests.sh
new file mode 100755
index 0000000..6a96928
--- /dev/null
+++ b/tools/cts-tradefed/tests/run_tests.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# 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.
+
+# Helper script for running unit tests for compatibility libraries
+
+CTS_DIR=$(dirname ${0})/../../..
+source ${CTS_DIR}/test_defs.sh
+
+JARS="
+ compatibility-common-util-hostsidelib\
+ compatibility-host-util\
+ cts-tradefed-tests_v2\
+ cts-tradefed_v2"
+
+run_tests "com.android.compatibility.tradefed.CtsTradefedTest" "${JARS}" "${@}"
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java
new file mode 100644
index 0000000..6469a01
--- /dev/null
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.tradefed;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.util.FileUtil;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+
+/**
+ * Tests for cts-tradefed.
+ */
+public class CtsTradefedTest extends TestCase {
+
+ private static final String PROPERTY_NAME = "CTS_V2_ROOT";
+ private static final String SUITE_FULL_NAME = "Compatibility Test Suite";
+ private static final String SUITE_NAME = "CTS_V2";
+ private static final String SUITE_PLAN = "cts";
+ private static final String DYNAMIC_CONFIG_URL = "";
+
+ public void testSuiteInfoLoad() throws Exception {
+ // Test the values in the manifest can be loaded
+ File root = FileUtil.createTempDir("root");
+ System.setProperty(PROPERTY_NAME, root.getAbsolutePath());
+ File base = new File(root, "android-cts_v2");
+ base.mkdirs();
+ File tests = new File(base, "testcases");
+ tests.mkdirs();
+ CompatibilityBuildProvider provider = new CompatibilityBuildProvider();
+ IBuildInfo info = provider.getBuild();
+ CompatibilityBuildHelper helper = new CompatibilityBuildHelper(info);
+ helper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ assertEquals("Incorrect suite full name", SUITE_FULL_NAME, helper.getSuiteFullName());
+ assertEquals("Incorrect suite name", SUITE_NAME, helper.getSuiteName());
+ FileUtil.recursiveDelete(root);
+ System.clearProperty(PROPERTY_NAME);
+ }
+}
diff --git a/tools/cts-xml-generator/src/Android.mk b/tools/cts-xml-generator/src/Android.mk
index a6d85b6..94c561b 100644
--- a/tools/cts-xml-generator/src/Android.mk
+++ b/tools/cts-xml-generator/src/Android.mk
@@ -18,15 +18,13 @@
# ============================================================
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
- $(call all-subdir-java-files) \
- ../../../libs/commonutil/src/com/android/cts/util/AbiUtils.java
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_JAR_MANIFEST := MANIFEST.mf
LOCAL_MODULE := cts-xml-generator
LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_JAVA_LIBRARIES := vogarexpectlib
+LOCAL_STATIC_JAVA_LIBRARIES := vogarexpectlib compatibility-host-util
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/TestCase.java b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/TestCase.java
index ed09b8e..c680c2a 100644
--- a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/TestCase.java
+++ b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/TestCase.java
@@ -46,4 +46,8 @@
public int compareTo(TestCase another) {
return getName().compareTo(another.getName());
}
+
+ public int countTests() {
+ return mTests.size();
+ }
}
diff --git a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/TestSuite.java b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/TestSuite.java
index 466f8d7..1d71e1f 100644
--- a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/TestSuite.java
+++ b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/TestSuite.java
@@ -66,4 +66,15 @@
public int compareTo(TestSuite another) {
return getName().compareTo(another.getName());
}
+
+ public int countTests() {
+ int count = 0;
+ for (TestSuite suite : mSuites.values()) {
+ count += suite.countTests();
+ }
+ for (TestCase testCase : mCases) {
+ count += testCase.countTests();
+ }
+ return count;
+ }
}
diff --git a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
index 328b855..f139053 100644
--- a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
+++ b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
@@ -16,12 +16,12 @@
package com.android.cts.xmlgenerator;
-import com.android.cts.util.AbiUtils;
-
import vogar.Expectation;
import vogar.ExpectationStore;
import vogar.Result;
+import com.android.compatibility.common.util.AbiUtils;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -166,6 +166,9 @@
StringBuilder nameCollector) {
Collection<TestSuite> sorted = sortCollection(suites);
for (TestSuite suite : sorted) {
+ if (suite.countTests() == 0) {
+ continue;
+ }
writer.append("<TestSuite name=\"").append(suite.getName()).println("\">");
String namePart = suite.getName();
@@ -187,6 +190,9 @@
StringBuilder nameCollector) {
Collection<TestCase> sorted = sortCollection(cases);
for (TestCase testCase : sorted) {
+ if (testCase.countTests() == 0) {
+ continue;
+ }
String name = testCase.getName();
writer.append("<TestCase name=\"").append(name).println("\">");
nameCollector.append('.').append(name);
@@ -259,7 +265,7 @@
String[] unsupportedAbis = description.split(":")[1].split(",");
for (String a : unsupportedAbis) {
String abi = a.trim();
- if (!AbiUtils.isAbiSupportedByCts(abi)) {
+ if (!AbiUtils.isAbiSupportedByCompatibility(abi)) {
throw new RuntimeException(
String.format("Unrecognised ABI %s in %s", abi, description));
}
diff --git a/tools/tradefed-host/.classpath b/tools/tradefed-host/.classpath
index dbeeb01..e716219 100644
--- a/tools/tradefed-host/.classpath
+++ b/tools/tradefed-host/.classpath
@@ -7,6 +7,5 @@
<classpathentry exported="true" kind="var" path="CTS_SRC_ROOT/out/host/common/obj/JAVA_LIBRARIES/ctsdeviceinfolib_intermediates/javalib.jar"/>
<classpathentry kind="var" path="CTS_SRC_ROOT/out/host/common/obj/JAVA_LIBRARIES/hosttestlib_intermediates/javalib.jar"/>
<classpathentry kind="var" path="CTS_SRC_ROOT/prebuilts/misc/common/tradefed/tradefed-prebuilt.jar"/>
- <classpathentry combineaccessrules="false" kind="src" path="/cts-commonutil"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/tools/tradefed-host/Android.mk b/tools/tradefed-host/Android.mk
index 1f73e95..c33a927 100644
--- a/tools/tradefed-host/Android.mk
+++ b/tools/tradefed-host/Android.mk
@@ -25,7 +25,7 @@
LOCAL_MODULE := cts-tradefed
LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LIBRARIES := tradefed-prebuilt hosttestlib
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceinfolib
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceinfolib compatibility-host-util
LOCAL_JAR_MANIFEST := MANIFEST.mf
diff --git a/tools/tradefed-host/res/config/basic-reporters.xml b/tools/tradefed-host/res/config/basic-reporters.xml
new file mode 100644
index 0000000..d52a85b
--- /dev/null
+++ b/tools/tradefed-host/res/config/basic-reporters.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+<configuration description="Configuration with basic cts reporters" >
+ <result_reporter class="com.android.cts.tradefed.result.CtsTestLogReporter" />
+ <result_reporter class="com.android.cts.tradefed.result.IssueReporter" />
+</configuration>
diff --git a/tools/tradefed-host/res/config/cts.xml b/tools/tradefed-host/res/config/cts.xml
index 416b400..794605c 100644
--- a/tools/tradefed-host/res/config/cts.xml
+++ b/tools/tradefed-host/res/config/cts.xml
@@ -22,7 +22,5 @@
<test class="com.android.cts.tradefed.testtype.CtsTest" />
<logger class="com.android.tradefed.log.FileLogger" />
<result_reporter class="com.android.cts.tradefed.result.CtsXmlResultReporter" />
- <result_reporter class="com.android.cts.tradefed.result.CtsTestLogReporter" />
- <result_reporter class="com.android.cts.tradefed.result.IssueReporter" />
-
+ <template-include name="reporters" default="basic-reporters" />
</configuration>
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index 66a4562..ca67746 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
@Option(name="cts-install-path", description="the path to the cts installation to use")
private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
- public static final String CTS_BUILD_VERSION = "6.0_r3";
+ public static final String CTS_BUILD_VERSION = "5.0_r1.91";
public static final String CTS_PACKAGE = "com.android.cts.tradefed.testtype";
/**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
index 24239e6..4cb9e16 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
@@ -15,6 +15,7 @@
*/
package com.android.cts.tradefed.command;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.cts.tradefed.build.CtsBuildProvider;
import com.android.cts.tradefed.result.ITestResultRepo;
@@ -23,7 +24,6 @@
import com.android.cts.tradefed.result.TestResultRepo;
import com.android.cts.tradefed.testtype.ITestPackageRepo;
import com.android.cts.tradefed.testtype.TestPackageRepo;
-import com.android.cts.util.AbiUtils;
import com.android.tradefed.build.IFolderBuildInfo;
import com.android.tradefed.command.Console;
import com.android.tradefed.config.ArgsOptionParser;
@@ -120,7 +120,7 @@
CtsBuildHelper ctsBuild = getCtsBuildHelper();
if (ctsBuild != null) {
// FIXME may want to only add certain ABIs
- addDerivedPlan(ctsBuild, AbiUtils.getAbisSupportedByCts(), flatArgs);
+ addDerivedPlan(ctsBuild, AbiUtils.getAbisSupportedByCompatibility(), flatArgs);
}
}
};
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java b/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java
index 61561a5..0ab70a7 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java
@@ -15,7 +15,7 @@
*/
package com.android.cts.tradefed.device;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.result.CtsXmlResultReporter;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
@@ -48,14 +48,14 @@
public static final String EXTENDED_APP_PACKAGE_NAME =
"com.android.compatibility.common.deviceinfo";
private static final String EXTENDED_INSTRUMENTATION_NAME =
- "com.android.compatibility.common.deviceinfo.DeviceInfoInstrument";
+ "android.support.test.runner.AndroidJUnitRunner";
private static final String DEVICE_INFO_FILES = "device-info-files";
public static final Set<String> IDS = new HashSet<String>();
public static final Set<String> EXTENDED_IDS = new HashSet<String>();
static {
- for (String abi : AbiUtils.getAbisSupportedByCts()) {
+ for (String abi : AbiUtils.getAbisSupportedByCompatibility()) {
IDS.add(AbiUtils.createId(abi, APP_PACKAGE_NAME));
EXTENDED_IDS.add(AbiUtils.createId(abi, EXTENDED_APP_PACKAGE_NAME));
}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java
index b7f064f..8500d01 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java
@@ -16,8 +16,8 @@
package com.android.cts.tradefed.result;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.device.DeviceInfoCollector;
-import com.android.cts.util.AbiUtils;
import com.android.ddmlib.Log;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.testrunner.TestIdentifier;
@@ -35,6 +35,8 @@
*/
public class CtsTestLogReporter extends StubTestInvocationListener implements IShardableListener {
+ private static final String DEVICE_INFO_ERROR = "DEVICE_INFO_ERROR_";
+
@Option(name = "quiet-output", description = "Mute display of test results.")
private boolean mQuietOutput = false;
@@ -84,6 +86,9 @@
*/
@Override
public void testStarted(TestIdentifier test) {
+ if (mIsExtendedDeviceInfoRun) {
+ return;
+ }
mCurrentPkgResult.insertTest(test);
}
@@ -92,6 +97,9 @@
*/
@Override
public void testFailed(TestIdentifier test, String trace) {
+ if (mIsExtendedDeviceInfoRun) {
+ return;
+ }
mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
}
@@ -100,6 +108,9 @@
*/
@Override
public void testAssumptionFailure(TestIdentifier test, String trace) {
+ if (mIsExtendedDeviceInfoRun) {
+ return;
+ }
// TODO: do something different here?
mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
}
@@ -109,6 +120,17 @@
*/
@Override
public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
+ if (mIsExtendedDeviceInfoRun) {
+ for (Map.Entry<String, String> metricsEntry : testMetrics.entrySet()) {
+ String key = metricsEntry.getKey();
+ String value = metricsEntry.getValue();
+ if (key.startsWith(DEVICE_INFO_ERROR)) {
+ throw new RuntimeException(String.format(
+ "Error collecting extended device info: %s=%s", key, value));
+ }
+ }
+ return;
+ }
mCurrentPkgResult.reportTestEnded(test, testMetrics);
Test result = mCurrentPkgResult.findTest(test);
String stack = result.getStackTrace() == null ? "" : "\n" + result.getStackTrace();
@@ -121,6 +143,9 @@
*/
@Override
public void invocationEnded(long elapsedTime) {
+ if (mIsExtendedDeviceInfoRun) {
+ return;
+ }
// display the results of the last completed run
if (mCurrentPkgResult != null) {
logCompleteRun(mCurrentPkgResult);
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
index 3efc7fc..07caaef 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
@@ -61,6 +61,8 @@
implements ITestInvocationListener, ITestSummaryListener, ILogSaverListener {
private static final String LOG_TAG = "CtsXmlResultReporter";
+ private static final String DEVICE_INFO = "DEVICE_INFO_";
+ private static final String DEVICE_INFO_EXT = ".deviceinfo.json";
public static final String CTS_RESULT_DIR = "cts-result-dir";
static final String TEST_RESULT_FILE_NAME = "testResult.xml";
@@ -238,6 +240,7 @@
@Override
public void testLogSaved(String dataName, LogDataType dataType, InputStreamSource dataStream,
LogFile logFile) {
+ CLog.i("Got log for %s %s %s", dataName, dataType, logFile.getUrl());
if (mIncludeTestLogTags && mCurrentTest != null) {
TestLog log = TestLog.fromDataName(dataName, logFile.getUrl());
if (log != null) {
@@ -335,9 +338,10 @@
private void checkExtendedDeviceInfoMetrics(Map<String, String> runMetrics) {
for (Map.Entry<String, String> metricEntry : runMetrics.entrySet()) {
+ String key = metricEntry.getKey();
String value = metricEntry.getValue();
- if (!value.endsWith(".deviceinfo.json")) {
- CLog.e(String.format("%s failed: %s", metricEntry.getKey(), value));
+ if (!key.startsWith(DEVICE_INFO) && !value.endsWith(DEVICE_INFO_EXT)) {
+ CLog.e(String.format("%s failed: %s", key, value));
}
}
}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/PlanCreator.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/PlanCreator.java
index 3881c0e..0926635 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/PlanCreator.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/PlanCreator.java
@@ -22,7 +22,6 @@
import com.android.cts.tradefed.testtype.ITestPlan;
import com.android.cts.tradefed.testtype.TestPackageRepo;
import com.android.cts.tradefed.testtype.TestPlan;
-import com.android.cts.util.AbiUtils;
import com.android.ddmlib.Log;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.testrunner.TestIdentifier;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java
index 12a2b29..e25ea5a 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java
@@ -15,7 +15,8 @@
*/
package com.android.cts.tradefed.result;
-import com.android.ddmlib.Log;
+import com.android.compatibility.common.util.MetricsXmlSerializer;
+import com.android.compatibility.common.util.ReportLog;
import com.android.cts.tradefed.result.TestLog.TestLogType;
import org.kxml2.io.KXmlSerializer;
@@ -38,27 +39,13 @@
private static final String RESULT_ATTR = "result";
private static final String SCENE_TAG = "FailedScene";
private static final String STACK_TAG = "StackTrace";
- private static final String SUMMARY_TAG = "Summary";
- private static final String DETAILS_TAG = "Details";
- private static final String VALUEARRAY_TAG = "ValueArray";
- private static final String VALUE_TAG = "Value";
- private static final String TARGET_ATTR = "target";
- private static final String SCORETYPE_ATTR = "scoreType";
- private static final String UNIT_ATTR = "unit";
- private static final String SOURCE_ATTR = "source";
- // separators for the message
- private static final String LOG_SEPARATOR = "\\+\\+\\+";
- private static final String LOG_ELEM_SEPARATOR = "\\|";
-
private String mName;
private CtsTestStatus mResult;
private String mStartTime;
private String mEndTime;
private String mMessage;
private String mStackTrace;
- // summary and details passed from cts
- private String mSummary;
- private String mDetails;
+ private ReportLog mReport;
/**
* Log info for this test like a logcat dump or bugreport.
@@ -73,7 +60,7 @@
}
/**
- * Create a {@link Test} from a {@link TestResult}.
+ * Create a {@link Test}.
*
* @param name
*/
@@ -135,20 +122,12 @@
mMessage = getFailureMessageFromStackTrace(mStackTrace);
}
- public String getSummary() {
- return mSummary;
+ public ReportLog getReportLog() {
+ return mReport;
}
- public void setSummary(String summary) {
- mSummary = summary;
- }
-
- public String getDetails() {
- return mDetails;
- }
-
- public void setDetails(String details) {
- mDetails = details;
+ public void setReportLog(ReportLog report) {
+ mReport = report;
}
public void updateEndTime() {
@@ -185,113 +164,12 @@
}
serializer.endTag(CtsXmlResultReporter.ns, SCENE_TAG);
}
- if (mSummary != null) {
- // <Summary message = "screen copies per sec" scoretype="higherBetter" unit="fps">
- // 23938.82978723404</Summary>
- PerfResultSummary summary = parseSummary(mSummary);
- if (summary != null) {
- serializer.startTag(CtsXmlResultReporter.ns, SUMMARY_TAG);
- serializer.attribute(CtsXmlResultReporter.ns, MESSAGE_ATTR, summary.mMessage);
- if (summary.mTarget.length() != 0 && !summary.mTarget.equals(" ")) {
- serializer.attribute(CtsXmlResultReporter.ns, TARGET_ATTR, summary.mTarget);
- }
- serializer.attribute(CtsXmlResultReporter.ns, SCORETYPE_ATTR, summary.mType);
- serializer.attribute(CtsXmlResultReporter.ns, UNIT_ATTR, summary.mUnit);
- serializer.text(summary.mValue);
- serializer.endTag(CtsXmlResultReporter.ns, SUMMARY_TAG);
- // add details only if summary is present
- // <Details>
- // <ValueArray source=”com.android.cts.dram.BandwidthTest#doRunMemcpy:98”
- // message=”measure1” unit="ms" scoretype="higherBetter">
- // <Value>0.0</Value>
- // <Value>0.1</Value>
- // </ValueArray>
- // </Details>
- if (mDetails != null) {
- PerfResultDetail[] ds = parseDetails(mDetails);
- serializer.startTag(CtsXmlResultReporter.ns, DETAILS_TAG);
- for (PerfResultDetail d : ds) {
- if (d == null) {
- continue;
- }
- serializer.startTag(CtsXmlResultReporter.ns, VALUEARRAY_TAG);
- serializer.attribute(CtsXmlResultReporter.ns, SOURCE_ATTR, d.mSource);
- serializer.attribute(CtsXmlResultReporter.ns, MESSAGE_ATTR,
- d.mMessage);
- serializer.attribute(CtsXmlResultReporter.ns, SCORETYPE_ATTR, d.mType);
- serializer.attribute(CtsXmlResultReporter.ns, UNIT_ATTR, d.mUnit);
- for (String v : d.mValues) {
- if (v == null) {
- continue;
- }
- serializer.startTag(CtsXmlResultReporter.ns, VALUE_TAG);
- serializer.text(v);
- serializer.endTag(CtsXmlResultReporter.ns, VALUE_TAG);
- }
- serializer.endTag(CtsXmlResultReporter.ns, VALUEARRAY_TAG);
- }
- serializer.endTag(CtsXmlResultReporter.ns, DETAILS_TAG);
- }
- }
- }
+ MetricsXmlSerializer metricsXmlSerializer = new MetricsXmlSerializer(serializer);
+ metricsXmlSerializer.serialize(mReport);
serializer.endTag(CtsXmlResultReporter.ns, TAG);
}
/**
- * class containing performance result.
- */
- public static class PerfResultCommon {
- public String mMessage;
- public String mType;
- public String mUnit;
- }
-
- private class PerfResultSummary extends PerfResultCommon {
- public String mTarget;
- public String mValue;
- }
-
- private class PerfResultDetail extends PerfResultCommon {
- public String mSource;
- public String[] mValues;
- }
-
- private PerfResultSummary parseSummary(String summary) {
- String[] elems = summary.split(LOG_ELEM_SEPARATOR);
- PerfResultSummary r = new PerfResultSummary();
- if (elems.length < 5) {
- Log.w(TAG, "wrong message " + summary);
- return null;
- }
- r.mMessage = elems[0];
- r.mTarget = elems[1];
- r.mType = elems[2];
- r.mUnit = elems[3];
- r.mValue = elems[4];
- return r;
- }
-
- private PerfResultDetail[] parseDetails(String details) {
- String[] arrays = details.split(LOG_SEPARATOR);
- PerfResultDetail[] rs = new PerfResultDetail[arrays.length];
- for (int i = 0; i < arrays.length; i++) {
- String[] elems = arrays[i].split(LOG_ELEM_SEPARATOR);
- if (elems.length < 5) {
- Log.w(TAG, "wrong message " + arrays[i]);
- continue;
- }
- PerfResultDetail r = new PerfResultDetail();
- r.mSource = elems[0];
- r.mMessage = elems[1];
- r.mType = elems[2];
- r.mUnit = elems[3];
- r.mValues = elems[4].split(" ");
- rs[i] = r;
- }
- return rs;
- }
-
- /**
* Strip out any invalid XML characters that might cause the report to be unviewable.
* http://www.w3.org/TR/REC-xml/#dt-character
*/
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java
index 45224f6..2229671 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java
@@ -15,9 +15,10 @@
*/
package com.android.cts.tradefed.result;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.compatibility.common.util.MetricsStore;
+import com.android.compatibility.common.util.ReportLog;
import com.android.cts.tradefed.testtype.CtsTest;
-import com.android.cts.tradefed.util.CtsHostStore;
-import com.android.cts.util.AbiUtils;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.log.LogUtil.CLog;
@@ -33,8 +34,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
* Data structure for a CTS test package result.
@@ -45,7 +44,7 @@
static final String TAG = "TestPackage";
- public static final String CTS_RESULT_KEY = "CTS_TEST_RESULT";
+ public static final String RESULT_KEY = "COMPATIBILITY_TEST_RESULT";
private static final String DIGEST_ATTR = "digest";
private static final String APP_PACKAGE_NAME_ATTR = "appPackageName";
@@ -54,8 +53,6 @@
private static final String ns = CtsXmlResultReporter.ns;
private static final String SIGNATURE_TEST_PKG = "android.tests.sigtest";
- private static final Pattern mCtsLogPattern = Pattern.compile("(.*)\\+\\+\\+\\+(.*)");
-
private String mDeviceSerial;
private String mAppPackageName;
private String mName;
@@ -249,23 +246,22 @@
// Collect performance results
for (TestIdentifier test : mTestMetrics.keySet()) {
// device test can have performance results in test metrics
- String perfResult = mTestMetrics.get(test).get(CTS_RESULT_KEY);
- // host test should be checked in CtsHostStore.
- if (perfResult == null) {
- perfResult = CtsHostStore.removeCtsResult(mDeviceSerial, mAbi, test.toString());
+ String perfResult = mTestMetrics.get(test).get(RESULT_KEY);
+ ReportLog report = null;
+ if (perfResult != null) {
+ try {
+ report = ReportLog.parse(perfResult);
+ } catch (XmlPullParserException | IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ // host test should be checked into MetricsStore.
+ report = MetricsStore.removeResult(mDeviceSerial, getAbi(), test.toString());
}
Test result = findTest(test);
- if (perfResult != null && !result.getResult().equals(CtsTestStatus.FAIL)) {
- // CTS result is passed in Summary++++Details format.
- // Extract Summary and Details, and pass them.
- Matcher m = mCtsLogPattern.matcher(perfResult);
- if (m.find()) {
- result.setResultStatus(CtsTestStatus.PASS);
- result.setSummary(m.group(1));
- result.setDetails(m.group(2));
- } else {
- CLog.e("CTS Result unrecognizable:" + perfResult);
- }
+ if (report != null && !result.getResult().equals(CtsTestStatus.FAIL)) {
+ result.setResultStatus(CtsTestStatus.PASS);
+ result.setReportLog(report);
}
}
}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java
index 9f67f2d..a3f1591 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java
@@ -15,8 +15,8 @@
*/
package com.android.cts.tradefed.result;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.build.CtsBuildProvider;
-import com.android.cts.util.AbiUtils;
import com.android.tradefed.log.LogUtil.CLog;
import org.kxml2.io.KXmlSerializer;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/CtsRootDeviceSetup.java b/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/CtsRootDeviceSetup.java
index 0e768e2..f75a99e 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/CtsRootDeviceSetup.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/CtsRootDeviceSetup.java
@@ -41,7 +41,7 @@
*/
public class CtsRootDeviceSetup implements ITargetPreparer {
- private static final String DEVICE_ADMIN_APK_FILE_NAME = "CtsDeviceAdmin.apk";
+ private static final String DEVICE_ADMIN_APK_FILE_NAME = "CtsAdminApp.apk";
/**
* {@inheritDoc}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsInstrumentationApkTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsInstrumentationApkTest.java
index 66d1135f..1fa4e7b 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsInstrumentationApkTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsInstrumentationApkTest.java
@@ -15,8 +15,8 @@
*/
package com.android.cts.tradefed.testtype;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
import com.android.ddmlib.Log;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
index 244f348..dc0d040 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
@@ -16,11 +16,11 @@
package com.android.cts.tradefed.testtype;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.cts.tradefed.device.DeviceInfoCollector;
import com.android.cts.tradefed.result.CtsTestStatus;
import com.android.cts.tradefed.result.PlanCreator;
-import com.android.cts.util.AbiUtils;
import com.android.ddmlib.Log;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.testrunner.TestIdentifier;
@@ -64,7 +64,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -252,20 +251,6 @@
}
}
-
- /**
- * A {@link Comparator} for sorting {@link TestPackage}s by running time hint.
- */
- static class RuntimeHintComparator implements Comparator<TestPackage> {
-
- @Override
- public int compare(TestPackage left, TestPackage right) {
- return Long.compare(left.getPackageDef().getRuntimeHint(),
- right.getPackageDef().getRuntimeHint());
- }
-
- }
-
/**
* A {@link ResultForwarder} that will forward a bugreport on each failed test.
*/
@@ -826,10 +811,6 @@
int numTestPackages = testPackageList.size();
int totalShards = Math.min(mTotalShards, numTestPackages);
- // Sort test packages by running time hint, to force packages with large expected
- // running times to different shards if possible.
- Collections.sort(testPackageList, new RuntimeHintComparator());
-
List<TestPackage> shardTestPackageList = new ArrayList<>();
for (int i = mShardAssignment; i < numTestPackages; i += totalShards) {
shardTestPackageList.add(testPackageList.get(i));
@@ -1096,7 +1077,7 @@
* Exposed for unit testing
*/
ITestPlan createPlan(String planName) {
- return new TestPlan(planName, AbiUtils.getAbisSupportedByCts());
+ return new TestPlan(planName, AbiUtils.getAbisSupportedByCompatibility());
}
/**
@@ -1110,7 +1091,7 @@
String bitness = (mForceAbi == null) ? "" : mForceAbi;
Set<String> abis = new HashSet<>();
for (String abi : AbiFormatter.getSupportedAbis(mDevice, bitness)) {
- if (AbiUtils.isAbiSupportedByCts(abi)) {
+ if (AbiUtils.isAbiSupportedByCompatibility(abi)) {
abis.add(abi);
}
}
@@ -1125,7 +1106,7 @@
*/
ITestPlan createPlan(PlanCreator planCreator)
throws ConfigurationException {
- return planCreator.createDerivedPlan(mCtsBuild, AbiUtils.getAbisSupportedByCts());
+ return planCreator.createDerivedPlan(mCtsBuild, AbiUtils.getAbisSupportedByCompatibility());
}
/**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
index 6f4d42d..66fcd44 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
@@ -1,7 +1,7 @@
package com.android.cts.tradefed.testtype;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.MultiLineReceiver;
@@ -161,7 +161,7 @@
}
private static final class CapabilityQueryFailureException extends Exception {
- };
+ }
/**
* Test configuration of dEPQ test instance execution.
@@ -241,13 +241,13 @@
private boolean mGotTestResult;
private String mCurrentTestLog;
- private class PendingResult
- {
+ private class PendingResult {
boolean allInstancesPassed;
Map<BatchRunConfiguration, String> testLogs;
Map<BatchRunConfiguration, String> errorMessages;
Set<BatchRunConfiguration> remainingConfigs;
- };
+ }
+
private final Map<TestIdentifier, PendingResult> mPendingResults = new HashMap<>();
public void setSink(ITestInvocationListener sink) {
@@ -728,7 +728,7 @@
*/
public static interface ISleepProvider {
public void sleep(int milliseconds);
- };
+ }
private static class SleepProvider implements ISleepProvider {
public void sleep(int milliseconds) {
@@ -737,7 +737,7 @@
} catch (InterruptedException ex) {
}
}
- };
+ }
/**
* Interface for failure recovery.
@@ -997,7 +997,7 @@
private void rebootDevice() throws DeviceNotAvailableException {
mDevice.reboot();
}
- };
+ }
/**
* Parse map of instance arguments to map of BatchRunConfigurations
@@ -1319,12 +1319,13 @@
public AdbComLinkOpenError(String description, Throwable inner) {
super(description, inner);
}
- };
+ }
+
private static final class AdbComLinkKilledError extends Exception {
public AdbComLinkKilledError(String description, Throwable inner) {
super(description, inner);
}
- };
+ }
/**
* Executes a given command in adb shell
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
index 9cbcd20..f11c76d 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
@@ -16,6 +16,7 @@
package com.android.cts.tradefed.testtype;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.ddmlib.testrunner.ITestRunListener;
import com.android.tradefed.build.IBuildInfo;
@@ -149,7 +150,8 @@
}
void runTest(ITestRunListener listener) throws DeviceNotAvailableException {
- GeeTestResultParser resultParser = new GeeTestResultParser(mPackageName, listener);
+ String id = AbiUtils.createId(mAbi.getName(), mPackageName);
+ GeeTestResultParser resultParser = new GeeTestResultParser(id, listener);
resultParser.setFakePackagePrefix(mPackageName + ".");
String fullPath = NATIVE_TESTS_DIRECTORY + ANDROID_PATH_SEPARATOR + mExeName;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java
index 630dee3..13f3572 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java
@@ -72,11 +72,6 @@
public IAbi getAbi();
/**
- * @return the estimated running time of this test package.
- */
- public long getRuntimeHint();
-
- /**
* Set the filter to use for tests
*
* @param testFilter
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageRepo.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageRepo.java
index 234f437..893758f 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageRepo.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageRepo.java
@@ -16,7 +16,7 @@
package com.android.cts.tradefed.testtype;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
import java.util.List;
import java.util.Map;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
index d08c0bc..b75a67a 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
@@ -16,7 +16,7 @@
package com.android.cts.tradefed.testtype;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.log.LogUtil.CLog;
@@ -66,7 +66,6 @@
private String mRunTimeArgs = null;
private String mTestPackageName = null;
private String mDigest = null;
- private long mRuntimeHint = 0;
private IAbi mAbi = null;
private List<ITargetPreparer> mPreparers = null;
@@ -138,18 +137,6 @@
* {@inheritDoc}
*/
@Override
- public long getRuntimeHint() {
- return mRuntimeHint;
- }
-
- void setRuntimeHint(long runtimeHint) {
- mRuntimeHint = runtimeHint;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public String getName() {
return mName;
}
@@ -254,7 +241,7 @@
CLog.d("Setting new timeout to " + mTimeoutInMins + " mins");
hostTest.setTimeout(mTimeoutInMins * 60 * 1000);
}
- hostTest.setRunName(mAppPackageName);
+ hostTest.setRunName(getId());
hostTest.setJarFileName(mJarPath);
hostTest.setTests(mTests);
hostTest.setAbi(mAbi);
@@ -263,7 +250,7 @@
} else if (VM_HOST_TEST.equals(mTestType)) {
CLog.d("Creating vm host test for %s", mName);
VMHostTest vmHostTest = new VMHostTest();
- vmHostTest.setRunName(mAppPackageName);
+ vmHostTest.setRunName(getId());
vmHostTest.setJarFileName(mJarPath);
vmHostTest.setTests(mTests);
vmHostTest.setAbi(mAbi);
@@ -285,11 +272,12 @@
return wrappedGeeTest;
} else if (UIAUTOMATOR_TEST.equals(mTestType)) {
UiAutomatorJarTest uiautomatorTest = new UiAutomatorJarTest();
+ uiautomatorTest.setRunName(getId());
return setUiAutomatorTest(uiautomatorTest);
} else if (JUNIT_DEVICE_TEST.equals(mTestType)){
CLog.d("Creating JUnit device test %s", mName);
JUnitDeviceTest jUnitDeviceTest = new JUnitDeviceTest();
- jUnitDeviceTest.setRunName(mAppPackageName);
+ jUnitDeviceTest.setRunName(getId());
jUnitDeviceTest.addTestJarFileName(mJarPath);
jUnitDeviceTest.addRunTimeArgs(mRunTimeArgs);
jUnitDeviceTest.setTests(mTests);
@@ -318,7 +306,7 @@
*/
private InstrumentationTest setInstrumentationTest(CtsInstrumentationApkTest instrTest,
File testCaseDir) {
- instrTest.setRunName(mAppPackageName);
+ instrTest.setRunName(getId());
instrTest.setPackageName(mAppNameSpace);
instrTest.setRunnerName(mRunner);
instrTest.setAbi(mAbi);
@@ -353,7 +341,7 @@
} else {
uiautomatorTest.addClassNames(mTestClasses);
}
- uiautomatorTest.setRunName(mAppPackageName);
+ uiautomatorTest.setRunName(getId());
uiautomatorTest.setCaptureLogs(false);
return uiautomatorTest;
}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageRepo.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageRepo.java
index 7e16170..9857105b 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageRepo.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageRepo.java
@@ -15,7 +15,7 @@
*/
package com.android.cts.tradefed.testtype;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.ddmlib.Log;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.ConfigurationFactory;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
index 951c461..acd977e 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
@@ -15,7 +15,7 @@
*/
package com.android.cts.tradefed.testtype;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.ddmlib.Log;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.util.xml.AbstractXmlParser;
@@ -86,12 +86,8 @@
final String targetNameSpace = attributes.getValue("targetNameSpace");
final String runTimeArgs = attributes.getValue("runtimeArgs");
final String testType = getTestType(attributes);
- long runTimeHint = 0;
- if (attributes.getValue("runtimeHint") != null) {
- runTimeHint = Long.parseLong(attributes.getValue("runtimeHint"));
- }
- for (String abiName : AbiUtils.getAbisSupportedByCts()) {
+ for (String abiName : AbiUtils.getAbisSupportedByCompatibility()) {
Abi abi = new Abi(abiName, AbiUtils.getBitness(abiName));
TestPackageDef packageDef = new TestPackageDef();
packageDef.setAppPackageName(appPackageName);
@@ -106,7 +102,6 @@
}
packageDef.setTargetBinaryName(targetBinaryName);
packageDef.setTargetNameSpace(targetNameSpace);
- packageDef.setRuntimeHint(runTimeHint);
packageDef.setAbi(abi);
mPackageDefs.put(abiName, packageDef);
}
@@ -159,7 +154,7 @@
Set<String> abis = new HashSet<String>();
if (abiList == null) {
// If no specification, add all supported abis
- abis.addAll(AbiUtils.getAbisSupportedByCts());
+ abis.addAll(AbiUtils.getAbisSupportedByCompatibility());
} else {
for (String abi : abiList.split(",")) {
// Else only add the abi which are supported
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPlan.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPlan.java
index 2419784..6b02db9 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPlan.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPlan.java
@@ -16,7 +16,7 @@
package com.android.cts.tradefed.testtype;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.util.ArrayUtil;
import com.android.tradefed.util.xml.AbstractXmlParser;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
index e3ff8257..4f40c89 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
@@ -16,8 +16,8 @@
package com.android.cts.tradefed.testtype;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.util.AbiUtils;
import com.android.ddmlib.testrunner.ITestRunListener;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/util/CtsHostStore.java b/tools/tradefed-host/src/com/android/cts/tradefed/util/CtsHostStore.java
deleted file mode 100644
index 288b48c..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/util/CtsHostStore.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.cts.tradefed.util;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Utility class for storing Cts Results.
- * This is necessary for host tests where test metrics cannot be passed.
- */
-public class CtsHostStore {
-
- // needs concurrent version as there can be multiple client accessing this.
- // But there is no additional protection for the same key as that should not happen.
- private static final ConcurrentHashMap<String, String> mMap =
- new ConcurrentHashMap<String, String>();
-
- /**
- * Stores CTS result. Existing result with the same key will be replaced.
- * Note that key is generated in the form of device_serial#class#method name.
- * So there should be no concurrent test for the same (serial, class, method).
- * @param deviceSerial
- * @param abi
- * @param classMethodName
- * @param result CTS result string
- */
- public static void storeCtsResult(String deviceSerial, String abi, String classMethodName, String result) {
- mMap.put(generateTestKey(deviceSerial, abi, classMethodName), result);
- }
-
- /**
- * retrieves a CTS result for the given condition and remove it from the internal
- * storage. If there is no result for the given condition, it will return null.
- */
- public static String removeCtsResult(String deviceSerial, String abi, String classMethodName) {
- return mMap.remove(generateTestKey(deviceSerial, abi, classMethodName));
- }
-
- /**
- * @return test key in the form of device_serial#abi#class_name#method_name
- */
- private static String generateTestKey(String deviceSerial, String abi, String classMethodName) {
- return String.format("%s#%s#%s", deviceSerial, abi, classMethodName);
-
- }
-}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/util/HostReportLog.java b/tools/tradefed-host/src/com/android/cts/tradefed/util/HostReportLog.java
index 645dbb9..f72b097 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/util/HostReportLog.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/util/HostReportLog.java
@@ -16,17 +16,17 @@
package com.android.cts.tradefed.util;
+import com.android.compatibility.common.util.MetricsReportLog;
import com.android.cts.util.ReportLog;
/**
* ReportLog for host tests
* Note that setTestInfo should be set before throwing report
+ *
+ * This class is deprecated, use {@link MetricsReportLog} instead.
*/
+@Deprecated
public class HostReportLog extends ReportLog {
- private final String mDeviceSerial;
- private final String mAbiName;
- private final String mClassMethodName;
-
/**
* @param deviceSerial serial number of the device
* @param abiName the name of the ABI on which the test was run
@@ -34,12 +34,10 @@
* Note that ReportLog.getClassMethodNames() provide this.
*/
public HostReportLog(String deviceSerial, String abiName, String classMethodName) {
- mDeviceSerial = deviceSerial;
- mAbiName = abiName;
- mClassMethodName = classMethodName;
+ super(new MetricsReportLog(deviceSerial, abiName, classMethodName));
}
public void deliverReportToHost() {
- CtsHostStore.storeCtsResult(mDeviceSerial, mAbiName, mClassMethodName, generateReport());
+ ((MetricsReportLog) mReportLog).submit();
}
-}
+}
\ No newline at end of file
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
index 958dbe4..361b91c 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
@@ -17,11 +17,10 @@
import static com.android.cts.tradefed.result.CtsXmlResultReporter.CTS_RESULT_FILE_VERSION;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.UnitTests;
-import com.android.cts.util.AbiUtils;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IFolderBuildInfo;
-import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.LogFile;
import com.android.tradefed.result.TestSummary;
@@ -36,8 +35,8 @@
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/CtsTestTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/CtsTestTest.java
index 98caad1..19204b7 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/CtsTestTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/CtsTestTest.java
@@ -15,10 +15,10 @@
*/
package com.android.cts.tradefed.testtype;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.UnitTests;
import com.android.cts.tradefed.build.StubCtsBuildHelper;
import com.android.cts.tradefed.result.PlanCreator;
-import com.android.cts.util.AbiUtils;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
index 7ec09c9..2c8a816 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
@@ -15,18 +15,16 @@
*/
package com.android.cts.tradefed.testtype;
-import com.android.cts.tradefed.build.StubCtsBuildHelper;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.cts.tradefed.UnitTests;
-import com.android.cts.util.AbiUtils;
+import com.android.cts.tradefed.build.StubCtsBuildHelper;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.ShellCommandUnresponsiveException;
-import com.android.ddmlib.testrunner.ITestRunListener;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.util.IRunUtil;
import com.android.tradefed.util.RunInterruptedException;
@@ -38,7 +36,6 @@
import java.io.File;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
index bd48c51..8655885 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
@@ -16,7 +16,7 @@
package com.android.cts.tradefed.testtype;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.util.xml.AbstractXmlParser.ParseException;
@@ -100,7 +100,7 @@
assertEquals("com.example", def.getAppNameSpace());
assertEquals("android.example", def.getAppPackageName());
assertEquals("android.test.InstrumentationTestRunner", def.getRunner());
- assertTrue(AbiUtils.isAbiSupportedByCts(def.getAbi().getName()));
+ assertTrue(AbiUtils.isAbiSupportedByCompatibility(def.getAbi().getName()));
}
}
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPlanTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPlanTest.java
index 5b28539..be260ea 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPlanTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPlanTest.java
@@ -16,7 +16,7 @@
package com.android.cts.tradefed.testtype;
-import com.android.cts.util.AbiUtils;
+import com.android.compatibility.common.util.AbiUtils;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.util.xml.AbstractXmlParser.ParseException;
@@ -75,7 +75,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mPlan = new TestPlan("plan", AbiUtils.getAbisSupportedByCts());
+ mPlan = new TestPlan("plan", AbiUtils.getAbisSupportedByCompatibility());
}
/**
@@ -91,7 +91,7 @@
* @param plan
*/
private void assertTestData(TestPlan plan) {
- Set<String> abis = AbiUtils.getAbisSupportedByCts();
+ Set<String> abis = AbiUtils.getAbisSupportedByCompatibility();
assertEquals(2 * abis.size(), plan.getTestIds().size());
List<String> sortedAbis = new ArrayList<String>(abis);
Collections.sort(sortedAbis);
@@ -112,7 +112,7 @@
*/
public void testParse_exclude() throws ParseException {
mPlan.parse(getStringAsStream(TEST_EXCLUDED_DATA));
- Set<String> abis = AbiUtils.getAbisSupportedByCts();
+ Set<String> abis = AbiUtils.getAbisSupportedByCompatibility();
assertEquals(abis.size(), mPlan.getTestIds().size());
for (String abi : abis) {
@@ -136,7 +136,7 @@
* @param plan
*/
private void assertMultiExcluded(TestPlan plan) {
- Set<String> abis = AbiUtils.getAbisSupportedByCts();
+ Set<String> abis = AbiUtils.getAbisSupportedByCompatibility();
assertEquals(abis.size(), plan.getTestIds().size());
for (String abi : abis) {
@@ -154,7 +154,7 @@
*/
public void testParse_classExclude() throws ParseException {
mPlan.parse(getStringAsStream(TEST_CLASS_EXCLUDED_DATA));
- Set<String> abis = AbiUtils.getAbisSupportedByCts();
+ Set<String> abis = AbiUtils.getAbisSupportedByCompatibility();
assertEquals(abis.size(), mPlan.getTestIds().size());
for (String abi : abis) {
@@ -179,14 +179,14 @@
* @throws IOException
*/
public void testSerialize_packages() throws ParseException, IOException {
- Set<String> abis = AbiUtils.getAbisSupportedByCts();
+ Set<String> abis = AbiUtils.getAbisSupportedByCompatibility();
for (String abi : abis) {
mPlan.addPackage(AbiUtils.createId(abi, TEST_NAME1));
mPlan.addPackage(AbiUtils.createId(abi, TEST_NAME2));
}
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
mPlan.serialize(outStream);
- TestPlan parsedPlan = new TestPlan("parsed", AbiUtils.getAbisSupportedByCts());
+ TestPlan parsedPlan = new TestPlan("parsed", AbiUtils.getAbisSupportedByCompatibility());
parsedPlan.parse(getStringAsStream(outStream.toString()));
// parsedPlan should contain same contents as TEST_DATA
assertTestData(parsedPlan);
@@ -196,7 +196,7 @@
* Test serializing and deserializing plan with multiple excluded tests
*/
public void testSerialize_multiExclude() throws ParseException, IOException {
- Set<String> abis = AbiUtils.getAbisSupportedByCts();
+ Set<String> abis = AbiUtils.getAbisSupportedByCompatibility();
for (String abi : abis) {
String test1Id = AbiUtils.createId(abi, TEST_NAME1);
@@ -208,7 +208,7 @@
}
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
mPlan.serialize(outStream);
- TestPlan parsedPlan = new TestPlan("parsed", AbiUtils.getAbisSupportedByCts());
+ TestPlan parsedPlan = new TestPlan("parsed", AbiUtils.getAbisSupportedByCompatibility());
parsedPlan.parse(getStringAsStream(outStream.toString()));
// parsedPlan should contain same contents as TEST_DATA
assertMultiExcluded(parsedPlan);
diff --git a/tools/utils/Android.mk b/tools/utils/Android.mk
index 0ba5cf4..d26abb1 100644
--- a/tools/utils/Android.mk
+++ b/tools/utils/Android.mk
@@ -25,6 +25,6 @@
LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
LOCAL_JAVA_LIBRARIES := junit
-LOCAL_STATIC_JAVA_LIBRARIES := ctsabiutilslib vogarexpectlib
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-host-util vogarexpectlib
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/utils/CollectAllTests.java b/tools/utils/CollectAllTests.java
index 0bce11c..8003f4d 100644
--- a/tools/utils/CollectAllTests.java
+++ b/tools/utils/CollectAllTests.java
@@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import com.android.cts.util.AbiUtils;
+
+import com.android.compatibility.common.util.AbiUtils;
import org.junit.runner.RunWith;
import org.w3c.dom.Document;
diff --git a/tools/utils/VogarUtils.java b/tools/utils/VogarUtils.java
index 8e77e7c..77c62da 100644
--- a/tools/utils/VogarUtils.java
+++ b/tools/utils/VogarUtils.java
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-import com.android.cts.util.AbiUtils;
-
import vogar.Expectation;
import vogar.ExpectationStore;
import vogar.ModeId;
import vogar.Result;
+import com.android.compatibility.common.util.AbiUtils;
+
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index 9f462ca..30dfcd2 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -20,6 +20,7 @@
import os
import re
import shutil
+import string
import subprocess
import sys
import xml.dom.minidom as dom
@@ -37,6 +38,16 @@
f.close()
return lines
+def ReadDeqpTestList(testRoot, file):
+ """Reads a file, converts test names from deqp to CTS format, and returns
+ its contents as a line list.
+ """
+ REPO_ROOT = os.path.join(testRoot, "../../..")
+ f = open(os.path.join(REPO_ROOT, "external/deqp/android/cts", file), 'r');
+ lines = [string.join(line.strip().rsplit('.',1),'#') for line in f.readlines()]
+ f.close()
+ return lines
+
def GetMakeFileVars(makefile_path):
"""Extracts variable definitions from the given make file.
@@ -127,12 +138,12 @@
plan = tools.TestPlan(packages)
plan.Include(r'android\.core\.tests.*')
- plan.Exclude(r'android\.core\.tests\.libcore.\package.\harmony*')
+ plan.Exclude(r'android\.core\.tests\.libcore\.package\.harmony*')
self.__WritePlan(plan, 'Java')
# TODO: remove this once the tests are fixed and merged into Java plan above.
plan = tools.TestPlan(packages)
- plan.Include(r'android\.core\.tests\.libcore.\package.\harmony*')
+ plan.Include(r'android\.core\.tests\.libcore\.package\.harmony*')
self.__WritePlan(plan, 'Harmony')
plan = tools.TestPlan(packages)
@@ -165,7 +176,7 @@
# CTS Stable plan
plan = tools.TestPlan(packages)
- plan.Exclude(r'com\.android\.cts\.browserbench')
+ plan.Exclude(r'android\.browser')
for package, test_list in flaky_tests.iteritems():
plan.ExcludeTests(package, test_list)
for package, test_list in releasekey_tests.iteritems():
@@ -175,7 +186,7 @@
# CTS Flaky plan - list of tests known to be flaky in lab environment
plan = tools.TestPlan(packages)
plan.Exclude('.*')
- plan.Include(r'com\.android\.cts\.browserbench')
+ plan.Include(r'android\.browser')
for package, test_list in flaky_tests.iteritems():
plan.Include(package+'$')
plan.IncludeTests(package, test_list)
@@ -190,7 +201,7 @@
plan.Exclude('.*')
for package, test_list in small_tests.iteritems():
plan.Include(package+'$')
- plan.Exclude(r'com\.android\.cts\.browserbench')
+ plan.Exclude(r'android\.browser')
for package, test_list in flaky_tests.iteritems():
plan.ExcludeTests(package, test_list)
for package, test_list in releasekey_tests.iteritems():
@@ -203,7 +214,7 @@
plan.Exclude('.*')
for package, test_list in medium_tests.iteritems():
plan.Include(package+'$')
- plan.Exclude(r'com\.android\.cts\.browserbench')
+ plan.Exclude(r'android\.browser')
for package, test_list in flaky_tests.iteritems():
plan.ExcludeTests(package, test_list)
for package, test_list in releasekey_tests.iteritems():
@@ -215,7 +226,7 @@
plan = tools.TestPlan(packages)
plan.Exclude('.*')
plan.Include(r'android\.hardware$')
- plan.Exclude(r'com\.android\.cts\.browserbench')
+ plan.Exclude(r'android\.browser')
for package, test_list in flaky_tests.iteritems():
plan.ExcludeTests(package, test_list)
for package, test_list in releasekey_tests.iteritems():
@@ -241,7 +252,7 @@
plan.Exclude('.*')
plan.Include(r'android\.media$')
plan.Include(r'android\.view$')
- plan.Exclude(r'com\.android\.cts\.browserbench')
+ plan.Exclude(r'android\.browser')
for package, test_list in flaky_tests.iteritems():
plan.ExcludeTests(package, test_list)
for package, test_list in releasekey_tests.iteritems():
@@ -252,7 +263,7 @@
plan = tools.TestPlan(packages)
plan.Exclude('.*')
plan.Include(r'android\.mediastress$')
- plan.Exclude(r'com\.android\.cts\.browserbench')
+ plan.Exclude(r'android\.browser')
for package, test_list in flaky_tests.iteritems():
plan.ExcludeTests(package, test_list)
for package, test_list in releasekey_tests.iteritems():
@@ -264,7 +275,7 @@
plan.Exclude('.*')
for package, test_list in new_test_packages.iteritems():
plan.Include(package+'$')
- plan.Exclude(r'com\.android\.cts\.browserbench')
+ plan.Exclude(r'android\.browser')
for package, test_list in flaky_tests.iteritems():
plan.ExcludeTests(package, test_list)
for package, test_list in releasekey_tests.iteritems():
@@ -275,8 +286,21 @@
plan = tools.TestPlan(packages)
plan.Exclude('.*')
plan.Include(r'com\.drawelements\.')
+ plan.IncludeTests('com.drawelements.deqp.egl', ReadDeqpTestList(self.test_root, 'mnc/egl-master.txt'))
+ plan.IncludeTests('com.drawelements.deqp.gles2', ReadDeqpTestList(self.test_root, 'mnc/gles2-master.txt'))
+ plan.IncludeTests('com.drawelements.deqp.gles3', ReadDeqpTestList(self.test_root, 'mnc/gles3-master.txt'))
+ plan.IncludeTests('com.drawelements.deqp.gles31', ReadDeqpTestList(self.test_root, 'mnc/gles31-master.txt'))
self.__WritePlan(plan, 'CTS-DEQP')
+ plan = tools.TestPlan(packages)
+ plan.Exclude('.*')
+ plan.Include(r'com\.drawelements\.')
+ plan.ExcludeTests('com.drawelements.deqp.egl', ReadDeqpTestList(self.test_root, 'mnc/egl-master.txt'))
+ plan.ExcludeTests('com.drawelements.deqp.gles2', ReadDeqpTestList(self.test_root, 'mnc/gles2-master.txt'))
+ plan.ExcludeTests('com.drawelements.deqp.gles3', ReadDeqpTestList(self.test_root, 'mnc/gles3-master.txt'))
+ plan.ExcludeTests('com.drawelements.deqp.gles31', ReadDeqpTestList(self.test_root, 'mnc/gles31-master.txt'))
+ self.__WritePlan(plan, 'CTS-DEQP-for-next-rel')
+
# CTS - sub plan for new test packages added for staging
plan = tools.TestPlan(packages)
for package, test_list in small_tests.iteritems():
@@ -290,7 +314,7 @@
plan.Exclude(r'android\.media$')
plan.Exclude(r'android\.view$')
plan.Exclude(r'android\.mediastress$')
- plan.Exclude(r'com\.android\.cts\.browserbench')
+ plan.Exclude(r'android\.browser')
for package, test_list in flaky_tests.iteritems():
plan.ExcludeTests(package, test_list)
for package, test_list in releasekey_tests.iteritems():
@@ -334,7 +358,7 @@
'android.telephony' : [],
'android.webkit' : [],
'android.widget' : [],
- 'com.android.cts.browserbench' : []}
+ 'android.browser' : []}
def BuildAospSmallSizeTestList():
""" Construct a default dict that lists packages names of small tests
@@ -347,6 +371,7 @@
'android.accounts' : [],
'android.admin' : [],
'android.animation' : [],
+ 'android.appsecurity' : [],
'android.bionic' : [],
'android.bluetooth' : [],
'android.calendarcommon' : [],
@@ -357,9 +382,11 @@
'android.core.tests.libcore.package.sun' : [],
'android.core.tests.libcore.package.tests' : [],
'android.database' : [],
+ 'android.dram' : [],
'android.dreams' : [],
'android.drm' : [],
'android.effect' : [],
+ 'android.filesystem' : [],
'android.gesture' : [],
'android.graphics' : [],
'android.graphics2' : [],
@@ -368,7 +395,6 @@
'android.location' : [],
'android.nativemedia.sl' : [],
'android.nativemedia.xa' : [],
- 'android.nativeopengl' : [],
'android.ndef' : [],
'android.opengl' : [],
'android.openglperf' : [],
@@ -380,23 +406,21 @@
'android.rscpp' : [],
'android.rsg' : [],
'android.sax' : [],
+ 'android.server' : [],
'android.signature' : [],
+ 'android.simplecpu' : [],
'android.speech' : [],
- 'android.tests.appsecurity' : [],
'android.text' : [],
'android.textureview' : [],
'android.theme' : [],
'android.usb' : [],
'android.util' : [],
- 'com.android.cts.dram' : [],
- 'com.android.cts.filesystemperf' : [],
+ 'android.video' : [],
'com.android.cts.jank' : [],
'com.android.cts.jank2' : [],
'com.android.cts.opengl' : [],
- 'com.android.cts.simplecpu' : [],
'com.android.cts.ui' : [],
'com.android.cts.uihost' : [],
- 'com.android.cts.videoperf' : [],
'zzz.android.monkey' : []}
def BuildCtsVettedNewPackagesList():
@@ -516,8 +540,8 @@
'android.voicesettings' : [
'android.voicesettings.cts.ZenModeTest#testAll',
],
- 'com.android.cts.systemui' : [
- 'com.android.cts.systemui.LightStatusBarTests#testLightStatusBarIcons',
+ 'android.systemui.cts' : [
+ 'android.systemui.cts.LightStatusBarTests#testLightStatusBarIcons',
],
'com.android.cts.app.os' : [
'com.android.cts.app.os.OsHostTests#testNonExportedActivities',
diff --git a/tools/utils/java-cert-list-generator.sh b/tools/utils/java-cert-list-generator.sh
index b8cee18..33e9aaa 100755
--- a/tools/utils/java-cert-list-generator.sh
+++ b/tools/utils/java-cert-list-generator.sh
@@ -50,7 +50,7 @@
static final String[] CERTIFICATE_DATA = {
STARTCLASS
-CERT_DIRECTORY=$ANDROID_BUILD_TOP/libcore/luni/src/main/files/cacerts
+CERT_DIRECTORY=$ANDROID_BUILD_TOP/system/ca-certificates/files/
for FILE in `ls $CERT_DIRECTORY`; do
FINGERPRINT=`cat $CERT_DIRECTORY/$FILE | grep "SHA1 Fingerprint=" | cut -d '=' -f 2`
echo " \"${FINGERPRINT}\","