Merge "Update the usage of telecom comamnd"
diff --git a/CtsCoverage.mk b/CtsCoverage.mk
index 4b01005..1fb98dc 100644
--- a/CtsCoverage.mk
+++ b/CtsCoverage.mk
@@ -17,8 +17,6 @@
# Makefile for producing CTS coverage reports.
# Run "make cts-test-coverage" in the $ANDROID_BUILD_TOP directory.
-include cts/CtsTestCaseList.mk
-
cts_api_coverage_exe := $(HOST_OUT_EXECUTABLES)/cts-api-coverage
dexdeps_exe := $(HOST_OUT_EXECUTABLES)/dexdeps
@@ -38,41 +36,40 @@
cts_api_coverage_dependencies := $(cts_api_coverage_exe) $(dexdeps_exe) $(api_xml_description)
-cts_coverage_test_cases_dependencies := $(foreach c, $(CTS_COVERAGE_TEST_CASE_LIST), $(call intermediates-dir-for,APPS,$(c))/package.apk)
-$(cts-test-coverage-report): PRIVATE_TEST_CASES_APKS := $(cts_coverage_test_cases_dependencies)
+android_cts_zip := $(HOST_OUT)/cts/android-cts.zip
+cts_verifier_apk := $(call intermediates-dir-for,APPS,CtsVerifier)/package.apk
+
+$(cts-test-coverage-report): PRIVATE_TEST_CASES := $(CTS_TESTCASES_OUT)
$(cts-test-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
$(cts-test-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
$(cts-test-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
-$(cts-test-coverage-report) : $(cts_coverage_test_cases_dependencies) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-test-coverage-report) : $(android_cts_zip) $(cts_api_coverage_dependencies) | $(ACP)
$(call generate-coverage-report,"CTS Tests API Coverage Report",\
- $(PRIVATE_TEST_CASES_APKS),html)
+ $(PRIVATE_TEST_CASES),html)
-cts_coverage_test_cases_dependencies := $(call intermediates-dir-for,APPS,CtsVerifier)/package.apk
-$(cts-verifier-coverage-report): PRIVATE_TEST_CASES_APKS := $(cts_coverage_test_cases_dependencies)
+$(cts-verifier-coverage-report): PRIVATE_TEST_CASES := $(cts_verifier_apk)
$(cts-verifier-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
$(cts-verifier-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
$(cts-verifier-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
-$(cts-verifier-coverage-report) : $(cts_coverage_test_cases_dependencies) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-verifier-coverage-report) : $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
$(call generate-coverage-report,"CTS Verifier API Coverage Report",\
- $(PRIVATE_TEST_CASES_APKS),html)
+ $(PRIVATE_TEST_CASES),html)
-cts_coverage_test_cases_dependencies := $(foreach c, $(CTS_COVERAGE_TEST_CASE_LIST) CtsVerifier, $(call intermediates-dir-for,APPS,$(c))/package.apk)
-$(cts-combined-coverage-report): PRIVATE_TEST_CASES_APKS := $(cts_coverage_test_cases_dependencies)
+$(cts-combined-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(CTS_TESTCASES_OUT), $(c))
$(cts-combined-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
$(cts-combined-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
$(cts-combined-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
-$(cts-combined-coverage-report) : $(cts_coverage_test_cases_dependencies) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-combined-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
$(call generate-coverage-report,"CTS Combined API Coverage Report",\
- $(PRIVATE_TEST_CASES_APKS),html)
+ $(PRIVATE_TEST_CASES),html)
-cts_coverage_test_cases_dependencies := $(foreach c, $(CTS_COVERAGE_TEST_CASE_LIST) CtsVerifier, $(call intermediates-dir-for,APPS,$(c))/package.apk)
-$(cts-combined-xml-coverage-report): PRIVATE_TEST_CASES_APKS := $(cts_coverage_test_cases_dependencies)
+$(cts-combined-xml-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(CTS_TESTCASES_OUT), $(c))
$(cts-combined-xml-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
$(cts-combined-xml-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
$(cts-combined-xml-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
-$(cts-combined-xml-coverage-report) : $(cts_coverage_test_cases_dependencies) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-combined-xml-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
$(call generate-coverage-report,"CTS Combined API Coverage Report - XML",\
- $(PRIVATE_TEST_CASES_APKS),xml)
+ $(PRIVATE_TEST_CASES),xml)
.PHONY: cts-test-coverage
cts-test-coverage : $(cts-test-coverage-report)
@@ -106,7 +103,6 @@
# Reset temp vars
cts_api_coverage_dependencies :=
-cts_coverage_test_cases_dependencies :=
cts-combined-coverage-report :=
cts-combined-xml-coverage-report :=
cts-verifier-coverage-report :=
@@ -116,3 +112,5 @@
coverage_out :=
dexdeps_exe :=
cts_api_coverage_exe :=
+cts_verifier_apk :=
+android_cts_zip :=
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index f239326..04e79f98 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -17,8 +17,12 @@
CtsAppWithData \
CtsDocumentProvider \
CtsDocumentClient \
+ CtsEncryptionApp \
CtsExternalStorageApp \
CtsInstrumentationAppDiffCert \
+ CtsNetSecPolicyUsesCleartextTrafficFalse \
+ CtsNetSecPolicyUsesCleartextTrafficTrue \
+ CtsNetSecPolicyUsesCleartextTrafficUnspecified \
CtsUsePermissionApp \
CtsUsePermissionAppCompat \
CtsPermissionDeclareApp \
@@ -72,6 +76,7 @@
CtsUnaffiliatedAccountAuthenticators
cts_support_packages := \
+ CtsAccountManagementDevicePolicyApp \
CtsAlarmClockService \
CtsAppTestStubs \
CtsAppUsageTestApp \
@@ -79,13 +84,14 @@
CtsAssistApp \
CtsAtraceTestApp \
CtsCertInstallerApp \
+ CtsContactDirectoryProvider \
CtsAdminApp \
CtsWifiConfigCreator \
CtsDeviceAndProfileOwnerApp \
CtsDeviceInfo \
CtsDeviceOsTestApp \
CtsDeviceOwnerApp \
- CtsDeviceServicesTestApp \
+ CtsServicesTestApp \
CtsDeviceTaskSwitchingAppA \
CtsDeviceTaskSwitchingAppB \
CtsDeviceTaskSwitchingControl \
@@ -138,6 +144,7 @@
CtsAppTestCases \
CtsAppWidgetTestCases \
CtsAssistTestCases \
+ CtsAutomotiveTestCases \
CtsBluetoothTestCases \
CtsBrowserTestCases \
CtsCalendarcommon2TestCases \
@@ -166,8 +173,12 @@
CtsLocationTestCases \
CtsLocation2TestCases \
CtsMediaStressTestCases \
+ CtsMediaTestCases \
CtsMidiTestCases \
CtsNdefTestCases \
+ CtsNetSecPolicyUsesCleartextTrafficFalseTestCases \
+ CtsNetSecPolicyUsesCleartextTrafficTrueTestCases \
+ CtsNetSecPolicyUsesCleartextTrafficUnspecifiedTestCases \
CtsNetTestCases \
CtsNetTestCasesLegacyApi22 \
CtsNetTestCasesLegacyPermission22 \
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/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 7d106a6..f15b6ee 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1475,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" />
@@ -1764,7 +1776,7 @@
<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" />
+ <meta-data android:name="test_required_features" android:value="android.hardware.audio.output" />
</activity>
<activity android:name=".audio.AudioOutputDeviceNotificationsActivity"
@@ -1854,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/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 0560c1c..34d21cd 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1481,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">
@@ -1927,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>
@@ -2203,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>
@@ -2286,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/TestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
index 6a96961..807e02a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
@@ -22,6 +22,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PermissionInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
@@ -49,12 +50,22 @@
super.onCreate(savedInstanceState);
try {
- PackageInfo packageInfo = getPackageManager().getPackageInfo(
- getApplicationInfo().packageName, PackageManager.GET_PERMISSIONS);
+ PackageManager pm = getPackageManager();
+ PackageInfo packageInfo = pm.getPackageInfo(
+ getApplicationInfo().packageName, PackageManager.GET_PERMISSIONS);
if (packageInfo.requestedPermissions != null) {
for (String permission : packageInfo.requestedPermissions) {
Log.v(TAG, "Checking permissions for: " + permission);
+ try {
+ PermissionInfo info = pm.getPermissionInfo(permission, 0);
+ if ((info.protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) == 0) {
+ continue;
+ }
+ } catch (NameNotFoundException e) {
+ Log.v(TAG, "Checking permissions for: " + permission + "not found");
+ continue;
+ }
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(packageInfo.requestedPermissions,
CTS_VERIFIER_PERMISSION_REQUEST);
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/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/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/build/device_info_package.mk b/build/device_info_package.mk
index 036218a..1f4d350 100644
--- a/build/device_info_package.mk
+++ b/build/device_info_package.mk
@@ -25,6 +25,7 @@
$(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 \
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/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/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/DeviceAndProfileOwner/res/values/strings.xml b/hostsidetests/devicepolicy/app/AccountManagement/res/values/strings.xml
similarity index 89%
rename from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
rename to hostsidetests/devicepolicy/app/AccountManagement/res/values/strings.xml
index 4aca824..dc8bc5d 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
+++ b/hostsidetests/devicepolicy/app/AccountManagement/res/values/strings.xml
@@ -16,5 +16,5 @@
<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>
+ <string name="authenticator_label">DevicePolicy mock account</string>
</resources>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/authenticator.xml b/hostsidetests/devicepolicy/app/AccountManagement/res/xml/authenticator.xml
similarity index 90%
rename from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/authenticator.xml
rename to hostsidetests/devicepolicy/app/AccountManagement/res/xml/authenticator.xml
index 0d8ecd8..9c82b80 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/authenticator.xml
+++ b/hostsidetests/devicepolicy/app/AccountManagement/res/xml/authenticator.xml
@@ -17,6 +17,6 @@
<!-- for the Account Manager. -->
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
- android:accountType="com.android.cts.deviceandprofileowner.account.type"
+ 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/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountAuthenticator.java b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountAuthenticator.java
similarity index 91%
rename from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountAuthenticator.java
rename to hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountAuthenticator.java
index e8e5b45..0ef310bf 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountAuthenticator.java
+++ b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountAuthenticator.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.cts.deviceandprofileowner;
+package com.android.cts.devicepolicy.accountmanagement;
import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
@@ -26,8 +26,10 @@
/* 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 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";
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountService.java
similarity index 88%
rename from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
rename to hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountService.java
index dfedccb..ace585b 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
+++ b/hostsidetests/devicepolicy/app/AccountManagement/src/com/android/cts/devicepolicy/accountmanagement/MockAccountService.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.cts.deviceandprofileowner;
+package com.android.cts.devicepolicy.accountmanagement;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
/**
- * a basic Mock Service for wrapping the MockAccountAuthenticator
+ * Service for wrapping the {@link MockAccountAuthenticator}
*/
public class MockAccountService extends Service {
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/DeviceAndProfileOwner/res/values/strings.xml b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/res/values/strings.xml
similarity index 83%
copy from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
copy to hostsidetests/devicepolicy/app/ContactDirectoryProvider/res/values/strings.xml
index 4aca824..fe0ec10 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
+++ b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/res/values/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -16,5 +16,5 @@
<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>
+ <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/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/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/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/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
index 77ecfe1..19ea2a2 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
@@ -24,20 +24,22 @@
import android.content.OperationApplicationException;
import android.content.res.Resources.NotFoundException;
import android.database.Cursor;
+import android.graphics.Rect;
import android.net.Uri;
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 +68,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 +105,7 @@
}
private boolean hasPhotoId() {
- return photoId != null;
+ return photoId != null && Long.parseLong(photoId) > 0;
}
}
@@ -116,14 +124,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 +152,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 +178,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 +200,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 +219,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 +231,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 +244,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 +256,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 +267,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 +277,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 +287,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 +297,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 +321,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 +332,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 +343,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 +353,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 +420,366 @@
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);
+ }
+
+ public void testQuickContact() throws Exception {
+ showQuickContactInternal(null);
+ showQuickContactInternal(Directory.ENTERPRISE_DEFAULT);
+ showQuickContactInternal(getEnterpriseRemoteDirectoryId());
+ }
+
+ private void showQuickContactInternal(Long directoryId) throws Exception {
+ final Uri phoneLookupUri =
+ Uri.withAppendedPath(
+ PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI, MANAGED_CONTACT_PHONE);
+ if (directoryId != null) {
+ phoneLookupUri.buildUpon().appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId)).build();
+ }
+ final Cursor cursor =
+ getContext().getContentResolver().query(phoneLookupUri, null, null, null, null);
+ try {
+ assertTrue(cursor.moveToFirst());
+ final long contactId =
+ cursor.getLong(cursor.getColumnIndex(ContactsContract.PhoneLookup._ID));
+ final String lookupKey =
+ cursor.getString(
+ cursor.getColumnIndex(ContactsContract.PhoneLookup.LOOKUP_KEY));
+ final Uri lookupUri = Contacts.getLookupUri(contactId, lookupKey);
+ // TODO: It is better to verify the uri received by quick contacts, but it is difficult
+ // to verify it as the quick contacts in managed profile is started. We now just make
+ // sure no exception is thrown due to invalid uri (eg: directory id is missing).
+ // Also, consider using UiAutomator to verify the activtiy is started.
+ ContactsContract.QuickContact.showQuickContact(getContext(), (Rect) null, lookupUri,
+ ContactsContract.QuickContact.MODE_LARGE, null);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+
+ 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 +858,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 +1008,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/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 3d6a388..6ee1aec 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -99,6 +99,7 @@
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 = MigrationHelper.getTestFile(mCtsBuild, appFileName);
@@ -108,8 +109,8 @@
}
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. */
@@ -188,7 +189,7 @@
}
protected void stopUser(int userId) throws Exception {
- String stopUserCommand = "am stop-user -w " + userId;
+ 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));
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
index 7602802..2740c20 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
@@ -36,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";
@@ -60,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();
@@ -117,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));
}
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index a936408..bc8d9c2 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -51,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.
@@ -67,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();
}
@@ -180,17 +191,81 @@
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 {
@@ -234,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 =
@@ -270,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/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index cc06b9f..c513e62 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";
@@ -210,13 +219,8 @@
// Now there's only the browser in the managed profile left
assertAppLinkResult("testReceivedByBrowserActivityInManaged");
- changeVerificationStatus(mParentUserId, INTENT_RECEIVER_PKG, "always");
- changeVerificationStatus(mProfileUserId, INTENT_RECEIVER_PKG, "ask");
- // We've set the receiver in the primary user to always: only this one should receive the
- // intent.
- assertAppLinkResult("testReceivedByAppLinkActivityInPrimary");
-
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");
@@ -299,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) {
@@ -399,6 +403,16 @@
}
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", mParentUserId));
@@ -414,7 +428,6 @@
"testManagedProfileDuplicatedPhoneEmailContact_insertedAndfound",
mProfileUserId));
-
// Set cross profile caller id to enabled
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testSetCrossProfileCallerIdDisabled_false", mProfileUserId));
@@ -517,6 +530,11 @@
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"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",
@@ -525,12 +543,72 @@
assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testManagedProfileEnterprisePhoneLookupDuplicated_canAccessEnterpriseContact",
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));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+ "testQuickContact", mParentUserId));
} finally {
// Clean up in managed profile and primary profile
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testCurrentProfileContacts_removeContacts", mProfileUserId);
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
"testCurrentProfileContacts_removeContacts", mParentUserId);
+ getDevice().uninstallPackage(DIRECTORY_PROVIDER_PKG);
}
}
@@ -635,6 +713,16 @@
}
}
+ 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
diff --git a/hostsidetests/sample/AndroidTest.xml b/hostsidetests/sample/AndroidTest.xml
index bb1c146..5f5d23d 100644
--- a/hostsidetests/sample/AndroidTest.xml
+++ b/hostsidetests/sample/AndroidTest.xml
@@ -21,9 +21,4 @@
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsSampleHostTestCases.jar" />
</test>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="host" />
- <option name="module-name" value="CtsSampleHostTestCases"/>
- <option name="version-name" value="1.0"/>
- </target_preparer>
</configuration>
diff --git a/hostsidetests/sample/DynamicConfig.xml b/hostsidetests/sample/DynamicConfig.xml
deleted file mode 100644
index 18c07ef..0000000
--- a/hostsidetests/sample/DynamicConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<DynamicConfig>
- <Config key ="local-config">local-config-val</Config>
-</DynamicConfig>
diff --git a/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java b/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java
index df86444..f276712 100644
--- a/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java
+++ b/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java
@@ -16,7 +16,6 @@
package android.sample.cts;
-import com.android.compatibility.common.util.DynamicConfigHostSide;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -53,24 +52,6 @@
private static final String TEST_STRING = "SampleTestString";
/**
- * Test if dynamic config on the host side works
- * @throws Exception
- */
- public void testDynamicConfigLocal() throws Exception {
- DynamicConfigHostSide config = new DynamicConfigHostSide("CtsSampleHostTestCases");
- assertEquals("local-config-val", config.getConfig("local-config"));
- }
-
- /**
- * Test if dynamic config override on the host side works
- * @throws Exception
- */
- public void testDynamicConfigOverride() throws Exception {
- DynamicConfigHostSide config = new DynamicConfigHostSide("CtsSampleHostTestCases");
- assertEquals("host-1.0-cts-keyone", config.getConfig("sample_host_key_one"));
- }
-
- /**
* Tests the string was successfully logged to Logcat from the activity.
*
* @throws Exception
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 022e2f4..3163100 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -724,7 +724,7 @@
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}+)$",
+ "^([\\w_:]+)\\s+([\\w_]+)\\s+(\\d+)\\s+(\\d+)\\s+(\\p{Graph}+)\\s*$",
Pattern.MULTILINE);
Matcher m = p.matcher(psOutString);
procMap = new HashMap<String, ArrayList<ProcessDetails>>();
diff --git a/hostsidetests/services/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
index 32dba48..09dc4d8 100755
--- a/hostsidetests/services/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
@@ -16,22 +16,65 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.server.app">
+ 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
index 31c169e..388c9a6 100644
--- a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchToSideActivity.java
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchToSideActivity.java
@@ -9,14 +9,12 @@
import android.util.Log;
public class LaunchToSideActivity extends Activity {
- private static final String TAG = "LaunchToSide";
-
@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("android.settings.SETTINGS");
+ 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
index 8a89deb..b750389 100644
--- a/hostsidetests/services/activitymanager/app/src/android/server/app/PipActivity.java
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/PipActivity.java
@@ -19,9 +19,4 @@
import android.app.Activity;
public class PipActivity extends Activity {
- @Override
- protected void onResume() {
- super.onResume();
- enterPictureInPictureMode();
- }
}
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/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..785e487d
--- /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/ActivityManagerTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTests.java
deleted file mode 100644
index aed23d8..0000000
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTests.java
+++ /dev/null
@@ -1,207 +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.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;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.DeviceTestCase;
-
-import java.util.HashSet;
-
-public class ActivityManagerTests extends DeviceTestCase {
-
- // 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 STACK_ID_PREFIX = "Stack id=";
- private static final String TASK_ID_PREFIX = "taskId";
-
- private static final String TEST_ACTIVITY_NAME = "TestActivity";
- private static final String LAUNCH_TO_SIDE_ACTIVITY_NAME = "LaunchToSideActivity";
- private static final String PIP_ACTIVITY_NAME = "PipActivity";
-
- private static final String AM_STACK_LIST = "am stack list";
- private static final String AM_START_TEST_ACTIVITY =
- "am start -n android.server.app/." + TEST_ACTIVITY_NAME;
- private static final String AM_START_LAUNCH_TO_SIDE_ACTIVITY =
- "am start -n android.server.app/." + LAUNCH_TO_SIDE_ACTIVITY_NAME;
- private static final String AM_START_PIP_ACTIVITY =
- "am start -n android.server.app/." + PIP_ACTIVITY_NAME;
- private static final String AM_FORCE_STOP_TEST = "am force-stop android.server.app";
- private static final String AM_FORCE_STOP_SETTINGS = "com.android.settings";
- private static final String AM_MOVE_TASK = "am stack movetask ";
-
- /** A reference to the device under test. */
- private ITestDevice mDevice;
-
- private HashSet<String> mAvailableFeatures;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- // Get the device, this gives a handle to run commands and install APKs.
- mDevice = getDevice();
- }
-
- @Override
- protected void tearDown() {
- try {
- mDevice.executeShellCommand(AM_FORCE_STOP_TEST);
- mDevice.executeShellCommand(AM_FORCE_STOP_SETTINGS);
- } catch (DeviceNotAvailableException e) {
- }
- }
-
- public void testStackList() throws Exception {
- mDevice.executeShellCommand(AM_START_TEST_ACTIVITY);
- HashSet<Integer> stacks = collectStacks();
- assertTrue("At least two stacks expected, home and fullscreen.", stacks.size() >= 2);
- assertTrue("Stacks must contain home stack.", stacks.contains(HOME_STACK_ID));
- assertTrue("Stacks must contain fullscreen stack.", stacks.contains(
- FULLSCREEN_WORKSPACE_STACK_ID));
- }
-
- // Utility method for debugging, not used directly here, but useful, so kept around.
- private 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);
- }
- }
-
- private 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;
- }
-
- public void testDockActivity() throws Exception {
- mDevice.executeShellCommand(AM_START_TEST_ACTIVITY);
- final int taskId = getActivityTaskId(TEST_ACTIVITY_NAME);
- final String cmd = AM_MOVE_TASK + taskId + " " + DOCKED_STACK_ID + " true";
- mDevice.executeShellCommand(cmd);
- HashSet<Integer> stacks = collectStacks();
- assertTrue("At least two stacks expected, home and docked.", stacks.size() >= 2);
- assertTrue("Stacks must contain home stack.", stacks.contains(HOME_STACK_ID));
- assertTrue("Stacks must contain docked stack.", stacks.contains(DOCKED_STACK_ID));
- }
-
- public void testLaunchToSide() throws Exception {
- mDevice.executeShellCommand(AM_START_LAUNCH_TO_SIDE_ACTIVITY);
- final int taskId = getActivityTaskId(LAUNCH_TO_SIDE_ACTIVITY_NAME);
- final String cmd = AM_MOVE_TASK + taskId + " " + DOCKED_STACK_ID + " true";
- mDevice.executeShellCommand(cmd);
- printStacksAndTasks();
- mDevice.executeShellCommand(AM_START_LAUNCH_TO_SIDE_ACTIVITY
- + " -f 0x20000000 --ez launch_to_the_side true");
- HashSet<Integer> stacks = collectStacks();
- assertTrue("At least two stacks expected, docked and fullscreen.", stacks.size() >= 2);
- assertTrue("Stacks must contain fullscreen stack.", stacks.contains(
- FULLSCREEN_WORKSPACE_STACK_ID));
- assertTrue("Stacks must contain docked stack.", stacks.contains(DOCKED_STACK_ID));
- }
-
- public void testEnterPictureInPictureMode() throws Exception {
- final boolean supportsPip = hasDeviceFeature("android.software.picture_in_picture");
- mDevice.executeShellCommand(AM_START_PIP_ACTIVITY);
- final HashSet<Integer> stacks = collectStacks();
- final boolean containsPinnedStack = stacks.contains(PINNED_STACK_ID);
- if (supportsPip) {
- assertTrue("Stacks must contain pinned stack.", containsPinnedStack);
- } else {
- assertFalse("Stacks must not contain pinned stack.", containsPinnedStack);
- }
- }
-
- private HashSet<Integer> collectStacks() throws DeviceNotAvailableException {
- final CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
- mDevice.executeShellCommand(AM_STACK_LIST, outputReceiver);
- final String output = outputReceiver.getOutput();
- HashSet<Integer> stacks = new HashSet<>();
- for (String line : output.split("\\n")) {
- CLog.logAndDisplay(LogLevel.INFO, line);
- if (line.startsWith(STACK_ID_PREFIX)) {
- final String sub = line.substring(STACK_ID_PREFIX.length());
- final int index = sub.indexOf(" ");
- final int currentStack = Integer.parseInt(sub.substring(0, index));
- stacks.add(currentStack);
- }
- }
- return stacks;
- }
-
- private boolean hasDeviceFeature(String requiredFeature) throws DeviceNotAvailableException {
- if (mAvailableFeatures == null) {
- // TODO: Move this logic to ITestDevice.
- String command = "pm list features";
- String commandOutput = mDevice.executeShellCommand(command);
- CLog.i("Output for command " + command + ": " + commandOutput);
-
- // Extract the id of the new user.
- mAvailableFeatures = new HashSet<>();
- for (String feature: commandOutput.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 have required feature "
- + requiredFeature + ". Test won't run.");
- }
- return result;
- }
-}
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/libs/deviceutil/jni/Android.mk b/libs/deviceutil/jni/Android.mk
index b801a4d..e413250 100644
--- a/libs/deviceutil/jni/Android.mk
+++ b/libs/deviceutil/jni/Android.mk
@@ -27,6 +27,7 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog libdl
+LOCAL_SHARED_LIBRARIES := libnativehelper_compat_libc++ liblog libdl
+LOCAL_SDK_VERSION := 19
-include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java b/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
index 2933b0b..b9ee987 100644
--- a/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
+++ b/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
@@ -807,6 +807,17 @@
});
}
+ public void setLayoutToMatchParent() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ setMatchParent((View) mWebView.getParent());
+ setMatchParent(mWebView);
+ mWebView.requestLayout();
+ }
+ });
+ }
+
public void setAcceptThirdPartyCookies(final boolean accept) {
runOnUiThread(new Runnable() {
@Override
@@ -978,6 +989,18 @@
}
/**
+ * Set LayoutParams to MATCH_PARENT.
+ *
+ * @param view Target view
+ */
+ private void setMatchParent(View view) {
+ ViewGroup.LayoutParams params = view.getLayoutParams();
+ params.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ params.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ view.setLayoutParams(params);
+ }
+
+ /**
* A WebChromeClient used to capture the onProgressChanged for use
* in waitFor functions. If a test must override the WebChromeClient,
* it can derive from this class or call onProgressChanged
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
old mode 100644
new mode 100755
index 3a60fc0..3f27cd7
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
@@ -30,6 +30,7 @@
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;
@@ -729,6 +730,7 @@
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
@@ -783,6 +785,13 @@
}, 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();
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index c45bb2f..c64e977 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -320,6 +320,8 @@
</intent-filter>
</activity>
+ <activity android:name="android.app.stubs.KeyboardShortcutsActivity" />
+
</application>
</manifest>
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/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/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/DialogTest.java b/tests/app/src/android/app/cts/DialogTest.java
old mode 100644
new mode 100755
index 473835c..8ae4c66
--- a/tests/app/src/android/app/cts/DialogTest.java
+++ b/tests/app/src/android/app/cts/DialogTest.java
@@ -31,6 +31,7 @@
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;
@@ -380,7 +381,7 @@
long now = SystemClock.uptimeMillis();
MotionEvent touchMotionEvent = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
- 1, 100, 0);
+ 1, getStatusBarHeight(), 0);
mInstrumentation.sendPointerSync(touchMotionEvent);
new PollingCheck(TEST_TIMEOUT) {
@@ -403,7 +404,7 @@
d.setCanceledOnTouchOutside(true);
touchMotionEvent = MotionEvent.obtain(now, now + 1, MotionEvent.ACTION_DOWN,
- 1, 100, 0);
+ 1, getStatusBarHeight(), 0);
mInstrumentation.sendPointerSync(touchMotionEvent);
new PollingCheck(TEST_TIMEOUT) {
@@ -420,6 +421,13 @@
}
}
+ 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();
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 55ad392..21a227b 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.cts.util.PollingCheck;
import android.database.Cursor;
import android.net.Uri;
@@ -30,6 +31,7 @@
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.text.format.DateUtils;
+import android.util.Log;
import android.webkit.cts.CtsTestServer;
import java.io.File;
@@ -37,6 +39,7 @@
import java.util.HashSet;
public class DownloadManagerTest extends AndroidTestCase {
+ private static final String TAG = "DownloadManagerTest";
/**
* According to the CDD Section 7.6.1, the DownloadManager implementation must be able to
@@ -115,6 +118,11 @@
}
public void testDownloadManagerSupportsHttpWithExternalWebServer() throws Exception {
+ if (!hasInternetConnection()) {
+ Log.i(TAG, "testDownloadManagerSupportsHttpWithExternalWebServer() ignored on device without Internet");
+ return;
+ }
+
// As a result of testDownloadManagerSupportsHttpsWithExternalWebServer relying on an
// external resource https://www.example.com this test uses http://www.example.com to help
// disambiguate errors from testDownloadManagerSupportsHttpsWithExternalWebServer.
@@ -141,6 +149,11 @@
}
public void testDownloadManagerSupportsHttpsWithExternalWebServer() throws Exception {
+ if (!hasInternetConnection()) {
+ Log.i(TAG, "testDownloadManagerSupportsHttpsWithExternalWebServer() ignored on device without Internet");
+ return;
+ }
+
// For HTTPS, DownloadManager trusts only SSL server certs issued by CAs trusted by the
// system. Unfortunately, this means that it cannot trust the mock web server's SSL cert.
// Until this is resolved (e.g., by making it possible to specify additional CA certs to
@@ -459,4 +472,11 @@
}
}
}
+
+ private boolean hasInternetConnection() {
+ // TODO: expand this to include devices with ethernet
+ final PackageManager pm = getContext().getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
+ || pm.hasSystemFeature(PackageManager.FEATURE_WIFI);
+ }
}
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/app/src/android/app/cts/UiModeManagerTest.java b/tests/app/src/android/app/cts/UiModeManagerTest.java
index 71a6427..40fe0f5 100644
--- a/tests/app/src/android/app/cts/UiModeManagerTest.java
+++ b/tests/app/src/android/app/cts/UiModeManagerTest.java
@@ -26,53 +26,81 @@
private static final String TAG = "UiModeManagerTest";
private UiModeManager mUiModeManager;
- private boolean mIsAuto = false;
@Override
protected void setUp() throws Exception {
super.setUp();
mUiModeManager = (UiModeManager) getContext().getSystemService(Context.UI_MODE_SERVICE);
assertNotNull(mUiModeManager);
- mIsAuto = getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE);
}
- public void testCarMode() throws Exception {
- if (mIsAuto) {
- Log.i(TAG, "testCarMode automotive");
- doTestCarModeAutomotive();
+ 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, "testCarMode generic");
- doTestCarModeGeneric();
+ Log.i(TAG, "testUiMode generic");
+ doTestUiModeGeneric();
}
}
- private void doTestCarModeAutomotive() throws Exception {
+ 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();
- assertTrue(mUiModeManager.isNightModeLocked());
- doTestLockedNightMode();
}
- private void doTestCarModeGeneric() throws Exception {
+ private void doTestUiModeGeneric() throws Exception {
if (mUiModeManager.isUiModeLocked()) {
doTestLockedUiMode();
} else {
doTestUnlockedUiMode();
}
- if (mUiModeManager.isNightModeLocked()) {
- doTestLockedNightMode();
- } else {
- doTestUnlockedNightMode();
- }
}
private void doTestLockedUiMode() throws Exception {
+ int originalMode = mUiModeManager.getCurrentModeType();
mUiModeManager.enableCarMode(0);
- assertEquals(Configuration.UI_MODE_TYPE_CAR, mUiModeManager.getCurrentModeType());
+ assertEquals(originalMode, mUiModeManager.getCurrentModeType());
mUiModeManager.disableCarMode(0);
- assertEquals(Configuration.UI_MODE_TYPE_CAR, mUiModeManager.getCurrentModeType());
+ assertEquals(originalMode, mUiModeManager.getCurrentModeType());
}
private void doTestUnlockedUiMode() throws Exception {
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/core/ctscore.mk b/tests/core/ctscore.mk
index fea0b07..10a91f1 100644
--- a/tests/core/ctscore.mk
+++ b/tests/core/ctscore.mk
@@ -23,7 +23,10 @@
# Don't delete META-INF from the core-tests jar
LOCAL_DONT_DELETE_JAR_META_INF := true
-LOCAL_JNI_SHARED_LIBRARIES := libjavacoretests
+# TODO: Clean up this mess. (b/26483949). libnativehelper_compat_libc++ pulls in its own
+# static copy of libc++ and the libc++ we're bundling here is the platform libc++. This is
+# bround to break but is being submitted as a workaround for failing CTS tests.
+LOCAL_JNI_SHARED_LIBRARIES := libjavacoretests libsqlite_jni libnativehelper_compat_libc++ libc++
# Include both the 32 and 64 bit versions of libjavacoretests,
# where applicable.
diff --git a/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java
index 7656cbd..c68d448 100644
--- a/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java
@@ -20,6 +20,7 @@
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;
@@ -93,6 +94,7 @@
* <li>{@link InputMethodService#onDestroy()}</li>
* </ul>
*/
+ @MediumTest
public void testCreateAndDestroy() {
if (!getInstrumentation().getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_INPUT_METHODS)) {
diff --git a/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml b/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml
index 013821e..c87b800 100644
--- a/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml
+++ b/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml
@@ -19,6 +19,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.netsecpolicy.usescleartext.false.cts">
<uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-library android:name="org.apache.http.legacy"/>
+
<application android:usesCleartextTraffic="false">
</application>
</manifest>
diff --git a/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml b/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml
index f50295e..da15ddd 100644
--- a/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml
+++ b/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml
@@ -19,6 +19,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.netsecpolicy.usescleartext.true.cts">
<uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-library android:name="org.apache.http.legacy"/>
<application android:usesCleartextTraffic="true">
diff --git a/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml b/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml
index 7e735c7..5b3a181 100644
--- a/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml
+++ b/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml
@@ -18,7 +18,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.netsecpolicy.usescleartext.unspecified.cts">
- <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-library android:name="org.apache.http.legacy"/>
+
<application>
</application>
</manifest>
diff --git a/tests/sample/AndroidTest.xml b/tests/sample/AndroidTest.xml
index 62b0d67..ae790fb 100644
--- a/tests/sample/AndroidTest.xml
+++ b/tests/sample/AndroidTest.xml
@@ -21,9 +21,4 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.sample.cts" />
</test>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="module-name" value="CtsSampleDeviceTestCases"/>
- <option name="version-name" value="1.0"/>
- </target_preparer>
</configuration>
diff --git a/tests/sample/DynamicConfig.xml b/tests/sample/DynamicConfig.xml
deleted file mode 100644
index 18c07ef..0000000
--- a/tests/sample/DynamicConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<DynamicConfig>
- <Config key ="local-config">local-config-val</Config>
-</DynamicConfig>
diff --git a/tests/sample/src/android/sample/cts/SampleDeviceTest.java b/tests/sample/src/android/sample/cts/SampleDeviceTest.java
index f51d227..13b7ea6 100644
--- a/tests/sample/src/android/sample/cts/SampleDeviceTest.java
+++ b/tests/sample/src/android/sample/cts/SampleDeviceTest.java
@@ -18,8 +18,6 @@
import android.sample.SampleDeviceActivity;
import android.test.ActivityInstrumentationTestCase2;
-import com.android.compatibility.common.util.DynamicConfigDeviceSide;
-
/**
* A simple compatibility test which tests the SharedPreferences API.
*
@@ -75,23 +73,4 @@
mActivity.clearPreferences();
assertNull("Preferences were not cleared", mActivity.getPreference(KEY));
}
-
- /**
- * Test if Dynamic Config on the device side works
- * @throws Exception
- */
- public void testDynamicConfigLocal() throws Exception {
- DynamicConfigDeviceSide config = new DynamicConfigDeviceSide("CtsSampleDeviceTestCases");
- assertEquals("local-config-val", config.getConfig("local-config"));
- }
-
- /**
- * Test if Dynamic Config override on the device side works
- * @throws Exception
- */
- public void testDynamicConfigOverride() throws Exception {
- DynamicConfigDeviceSide config = new DynamicConfigDeviceSide("CtsSampleDeviceTestCases");
- assertEquals("device-1.0-cts-keyone", config.getConfig("sample_device_key_one"));
-
- }
}
diff --git a/tests/tests/accounts/AndroidManifest.xml b/tests/tests/accounts/AndroidManifest.xml
index 0d4a534..d882690 100644
--- a/tests/tests/accounts/AndroidManifest.xml
+++ b/tests/tests/accounts/AndroidManifest.xml
@@ -36,8 +36,6 @@
<activity android:name="android.accounts.cts.AccountRemovalDummyActivity" >
</activity>
- <activity android:name="android.accounts.cts.AccountAuthenticatorDummyActivity" />
-
<service android:name="MockAccountService" android:exported="true"
android:process="android.accounts.cts">
<intent-filter>
diff --git a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/AndroidManifest.xml b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/AndroidManifest.xml
index 3708d83..c32f89f 100644
--- a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/AndroidManifest.xml
+++ b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/AndroidManifest.xml
@@ -41,15 +41,15 @@
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/standard_authenticator" />
</service>
-
- <service android:name=".CustomAccountAuthService"
- android:exported="false">
+<!--
+ <service android:name=".CustomAccountAuthService" android:exported="false">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/custom_authenticator" />
</service>
+ -->
</application>
</manifest>
diff --git a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/res/xml/custom_authenticator.xml b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/res/xml/custom_authenticator.xml
index 35b557a..3485f76 100644
--- a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/res/xml/custom_authenticator.xml
+++ b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/res/xml/custom_authenticator.xml
@@ -21,7 +21,7 @@
<!-- for the Account Manager. -->
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
- android:accountType="android.accounts.test.custom.unaffiliated"
+ android:accountType="android.accounts.test.custom"
android:icon="@drawable/ic_cts_selected_custom_account"
android:smallIcon="@drawable/ic_cts_minitab_selected_custom_account"
android:customTokens="true"
diff --git a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/src/android/accounts/cts/unaffiliated/CustomAccountAuthService.java b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/src/android/accounts/cts/unaffiliated/CustomAccountAuthService.java
deleted file mode 100644
index 0d32e2f..0000000
--- a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/src/android/accounts/cts/unaffiliated/CustomAccountAuthService.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package android.accounts.cts.unaffiliated;
-
-import android.accounts.cts.common.Fixtures;
-import android.accounts.cts.common.CustomTestAccountAuthenticator;
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-/**
- * a basic Mock Service for wrapping the CustomAccountAuthenticator.
- */
-public class CustomAccountAuthService extends Service {
-
- @Override
- public IBinder onBind(Intent intent) {
- CustomTestAccountAuthenticator auth = new CustomTestAccountAuthenticator(this,
- Fixtures.TYPE_CUSTOM_UNAFFILIATED);
- return auth.getIBinder();
- }
-}
-
diff --git a/tests/tests/accounts/common/src/android/accounts/cts/common/CustomTestAccountAuthenticator.java b/tests/tests/accounts/common/src/android/accounts/cts/common/CustomTestAccountAuthenticator.java
deleted file mode 100644
index 48726a5..0000000
--- a/tests/tests/accounts/common/src/android/accounts/cts/common/CustomTestAccountAuthenticator.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package android.accounts.cts.common;
-
-import android.accounts.Account;
-import android.accounts.AccountAuthenticatorResponse;
-import android.accounts.AccountManager;
-import android.accounts.NetworkErrorException;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Subclass of {@link TestAccountAuthenticator} with startAddAccountSession(...)
- * and startUpdateCredentialsSession(...) overridden but not finishSession(...)..
- */
-public class CustomTestAccountAuthenticator extends TestAccountAuthenticator {
-
- private final AtomicInteger mTokenCounter = new AtomicInteger(0);
- private final String mAccountType;
- private final Context mContext;
-
- /**
- * @param context
- * @param accountType
- */
- public CustomTestAccountAuthenticator(Context context, String accountType) {
- super(context, accountType);
- mAccountType = accountType;
- mContext = context;
- }
-
- /**
- * Starts add account flow of the specified accountType to authenticate user.
- */
- @Override
- public Bundle startAddAccountSession(
- AccountAuthenticatorResponse response,
- String accountType,
- String authTokenType,
- String[] requiredFeatures,
- Bundle options) throws NetworkErrorException {
-
- if (!mAccountType.equals(accountType)) {
- throw new IllegalArgumentException("Request to the wrong authenticator!");
- }
-
- String accountName = null;
- boolean isCallbackRequired = false;
- Bundle sessionBundle = null;
- if (options != null) {
- accountName = options.getString(Fixtures.KEY_ACCOUNT_NAME);
- isCallbackRequired = options.getBoolean(Fixtures.KEY_CALLBACK_REQUIRED, false);
- sessionBundle = options.getBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE);
- }
-
- Bundle result = new Bundle();
- String statusToken = Fixtures.PREFIX_STATUS_TOKEN + accountName;
- String password = Fixtures.PREFIX_PASSWORD + accountName;
- if (accountName.startsWith(Fixtures.PREFIX_NAME_SUCCESS)) {
- // fill bundle with a success result.
- result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- result.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN, statusToken);
- result.putString(AccountManager.KEY_PASSWORD, password);
- result.putString(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
- } else if (accountName.startsWith(Fixtures.PREFIX_NAME_INTERVENE)) {
- // Specify data to be returned by the eventual activity.
- Intent eventualActivityResultData = new Intent();
- eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
- statusToken);
- eventualActivityResultData.putExtra(AccountManager.KEY_PASSWORD, password);
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE,
- sessionBundle);
- // Fill result with Intent.
- Intent intent = new Intent(mContext, TestAuthenticatorActivity.class);
- intent.putExtra(Fixtures.KEY_RESULT, eventualActivityResultData);
- intent.putExtra(Fixtures.KEY_CALLBACK, response);
-
- result.putParcelable(AccountManager.KEY_INTENT, intent);
- } else {
- // fill with error
- int errorCode = AccountManager.ERROR_CODE_INVALID_RESPONSE;
- String errorMsg = "Default Error Message";
- if (options != null) {
- errorCode = options.getInt(AccountManager.KEY_ERROR_CODE);
- errorMsg = options.getString(AccountManager.KEY_ERROR_MESSAGE);
- }
- result.putInt(AccountManager.KEY_ERROR_CODE, errorCode);
- result.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
- }
-
- try {
- return (isCallbackRequired) ? null : result;
- } finally {
- if (isCallbackRequired) {
- response.onResult(result);
- }
- }
- }
-
- /**
- * Prompts user to re-authenticate to a specific account but defers updating local credentials.
- */
- @Override
- public Bundle startUpdateCredentialsSession(
- AccountAuthenticatorResponse response,
- Account account,
- String authTokenType,
- Bundle options) throws NetworkErrorException {
-
- if (!mAccountType.equals(account.type)) {
- throw new IllegalArgumentException("Request to the wrong authenticator!");
- }
-
- String accountName = null;
- boolean isCallbackRequired = false;
- Bundle sessionBundle = null;
- if (options != null) {
- accountName = options.getString(Fixtures.KEY_ACCOUNT_NAME);
- isCallbackRequired = options.getBoolean(Fixtures.KEY_CALLBACK_REQUIRED, false);
- sessionBundle = options.getBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE);
- }
-
- Bundle result = new Bundle();
- String statusToken = Fixtures.PREFIX_STATUS_TOKEN + accountName;
- String password = Fixtures.PREFIX_PASSWORD + accountName;
- if (accountName.startsWith(Fixtures.PREFIX_NAME_SUCCESS)) {
- // fill bundle with a success result.
- result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- result.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN, statusToken);
- result.putString(AccountManager.KEY_PASSWORD, password);
- result.putString(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
- } else if (accountName.startsWith(Fixtures.PREFIX_NAME_INTERVENE)) {
- // Specify data to be returned by the eventual activity.
- Intent eventualActivityResultData = new Intent();
- eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
- statusToken);
- eventualActivityResultData.putExtra(AccountManager.KEY_PASSWORD, password);
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE,
- sessionBundle);
- // Fill result with Intent.
- Intent intent = new Intent(mContext, TestAuthenticatorActivity.class);
- intent.putExtra(Fixtures.KEY_RESULT, eventualActivityResultData);
- intent.putExtra(Fixtures.KEY_CALLBACK, response);
-
- result.putParcelable(AccountManager.KEY_INTENT, intent);
- } else {
- // fill with error
- int errorCode = AccountManager.ERROR_CODE_INVALID_RESPONSE;
- String errorMsg = "Default Error Message";
- if (options != null) {
- errorCode = options.getInt(AccountManager.KEY_ERROR_CODE);
- errorMsg = options.getString(AccountManager.KEY_ERROR_MESSAGE);
- }
- result.putInt(AccountManager.KEY_ERROR_CODE, errorCode);
- result.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
- }
-
- try {
- return (isCallbackRequired) ? null : result;
- } finally {
- if (isCallbackRequired) {
- response.onResult(result);
- }
- }
- }
-
-}
diff --git a/tests/tests/accounts/common/src/android/accounts/cts/common/Fixtures.java b/tests/tests/accounts/common/src/android/accounts/cts/common/Fixtures.java
index b969caa..f8636a0 100644
--- a/tests/tests/accounts/common/src/android/accounts/cts/common/Fixtures.java
+++ b/tests/tests/accounts/common/src/android/accounts/cts/common/Fixtures.java
@@ -31,12 +31,9 @@
public static final String TYPE_STANDARD_UNAFFILIATED =
"android.accounts.test.standard.unaffiliated";
- public static final String TYPE_CUSTOM_UNAFFILIATED =
- "android.accounts.test.custom.unaffiliated";
public static final String PREFIX_TOKEN = "token:";
public static final String PREFIX_PASSWORD = "password:";
- public static final String PREFIX_STATUS_TOKEN = "status_token:";
public static final String SUFFIX_NAME_FIXTURE = "fixture.com";
public static final String SUFFIX_NAME_TEST = "test.com";
@@ -55,10 +52,6 @@
PREFIX_NAME_SUCCESS + "@" + SUFFIX_NAME_FIXTURE,
TYPE_STANDARD_UNAFFILIATED);
- public static final Account ACCOUNT_CUSTOM_UNAFFILIATED_FIXTURE_SUCCESS = new Account(
- PREFIX_NAME_SUCCESS + "@" + SUFFIX_NAME_FIXTURE,
- TYPE_CUSTOM_UNAFFILIATED);
-
public static List<String> getFixtureAccountNames() {
List<String> accountNames = new ArrayList<>(accountNamePrefixes.length);
for (String prefix : accountNamePrefixes) {
@@ -77,7 +70,5 @@
public static final String KEY_RESULT = "test:result";
public static final String KEY_TOKEN_EXPIRY = "test:token_duration";
- public static final String KEY_ACCOUNT_SESSION_BUNDLE = "test:account_session_bundle";
-
private Fixtures() {}
}
diff --git a/tests/tests/accounts/common/src/android/accounts/cts/common/tx/StartAddAccountSessionTx.aidl b/tests/tests/accounts/common/src/android/accounts/cts/common/tx/StartAddAccountSessionTx.aidl
deleted file mode 100644
index 4819ebb..0000000
--- a/tests/tests/accounts/common/src/android/accounts/cts/common/tx/StartAddAccountSessionTx.aidl
+++ /dev/null
@@ -1,3 +0,0 @@
-package android.accounts.cts.common.tx;
-
-parcelable StartAddAccountSessionTx;
diff --git a/tests/tests/accounts/common/src/android/accounts/cts/common/tx/StartAddAccountSessionTx.java b/tests/tests/accounts/common/src/android/accounts/cts/common/tx/StartAddAccountSessionTx.java
deleted file mode 100644
index 12a11ff..0000000
--- a/tests/tests/accounts/common/src/android/accounts/cts/common/tx/StartAddAccountSessionTx.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package android.accounts.cts.common.tx;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class StartAddAccountSessionTx implements Parcelable {
-
- public static final Parcelable.Creator<StartAddAccountSessionTx> CREATOR = new Parcelable.Creator<StartAddAccountSessionTx>() {
-
- @Override
- public StartAddAccountSessionTx createFromParcel(Parcel in) {
- return new StartAddAccountSessionTx(in);
- }
-
- @Override
- public StartAddAccountSessionTx[] newArray(int size) {
- return new StartAddAccountSessionTx[size];
- }
- };
-
- public final String accountType;
- public final String authTokenType;
- public final List<String> requiredFeatures = new ArrayList<>();
- public final Bundle options;
- public final Bundle result;
-
- private StartAddAccountSessionTx(Parcel in) {
- accountType = in.readString();
- authTokenType = in.readString();
- in.readStringList(requiredFeatures);
- options = in.readBundle();
- result = in.readBundle();
- }
-
- public StartAddAccountSessionTx(String accountType, String authTokenType, String[] requiredFeatures,
- Bundle options, Bundle result) {
- this.accountType = accountType;
- this.authTokenType = authTokenType;
- if (requiredFeatures != null) {
- for (String feature : requiredFeatures) {
- this.requiredFeatures.add(feature);
- }
- }
- this.options = options;
- this.result = result;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(accountType);
- out.writeString(authTokenType);
- out.writeStringList(requiredFeatures);
- out.writeBundle(options);
- out.writeBundle(result);
- }
-}
diff --git a/tests/tests/accounts/src/android/accounts/cts/AccountAuthenticatorDummyActivity.java b/tests/tests/accounts/src/android/accounts/cts/AccountAuthenticatorDummyActivity.java
deleted file mode 100644
index 76276b2..0000000
--- a/tests/tests/accounts/src/android/accounts/cts/AccountAuthenticatorDummyActivity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package android.accounts.cts;
-
-import android.accounts.AccountAuthenticatorResponse;
-import android.accounts.cts.common.Fixtures;
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-
-/**
- * TODO: Insert description here. (generated by sandrakwan)
- */
-public class AccountAuthenticatorDummyActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- Intent intent = getIntent();
- AccountAuthenticatorResponse response = intent.getParcelableExtra(Fixtures.KEY_CALLBACK);
- Intent result = intent.getParcelableExtra(Fixtures.KEY_RESULT);
- if (response != null) {
- response.onResult(result.getExtras());
- }
- setResult(RESULT_OK, result);
- finish();
- }
-}
\ No newline at end of file
diff --git a/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java b/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
index 7d7906d..4350191 100644
--- a/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
+++ b/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
@@ -24,10 +24,8 @@
import android.accounts.AuthenticatorException;
import android.accounts.OnAccountsUpdateListener;
import android.accounts.OperationCanceledException;
-import android.accounts.cts.common.Fixtures;
import android.app.Activity;
import android.content.Context;
-import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -62,8 +60,6 @@
public static final String ACCOUNT_PASSWORD = "android.accounts.cts.account.password";
- public static final String ACCOUNT_STATUS_TOKEN = "android.accounts.cts.account.status.token";
-
public static final String AUTH_TOKEN_TYPE = "mockAuthTokenType";
public static final String AUTH_EXPIRING_TOKEN_TYPE = "mockAuthExpiringTokenType";
public static final String AUTH_TOKEN_LABEL = "mockAuthTokenLabel";
@@ -98,29 +94,6 @@
public static final Account CUSTOM_TOKEN_ACCOUNT =
new Account(ACCOUNT_NAME,ACCOUNT_TYPE_CUSTOM);
- public static final String SESSION_DATA_NAME_1 = "session.data.name.1";
- public static final String SESSION_DATA_NAME_2 = "session.data.name.2";
- public static final String SESSION_DATA_NAME_3 = "session.data.name.3";
- public static final String SESSION_DATA_VALUE_1 = "session.data.value.1";
- public static final int SESSION_DATA_VALUE_2 = 364;
-
- public static Bundle getSessionBundle(String accountName) {
- Bundle bundle = new Bundle();
- bundle.putString(SESSION_DATA_NAME_1, SESSION_DATA_VALUE_1);
- bundle.putInt(SESSION_DATA_NAME_2, SESSION_DATA_VALUE_2);
- // Test null value in Bundle.
- bundle.putParcelable(SESSION_DATA_NAME_3, null);
- bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
- bundle.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- bundle.putAll(OPTIONS_BUNDLE);
- return bundle;
- }
-
- public static final String ERROR_MESSAGE = "android.accounts.cts.account.error.message";
-
- public static final String KEY_CIPHER = "cipher";
- public static final String KEY_MAC = "mac";
-
private static MockAccountAuthenticator mockAuthenticator;
private static final int LATCH_TIMEOUT_MS = 500;
private static AccountManager am;
@@ -1994,2052 +1967,4 @@
}
}
- /**
- * Tests a basic startAddAccountSession() which returns a bundle containing
- * encrypted session bundle, account password and status token.
- */
- public void testStartAddAccountSession()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- validateAccountAndAuthTokenType();
- validateFeatures();
-
- validateOptions(options, mockAuthenticator.mOptionsStartAddAccountSession);
- assertNotNull(mockAuthenticator.mOptionsStartAddAccountSession);
- assertEquals(accountName, mockAuthenticator.mOptionsStartAddAccountSession
- .getString(Fixtures.KEY_ACCOUNT_NAME));
-
- validateSystemOptions(mockAuthenticator.mOptionsStartAddAccountSession);
- validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
- validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
- validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
- validateOptions(null, mockAuthenticator.mOptionsAddAccount);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- }
-
- /**
- * Tests startAddAccountSession() with null session bundle. Only account
- * password and status token should be included in the result as session
- * bundle is not inspected.
- */
- public void testStartAddAccountSessionWithNullSessionBundle()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- validateAccountAndAuthTokenType();
- validateFeatures();
-
- validateOptions(options, mockAuthenticator.mOptionsStartAddAccountSession);
- assertNotNull(mockAuthenticator.mOptionsStartAddAccountSession);
- assertEquals(accountName, mockAuthenticator.mOptionsStartAddAccountSession
- .getString(Fixtures.KEY_ACCOUNT_NAME));
-
- validateSystemOptions(mockAuthenticator.mOptionsStartAddAccountSession);
- validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
- validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
- validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
- validateOptions(null, mockAuthenticator.mOptionsAddAccount);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- assertNull(resultBundle.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
- assertEquals(ACCOUNT_PASSWORD, resultBundle.getString(AccountManager.KEY_PASSWORD));
- assertEquals(ACCOUNT_STATUS_TOKEN,
- resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
- }
-
- /**
- * Tests startAddAccountSession() with empty session bundle. An encrypted
- * session bundle, account password and status token should be included in
- * the result as session bundle is not inspected.
- */
- public void testStartAddAccountSessionWithEmptySessionBundle()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, new Bundle());
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- validateAccountAndAuthTokenType();
- validateFeatures();
-
- validateOptions(options, mockAuthenticator.mOptionsStartAddAccountSession);
- assertNotNull(mockAuthenticator.mOptionsStartAddAccountSession);
- assertEquals(accountName, mockAuthenticator.mOptionsStartAddAccountSession
- .getString(Fixtures.KEY_ACCOUNT_NAME));
-
- validateSystemOptions(mockAuthenticator.mOptionsStartAddAccountSession);
- validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
- validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
- validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
- validateOptions(null, mockAuthenticator.mOptionsAddAccount);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- }
-
- /**
- * Tests startAddAccountSession with authenticator activity started. When
- * Activity is provided, AccountManager would start the resolution Intent
- * and return the final result which contains an encrypted session bundle,
- * account password and status token.
- */
- public void testStartAddAccountSessionIntervene()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- mActivity,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- validateAccountAndAuthTokenType();
- validateFeatures();
-
- validateStartAddAccountSessionOptions(accountName, options);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- }
-
- /**
- * Tests startAddAccountSession with KEY_INTENT returned but not started
- * automatically. When no Activity is provided and authenticator requires
- * additional data from user, KEY_INTENT will be returned by AccountManager.
- */
- public void testStartAddAccountSessionWithReturnIntent()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- validateAccountAndAuthTokenType();
- validateFeatures();
-
- validateStartAddAccountSessionOptions(accountName, options);
-
- // Assert returned result
- Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
- // Assert that KEY_INTENT is returned.
- assertNotNull(returnIntent);
- assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
- // Assert that no other data is returned.
- assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
- assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
- assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- }
-
- /**
- * Tests startAddAccountSession error case. AuthenticatorException is
- * expected when authenticator return
- * {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
- */
- public void testStartAddAccountSessionError() throws IOException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_ERROR + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE);
- options.putString(AccountManager.KEY_ERROR_MESSAGE, ERROR_MESSAGE);
- options.putAll(OPTIONS_BUNDLE);
-
- try {
- startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
- fail("startAddAccountSession should throw AuthenticatorException in error case.");
- } catch (AuthenticatorException e) {
- }
- }
-
- /**
- * Tests startAddAccountSession() with callback and handler. An encrypted
- * session bundle, account password and status token should be included in
- * the result. Callback should be triggered with the result regardless of a
- * handler is provider or not.
- */
- public void testStartAddAccountSessionWithCallbackAndHandler()
- throws IOException, AuthenticatorException, OperationCanceledException {
- testStartAddAccountSessionWithCallbackAndHandler(null /* handler */);
- testStartAddAccountSessionWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Tests startAddAccountSession() with callback and handler and activity
- * started. When Activity is provided, AccountManager would start the
- * resolution Intent and return the final result which contains an encrypted
- * session bundle, account password and status token. Callback should be
- * triggered with the result regardless of a handler is provider or not.
- */
- public void testStartAddAccountSessionWithCallbackAndHandlerWithIntervene()
- throws IOException, AuthenticatorException, OperationCanceledException {
- testStartAddAccountSessionWithCallbackAndHandlerWithIntervene(null /* handler */);
- testStartAddAccountSessionWithCallbackAndHandlerWithIntervene(
- new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Tests startAddAccountSession() with callback and handler with KEY_INTENT
- * returned. When no Activity is provided and authenticator requires
- * additional data from user, KEY_INTENT will be returned by AccountManager
- * in callback regardless of a handler is provider or not.
- */
- public void testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent()
- throws IOException, AuthenticatorException, OperationCanceledException {
- testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent(null /* handler */);
- testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent(
- new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Tests startAddAccountSession() error case with callback and handler.
- * AuthenticatorException is expected when authenticator return
- * {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
- */
- public void testStartAddAccountSessionErrorWithCallbackAndHandler()
- throws IOException, OperationCanceledException {
- testStartAddAccountSessionErrorWithCallbackAndHandler(null /* handler */);
- testStartAddAccountSessionErrorWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
- }
-
- private void testStartAddAccountSessionWithCallbackAndHandler(Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
- final Bundle options = new Bundle();
- final String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- Bundle resultBundle = null;
- try {
- resultBundle = bundleFuture.getResult();
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- fail("should not throw an AuthenticatorException");
- }
-
- // Assert parameters has been passed correctly
- validateAccountAndAuthTokenType();
- validateFeatures();
-
- validateStartAddAccountSessionOptions(accountName, options);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
-
- latch.countDown();
- }
- };
-
- startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- mActivity,
- callback,
- handler);
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private void testStartAddAccountSessionWithCallbackAndHandlerWithIntervene(Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
- final Bundle options = new Bundle();
- final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- Bundle resultBundle = null;
- try {
- resultBundle = bundleFuture.getResult();
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- fail("should not throw an AuthenticatorException");
- }
-
- // Assert parameters has been passed correctly
- validateAccountAndAuthTokenType();
- validateFeatures();
-
- validateStartAddAccountSessionOptions(accountName, options);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
-
- latch.countDown();
- }
- };
-
- startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- mActivity,
- callback,
- handler);
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private void testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent(Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
- final Bundle options = new Bundle();
- final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- Bundle resultBundle = null;
- try {
- resultBundle = bundleFuture.getResult();
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- fail("should not throw an AuthenticatorException");
- }
-
- // Assert parameters has been passed correctly
- validateAccountAndAuthTokenType();
- validateFeatures();
-
- validateStartAddAccountSessionOptions(accountName, options);
-
- // Assert returned result
- Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
- // Assert KEY_INTENT is returned.
- assertNotNull(returnIntent);
- assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
- // Assert that no other data is returned.
- assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
- assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
- assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
-
- latch.countDown();
- }
- };
-
- startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- callback,
- handler);
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private void testStartAddAccountSessionErrorWithCallbackAndHandler(Handler handler)
- throws IOException, OperationCanceledException {
- final Bundle options = new Bundle();
- final String accountName = Fixtures.PREFIX_NAME_ERROR + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE);
- options.putString(AccountManager.KEY_ERROR_MESSAGE, ERROR_MESSAGE);
- options.putAll(OPTIONS_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- try {
- bundleFuture.getResult();
- fail("should have thrown an AuthenticatorException");
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- latch.countDown();
- }
- }
- };
-
- try {
- startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- mActivity,
- callback,
- handler);
- // AuthenticatorException should be thrown when authenticator
- // returns AccountManager.ERROR_CODE_INVALID_RESPONSE.
- fail("should have thrown an AuthenticatorException");
- } catch (AuthenticatorException e1) {
- }
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private Bundle startAddAccountSession(AccountManager am, String accountType,
- String authTokenType, String[] requiredFeatures, Bundle options, Activity activity,
- AccountManagerCallback<Bundle> callback, Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
-
- AccountManagerFuture<Bundle> futureBundle = am.startAddAccountSession(
- accountType,
- authTokenType,
- requiredFeatures,
- options,
- activity,
- callback,
- handler);
-
- Bundle resultBundle = futureBundle.getResult();
- assertTrue(futureBundle.isDone());
- assertNotNull(resultBundle);
-
- return resultBundle;
- }
-
- private void validateStartAddAccountSessionOptions(String accountName, Bundle options) {
- validateOptions(options, mockAuthenticator.mOptionsStartAddAccountSession);
- assertNotNull(mockAuthenticator.mOptionsStartAddAccountSession);
- assertEquals(accountName, mockAuthenticator.mOptionsStartAddAccountSession
- .getString(Fixtures.KEY_ACCOUNT_NAME));
-
- validateSystemOptions(mockAuthenticator.mOptionsStartAddAccountSession);
- validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
- validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
- validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
- validateOptions(null, mockAuthenticator.mOptionsAddAccount);
- validateOptions(null, mockAuthenticator.mOptionsStartUpdateCredentialsSession);
- validateOptions(null, mockAuthenticator.mOptionsFinishSession);
- }
-
- private void validateSessionBundleAndPasswordAndStatusTokenResult(Bundle resultBundle) {
- Bundle sessionBundle = resultBundle.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
- assertNotNull(sessionBundle);
- // Assert that session bundle is encrypted and hence data not visible.
- assertNull(sessionBundle.getString(SESSION_DATA_NAME_1));
- assertEquals(ACCOUNT_PASSWORD, resultBundle.getString(AccountManager.KEY_PASSWORD));
- assertEquals(ACCOUNT_STATUS_TOKEN,
- resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
- }
-
- /**
- * Test a basic startUpdateCredentialsSession() which returns a bundle containing
- * encrypted session bundle, account password and status token.
- */
- public void testStartUpdateCredentialsSession()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startUpdateCredentialsSession(
- am,
- ACCOUNT,
- null /* authTokenType */,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertNull(mockAuthenticator.getAuthTokenType());
- assertEquals(ACCOUNT, mockAuthenticator.mAccount);
-
- validateStartUpdateCredentialsSessionOptions(accountName, options);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- }
-
- /**
- * Tests startUpdateCredentialsSession() with null session bundle. Only account
- * password and status token should be included in the result as session
- * bundle is not inspected.
- */
- public void testStartUpdateCredentialsSessionWithNullSessionBundle()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(AUTH_TOKEN_TYPE, mockAuthenticator.getAuthTokenType());
- assertEquals(ACCOUNT, mockAuthenticator.mAccount);
-
- validateOptions(options, mockAuthenticator.mOptionsStartUpdateCredentialsSession);
- assertNotNull(mockAuthenticator.mOptionsStartUpdateCredentialsSession);
- assertEquals(accountName, mockAuthenticator.mOptionsStartUpdateCredentialsSession
- .getString(Fixtures.KEY_ACCOUNT_NAME));
-
- validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
- validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
- validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
- validateOptions(null, mockAuthenticator.mOptionsAddAccount);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- assertNull(resultBundle.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
- assertEquals(ACCOUNT_PASSWORD, resultBundle.getString(AccountManager.KEY_PASSWORD));
- assertEquals(ACCOUNT_STATUS_TOKEN,
- resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
- }
-
- /**
- * Tests startUpdateCredentialsSession() with empty session bundle. An encrypted
- * session bundle, account password and status token should be included in
- * the result as session bundle is not inspected.
- */
- public void testStartUpdateCredentialsSessionWithEmptySessionBundle()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, new Bundle());
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(AUTH_TOKEN_TYPE, mockAuthenticator.getAuthTokenType());
- assertEquals(ACCOUNT, mockAuthenticator.mAccount);
-
- validateOptions(options, mockAuthenticator.mOptionsStartUpdateCredentialsSession);
- assertNotNull(mockAuthenticator.mOptionsStartUpdateCredentialsSession);
- assertEquals(accountName, mockAuthenticator.mOptionsStartUpdateCredentialsSession
- .getString(Fixtures.KEY_ACCOUNT_NAME));
-
- validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
- validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
- validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
- validateOptions(null, mockAuthenticator.mOptionsAddAccount);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- }
-
- /**
- * Tests startUpdateCredentialsSession with authenticator activity started. When
- * Activity is provided, AccountManager would start the resolution Intent
- * and return the final result which contains an encrypted session bundle,
- * account password and status token.
- */
- public void testStartUpdateCredentialsSessionIntervene()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- mActivity,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(AUTH_TOKEN_TYPE, mockAuthenticator.getAuthTokenType());
- assertEquals(ACCOUNT, mockAuthenticator.mAccount);
-
- validateStartUpdateCredentialsSessionOptions(accountName, options);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- }
-
- /**
- * Tests startUpdateCredentialsSession with KEY_INTENT returned but not
- * started automatically. When no Activity is provided and authenticator requires
- * additional data from user, KEY_INTENT will be returned by AccountManager.
- */
- public void testStartUpdateCredentialsSessionWithReturnIntent()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- Bundle resultBundle = startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(AUTH_TOKEN_TYPE, mockAuthenticator.getAuthTokenType());
- assertEquals(ACCOUNT, mockAuthenticator.mAccount);
-
- validateStartUpdateCredentialsSessionOptions(accountName, options);
-
- // Assert returned result
- Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
- // Assert that KEY_INTENT is returned.
- assertNotNull(returnIntent);
- assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
- // Assert that no other data is returned.
- assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
- assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
- assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- }
-
- /**
- * Tests startUpdateCredentialsSession error case. AuthenticatorException is
- * expected when authenticator return
- * {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
- */
- public void testStartUpdateCredentialsSessionError()
- throws IOException, OperationCanceledException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_ERROR + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE);
- options.putString(AccountManager.KEY_ERROR_MESSAGE, ERROR_MESSAGE);
- options.putAll(OPTIONS_BUNDLE);
-
- try {
- startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
- fail("startUpdateCredentialsSession should throw AuthenticatorException in error.");
- } catch (AuthenticatorException e) {
- }
- }
-
- /**
- * Tests startUpdateCredentialsSession() with callback and handler. An encrypted
- * session bundle, account password and status token should be included in
- * the result. Callback should be triggered with the result regardless of a
- * handler is provider or not.
- */
- public void testStartUpdateCredentialsSessionWithCallbackAndHandler()
- throws IOException, AuthenticatorException, OperationCanceledException {
- testStartUpdateCredentialsSessionWithCallbackAndHandler(null /* handler */);
- testStartUpdateCredentialsSessionWithCallbackAndHandler(
- new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Tests startUpdateCredentialsSession() with callback and handler and
- * activity started. When Activity is provided, AccountManager would start the
- * resolution Intent and return the final result which contains an encrypted
- * session bundle, account password and status token. Callback should be
- * triggered with the result regardless of a handler is provider or not.
- */
- public void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene()
- throws IOException, AuthenticatorException, OperationCanceledException {
- testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene(null /* handler */);
- testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene(
- new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Tests startUpdateCredentialsSession() with callback and handler with
- * KEY_INTENT returned. When no Activity is provided and authenticator requires
- * additional data from user, KEY_INTENT will be returned by AccountManager
- * in callback regardless of a handler is provider or not.
- */
- public void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent()
- throws IOException, AuthenticatorException, OperationCanceledException {
- testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent(null /* handler */);
- testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent(
- new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Tests startUpdateCredentialsSession() error case with callback and
- * handler. AuthenticatorException is expected when authenticator return
- * {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
- */
- public void testStartUpdateCredentialsSessionErrorWithCallbackAndHandler()
- throws IOException, OperationCanceledException {
- testStartUpdateCredentialsSessionErrorWithCallbackAndHandler(null /* handler */);
- testStartUpdateCredentialsSessionErrorWithCallbackAndHandler(
- new Handler(Looper.getMainLooper()));
- }
-
- private void testStartUpdateCredentialsSessionWithCallbackAndHandler(Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
- final Bundle options = new Bundle();
- final String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- Bundle resultBundle = null;
- try {
- resultBundle = bundleFuture.getResult();
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- fail("should not throw an AuthenticatorException");
- }
-
- // Assert parameters has been passed correctly
- assertEquals(AUTH_TOKEN_TYPE, mockAuthenticator.getAuthTokenType());
- assertEquals(ACCOUNT, mockAuthenticator.mAccount);
-
- validateStartUpdateCredentialsSessionOptions(accountName, options);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
-
- latch.countDown();
- }
- };
-
- startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- mActivity,
- callback,
- handler);
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene(
- Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
- final Bundle options = new Bundle();
- final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- Bundle resultBundle = null;
- try {
- resultBundle = bundleFuture.getResult();
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- fail("should not throw an AuthenticatorException");
- }
-
- // Assert parameters has been passed correctly
- assertEquals(AUTH_TOKEN_TYPE, mockAuthenticator.getAuthTokenType());
- assertEquals(ACCOUNT, mockAuthenticator.mAccount);
-
- validateStartUpdateCredentialsSessionOptions(accountName, options);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
-
- latch.countDown();
- }
- };
-
- startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- mActivity,
- callback,
- handler);
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent(
- Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
- final Bundle options = new Bundle();
- final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putAll(OPTIONS_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- Bundle resultBundle = null;
- try {
- resultBundle = bundleFuture.getResult();
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- fail("should not throw an AuthenticatorException");
- }
-
- // Assert parameters has been passed correctly
- assertEquals(AUTH_TOKEN_TYPE, mockAuthenticator.getAuthTokenType());
- assertEquals(ACCOUNT, mockAuthenticator.mAccount);
-
- validateStartUpdateCredentialsSessionOptions(accountName, options);
-
- // Assert returned result
- Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
- // Assert KEY_INTENT is returned.
- assertNotNull(returnIntent);
- assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
- // Assert that no other data is returned.
- assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
- assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
- assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
-
- latch.countDown();
- }
- };
-
- startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- null,
- callback,
- handler);
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private void testStartUpdateCredentialsSessionErrorWithCallbackAndHandler(Handler handler)
- throws IOException, OperationCanceledException {
- final Bundle options = new Bundle();
- final String accountName = Fixtures.PREFIX_NAME_ERROR + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, getSessionBundle(null));
- options.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE);
- options.putString(AccountManager.KEY_ERROR_MESSAGE, ERROR_MESSAGE);
- options.putAll(OPTIONS_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- try {
- bundleFuture.getResult();
- fail("should have thrown an AuthenticatorException");
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- latch.countDown();
- }
- }
- };
-
- try {
- startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- mActivity,
- callback,
- handler);
- // AuthenticatorException should be thrown when authenticator
- // returns AccountManager.ERROR_CODE_INVALID_RESPONSE.
- fail("should have thrown an AuthenticatorException");
- } catch (AuthenticatorException e1) {
- }
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private Bundle startUpdateCredentialsSession(AccountManager am, Account account,
- String authTokenType, Bundle options, Activity activity,
- AccountManagerCallback<Bundle> callback, Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
-
- AccountManagerFuture<Bundle> futureBundle = am.startUpdateCredentialsSession(account,
- authTokenType, options, activity, callback, handler);
-
- Bundle resultBundle = futureBundle.getResult();
- assertTrue(futureBundle.isDone());
- assertNotNull(resultBundle);
-
- return resultBundle;
- }
-
- private void validateStartUpdateCredentialsSessionOptions(String accountName, Bundle options) {
- validateOptions(options, mockAuthenticator.mOptionsStartUpdateCredentialsSession);
- assertNotNull(mockAuthenticator.mOptionsStartUpdateCredentialsSession);
- assertEquals(accountName, mockAuthenticator.mOptionsStartUpdateCredentialsSession
- .getString(Fixtures.KEY_ACCOUNT_NAME));
-
- validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
- validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
- validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
- validateOptions(null, mockAuthenticator.mOptionsAddAccount);
- validateOptions(null, mockAuthenticator.mOptionsStartAddAccountSession);
- }
-
- /**
- * Tests a basic finishSession() with session bundle created by
- * startAddAccountSession(...). A bundle containing account name and account
- * type is expected.
- */
- public void testFinishSessionWithStartAddAccountSession()
- throws IOException, AuthenticatorException, OperationCanceledException {
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- Bundle sessionBundle = getSessionBundle(accountName);
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- resultBundle = finishSession(
- am,
- encryptedSessionBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result containing account name, type but not auth token type.
- validateAccountAndNoAuthTokenResult(resultBundle);
- }
-
- /**
- * Tests a basic finishSession() with session bundle created by
- * startUpdateCredentialsSession(...). A bundle containing account name and account
- * type is expected.
- */
- public void testFinishSessionWithStartUpdateCredentialsSession()
- throws IOException, AuthenticatorException, OperationCanceledException {
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- Bundle sessionBundle = getSessionBundle(accountName);
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startUpdateCredentialsSession(...)
- Bundle resultBundle = startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- resultBundle = finishSession(
- am,
- encryptedSessionBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result containing account name, type but not auth token type.
- validateAccountAndNoAuthTokenResult(resultBundle);
- }
-
- /**
- * Tests finishSession() with null session bundle. IllegalArgumentException
- * is expected as session bundle cannot be null.
- */
- public void testFinishSessionWithNullSessionBundle()
- throws IOException, AuthenticatorException, OperationCanceledException {
- try {
- finishSession(
- am,
- null /* sessionBundle */,
- null /* activity */,
- null /* callback */,
- null /* handler */);
- fail("Should have thrown IllegalArgumentException when sessionBundle is null");
- } catch (IllegalArgumentException e) {
-
- }
- }
-
- /**
- * Tests finishSession() with empty session bundle. IllegalArgumentException
- * is expected as session bundle would always contain something if it was
- * processed properly by AccountManagerService.
- */
- public void testFinishSessionWithEmptySessionBundle()
- throws IOException, AuthenticatorException, OperationCanceledException {
-
- try {
- finishSession(am,
- new Bundle(),
- null /* activity */,
- null /* callback */,
- null /* handler */);
- fail("Should have thrown IllegalArgumentException when sessionBundle is empty");
- } catch (IllegalArgumentException e) {
-
- }
- }
-
- /**
- * Tests finishSession() with sessionBundle not encrypted by the right key.
- * AuthenticatorException is expected if AccountManagerService failed to
- * decrypt the session bundle because of wrong key or crypto data was
- * tampered.
- */
- public void testFinishSessionWithDecryptionError()
- throws IOException, OperationCanceledException {
- byte[] mac = new byte[] {
- 1, 1, 0, 0
- };
- byte[] cipher = new byte[] {
- 1, 0, 0, 1, 1
- };
- Bundle sessionBundle = new Bundle();
- sessionBundle.putByteArray(KEY_MAC, mac);
- sessionBundle.putByteArray(KEY_CIPHER, cipher);
-
- try {
- finishSession(am,
- sessionBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
- fail("Should have thrown AuthenticatorException when failed to decrypt sessionBundle");
- } catch (AuthenticatorException e) {
-
- }
- }
-
- /**
- * Tests finishSession() with sessionBundle invalid contents.
- * AuthenticatorException is expected if AccountManagerService failed to
- * decrypt the session bundle because of wrong key or crypto data was
- * tampered.
- */
- public void testFinishSessionWithInvalidEncryptedContent()
- throws IOException, OperationCanceledException {
- byte[] mac = new byte[] {};
- Bundle sessionBundle = new Bundle();
- sessionBundle.putByteArray(KEY_MAC, mac);
-
- try {
- finishSession(am,
- sessionBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
- fail("Should have thrown AuthenticatorException when failed to decrypt sessionBundle");
- } catch (AuthenticatorException e) {
-
- }
- }
-
- /**
- * Tests a finishSession() when account type is not added to session bundle
- * by startAddAccount(...) of authenticator. A bundle containing account
- * name and account type should still be returned as AccountManagerSerivce
- * will always add account type to the session bundle before encrypting it.
- */
- public void testFinishSessionFromStartAddAccountWithoutAccountType()
- throws IOException, AuthenticatorException, OperationCanceledException {
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
-
- // Create a session bundle without account type for MockAccountAuthenticator to return
- Bundle sessionBundle = getSessionBundle(accountName);
- sessionBundle.remove(AccountManager.KEY_ACCOUNT_TYPE);
-
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- resultBundle = finishSession(
- am,
- encryptedSessionBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
-
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result containing account name, type but not auth token type.
- validateAccountAndNoAuthTokenResult(resultBundle);
- }
-
- /**
- * Tests a finishSession() when account type is not added to session bundle
- * by startUpdateCredentialsSession(...) of authenticator. A bundle
- * containing account name and account type should still be returned as
- * AccountManagerSerivce will always add account type to the session bundle
- * before encrypting it.
- */
- public void testFinishSessionFromStartUpdateCredentialsSessionWithoutAccountType()
- throws IOException, AuthenticatorException, OperationCanceledException {
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
-
- // Create a session bundle without account type for MockAccountAuthenticator to return
- Bundle sessionBundle = getSessionBundle(accountName);
- sessionBundle.remove(AccountManager.KEY_ACCOUNT_TYPE);
-
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- resultBundle = finishSession(
- am,
- encryptedSessionBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
-
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result containing account name, type but not auth token type.
- validateAccountAndNoAuthTokenResult(resultBundle);
- }
-
- /**
- * Tests a finishSession() when a different account type is added to session bundle
- * by startAddAccount(...) of authenticator. A bundle containing account
- * name and the correct account type should be returned as AccountManagerSerivce
- * will always overrides account type to the session bundle before encrypting it.
- */
- public void testFinishSessionFromStartAddAccountAccountTypeOverriden()
- throws IOException, AuthenticatorException, OperationCanceledException {
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
-
- // Create a session bundle with a different account type for
- // MockAccountAuthenticator to return
- Bundle sessionBundle = getSessionBundle(accountName);
- sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, "randomAccountType");
-
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- resultBundle = finishSession(
- am,
- encryptedSessionBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
-
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result containing account name, correct type but not auth token type.
- validateAccountAndNoAuthTokenResult(resultBundle);
- }
-
- /**
- * Tests a finishSession() when a different account type is added to session bundle
- * by startUpdateCredentialsSession(...) of authenticator. A bundle
- * containing account name and the correct account type should be returned as
- * AccountManagerSerivce will always override account type to the session bundle
- * before encrypting it.
- */
- public void testFinishSessionFromStartUpdateCredentialsSessionAccountTypeOverriden()
- throws IOException, AuthenticatorException, OperationCanceledException {
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
-
- // Create a session bundle with a different account type for
- // MockAccountAuthenticator to return
- Bundle sessionBundle = getSessionBundle(accountName);
- sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, "randomAccountType");
-
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startUpdateCredentialsSession(
- am,
- ACCOUNT,
- AUTH_TOKEN_TYPE,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- resultBundle = finishSession(
- am,
- encryptedSessionBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
-
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result containing account name, correct type but not auth token type.
- validateAccountAndNoAuthTokenResult(resultBundle);
- }
-
- /**
- * Tests finishSession with authenticator activity started. When additional
- * info is needed from user for finishing the session and an Activity was
- * provided by caller, the resolution intent will be started automatically.
- * A bundle containing account name and type will be returned.
- */
- public void testFinishSessionIntervene()
- throws IOException, AuthenticatorException, OperationCanceledException {
- String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- Bundle sessionBundle = getSessionBundle(accountName);
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- mActivity,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- resultBundle = finishSession(
- am,
- encryptedSessionBundle,
- mActivity,
- null /* callback */,
- null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
-
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert returned result containing account name, type but not auth token type.
- validateAccountAndNoAuthTokenResult(resultBundle);
- }
-
- /**
- * Tests finishSession with KEY_INTENT returned but not started
- * automatically. When additional info is needed from user for finishing the
- * session and no Activity was provided by caller, the resolution intent
- * will not be started automatically. A bundle containing KEY_INTENT will be
- * returned instead.
- */
- public void testFinishSessionWithReturnIntent()
- throws IOException, AuthenticatorException, OperationCanceledException {
- String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- Bundle sessionBundle = getSessionBundle(accountName);
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- mActivity,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- resultBundle = finishSession(am, encryptedSessionBundle, null /* activity */,
- null /* callback */, null /* handler */);
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
-
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result
- Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
- assertNotNull(returnIntent);
- assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
-
- assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_NAME));
- assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_TYPE));
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- }
-
- /**
- * Tests finishSession error case. AuthenticatorException is expected when
- * AccountManager.ERROR_CODE_INVALID_RESPONSE is returned by authenticator.
- */
- public void testFinishSessionError()
- throws IOException, AuthenticatorException, OperationCanceledException {
- Bundle sessionBundle = new Bundle();
- String accountNameForFinish = Fixtures.PREFIX_NAME_ERROR + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- sessionBundle.putString(Fixtures.KEY_ACCOUNT_NAME, accountNameForFinish);
- sessionBundle.putInt(AccountManager.KEY_ERROR_CODE,
- AccountManager.ERROR_CODE_INVALID_RESPONSE);
- sessionBundle.putString(AccountManager.KEY_ERROR_MESSAGE, ERROR_MESSAGE);
-
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
-
- try {
- finishSession(
- am,
- encryptedSessionBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
- fail("finishSession should throw AuthenticatorException in error case.");
- } catch (AuthenticatorException e) {
- }
- }
-
- /**
- * Tests finishSession() with callback and handler. A bundle containing
- * account name and type should be returned via the callback regardless of
- * whether a handler is provided.
- */
- public void testFinishSessionWithCallbackAndHandler()
- throws IOException, AuthenticatorException, OperationCanceledException {
-
- testFinishSessionWithCallbackAndHandler(null /* handler */);
- testFinishSessionWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Tests finishSession() with callback and handler and activity started.
- * When additional info is needed from user for finishing the session and an
- * Activity was provided by caller, the resolution intent will be started
- * automatically. A bundle containing account name and type will be returned
- * via the callback regardless of if handler is provided or now.
- */
- public void testFinishSessionWithCallbackAndHandlerWithIntervene()
- throws IOException, AuthenticatorException, OperationCanceledException {
-
- testFinishSessionWithCallbackAndHandlerWithIntervene(null /* handler */);
- testFinishSessionWithCallbackAndHandlerWithIntervene(
- new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Tests finishSession() with callback and handler with KEY_INTENT
- * returned. When additional info is needed from user for finishing the
- * session and no Activity was provided by caller, the resolution intent
- * will not be started automatically. A bundle containing KEY_INTENT will be
- * returned instead via callback regardless of if handler is provided or not.
- */
- public void testFinishSessionWithCallbackAndHandlerWithReturnIntent()
- throws IOException, AuthenticatorException, OperationCanceledException {
-
- testFinishSessionWithCallbackAndHandlerWithReturnIntent(null /* handler */);
- testFinishSessionWithCallbackAndHandlerWithReturnIntent(
- new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Tests finishSession() error case with callback and handler.
- * AuthenticatorException is expected when
- * AccountManager.ERROR_CODE_INVALID_RESPONSE is returned by authenticator.
- */
- public void testFinishSessionErrorWithCallbackAndHandler()
- throws IOException, OperationCanceledException, AuthenticatorException {
-
- testFinishSessionErrorWithCallbackAndHandler(null /* handler */);
- testFinishSessionErrorWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
- }
-
- private void testFinishSessionWithCallbackAndHandler(Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
- final String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- final Bundle sessionBundle = getSessionBundle(accountName);
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- Bundle resultBundle = null;
- try {
- resultBundle = bundleFuture.getResult();
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- fail("should not throw an AuthenticatorException");
- }
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
-
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result containing account name, type but not auth token type.
- validateAccountAndNoAuthTokenResult(resultBundle);
-
- latch.countDown();
- }
- };
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- finishSession(am, encryptedSessionBundle, mActivity, callback, handler);
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private void testFinishSessionWithCallbackAndHandlerWithIntervene(Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
- final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- final Bundle sessionBundle = getSessionBundle(accountName);
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- mActivity,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- Bundle resultBundle = null;
- try {
- resultBundle = bundleFuture.getResult();
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- fail("should not throw an AuthenticatorException");
- }
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
-
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert returned result containing account name, type but not auth token type.
- validateAccountAndNoAuthTokenResult(resultBundle);
-
- latch.countDown();
- }
- };
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- finishSession(am, encryptedSessionBundle, mActivity, callback, handler);
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private void testFinishSessionWithCallbackAndHandlerWithReturnIntent(Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
- final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- final Bundle sessionBundle = getSessionBundle(accountName);
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- mActivity,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- Bundle resultBundle = null;
- try {
- resultBundle = bundleFuture.getResult();
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- fail("should not throw an AuthenticatorException");
- }
-
- // Assert parameters has been passed correctly
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
-
- validateFinishSessionOptions(accountName, sessionBundle);
-
- // Assert returned result
- Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
- assertNotNull(returnIntent);
- assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
-
- assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_NAME));
- assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_TYPE));
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
-
- latch.countDown();
- }
- };
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
- finishSession(am, encryptedSessionBundle, null, callback, handler);
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private void testFinishSessionErrorWithCallbackAndHandler(Handler handler)
- throws IOException, OperationCanceledException, AuthenticatorException {
- Bundle sessionBundle = new Bundle();
- String accountNameForFinish = Fixtures.PREFIX_NAME_ERROR + "@"
- + Fixtures.SUFFIX_NAME_FIXTURE;
- sessionBundle.putString(Fixtures.KEY_ACCOUNT_NAME, accountNameForFinish);
- sessionBundle.putInt(AccountManager.KEY_ERROR_CODE,
- AccountManager.ERROR_CODE_INVALID_RESPONSE);
- sessionBundle.putString(AccountManager.KEY_ERROR_MESSAGE, ERROR_MESSAGE);
-
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- options.putAll(OPTIONS_BUNDLE);
-
- // First get an encrypted session bundle from startAddAccountSession(...)
- Bundle resultBundle = startAddAccountSession(
- am,
- ACCOUNT_TYPE,
- AUTH_TOKEN_TYPE,
- REQUIRED_FEATURES,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- // Assert returned result
- // Assert that auth token was stripped.
- assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
- validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
- Bundle encryptedSessionBundle = resultBundle
- .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
- @Override
- public void run(AccountManagerFuture<Bundle> bundleFuture) {
- try {
- bundleFuture.getResult();
- fail("should have thrown an AuthenticatorException");
- } catch (OperationCanceledException e) {
- fail("should not throw an OperationCanceledException");
- } catch (IOException e) {
- fail("should not throw an IOException");
- } catch (AuthenticatorException e) {
- latch.countDown();
- }
- }
- };
-
- // Cleanup before calling finishSession(...) with the encrypted session bundle.
- mockAuthenticator.clearData();
-
- try {
- finishSession(am, encryptedSessionBundle, mActivity, callback, handler);
- fail("should have thrown an AuthenticatorException");
- } catch (AuthenticatorException e1) {
- }
-
- // Wait with timeout for the callback to do its work
- try {
- latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- fail("should not throw an InterruptedException");
- }
- }
-
- private Bundle finishSession(AccountManager am, Bundle sessionBundle, Activity activity,
- AccountManagerCallback<Bundle> callback, Handler handler)
- throws IOException, AuthenticatorException, OperationCanceledException {
-
- AccountManagerFuture<Bundle> futureBundle = am.finishSession(
- sessionBundle,
- activity,
- callback,
- handler);
-
- Bundle resultBundle = futureBundle.getResult();
- assertTrue(futureBundle.isDone());
- assertNotNull(resultBundle);
-
- return resultBundle;
- }
-
- private void validateFinishSessionOptions(String accountName, Bundle options) {
- validateOptions(options, mockAuthenticator.mOptionsFinishSession);
- assertNotNull(mockAuthenticator.mOptionsFinishSession);
- assertEquals(ACCOUNT_TYPE, mockAuthenticator.mOptionsFinishSession
- .getString(AccountManager.KEY_ACCOUNT_TYPE));
- assertEquals(accountName,
- mockAuthenticator.mOptionsFinishSession.getString(Fixtures.KEY_ACCOUNT_NAME));
-
- validateSystemOptions(mockAuthenticator.mOptionsFinishSession);
- validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
- validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
- validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
- validateOptions(null, mockAuthenticator.mOptionsAddAccount);
- validateOptions(null, mockAuthenticator.mOptionsStartAddAccountSession);
- validateOptions(null, mockAuthenticator.mOptionsStartUpdateCredentialsSession);
- }
}
diff --git a/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffiliatedAuthenticatorTests.java b/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffiliatedAuthenticatorTests.java
index 0105782..2068f4c 100644
--- a/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffiliatedAuthenticatorTests.java
+++ b/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffiliatedAuthenticatorTests.java
@@ -23,11 +23,8 @@
import android.accounts.OperationCanceledException;
import android.accounts.cts.common.AuthenticatorContentProvider;
import android.accounts.cts.common.Fixtures;
-import android.accounts.cts.common.tx.AddAccountTx;
-import android.accounts.cts.common.tx.UpdateCredentialsTx;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
-import android.os.Bundle;
import android.os.RemoteException;
import android.test.AndroidTestCase;
@@ -225,226 +222,5 @@
getContext().getPackageName());
assertEquals(0, accounts.length);
}
-
- /**
- * Tests startAddAccountSession default implementation. An encrypted session
- * bundle should always be returned without password or status token.
- */
- public void testStartAddAccountSessionDefaultImpl()
- throws OperationCanceledException, AuthenticatorException, IOException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
-
- AccountManagerFuture<Bundle> future = mAccountManager.startAddAccountSession(
- Fixtures.TYPE_STANDARD_UNAFFILIATED,
- null /* authTokenType */,
- null /* requiredFeatures */,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- Bundle result = future.getResult();
- assertTrue(future.isDone());
- assertNotNull(result);
-
- // Validate that auth token was stripped from result.
- assertNull(result.get(AccountManager.KEY_AUTHTOKEN));
-
- // Validate that no password nor status token is returned in the result
- // for default implementation.
- validateNullPasswordAndStatusToken(result);
-
- Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
- // Validate session bundle is returned but data in the bundle is
- // encrypted and hence not visible.
- assertNotNull(sessionBundle);
- assertNull(sessionBundle.getString(AccountManager.KEY_ACCOUNT_TYPE));
- }
-
- private void validateNullPasswordAndStatusToken(Bundle result) {
- assertNull(result.getString(AccountManager.KEY_PASSWORD));
- assertNull(result.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
- }
-
- /**
- * Tests startUpdateCredentialsSession default implementation. An encrypted session
- * bundle should always be returned without password or status token.
- */
- public void testStartUpdateCredentialsSessionDefaultImpl()
- throws OperationCanceledException, AuthenticatorException, IOException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
-
- AccountManagerFuture<Bundle> future = mAccountManager.startUpdateCredentialsSession(
- Fixtures.ACCOUNT_UNAFFILIATED_FIXTURE_SUCCESS,
- null /* authTokenType */,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- Bundle result = future.getResult();
- assertTrue(future.isDone());
- assertNotNull(result);
-
- // Validate no auth token in result.
- assertNull(result.get(AccountManager.KEY_AUTHTOKEN));
-
- // Validate that no password nor status token is returned in the result
- // for default implementation.
- validateNullPasswordAndStatusToken(result);
-
- Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
- // Validate session bundle is returned but data in the bundle is
- // encrypted and hence not visible.
- assertNotNull(sessionBundle);
- assertNull(sessionBundle.getString(Fixtures.KEY_ACCOUNT_NAME));
- }
-
- /**
- * Tests finishSession default implementation with default startAddAccountSession.
- * Only account name and account type should be returned as a bundle.
- */
- public void testFinishSessionAndStartAddAccountSessionDefaultImpl()
- throws OperationCanceledException, AuthenticatorException, IOException,
- RemoteException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
-
- // First obtain an encrypted session bundle from startAddAccountSession(...) default
- // implementation.
- AccountManagerFuture<Bundle> future = mAccountManager.startAddAccountSession(
- Fixtures.TYPE_STANDARD_UNAFFILIATED,
- null /* authTokenType */,
- null /* requiredFeatures */,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- Bundle result = future.getResult();
- assertTrue(future.isDone());
- assertNotNull(result);
-
- // Assert that result contains a non-null session bundle.
- Bundle escrowBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
- assertNotNull(escrowBundle);
-
- // Now call finishSession(...) with the session bundle we just obtained.
- future = mAccountManager.finishSession(
- escrowBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- result = future.getResult();
- assertTrue(future.isDone());
- assertNotNull(result);
-
- // Validate that parameters are passed to addAccount(...) correctly in default finishSession
- // implementation.
- Bundle providerBundle = mProviderClient.call(
- AuthenticatorContentProvider.METHOD_GET,
- null /* arg */,
- null /* extras */);
- providerBundle.setClassLoader(AddAccountTx.class.getClassLoader());
- AddAccountTx addAccountTx = providerBundle
- .getParcelable(AuthenticatorContentProvider.KEY_TX);
- assertNotNull(addAccountTx);
-
- // Assert parameters has been passed to addAccount(...) correctly
- assertEquals(Fixtures.TYPE_STANDARD_UNAFFILIATED, addAccountTx.accountType);
- assertNull(addAccountTx.authTokenType);
-
- validateSystemOptions(addAccountTx.options);
- // Validate options
- assertNotNull(addAccountTx.options);
- assertEquals(accountName, addAccountTx.options.getString(Fixtures.KEY_ACCOUNT_NAME));
- // Validate features.
- assertEquals(0, addAccountTx.requiredFeatures.size());
-
- // Assert returned result contains correct account name, account type and null auth token.
- assertEquals(accountName, result.get(AccountManager.KEY_ACCOUNT_NAME));
- assertEquals(Fixtures.TYPE_STANDARD_UNAFFILIATED,
- result.get(AccountManager.KEY_ACCOUNT_TYPE));
- assertNull(result.get(AccountManager.KEY_AUTHTOKEN));
- }
-
- /**
- * Tests finishSession default implementation with default startAddAccountSession.
- * Only account name and account type should be returned as a bundle.
- */
- public void testFinishSessionAndStartUpdateCredentialsSessionDefaultImpl()
- throws OperationCanceledException, AuthenticatorException, IOException,
- RemoteException {
- Bundle options = new Bundle();
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
-
- // First obtain an encrypted session bundle from startUpdateCredentialsSession(...) default
- // implementation.
- AccountManagerFuture<Bundle> future = mAccountManager.startUpdateCredentialsSession(
- Fixtures.ACCOUNT_UNAFFILIATED_FIXTURE_SUCCESS,
- null /* authTokenTYpe */,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- Bundle result = future.getResult();
- assertTrue(future.isDone());
- assertNotNull(result);
-
- // Assert that result contains a non-null session bundle.
- Bundle escrowBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
- assertNotNull(escrowBundle);
-
- // Now call finishSession(...) with the session bundle we just obtained.
- future = mAccountManager.finishSession(
- escrowBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- result = future.getResult();
- assertTrue(future.isDone());
- assertNotNull(result);
-
- // Validate that parameters are passed to updateCredentials(...) correctly in default
- // finishSession implementation.
- Bundle providerBundle = mProviderClient.call(
- AuthenticatorContentProvider.METHOD_GET,
- null /* arg */,
- null /* extras */);
- providerBundle.setClassLoader(UpdateCredentialsTx.class.getClassLoader());
- UpdateCredentialsTx updateCredentialsTx = providerBundle
- .getParcelable(AuthenticatorContentProvider.KEY_TX);
- assertNotNull(updateCredentialsTx);
-
- // Assert parameters has been passed to updateCredentials(...) correctly
- assertEquals(Fixtures.ACCOUNT_UNAFFILIATED_FIXTURE_SUCCESS, updateCredentialsTx.account);
- assertNull(updateCredentialsTx.authTokenType);
-
- validateSystemOptions(updateCredentialsTx.options);
- // Validate options
- assertNotNull(updateCredentialsTx.options);
- assertEquals(accountName, updateCredentialsTx.options.getString(Fixtures.KEY_ACCOUNT_NAME));
-
- // Assert returned result contains correct account name, account type and null auth token.
- assertEquals(accountName, result.get(AccountManager.KEY_ACCOUNT_NAME));
- assertEquals(Fixtures.TYPE_STANDARD_UNAFFILIATED,
- result.get(AccountManager.KEY_ACCOUNT_TYPE));
- assertNull(result.get(AccountManager.KEY_AUTHTOKEN));
- }
-
- private void validateSystemOptions(Bundle options) {
- assertNotNull(options.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME));
- assertTrue(options.containsKey(AccountManager.KEY_CALLER_UID));
- assertTrue(options.containsKey(AccountManager.KEY_CALLER_PID));
- }
}
diff --git a/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffliatedCustomAuthenticatorTests.java b/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffliatedCustomAuthenticatorTests.java
deleted file mode 100644
index 1329eb3..0000000
--- a/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffliatedCustomAuthenticatorTests.java
+++ /dev/null
@@ -1,139 +0,0 @@
-
-package android.accounts.cts;
-
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
-import android.accounts.cts.common.Fixtures;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.test.AndroidTestCase;
-
-import java.io.IOException;
-
-/**
- * Tests for AccountManager and AbstractAccountAuthenticator related behavior
- * using {@link android.accounts.cts.common.CustomTestAccountAuthenticator}
- * instances signed with different keys than the caller. This is important to
- * test that portion of the default implementation of the
- * {@link AccountManager#finishSession} API when implementers of
- * {@link android.accounts.AbstractAccountAuthenticator} override only
- * {@link AccountManager#startAddAccountSession} and/or
- * {@link AccountManager#startUpdateCredentialsSession} but not
- * {@link AccountManager#finishSession}.
- * <p>
- * You can run those unit tests with the following command line:
- * <p>
- * adb shell am instrument -e debug false -w -e class
- * android.accounts.cts.AccountManagerUnaffiliatedCustomAuthenticatorTests
- * android.accounts.cts/android.support.test.runner.AndroidJUnitRunner
- */
-public class AccountManagerUnaffliatedCustomAuthenticatorTests extends AndroidTestCase {
-
- private AccountManager mAccountManager;
-
- @Override
- public void setUp() throws Exception {
- // bind to the diagnostic service and set it up.
- mAccountManager = AccountManager.get(getContext());
- }
-
- /**
- * Tests finishSession default implementation with custom
- * startAddAccountSession implementation. AuthenticatorException is expected
- * because default implementation cannot understand custom session bundle.
- */
- public void testFinishSessiontWithCustomStartAddAccountSessionImpl()
- throws OperationCanceledException, AuthenticatorException, IOException {
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- // Creates session bundle to be returned by custom implementation of
- // startAddAccountSession of authenticator.
- Bundle sessionBundle = new Bundle();
- sessionBundle.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, Fixtures.TYPE_CUSTOM_UNAFFILIATED);
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
-
- // First get an encrypted session bundle from custom startAddAccountSession implementation.
- AccountManagerFuture<Bundle> future = mAccountManager.startAddAccountSession(
- Fixtures.TYPE_CUSTOM_UNAFFILIATED,
- null /* authTokenType */,
- null /* requiredFeatures */,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- Bundle result = future.getResult();
- assertTrue(future.isDone());
- assertNotNull(result);
-
- Bundle decryptedBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
- assertNotNull(decryptedBundle);
-
- try {
- // Call default implementation of finishSession of authenticator
- // with encrypted session bundle.
- future = mAccountManager.finishSession(
- decryptedBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
- future.getResult();
-
- fail("Should have thrown AuthenticatorException if finishSession is not overridden.");
- } catch (AuthenticatorException e) {
- }
- }
-
- /**
- * Tests finishSession default implementation with custom
- * startUpdateCredentialsSession implementation. AuthenticatorException is expected
- * because default implementation cannot understand custom session bundle.
- */
- public void testFinishSessionWithCustomStartUpdateCredentialsSessionImpl()
- throws OperationCanceledException, AuthenticatorException, IOException {
- String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
- // Creates session bundle to be returned by custom implementation of
- // startUpdateCredentialsSession of authenticator.
- Bundle sessionBundle = new Bundle();
- sessionBundle.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, Fixtures.TYPE_CUSTOM_UNAFFILIATED);
- Bundle options = new Bundle();
- options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
- options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
-
- // First get an encrypted session bundle from custom
- // startUpdateCredentialsSession implementation.
- AccountManagerFuture<Bundle> future = mAccountManager.startUpdateCredentialsSession(
- Fixtures.ACCOUNT_CUSTOM_UNAFFILIATED_FIXTURE_SUCCESS,
- null /* authTokenType */,
- options,
- null /* activity */,
- null /* callback */,
- null /* handler */);
-
- Bundle result = future.getResult();
- assertTrue(future.isDone());
- assertNotNull(result);
-
- Bundle decryptedBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
- assertNotNull(decryptedBundle);
-
- try {
- // Call default implementation of finishSession of authenticator
- // with encrypted session bundle.
- future = mAccountManager.finishSession(
- decryptedBundle,
- null /* activity */,
- null /* callback */,
- null /* handler */);
- future.getResult();
-
- fail("Should have thrown AuthenticatorException if finishSession is not overridden.");
- } catch (AuthenticatorException e) {
- }
- }
-}
diff --git a/tests/tests/accounts/src/android/accounts/cts/MockAccountAuthenticator.java b/tests/tests/accounts/src/android/accounts/cts/MockAccountAuthenticator.java
index 6f355fb..c1b08de 100644
--- a/tests/tests/accounts/src/android/accounts/cts/MockAccountAuthenticator.java
+++ b/tests/tests/accounts/src/android/accounts/cts/MockAccountAuthenticator.java
@@ -21,7 +21,6 @@
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.accounts.NetworkErrorException;
-import android.accounts.cts.common.Fixtures;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -56,9 +55,6 @@
public Bundle mOptionsConfirmCredentials;
public Bundle mOptionsAddAccount;
public Bundle mOptionsGetAuthToken;
- public Bundle mOptionsStartAddAccountSession;
- public Bundle mOptionsStartUpdateCredentialsSession;
- public Bundle mOptionsFinishSession;
Account mAccount;
String[] mFeatures;
@@ -119,9 +115,6 @@
mOptionsAddAccount = null;
mOptionsGetAuthToken = null;
mOptionsConfirmCredentials = null;
- mOptionsStartAddAccountSession = null;
- mOptionsStartUpdateCredentialsSession = null;
- mOptionsFinishSession = null;
mAccount = null;
mFeatures = null;
}
@@ -302,210 +295,4 @@
}
return result;
}
-
- /**
- * Starts add account flow of the specified accountType to authenticate
- * user.
- */
- @Override
- public Bundle startAddAccountSession(AccountAuthenticatorResponse response, String accountType,
- String authTokenType, String[] requiredFeatures, Bundle options)
- throws NetworkErrorException {
-
- this.mResponse = response;
- this.mAccountType = accountType;
- this.mAuthTokenType = authTokenType;
- this.mRequiredFeatures = requiredFeatures;
- this.mOptionsStartAddAccountSession = options;
-
- String accountName = null;
- boolean isCallbackRequired = false;
- Bundle sessionBundle = null;
- if (options != null) {
- accountName = options.getString(Fixtures.KEY_ACCOUNT_NAME);
- isCallbackRequired = options.getBoolean(Fixtures.KEY_CALLBACK_REQUIRED, false);
- sessionBundle = options.getBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE);
- }
-
- Bundle result = new Bundle();
- if (accountName.startsWith(Fixtures.PREFIX_NAME_SUCCESS)) {
- // fill bundle with a success result.
- result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- result.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
- AccountManagerTest.ACCOUNT_STATUS_TOKEN);
- result.putString(AccountManager.KEY_PASSWORD, AccountManagerTest.ACCOUNT_PASSWORD);
- result.putString(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
- } else if (accountName.startsWith(Fixtures.PREFIX_NAME_INTERVENE)) {
- // Specify data to be returned by the eventual activity.
- Intent eventualActivityResultData = new Intent();
- eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
- AccountManagerTest.ACCOUNT_STATUS_TOKEN);
- eventualActivityResultData.putExtra(AccountManager.KEY_PASSWORD,
- AccountManagerTest.ACCOUNT_PASSWORD);
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE,
- sessionBundle);
- // Fill result with Intent.
- Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
- intent.putExtra(Fixtures.KEY_RESULT, eventualActivityResultData);
- intent.putExtra(Fixtures.KEY_CALLBACK, response);
-
- result.putParcelable(AccountManager.KEY_INTENT, intent);
- } else {
- // fill with error
- int errorCode = AccountManager.ERROR_CODE_INVALID_RESPONSE;
- String errorMsg = "Default Error Message";
- if (options != null) {
- errorCode = options.getInt(AccountManager.KEY_ERROR_CODE);
- errorMsg = options.getString(AccountManager.KEY_ERROR_MESSAGE);
- }
- result.putInt(AccountManager.KEY_ERROR_CODE, errorCode);
- result.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
- }
-
- try {
- return (isCallbackRequired) ? null : result;
- } finally {
- if (isCallbackRequired) {
- response.onResult(result);
- }
- }
-
- }
-
- /**
- * Starts the update credentials flow to re-auth user but does not update
- * locally stored credentials for an account.
- */
- @Override
- public Bundle startUpdateCredentialsSession(AccountAuthenticatorResponse response, Account account,
- String authTokenType, Bundle options) throws NetworkErrorException {
-
- mResponse = response;
- mAccount = account;
- mAuthTokenType = authTokenType;
- mOptionsStartUpdateCredentialsSession = options;
-
- String accountName = null;
- boolean isCallbackRequired = false;
- Bundle sessionBundle = null;
- if (options != null) {
- accountName = options.getString(Fixtures.KEY_ACCOUNT_NAME);
- isCallbackRequired = options.getBoolean(Fixtures.KEY_CALLBACK_REQUIRED, false);
- sessionBundle = options.getBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE);
- }
-
- Bundle result = new Bundle();
- if (accountName.startsWith(Fixtures.PREFIX_NAME_SUCCESS)) {
- // fill bundle with a success result.
- result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
- result.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
- AccountManagerTest.ACCOUNT_STATUS_TOKEN);
- result.putString(AccountManager.KEY_PASSWORD, AccountManagerTest.ACCOUNT_PASSWORD);
- result.putString(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
- } else if (accountName.startsWith(Fixtures.PREFIX_NAME_INTERVENE)) {
- // Specify data to be returned by the eventual activity.
- Intent eventualActivityResultData = new Intent();
- eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
- AccountManagerTest.ACCOUNT_STATUS_TOKEN);
- eventualActivityResultData.putExtra(AccountManager.KEY_PASSWORD,
- AccountManagerTest.ACCOUNT_PASSWORD);
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE,
- sessionBundle);
- // Fill result with Intent.
- Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
- intent.putExtra(Fixtures.KEY_RESULT, eventualActivityResultData);
- intent.putExtra(Fixtures.KEY_CALLBACK, response);
-
- result.putParcelable(AccountManager.KEY_INTENT, intent);
- } else {
- // fill with error
- int errorCode = AccountManager.ERROR_CODE_INVALID_RESPONSE;
- String errorMsg = "Default Error Message";
- if (options != null) {
- errorCode = options.getInt(AccountManager.KEY_ERROR_CODE);
- errorMsg = options.getString(AccountManager.KEY_ERROR_MESSAGE);
- }
- result.putInt(AccountManager.KEY_ERROR_CODE, errorCode);
- result.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
- }
-
- try {
- return (isCallbackRequired) ? null : result;
- } finally {
- if (isCallbackRequired) {
- response.onResult(result);
- }
- }
- }
-
- /**
- * Finishes account session started by adding the account to device or updating the local
- * credentials.
- */
- @Override
- public Bundle finishSession(
- AccountAuthenticatorResponse response,
- String accountType,
- Bundle sessionBundle) throws NetworkErrorException {
-
- this.mResponse = response;
- this.mAccountType = accountType;
- this.mOptionsFinishSession = sessionBundle;
-
- String accountName = null;
- boolean isCallbackRequired = false;
- if (sessionBundle != null) {
- accountName = sessionBundle.getString(Fixtures.KEY_ACCOUNT_NAME);
- isCallbackRequired = sessionBundle.getBoolean(Fixtures.KEY_CALLBACK_REQUIRED, false);
- }
-
- Bundle result = new Bundle();
- if (accountName.startsWith(Fixtures.PREFIX_NAME_SUCCESS)) {
- // fill bundle with a success result.
- result.putString(AccountManager.KEY_ACCOUNT_NAME, AccountManagerTest.ACCOUNT_NAME);
- result.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountManagerTest.ACCOUNT_TYPE);
- result.putString(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
- } else if (accountName.startsWith(Fixtures.PREFIX_NAME_INTERVENE)) {
- // Specify data to be returned by the eventual activity.
- Intent eventualActivityResultData = new Intent();
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_NAME,
- AccountManagerTest.ACCOUNT_NAME);
- eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_TYPE,
- AccountManagerTest.ACCOUNT_TYPE);
- eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN,
- Integer.toString(mTokenCounter.incrementAndGet()));
-
- // Fill result with Intent.
- Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
- intent.putExtra(Fixtures.KEY_RESULT, eventualActivityResultData);
- intent.putExtra(Fixtures.KEY_CALLBACK, response);
-
- result.putParcelable(AccountManager.KEY_INTENT, intent);
- } else {
- // fill with error
- int errorCode = AccountManager.ERROR_CODE_INVALID_RESPONSE;
- String errorMsg = "Default Error Message";
- if (sessionBundle != null) {
- errorCode = sessionBundle.getInt(AccountManager.KEY_ERROR_CODE);
- errorMsg = sessionBundle.getString(AccountManager.KEY_ERROR_MESSAGE);
- }
- result.putInt(AccountManager.KEY_ERROR_CODE, errorCode);
- result.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
- }
-
- try {
- return (isCallbackRequired) ? null : result;
- } finally {
- if (isCallbackRequired) {
- response.onResult(result);
- }
- }
- }
}
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/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/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/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/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml b/tests/tests/content/res/values-hdpi/strings.xml
similarity index 71%
copy from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
copy to tests/tests/content/res/values-hdpi/strings.xml
index 4aca824..0ea4779 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
+++ b/tests/tests/content/res/values-hdpi/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,7 +14,6 @@
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>
+ <string name="density_string">hdpi</string>
</resources>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml b/tests/tests/content/res/values-ldpi/strings.xml
similarity index 71%
copy from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
copy to tests/tests/content/res/values-ldpi/strings.xml
index 4aca824..8a49f34 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
+++ b/tests/tests/content/res/values-ldpi/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,7 +14,6 @@
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>
+ <string name="density_string">ldpi</string>
</resources>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml b/tests/tests/content/res/values-mdpi/strings.xml
similarity index 71%
copy from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
copy to tests/tests/content/res/values-mdpi/strings.xml
index 4aca824..721481f 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
+++ b/tests/tests/content/res/values-mdpi/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -14,7 +14,6 @@
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>
+ <string name="density_string">mdpi</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/src/android/content/res/cts/AssetManagerTest.java b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
index 21a8682..fe98b72 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
@@ -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/ResourcesTest.java b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
index a3c1b49..1304b26 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -363,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);
@@ -431,6 +445,22 @@
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);
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 e31ffd6..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
@@ -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/drm/jni/Android.mk b/tests/tests/drm/jni/Android.mk
index 06b2df9..87f00a4 100644
--- a/tests/tests/drm/jni/Android.mk
+++ b/tests/tests/drm/jni/Android.mk
@@ -28,5 +28,6 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := liblog libdl
+LOCAL_SDK_VERSION := 23
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/drm/jni/android_drm_cts_NativeCodeTest.cpp b/tests/tests/drm/jni/android_drm_cts_NativeCodeTest.cpp
index e5c9f960..9fe4bb2 100644
--- a/tests/tests/drm/jni/android_drm_cts_NativeCodeTest.cpp
+++ b/tests/tests/drm/jni/android_drm_cts_NativeCodeTest.cpp
@@ -15,11 +15,11 @@
*/
#include <jni.h>
-#include <sys/types.h>
+#include <stdio.h>
#include <string.h>
-#include <unistd.h>
#include <sys/syscall.h>
-#include <utils/Log.h>
+#include <sys/types.h>
+#include <unistd.h>
/*
* Returns true iff this device may be vulnerable to installation of rogue drm
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index feb9f4d..e722fa8 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -18,7 +18,7 @@
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)
diff --git a/tests/tests/graphics/assets/bombfont2.ttf b/tests/tests/graphics/assets/bombfont2.ttf
new file mode 100644
index 0000000..604a698
--- /dev/null
+++ b/tests/tests/graphics/assets/bombfont2.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/bombfont2.ttx b/tests/tests/graphics/assets/bombfont2.ttx
new file mode 100644
index 0000000..ccac1b6
--- /dev/null
+++ b/tests/tests/graphics/assets/bombfont2.ttx
@@ -0,0 +1,241 @@
+<?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.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="a"/>
+ <GlyphID id="2" name="b"/>
+ <GlyphID id="3" name="c"/>
+ <GlyphID id="4" name="d"/>
+ <GlyphID id="5" name="e"/>
+ <GlyphID id="6" name="BombEmoji"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0xaf28220f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Sep 9 08:01:17 2015"/>
+ <modified value="Tue Dec 8 03:58:55 2015"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="0"/>
+ <yMax value="0"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="7"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="1000"/>
+ <descent value="-200"/>
+ <lineGap value="0"/>
+ <advanceWidthMax value="500"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="0"/>
+ <xMaxExtent value="0"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="1"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="7"/>
+ <maxPoints value="0"/>
+ <maxContours value="0"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="2"/>
+ <maxTwilightPoints value="12"/>
+ <maxStorage value="28"/>
+ <maxFunctionDefs value="119"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="61"/>
+ <maxSizeOfInstructions value="2967"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="594"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00001000"/>
+ <ySubscriptXSize value="650"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="650"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="350"/>
+ <yStrikeoutSize value="50"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="5"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="UKWN"/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="97"/>
+ <usLastCharIndex value="65535"/>
+ <sTypoAscender value="800"/>
+ <sTypoDescender value="-200"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="200"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="700"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="93"/>
+ <mtx name="BombEmoji" width="500" lsb="93"/>
+ <mtx name="a" width="500" lsb="93"/>
+ <mtx name="b" width="500" lsb="93"/>
+ <mtx name="c" width="500" lsb="93"/>
+ <mtx name="d" width="500" lsb="93"/>
+ <mtx name="e" width="500" lsb="93"/>
+ </hmtx>
+
+ <cmap ERROR="decompilation error" raw="True">
+ <!-- An error occurred during the decompilation of this table -->
+ <hexdata>
+ 00000002 00030001 00000014 00030001
+ 00000034 00040020 00000004 00040001
+ 00000065 ffff0000 0061ffff ffa00001
+ 00000000 000c0000 00000028 00000000
+ 00000002 00000063 0000005f 00000001
+ 0001f4a3 0001f4a3 00000006
+ </hexdata>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="BombEmoji"/><!-- contains no outline data -->
+
+ <TTGlyph name="a"/><!-- contains no outline data -->
+
+ <TTGlyph name="b"/><!-- contains no outline data -->
+
+ <TTGlyph name="c"/><!-- contains no outline data -->
+
+ <TTGlyph name="d"/><!-- contains no outline data -->
+
+ <TTGlyph name="e"/><!-- contains no outline data -->
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
+ SampleFont Test
+ </namerecord>
+ <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
+ SampleFont Test
+ </namerecord>
+ <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
+ SampleFontTest-Regular
+ </namerecord>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ SampleFont Test
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ SampleFont Test
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SampleFontTest-Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="2.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-166"/>
+ <underlineThickness value="20"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ <psNames>
+ <!-- This file uses unique glyph names based on the information
+ found in the 'post' table. Since these names might not be unique,
+ we have to invent artificial names in case of clashes. In order to
+ be able to retain the original information, we need a name to
+ ps name mapping for those cases where they differ. That's what
+ you see below.
+ -->
+ </psNames>
+ <extraNames>
+ <!-- following are the name that are not taken from the standard Mac glyph order -->
+ <psName name="BombEmoji"/>
+ </extraNames>
+ </post>
+
+</ttFont>
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/src/android/graphics/cts/TypefaceTest.java b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
index 2c1b132..5528372 100644
--- a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
@@ -192,4 +192,15 @@
float widthCustomTypeface = p.measureText(testString);
assertEquals(widthDefaultTypeface, widthCustomTypeface, 1.0f);
}
+
+ public void testInvalidCmapFont2() {
+ Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), "bombfont2.ttf");
+ assertNotNull(typeface);
+ Paint p = new Paint();
+ final String testString = "abcde";
+ float widthDefaultTypeface = p.measureText(testString);
+ p.setTypeface(typeface);
+ float widthCustomTypeface = p.measureText(testString);
+ assertEquals(widthDefaultTypeface, widthCustomTypeface, 1.0f);
+ }
}
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/RippleDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/RippleDrawableTest.java
index ab4fc0a..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,6 +16,8 @@
package android.graphics.drawable.cts;
+import static org.mockito.Mockito.*;
+
import org.xmlpull.v1.XmlPullParserException;
import android.content.res.ColorStateList;
@@ -24,6 +26,7 @@
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;
@@ -89,4 +92,13 @@
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 ccdedab..b6912a0 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
@@ -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/StateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
index 753db9b..9f6a771 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
@@ -41,7 +41,8 @@
public class StateListDrawableTest extends InstrumentationTestCase {
- private MockStateListDrawable mStateListDrawable;
+ private MockStateListDrawable mMockDrawable;
+ private StateListDrawable mDrawable;
private Resources mResources;
@@ -50,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();
}
@@ -63,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() {
@@ -96,61 +99,61 @@
}
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) {
}
@@ -238,47 +241,47 @@
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) {
}
@@ -287,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/hardware/AndroidManifest.xml b/tests/tests/hardware/AndroidManifest.xml
index 34a1475..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" />
@@ -82,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 a970b95..14027dd 100644
--- a/tests/tests/hardware/AndroidTest.xml
+++ b/tests/tests/hardware/AndroidTest.xml
@@ -25,7 +25,7 @@
<option name="teardown-command" value="dumpsys sensorservice enable" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.android.cts.hardware" />
+ <option name="package" value="android.hardware.cts" />
</test>
</configuration>
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/input/cts/tests/GamepadTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/GamepadTestCase.java
index 92fba12..2a772ae 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/GamepadTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/GamepadTestCase.java
@@ -22,7 +22,7 @@
import java.io.Writer;
import java.util.List;
-import com.android.cts.hardware.R;
+import android.hardware.cts.R;
public class GamepadTestCase extends InputTestCase {
private static final String TAG = "GamepadTests";
diff --git a/tests/tests/jni/Android.mk b/tests/tests/jni/Android.mk
index b65132d..4b4e770 100644
--- a/tests/tests/jni/Android.mk
+++ b/tests/tests/jni/Android.mk
@@ -32,7 +32,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
-LOCAL_JNI_SHARED_LIBRARIES := libjnitest
+LOCAL_JNI_SHARED_LIBRARIES := libjnitest libnativehelper_compat_libc++
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/jni/libjnitest/Android.mk b/tests/tests/jni/libjnitest/Android.mk
index 396e161..7a2d577 100644
--- a/tests/tests/jni/libjnitest/Android.mk
+++ b/tests/tests/jni/libjnitest/Android.mk
@@ -36,6 +36,9 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog
+LOCAL_SHARED_LIBRARIES := liblog libnativehelper_compat_libc++
+
+LOCAL_SDK_VERSION := 23
+LOCAL_NDK_STL_VARIANT := c++_static
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/jni/libjnitest/helper.c b/tests/tests/jni/libjnitest/helper.c
index 831d5b5..8f7f2f8 100644
--- a/tests/tests/jni/libjnitest/helper.c
+++ b/tests/tests/jni/libjnitest/helper.c
@@ -16,9 +16,10 @@
#include "helper.h"
-#include <cutils/log.h>
+#include <android/log.h>
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#define LOG_TAG "cts"
@@ -29,7 +30,7 @@
char *result;
va_start(args, format);
- LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args);
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, format, args);
va_end(args);
va_start(args, format);
@@ -58,7 +59,7 @@
JniTestFunction *function = va_arg(args, JniTestFunction *);
- ALOGI("running %s", name);
+ __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "running %s", name);
char *oneResult = function(env);
if (oneResult != NULL) {
diff --git a/tests/tests/jni/libjnitest/register.c b/tests/tests/jni/libjnitest/register.c
index 66eb265..b371b8b 100644
--- a/tests/tests/jni/libjnitest/register.c
+++ b/tests/tests/jni/libjnitest/register.c
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-#include <cutils/log.h>
+#include <android/log.h>
#include <jni.h>
#include <stdlib.h>
+#define LOG_TAG "Cts-JniTest"
+
/*
* This function is called automatically by the system when this
* library is loaded. We use it to register all our native functions,
@@ -32,25 +34,25 @@
extern int register_InstanceNonce(JNIEnv *);
if (register_InstanceNonce(env)) {
- ALOGE("failed to register InstanceNonce");
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "failed to register InstanceNonce");
return JNI_ERR;
}
extern int register_StaticNonce(JNIEnv *);
if (register_StaticNonce(env)) {
- ALOGE("failed to register StaticNonce");
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "failed to register StaticNonce");
return JNI_ERR;
}
extern int register_JniCTest(JNIEnv *);
if (register_JniCTest(env)) {
- ALOGE("failed to register JniCTest");
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "failed to register JniCTest");
return JNI_ERR;
}
extern int register_JniCppTest(JNIEnv *);
if (register_JniCppTest(env)) {
- ALOGE("failed to register JniCppTest");
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "failed to register JniCppTest");
return JNI_ERR;
}
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 16989f5..dff08f5 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -32,9 +32,12 @@
# 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
@@ -42,7 +45,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner
-LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni
+LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++
LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -50,11 +53,12 @@
# uncomment when b/13249737 is fixed
#LOCAL_SDK_VERSION := current
+
LOCAL_JAVA_LIBRARIES += android.test.runner org.apache.http.legacy
# Tag this module as a cts_v2 test artifact
LOCAL_COMPATIBILITY_SUITE := cts_v2
-include $(BUILD_PACKAGE)
+include $(BUILD_CTS_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/media/AndroidTest.xml b/tests/tests/media/AndroidTest.xml
index 0465bf1..5131fe4 100644
--- a/tests/tests/media/AndroidTest.xml
+++ b/tests/tests/media/AndroidTest.xml
@@ -18,11 +18,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="module-name" value="CtsMediaTestCases"/>
- <option name="version-name" value="1.0"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.media.cts" />
</test>
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/libmediandkjni/Android.mk b/tests/tests/media/libmediandkjni/Android.mk
index 23f9f5c..51210af 100644
--- a/tests/tests/media/libmediandkjni/Android.mk
+++ b/tests/tests/media/libmediandkjni/Android.mk
@@ -30,6 +30,8 @@
LOCAL_C_INCLUDES += $(call include-path-for, mediandk)
-LOCAL_SHARED_LIBRARIES := libandroid libnativehelper liblog libmediandk
+LOCAL_SHARED_LIBRARIES := libandroid libnativehelper_compat_libc++ liblog libmediandk
+
+LOCAL_SDK_VERSION := 23
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/libmediandkjni/native-media-jni.cpp b/tests/tests/media/libmediandkjni/native-media-jni.cpp
index 2624c25..f15a196 100644
--- a/tests/tests/media/libmediandkjni/native-media-jni.cpp
+++ b/tests/tests/media/libmediandkjni/native-media-jni.cpp
@@ -30,11 +30,11 @@
#include <android/native_window_jni.h>
-#include "ndk/NdkMediaExtractor.h"
-#include "ndk/NdkMediaCodec.h"
-#include "ndk/NdkMediaCrypto.h"
-#include "ndk/NdkMediaFormat.h"
-#include "ndk/NdkMediaMuxer.h"
+#include "media/NdkMediaExtractor.h"
+#include "media/NdkMediaCodec.h"
+#include "media/NdkMediaCrypto.h"
+#include "media/NdkMediaFormat.h"
+#include "media/NdkMediaMuxer.h"
template <class T>
class simplevector {
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index af2145a..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,6 @@
package android.media.cts;
-import com.android.compatibility.common.util.DynamicConfigDeviceSide;
import android.media.cts.R;
import android.content.Context;
@@ -66,6 +65,20 @@
private MediaCodecTunneledPlayer mMediaCodecPlayer;
private static final int SLEEP_TIME_MS = 1000;
private static final long PLAY_TIME_MS = TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES);
+ private static final Uri AUDIO_URL = Uri.parse(
+ "http://redirector.c.youtube.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"); // H.264 Base + AAC
+ private static final Uri VIDEO_URL = Uri.parse(
+ "http://redirector.c.youtube.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"); // H.264 Base + AAC
@Override
protected void setUp() throws Exception {
@@ -1946,11 +1959,8 @@
mMediaCodecPlayer = new MediaCodecTunneledPlayer(
getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
- DynamicConfigDeviceSide config = new DynamicConfigDeviceSide("CtsMediaTestCases");
- Uri audio_url = Uri.parse(config.getConfig("DecoderTest-AUDIO_URL"));
- mMediaCodecPlayer.setAudioDataSource(audio_url, null);
- Uri video_url = Uri.parse(config.getConfig("DecoderTest-VIDEO_URL"));
- mMediaCodecPlayer.setVideoDataSource(video_url, null);
+ mMediaCodecPlayer.setAudioDataSource(AUDIO_URL, null);
+ mMediaCodecPlayer.setVideoDataSource(VIDEO_URL, null);
assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
@@ -1988,11 +1998,8 @@
mMediaCodecPlayer = new MediaCodecTunneledPlayer(
getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
- DynamicConfigDeviceSide config = new DynamicConfigDeviceSide("CtsMediaTestCases");
- Uri audio_url = Uri.parse(config.getConfig("DecoderTest-AUDIO_URL"));
- mMediaCodecPlayer.setAudioDataSource(audio_url, null);
- Uri video_url = Uri.parse(config.getConfig("DecoderTest-VIDEO_URL"));
- mMediaCodecPlayer.setVideoDataSource(video_url, null);
+ mMediaCodecPlayer.setAudioDataSource(AUDIO_URL, null);
+ mMediaCodecPlayer.setVideoDataSource(VIDEO_URL, null);
assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index 7135dab..5b2936b 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -36,8 +36,6 @@
import android.os.Build;
import android.util.Log;
-import com.android.compatibility.common.util.DynamicConfigDeviceSide;
-
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
@@ -174,18 +172,27 @@
return; // skip
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("MediaCodecCapabilitiesTest-testAvcBaseline12");
- playVideoWithRetries(url, 256, 144, PLAY_TIME_MS);
+ playVideoWithRetries("http://redirector.c.youtube.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", 256, 144, PLAY_TIME_MS);
}
public void testAvcBaseline30() throws Exception {
if (!checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileBaseline, AVCLevel3)) {
return; // skip
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("MediaCodecCapabilitiesTest-testAvcBaseline30");
- playVideoWithRetries(url, 640, 360, PLAY_TIME_MS);
+
+ 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"
+ + "&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&signature=7DCDE3A6594D0B91A27676A3CDC3A87B149F82EA."
+ + "7A83031734CB1EDCE06766B6228842F954927960"
+ + "&key=ik0", 640, 360, PLAY_TIME_MS);
}
public void testAvcHigh31() throws Exception {
@@ -193,9 +200,13 @@
return; // skip
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("MediaCodecCapabilitiesTest-testAvcHigh31");
- playVideoWithRetries(url, 1280, 720, PLAY_TIME_MS);
+ 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"
+ + "&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&signature=179525311196616BD8E1381759B0E5F81A9E91B5."
+ + "C4A50E44059FEBCC6BBC78E3B3A4E0E0065777"
+ + "&key=ik0", 1280, 720, PLAY_TIME_MS);
}
public void testAvcHigh40() throws Exception {
@@ -207,9 +218,13 @@
return;
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("MediaCodecCapabilitiesTest-testAvcHigh40");
- playVideoWithRetries(url, 1920, 1080, PLAY_TIME_MS);
+ 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"
+ + "&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&signature=B0976085596DD42DEA3F08307F76587241CB132B."
+ + "043B719C039E8B92F45391ADC0BE3665E2332930"
+ + "&key=ik0", 1920, 1080, PLAY_TIME_MS);
}
public void testHevcMain1() 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 2c2cd2f..e7ae935 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -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/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index a1f380c..0464cb6 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -26,8 +26,6 @@
import android.util.Log;
import android.webkit.cts.CtsTestServer;
-import com.android.compatibility.common.util.DynamicConfigDeviceSide;
-
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
@@ -75,36 +73,51 @@
return; // skip
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("StreamingMediaPlayerTest-testHTTP_H263_AMR_Video1");
- playVideoTest(url, 176, 144);
+ playVideoTest("http://redirector.c.youtube.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", 176, 144);
}
+
public void testHTTP_H263_AMR_Video2() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_H263, MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
return; // skip
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("StreamingMediaPlayerTest-testHTTP_H263_AMR_Video2");
- playVideoTest(url, 176, 144);
+ playVideoTest("http://redirector.c.youtube.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", 176, 144);
}
public void testHTTP_MPEG4SP_AAC_Video1() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
return; // skip
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("StreamingMediaPlayerTest-testHTTP_MPEG4SP_AAC_Video1");
- playVideoTest(url, 176, 144);
+
+ playVideoTest("http://redirector.c.youtube.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", 176, 144);
}
+
public void testHTTP_MPEG4SP_AAC_Video2() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
return; // skip
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("StreamingMediaPlayerTest-testHTTP_MPEG4SP_AAC_Video2");
- playVideoTest(url, 176, 144);
+ playVideoTest("http://redirector.c.youtube.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", 176, 144);
}
public void testHTTP_H264Base_AAC_Video1() throws Exception {
@@ -112,18 +125,25 @@
return; // skip
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("StreamingMediaPlayerTest-testHTTP_H264Base_AAC_Video1");
- playVideoTest(url, 640, 360);
+ playVideoTest("http://redirector.c.youtube.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", 640, 360);
}
+
public void testHTTP_H264Base_AAC_Video2() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
return; // skip
}
- String url = new DynamicConfigDeviceSide("CtsMediaTestCases")
- .getConfig("StreamingMediaPlayerTest-testHTTP_H264Base_AAC_Video2");
- playVideoTest(url, 640, 360);
+ playVideoTest("http://redirector.c.youtube.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", 640, 360);
}
// Streaming HLS video from YouTube
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
index 08097f9..ab5b65d 100644
--- a/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
+++ b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
@@ -16,6 +16,7 @@
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;
@@ -38,13 +39,14 @@
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
-import java.net.MalformedURLException;
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
*/
@@ -66,12 +68,11 @@
*/
protected static final String MEDIA_FOLDER_NAME = "android-cts-media";
- /*
- * The URL from which to download the compressed media files
- * TODO: Find a way to retrieve this programmatically
- */
- private static final String MEDIA_URL_STRING =
- "https://dl.google.com/dl/android/cts/android-cts-media-1.1.zip";
+ /* 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
@@ -227,10 +228,12 @@
URL url;
try {
- url = new URL(MEDIA_URL_STRING);
- } catch (MalformedURLException e) {
- throw new TargetSetupError(
- String.format("Trouble finding android media files at %s", MEDIA_URL_STRING));
+ 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);
diff --git a/tests/tests/net/Android.mk b/tests/tests/net/Android.mk
index 716141d..608ea47 100644
--- a/tests/tests/net/Android.mk
+++ b/tests/tests/net/Android.mk
@@ -27,7 +27,7 @@
LOCAL_JAVA_LIBRARIES := voip-common conscrypt org.apache.http.legacy
LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libnativedns_jni \
- libnativemultinetwork_jni
+ libnativemultinetwork_jni libnativehelper_compat_libc++
# include CtsTestServer as a temporary hack to free net.cts from cts.stub.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/net/jni/Android.mk b/tests/tests/net/jni/Android.mk
index ca82b30..0ec8d28 100644
--- a/tests/tests/net/jni/Android.mk
+++ b/tests/tests/net/jni/Android.mk
@@ -25,8 +25,8 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog
-
+LOCAL_SHARED_LIBRARIES := libnativehelper_compat_libc++ liblog
+LOCAL_CXX_STL := libc++_static
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
@@ -35,5 +35,6 @@
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := NativeMultinetworkJni.c
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-LOCAL_SHARED_LIBRARIES := libandroid libnativehelper liblog
+LOCAL_SHARED_LIBRARIES := libandroid libnativehelper_compat_libc++ liblog
+LOCAL_CXX_STL := libc++_static
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/net/src/org/apache/http/conn/ssl/cts/AbstractVerifierTest.java b/tests/tests/net/src/org/apache/http/conn/ssl/cts/AbstractVerifierTest.java
index 826b7ae..16d3ac4 100644
--- a/tests/tests/net/src/org/apache/http/conn/ssl/cts/AbstractVerifierTest.java
+++ b/tests/tests/net/src/org/apache/http/conn/ssl/cts/AbstractVerifierTest.java
@@ -106,8 +106,8 @@
public void testGetCns_whitespace() {
assertCns("cn= p", "p");
- assertCns("cn=\np", "\np");
- assertCns("cn=\tp", "\tp");
+ assertCns("cn=\np", "p");
+ assertCns("cn=\tp", "p");
}
public void testGetCnsWithOid() {
@@ -140,7 +140,6 @@
private static void assertCns(String dn, String... expected) {
String[] result = AbstractVerifier.getCNs(createStubCertificate(dn));
- System.out.println("Expected is: " + expected.length);
if (expected.length == 0) {
assertNull(result);
} else {
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-false/Android.mk b/tests/tests/netsecpolicy/usescleartexttraffic-false/Android.mk
index 0441f2b..01ea6b7 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-false/Android.mk
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-false/Android.mk
@@ -24,7 +24,7 @@
ctstestserver \
org.apache.http.legacy
-LOCAL_SRC_FILES := $(call all-java-files-under, src ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src common)
LOCAL_PACKAGE_NAME := CtsNetSecPolicyUsesCleartextTrafficFalseTestCases
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-false/common b/tests/tests/netsecpolicy/usescleartexttraffic-false/common
new file mode 120000
index 0000000..5cd551cf
--- /dev/null
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-false/common
@@ -0,0 +1 @@
+../src
\ No newline at end of file
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-true/Android.mk b/tests/tests/netsecpolicy/usescleartexttraffic-true/Android.mk
index 5a4a41d..9f53f18 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-true/Android.mk
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-true/Android.mk
@@ -24,7 +24,7 @@
ctstestserver \
org.apache.http.legacy
-LOCAL_SRC_FILES := $(call all-java-files-under, src ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src common)
LOCAL_PACKAGE_NAME := CtsNetSecPolicyUsesCleartextTrafficTrueTestCases
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-true/common b/tests/tests/netsecpolicy/usescleartexttraffic-true/common
new file mode 120000
index 0000000..5cd551cf
--- /dev/null
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-true/common
@@ -0,0 +1 @@
+../src
\ No newline at end of file
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/Android.mk b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/Android.mk
index faa3c23..fe7d36e 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/Android.mk
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/Android.mk
@@ -24,7 +24,7 @@
ctstestserver \
org.apache.http.legacy
-LOCAL_SRC_FILES := $(call all-java-files-under, src ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src common)
LOCAL_PACKAGE_NAME := CtsNetSecPolicyUsesCleartextTrafficUnspecifiedTestCases
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/common b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/common
new file mode 120000
index 0000000..5cd551cf
--- /dev/null
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/common
@@ -0,0 +1 @@
+../src
\ 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 cb9ad8f..8fbb7d1 100644
--- a/tests/tests/openglperf/Android.mk
+++ b/tests/tests/openglperf/Android.mk
@@ -26,7 +26,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
-LOCAL_JNI_SHARED_LIBRARIES := libctsopenglperf_jni
+LOCAL_JNI_SHARED_LIBRARIES := libctsopenglperf_jni libnativehelper_compat_libc++
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/openglperf/jni/Android.mk b/tests/tests/openglperf/jni/Android.mk
index f67900c..d6df59b2 100644
--- a/tests/tests/openglperf/jni/Android.mk
+++ b/tests/tests/openglperf/jni/Android.mk
@@ -24,7 +24,7 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) $(call include-path-for, system-core) frameworks/native/opengl/include
-LOCAL_SHARED_LIBRARIES := libnativehelper libcutils liblog libEGL
+LOCAL_SHARED_LIBRARIES := libnativehelper_compat_libc++ liblog libEGL
LOCAL_SDK_VERSION := 14
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index 6a2f8f8..0568ef4 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -26,7 +26,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner guava
-LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni
+LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni libnativehelper_compat_libc++
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
src/android/os/cts/IParcelFileDescriptorPeer.aidl \
diff --git a/tests/tests/os/assets/dex1.bytes b/tests/tests/os/assets/dex1.bytes
new file mode 100644
index 0000000..a9f914e
--- /dev/null
+++ b/tests/tests/os/assets/dex1.bytes
Binary files differ
diff --git a/tests/tests/os/jni/Android.mk b/tests/tests/os/jni/Android.mk
index c125f5c..6d2f1dd 100644
--- a/tests/tests/os/jni/Android.mk
+++ b/tests/tests/os/jni/Android.mk
@@ -62,10 +62,11 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog libdl libcutils
+LOCAL_SHARED_LIBRARIES := libnativehelper_compat_libc++ liblog libdl
+LOCAL_CXX_STL := none
LOCAL_SRC_FILES += android_os_cts_CpuFeatures.cpp
LOCAL_C_INCLUDES += ndk/sources/cpufeatures
-LOCAL_STATIC_LIBRARIES := cpufeatures
+LOCAL_STATIC_LIBRARIES := cpufeatures libc++_static
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/os/jni/android_os_cts_HardwareName.cpp b/tests/tests/os/jni/android_os_cts_HardwareName.cpp
index 6752aa3..74b630e 100644
--- a/tests/tests/os/jni/android_os_cts_HardwareName.cpp
+++ b/tests/tests/os/jni/android_os_cts_HardwareName.cpp
@@ -16,15 +16,13 @@
*/
#include <jni.h>
-#include <cutils/properties.h>
+#include <sys/system_properties.h>
jstring android_os_cts_HardwareName_getName(JNIEnv* env, jobject thiz)
{
- char name[PROPERTY_VALUE_MAX];
- int ret;
+ char name[PROP_VALUE_MAX];
- ret = property_get("ro.boot.hardware", name, NULL);
- if (ret <= 0) {
+ if (__system_property_get("ro.boot.hardware", name) <= 0) {
return NULL;
}
diff --git a/tests/tests/os/src/android/os/cts/CustomClassLoaderTest.java b/tests/tests/os/src/android/os/cts/CustomClassLoaderTest.java
new file mode 100644
index 0000000..bd88073
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/CustomClassLoaderTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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 java.io.*;
+import java.lang.reflect.*;
+
+import android.test.AndroidTestCase;
+
+public class CustomClassLoaderTest extends AndroidTestCase {
+ File tf;
+
+ @Override
+ public void setUp() throws Exception {
+ /*
+ * dex1.bytes is a jar file with a classes.dex in it.
+ * The classes.dex has been javac'ed and dx'ed
+ * with the following java file:
+ *
+ * package android.os.cts;
+ * public class TestClass {
+ * public static final String MESSAGE = "expected_field";
+ * }
+ *
+ */
+
+ super.setUp();
+ // Extract the packaged dex/jar file to a temporary file so we
+ // can use it with our classloader.
+ tf = File.createTempFile("CustomClassLoaderTest_TestClass", ".dex");
+ tf.deleteOnExit();
+ InputStream is = mContext.getAssets().open("dex1.bytes");
+ assertNotNull(is);
+ OutputStream fos = new FileOutputStream(tf);
+ byte[] buffer = new byte[8192];
+ int len = is.read(buffer);
+ while (len != -1) {
+ fos.write(buffer, 0, len);
+ len = is.read(buffer);
+ }
+ fos.flush();
+ fos.close();
+ }
+
+ /* Test a custom class loader based on the DexClassLoader.
+ */
+ public void testCustomDexClassLoader() throws Exception {
+ // Try to load the TestClass class by the CustomDexClassLoader.
+ try {
+ CustomDexClassLoader cl = new CustomDexClassLoader(
+ tf.getAbsolutePath(),
+ mContext.getCodeCacheDir().getAbsolutePath(),
+ ClassLoader.getSystemClassLoader().getParent());
+ // Load the class and get the field 'MESSAGE' and
+ // check that it is from the dex1.bytes .jar file.
+ Field field = cl.loadClass("android.os.cts.TestClass").getField("MESSAGE");
+ assertTrue(((String)field.get(null)).equals("expected_field"));
+ } catch (Exception e) {
+ throw new RuntimeException("test exception", e);
+ }
+ }
+
+ /* Test a custom class loader based on the PathClassLoader.
+ */
+ public void testCustomPathClassLoader() throws Exception {
+ // Try to load the TestClass class by the CustomPathClassLoader.
+ try {
+ CustomPathClassLoader cl = new CustomPathClassLoader(
+ tf.getAbsolutePath(),
+ ClassLoader.getSystemClassLoader().getParent());
+ // Load the class and get the field 'MESSAGE' and
+ // check that it is from the dex1.bytes .jar file.
+ Field field = cl.loadClass("android.os.cts.TestClass").getField("MESSAGE");
+ assertTrue(((String)field.get(null)).equals("expected_field"));
+ } catch (Exception e) {
+ throw new RuntimeException("test exception", e);
+ }
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java b/tests/tests/os/src/android/os/cts/CustomDexClassLoader.java
similarity index 61%
copy from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
copy to tests/tests/os/src/android/os/cts/CustomDexClassLoader.java
index dfedccb..c009bd8 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
+++ b/tests/tests/os/src/android/os/cts/CustomDexClassLoader.java
@@ -14,19 +14,14 @@
* limitations under the License.
*/
-package com.android.cts.deviceandprofileowner;
+package android.os.cts;
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
+import dalvik.system.DexClassLoader;
-/**
- * a basic Mock Service for wrapping the MockAccountAuthenticator
- */
-public class MockAccountService extends Service {
+// Trivial subclass of DexClassLoader
+public class CustomDexClassLoader extends DexClassLoader {
- @Override
- public IBinder onBind(Intent intent) {
- return MockAccountAuthenticator.getMockAuthenticator(this).getIBinder();
+ public CustomDexClassLoader(String dexPath, String optimizedDirectory, ClassLoader parent) {
+ super(dexPath, optimizedDirectory, null, parent);
}
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java b/tests/tests/os/src/android/os/cts/CustomPathClassLoader.java
similarity index 61%
copy from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
copy to tests/tests/os/src/android/os/cts/CustomPathClassLoader.java
index dfedccb..f7bdb51 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
+++ b/tests/tests/os/src/android/os/cts/CustomPathClassLoader.java
@@ -14,19 +14,14 @@
* limitations under the License.
*/
-package com.android.cts.deviceandprofileowner;
+package android.os.cts;
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
+import dalvik.system.PathClassLoader;
-/**
- * a basic Mock Service for wrapping the MockAccountAuthenticator
- */
-public class MockAccountService extends Service {
+// Trivial subclass of PathClassLoader
+public class CustomPathClassLoader extends PathClassLoader {
- @Override
- public IBinder onBind(Intent intent) {
- return MockAccountAuthenticator.getMockAuthenticator(this).getIBinder();
+ public CustomPathClassLoader(String dexPath, ClassLoader parent) {
+ super(dexPath, parent);
}
}
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index d63f8bc..2407309 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -16,6 +16,7 @@
package android.os.cts;
+import android.content.pm.PackageManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.test.AndroidTestCase;
@@ -48,6 +49,11 @@
}
public void testCleartextNetwork() throws Exception {
+ if (!hasInternetConnection()) {
+ Log.i(TAG, "testCleartextNetwork() ignored on device without Internet");
+ return;
+ }
+
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectCleartextNetwork()
.penaltyLog()
@@ -66,6 +72,11 @@
}
public void testEncryptedNetwork() throws Exception {
+ if (!hasInternetConnection()) {
+ Log.i(TAG, "testEncryptedNetwork() ignored on device without Internet");
+ return;
+ }
+
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectCleartextNetwork()
.penaltyLog()
@@ -95,4 +106,11 @@
Log.d(TAG, "Log output was " + buf.size() + " bytes, exit code " + res);
return new String(buf.toByteArray());
}
+
+ private boolean hasInternetConnection() {
+ // TODO: expand this to include devices with ethernet
+ final PackageManager pm = getContext().getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
+ || pm.hasSystemFeature(PackageManager.FEATURE_WIFI);
+ }
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java b/tests/tests/os/src/android/os/cts/TestClass.java
similarity index 60%
copy from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
copy to tests/tests/os/src/android/os/cts/TestClass.java
index dfedccb..f0959bc 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
+++ b/tests/tests/os/src/android/os/cts/TestClass.java
@@ -14,19 +14,9 @@
* limitations under the License.
*/
-package com.android.cts.deviceandprofileowner;
+package android.os.cts;
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
+public class TestClass {
-/**
- * a basic Mock Service for wrapping the MockAccountAuthenticator
- */
-public class MockAccountService extends Service {
-
- @Override
- public IBinder onBind(Intent intent) {
- return MockAccountAuthenticator.getMockAuthenticator(this).getIBinder();
- }
+ public static final String MESSAGE = "WRONG_FIELD";
}
diff --git a/tests/tests/permission/Android.mk b/tests/tests/permission/Android.mk
index 58c4f08..0b79ceb 100644
--- a/tests/tests/permission/Android.mk
+++ b/tests/tests/permission/Android.mk
@@ -31,7 +31,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner guava android-ex-camera2
-LOCAL_JNI_SHARED_LIBRARIES := libctspermission_jni
+LOCAL_JNI_SHARED_LIBRARIES := libctspermission_jni libnativehelper_compat_libc++
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/permission/jni/Android.mk b/tests/tests/permission/jni/Android.mk
index 44e742e..ea45096 100644
--- a/tests/tests/permission/jni/Android.mk
+++ b/tests/tests/permission/jni/Android.mk
@@ -27,6 +27,7 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog
+LOCAL_SHARED_LIBRARIES := libnativehelper_compat_libc++ liblog
+LOCAL_SDK_VERSION := 23
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp b/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp
index 8f32027..0547be4 100644
--- a/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp
+++ b/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
+#include <android/log.h>
#include <jni.h>
#include <stdio.h>
-#include <cutils/log.h>
#include <linux/xattr.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -104,7 +104,8 @@
sizeof(capData));
if (result <= 0)
{
- ALOGD("isPermittedCapBitSet(): getxattr(\"%s\") call failed: "
+ __android_log_print(ANDROID_LOG_DEBUG, NULL,
+ "isPermittedCapBitSet(): getxattr(\"%s\") call failed: "
"return %d (error: %s (%d))\n",
cPath.c_str(), result, strerror(errno), errno);
return false;
@@ -132,7 +133,8 @@
ScopedLocalRef<jclass> eClazz(env, env->FindClass(className));
if (eClazz.get() == NULL)
{
- ALOGE("throwNamedException(): failed to find class %s, cannot throw",
+ __android_log_print(ANDROID_LOG_ERROR, NULL,
+ "throwNamedException(): failed to find class %s, cannot throw",
className);
return false;
}
@@ -186,7 +188,8 @@
sizeof(actualCapData));
if (result <= 0)
{
- ALOGD("fileHasOnly(): getxattr(\"%s\") call failed: "
+ __android_log_print(ANDROID_LOG_DEBUG, NULL,
+ "fileHasOnly(): getxattr(\"%s\") call failed: "
"return %d (error: %s (%d))\n",
cPath.c_str(), result, strerror(errno), errno);
return false;
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index 7096757..d20e550 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -19,7 +19,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Environment;
-import android.os.SystemProperties;
import android.system.Os;
import android.system.OsConstants;
import android.system.StructStatVfs;
@@ -374,7 +373,6 @@
@MediumTest
public void testDeviceTreeCpuCurrent() throws Exception {
String arch = System.getProperty("os.arch");
- String flavor = SystemProperties.get("ro.build.flavor");
String[] osVersion = System.getProperty("os.version").split("\\.");
/*
* Perform the test for only arm-based architecture and
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
index 577e29a..2b62504 100644
--- a/tests/tests/print/src/android/print/cts/BasePrintTest.java
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -78,21 +78,15 @@
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;
/**
@@ -422,9 +416,9 @@
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));
+ 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,
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..f325c1b
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/PrinterInfoTest.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.print.cts;
+
+import android.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
+ RuntimeException e = null;
+ PrinterId printerId = null;
+ try {
+ if (localPrinterId == null) {
+ printerId = mDiscoverySession
+ .getService()
+ .generatePrinterId(
+ localPrinterId);
+ } else {
+ printerId = mDiscoverySession
+ .getService()
+ .generatePrinterId(
+ localPrinterId
+ + printers
+ .size());
+ }
+ } catch (RuntimeException ex) {
+ e = ex;
+ }
+
+ // Expect exception if localId is null
+ if (localPrinterId == null) {
+ if (e == null) {
+ throw new IllegalStateException();
+ }
+ } else if (e != null) {
+ throw e;
+ }
+
+ // Constructor
+ PrinterInfo.Builder b = null;
+ 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/provider/Android.mk b/tests/tests/provider/Android.mk
index d9642d3b..6542c81 100644
--- a/tests/tests/provider/Android.mk
+++ b/tests/tests/provider/Android.mk
@@ -34,7 +34,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-LOCAL_JNI_SHARED_LIBRARIES := libcts_jni
+LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libnativehelper_compat_libc++
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index ecd7aba..a6e7a45 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -74,7 +74,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy
-LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni libcts_jni
+LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni libcts_jni libnativehelper_compat_libc++
LOCAL_SRC_FILES := $(call all-java-files-under, src)\
src/android/security/cts/activity/ISecureRandomService.aidl
diff --git a/tests/tests/security/jni/android_security_cts_MediaCryptoTest.cpp b/tests/tests/security/jni/android_security_cts_MediaCryptoTest.cpp
new file mode 100644
index 0000000..abb26eb
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_MediaCryptoTest.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Original code copied from NDK Native-media sample code */
+
+//#define LOG_NDEBUG 0
+#define TAG "NativeMediaCrypto"
+#include <log/log.h>
+
+#include <android_media_MediaCrypto.h>
+#include <assert.h>
+#include <binder/MemoryDealer.h>
+#include <jni.h>
+#include <media/ICrypto.h>
+#include <media/stagefright/foundation/AString.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <utils/StrongPointer.h>
+#include <semaphore.h>
+
+
+static const size_t kBufferSize = 1024;
+
+using namespace android;
+
+static jboolean testCrypto(sp<ICrypto> icrypto,
+ const CryptoPlugin::SubSample *subSample, CryptoPlugin::Mode mode)
+{
+ // Allocate source buffer
+ sp<MemoryDealer> memDealer = new MemoryDealer(kBufferSize, "MediaCryptoTest");
+ sp<IMemory> srcBuffer = memDealer->allocate(kBufferSize);
+ if (!srcBuffer->pointer()) {
+ ALOGE("Failed to allocate source buffer");
+ return false;
+ }
+ memset(srcBuffer->pointer(), 's', kBufferSize);
+
+ // Invalid dest pointer should fault if mediaserver attempts
+ // to write to it. Don't use NULL because that's probably
+ // checked for.
+ void *dstPtr = reinterpret_cast<void *>(1);
+
+ // Spoof the device as being secure
+ bool secure = true;
+
+ uint8_t key[16] = {0};
+ uint8_t iv[16] = {0};
+ uint32_t offset = 0;
+ AString errorDetailMsg;
+
+ ssize_t result = icrypto->decrypt(secure, key, iv, mode, srcBuffer, offset,
+ subSample, 1, dstPtr, &errorDetailMsg);
+
+ // call should return an error and shouldn't kill media server
+ return (result != OK && result != DEAD_OBJECT);
+}
+
+// Test for icrypto interface vulnerabilities
+extern "C" jboolean Java_android_security_cts_MediaCryptoTest_validateCryptoNative(JNIEnv *env,
+ jclass /*clazz*/, jobject crypto)
+{
+ bool result = false;
+ sp<ICrypto> icrypto = JCrypto::GetCrypto(env, crypto);
+ if (icrypto != NULL) {
+ if (icrypto->requiresSecureDecoderComponent("video/avc")) {
+ ALOGI("device is secure, bypassing test");
+ return true;
+ }
+
+ CryptoPlugin::Mode unencryptedMode = CryptoPlugin::kMode_Unencrypted;
+ CryptoPlugin::Mode aesCtrMode = CryptoPlugin::kMode_AES_CTR;
+
+ CryptoPlugin::SubSample clrSubSample = {kBufferSize, 0};
+ CryptoPlugin::SubSample encSubSample = {0, kBufferSize};
+
+ result =
+ testCrypto(icrypto, &clrSubSample, unencryptedMode) &&
+ testCrypto(icrypto, &clrSubSample, aesCtrMode) &&
+ testCrypto(icrypto, &encSubSample, unencryptedMode) &&
+ testCrypto(icrypto, &encSubSample, aesCtrMode);
+ } else {
+ ALOGE("Failed to get icrypto interface");
+ }
+ return result;
+}
+
+
+
diff --git a/tests/tests/security/res/raw/bug_25765591.mp2 b/tests/tests/security/res/raw/bug_25765591.mp2
new file mode 100644
index 0000000..200f5751
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_25765591.mp2
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_25812590.mp2 b/tests/tests/security/res/raw/bug_25812590.mp2
new file mode 100644
index 0000000..dbde03e
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_25812590.mp2
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_26070014.mp2 b/tests/tests/security/res/raw/bug_26070014.mp2
new file mode 100644
index 0000000..ccb8e41
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_26070014.mp2
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_26366256.midi b/tests/tests/security/res/raw/bug_26366256.midi
new file mode 100644
index 0000000..5114d92
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_26366256.midi
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/HttpPost.java b/tests/tests/security/src/android/security/cts/HttpPost.java
new file mode 100644
index 0000000..7f855d9
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/HttpPost.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.annotation.SuppressLint;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.util.Log;
+import android.util.Pair;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * HttpPost utility functions.
+ */
+public final class HttpPost {
+ private static final String TAG = "HttpPost";
+
+ private HttpPost() {}
+
+ /**
+ * Executes a post request using {@link HttpURLConnection}.
+ *
+ * @param url The request URL.
+ * @param data The request body, or null.
+ * @param requestProperties Request properties, or null.
+ * @return The response code and body.
+ * @throws IOException If an error occurred making the request.
+ */
+ public static Pair<Integer, byte[]> execute(String url, byte[] data,
+ Map<String, String> requestProperties) throws IOException {
+ HttpURLConnection urlConnection = null;
+ try {
+ urlConnection = (HttpURLConnection) new URL(url).openConnection();
+ urlConnection.setRequestMethod("POST");
+ urlConnection.setDoOutput(data != null);
+ urlConnection.setDoInput(true);
+ urlConnection.setConnectTimeout(5000);
+ urlConnection.setReadTimeout(5000);
+ if (requestProperties != null) {
+ for (Map.Entry<String, String> requestProperty : requestProperties.entrySet()) {
+ urlConnection.setRequestProperty(requestProperty.getKey(),
+ requestProperty.getValue());
+ }
+ }
+ // Write the request body, if there is one.
+ if (data != null) {
+ OutputStream out = urlConnection.getOutputStream();
+ try {
+ out.write(data);
+ } finally {
+ out.close();
+ }
+ }
+ // Read the response code.
+ int responseCode = urlConnection.getResponseCode();
+ // Read the response body.
+ InputStream inputStream = urlConnection.getInputStream();
+ try {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ byte scratch[] = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(scratch)) != -1) {
+ byteArrayOutputStream.write(scratch, 0, bytesRead);
+ }
+ byte[] responseBody = byteArrayOutputStream.toByteArray();
+ Log.d(TAG, "responseCode=" + responseCode + ", length=" + responseBody.length);
+ return Pair.create(responseCode, responseBody);
+ } finally {
+ inputStream.close();
+ }
+ } finally {
+ if (urlConnection != null) {
+ urlConnection.disconnect();
+ }
+ }
+ }
+
+}
diff --git a/tests/tests/security/src/android/security/cts/KeyRequester.java b/tests/tests/security/src/android/security/cts/KeyRequester.java
new file mode 100644
index 0000000..26a3337
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/KeyRequester.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 android.security.cts;
+
+import android.media.DeniedByServerException;
+import android.media.MediaDrm;
+import android.media.NotProvisionedException;
+import android.util.Log;
+import android.util.Pair;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class KeyRequester {
+ private final String TAG = "KeyRequester";
+ private final int MAX_RETRY_COUNT = 3;
+ private final int POOL_SIZE = 1;
+ private final int POOL_TERMINATION_MS_TIMEOUT = 3000; // in milliseconds
+ private final int KEYREQUEST_MS_TIMEOUT = 5000; // in milliseconds
+
+ private byte[] mPssh;
+ private ExecutorService mExecutorService;
+ private Future<byte[]> mFuture;
+ private String mDefaultHeartbeatUrl;
+ private String mServerUrl;
+
+ public KeyRequester(byte[] pssh, String url) {
+ mPssh = pssh;
+ mServerUrl = url;
+ }
+
+ public final String getDefaultHeartbeatUrl() {
+ return mDefaultHeartbeatUrl;
+ }
+
+ public byte[] doTransact(final MediaDrm drm, final byte[] sessionId, final int keyType) {
+ boolean retryRequest;
+ boolean retryTransaction;
+ byte[] keySetIdResult;
+ int getKeyRequestRetryCount;
+ int provisioningRetryCount = 0;
+ MediaDrm.KeyRequest drmRequest;
+
+ mExecutorService = Executors.newFixedThreadPool(POOL_SIZE);
+
+ do {
+ drmRequest = null;
+ getKeyRequestRetryCount = 0;
+ keySetIdResult = null;
+ retryTransaction = false;
+
+ do {
+ retryRequest = false;
+
+ try {
+ drmRequest = drm.getKeyRequest(sessionId, mPssh,
+ "video/avc", keyType, null);
+ } catch (NotProvisionedException e) {
+ Log.i(TAG, "Invalid certificate, reprovisioning");
+ ProvisionRequester provisionRequester = new ProvisionRequester();
+ provisionRequester.doTransact(drm);
+ retryRequest = true;
+ }
+ } while (retryRequest && ++getKeyRequestRetryCount < MAX_RETRY_COUNT);
+
+ if (drmRequest == null) {
+ Log.e(TAG, "Failed to get key request");
+ return null;
+ }
+
+ try {
+ mFuture = mExecutorService.submit(new KeyRequesterTask(mServerUrl, drmRequest));
+ } catch (RejectedExecutionException e) {
+ Log.e(TAG, "Failed to submit KeyRequesterTask for execution", e);
+ if (++provisioningRetryCount < MAX_RETRY_COUNT) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ try {
+ byte[] responseBody = mFuture.get(KEYREQUEST_MS_TIMEOUT, TimeUnit.MILLISECONDS);
+ if (responseBody == null) {
+ Log.e(TAG, "No response from license server!");
+ retryTransaction = true;
+ } else {
+ byte[] drmResponse = parseResponseBody(responseBody);
+ try {
+ keySetIdResult = drm.provideKeyResponse(sessionId, drmResponse);
+ } catch (NotProvisionedException e) {
+ Log.i(TAG, "Response invalidated the certificate, reprovisioning");
+ ProvisionRequester provisionRequester = new ProvisionRequester();
+ provisionRequester.doTransact(drm);
+ retryTransaction = true;
+ } catch (DeniedByServerException e) {
+ // informational, the event handler will take care of provisioning
+ Log.i(TAG, "Server rejected the key request");
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "provideKeyResponse failed", e);
+ }
+
+ try {
+ // first call to getKeyRequest does not return heartbeat url
+ drmRequest = drm.getKeyRequest(sessionId, mPssh, "video/avc",
+ keyType, null);
+ try {
+ mDefaultHeartbeatUrl = drmRequest.getDefaultUrl();
+ } catch (Exception e) {
+ // ignore
+ }
+ } catch (NotProvisionedException e) {
+ Log.e(TAG, "Fails to get heartbeat url");
+ }
+ break;
+ }
+ } catch (ExecutionException | InterruptedException ex) {
+ Log.e(TAG, "Failed to execute KeyRequesterTask", ex);
+ shutdownAndAwaitTermination(mExecutorService);
+ return null;
+ } catch (TimeoutException te) {
+ // The request timed out. The network is possibly too slow.
+ // Cancel the running task.
+ Log.d(TAG, "Request timed out, retry...");
+ mFuture.cancel(true);
+ retryTransaction = true;
+ }
+ } while (retryTransaction && ++provisioningRetryCount < MAX_RETRY_COUNT);
+
+ shutdownAndAwaitTermination(mExecutorService);
+ return keySetIdResult;
+ }
+
+ private void shutdownAndAwaitTermination(ExecutorService pool) {
+ pool.shutdown(); // disable new tasks from being submitted
+ try {
+ // wait for existing tasks to terminate
+ if (!pool.awaitTermination(POOL_TERMINATION_MS_TIMEOUT, TimeUnit.MILLISECONDS)) {
+ pool.shutdownNow();
+ // wait for tasks to respond to being cancelled
+ if (!pool.awaitTermination(POOL_TERMINATION_MS_TIMEOUT, TimeUnit.MILLISECONDS))
+ Log.e(TAG, "Pool did not terminate");
+ }
+ } catch (InterruptedException ie) {
+ // (Re-)Cancel if current thread also interrupted
+ pool.shutdownNow();
+ // Preserve interrupt status
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ // Validate the response body and return the drmResponse blob.
+ private byte[] parseResponseBody(byte[] responseBody) {
+ String bodyString = null;
+ try {
+ bodyString = new String(responseBody, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+
+ if (bodyString == null) {
+ return null;
+ }
+
+ if (bodyString.startsWith("GLS/")) {
+ if (!bodyString.startsWith("GLS/1.")) {
+ Log.e(TAG, "Invalid server version, expected 1.x");
+ return null;
+ }
+ int drmMessageOffset = bodyString.indexOf("\r\n\r\n");
+ if (drmMessageOffset == -1) {
+ Log.e(TAG, "Invalid server response, could not locate drm message");
+ return null;
+ }
+ responseBody = Arrays.copyOfRange(responseBody, drmMessageOffset + 4,
+ responseBody.length);
+ }
+ return responseBody;
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/KeyRequesterTask.java b/tests/tests/security/src/android/security/cts/KeyRequesterTask.java
new file mode 100644
index 0000000..c4d96dd
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/KeyRequesterTask.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.media.MediaDrm;
+import android.util.Log;
+import android.util.Pair;
+
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.HashMap;
+
+public class KeyRequesterTask implements Callable<byte[]> {
+ private static final String TAG = "KeyRequesterTask";
+ private final MediaDrm.KeyRequest mDrmRequest;
+ private final String mUrl;
+
+ public KeyRequesterTask(String url, MediaDrm.KeyRequest drmRequest) {
+ mDrmRequest = drmRequest;
+ mUrl = url;
+ }
+
+ /**
+ * @return a byte array containing the license response if successful,
+ * {@code null} otherwise.
+ */
+ @Override
+ public byte[] call() throws Exception {
+ byte[] drmRequest = mDrmRequest.getData();
+ Log.d(TAG, "PostRequest:" + mUrl);
+
+ HashMap<String, String> headers = new HashMap<>();
+ headers.put("User-Agent", "Widevine CDM v1.0");
+ headers.put("Connection", "close");
+
+ try {
+ Pair<Integer, byte[]> response = HttpPost.execute(mUrl, drmRequest, headers);
+ int responseCode = response.first;
+ if (responseCode != 200) {
+ Log.d(TAG, "Server returned HTTP error code " + responseCode);
+ return null;
+ }
+ return response.second;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
+
diff --git a/tests/tests/security/src/android/security/cts/MediaCryptoTest.java b/tests/tests/security/src/android/security/cts/MediaCryptoTest.java
new file mode 100644
index 0000000..b5639a7
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MediaCryptoTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.media.MediaCrypto;
+import android.media.MediaCryptoException;
+import android.media.MediaDrm;
+import android.media.MediaDrmException;
+import android.media.NotProvisionedException;
+import android.media.ResourceBusyException;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import java.util.UUID;
+
+public class MediaCryptoTest extends AndroidTestCase {
+ private static final String TAG = "MediaCryptoTest";
+
+ private static final UUID CLEARKEY_SCHEME_UUID =
+ new UUID(0x1077efecc0b24d02L, 0xace33c1e52e2fb4bL);
+ private static final UUID WIDEVINE_SCHEME_UUID =
+ new UUID(0xedef8ba979d64aceL, 0xa3c827dcd51d21edL);
+
+ static {
+ System.loadLibrary("ctssecurity_jni");
+ }
+
+ private native boolean validateCryptoNative(MediaCrypto crypto);
+
+ public void testMediaCryptoClearKey() throws Exception {
+ MediaCrypto crypto = null;
+ if (!MediaDrm.isCryptoSchemeSupported(CLEARKEY_SCHEME_UUID)) {
+ Log.i(TAG, "No ClearKey plugin, skipping test");
+ return;
+ }
+ try {
+ byte[] initData = new byte[0];
+ crypto = new MediaCrypto(CLEARKEY_SCHEME_UUID, initData);
+ } catch (MediaCryptoException e) {
+ throw new Error("Failed to create MediaCrypto using ClearKey plugin");
+ }
+
+ assertTrue("MediaCrypto validation failed", validateCryptoNative(crypto));
+ }
+
+ public void testMediaCryptoWidevine() throws Exception {
+ if (!MediaDrm.isCryptoSchemeSupported(WIDEVINE_SCHEME_UUID)) {
+ Log.i(TAG, "No Widevine plugin, skipping test");
+ return;
+ }
+
+ MediaDrm drm = null;
+ byte[] sessionId = null;
+
+ try {
+ drm = new MediaDrm(WIDEVINE_SCHEME_UUID);
+ sessionId = openSession(drm);
+ getWidevineKeys(drm, sessionId);
+ MediaCrypto crypto = new MediaCrypto(WIDEVINE_SCHEME_UUID, sessionId);
+ assertTrue("MediaCrypto validation failed", validateCryptoNative(crypto));
+ } catch (MediaCryptoException | MediaDrmException e) {
+ if (drm != null && sessionId != null) {
+ drm.closeSession(sessionId);
+ }
+ throw e;
+ }
+ }
+
+ private byte[] openSession(MediaDrm drm) throws Exception {
+ byte[] sessionId = null;
+ int retryCount = 3;
+ while (retryCount-- > 0) {
+ try {
+ return drm.openSession();
+ } catch (NotProvisionedException e) {
+ Log.i(TAG, "Missing certificate, provisioning");
+ ProvisionRequester provisionRequester = new ProvisionRequester();
+ provisionRequester.doTransact(drm);
+ } catch (ResourceBusyException e) {
+ Log.w(TAG, "Resource busy in openSession, retrying...");
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
+ // ignore
+ }
+ }
+ }
+ throw new Error("Failed to open session");
+ }
+
+ private void getWidevineKeys(MediaDrm drm, byte[] sessionId) throws Exception {
+ final String kKeyServerUrl = "https://jmt17.google.com/video/license/GetCencLicense";
+ final byte[] kPssh = hex2ba("08011210e02562e04cd55351b14b3d748d36ed8e");
+ final String kClientAuth = "?source=YOUTUBE&video_id=EGHC6OHNbOo&oauth=ya.gtsqawidevine";
+ final String kPort = "80";
+ KeyRequester keyRequester = new KeyRequester(kPssh, kKeyServerUrl + ":" + kPort + kClientAuth);
+ if (keyRequester.doTransact(drm, sessionId, MediaDrm.KEY_TYPE_STREAMING) == null) {
+ throw new Error("Failed to get keys from license server!");
+ }
+ }
+
+ private static byte[] hex2ba(String s) {
+ int len = s.length();
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ + Character.digit(s.charAt(i+1), 16));
+ }
+ return data;
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/ProvisionRequester.java b/tests/tests/security/src/android/security/cts/ProvisionRequester.java
new file mode 100644
index 0000000..ee1cb9e
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/ProvisionRequester.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.media.DeniedByServerException;
+import android.media.MediaDrm;
+import android.util.Log;
+import android.util.Pair;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+public class ProvisionRequester {
+ private final String TAG = "ProvisionRequester";
+
+ public ProvisionRequester() {
+ }
+
+ public void doTransact(final MediaDrm drm) {
+ Thread t = new Thread() {
+ @Override
+ public void run() {
+ MediaDrm.ProvisionRequest drmRequest;
+ drmRequest = drm.getProvisionRequest();
+ byte[] responseBody = postRequest(drmRequest.getDefaultUrl(),
+ drmRequest.getData());
+
+ if (responseBody == null) {
+ Log.e(TAG, "No response from provisioning server!");
+ } else {
+ try {
+ drm.provideProvisionResponse(responseBody);
+ } catch (DeniedByServerException e) {
+ Log.e(TAG, "Server denied provisioning request");
+ }
+ }
+ }
+ };
+ t.start();
+
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ }
+ }
+
+ // TODO May want to throw exceptions without having try/catch in body.
+ private byte[] postRequest(String url, byte[] drmRequest) {
+ String signedUrl = url + "&signedRequest=" + new String(drmRequest);
+ Log.d(TAG, "PostRequest:" + signedUrl);
+
+ HashMap<String, String> headers = new HashMap<>();
+ headers.put("Accept", "*/*");
+ headers.put("User-Agent", "Widevine CDM v1.0");
+ headers.put("Content-Type", "application/json");
+ headers.put("Connection", "close");
+
+ try {
+ Pair<Integer, byte[]> response = HttpPost.execute(signedUrl, null, headers);
+ int responseCode = response.first;
+ if (responseCode != 200) {
+ Log.e(TAG, "Server returned HTTP error code " + responseCode);
+ return null;
+ }
+ return response.second;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private void sleep(int msec) {
+ try {
+ Thread.sleep(msec);
+ } catch (InterruptedException e) {
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 6e6ae25..1d93243 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -26,12 +26,24 @@
import android.util.Log;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.graphics.SurfaceTexture;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
import android.media.MediaPlayer;
+import android.opengl.GLES20;
+import android.opengl.GLES11Ext;
import android.os.Looper;
+import android.os.SystemClock;
import android.test.InstrumentationTestCase;
import android.util.Log;
+import android.view.Surface;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -45,6 +57,8 @@
public class StagefrightTest extends InstrumentationTestCase {
static final String TAG = "StagefrightTest";
+ private final long TIMEOUT_NS = 10000000000L; // 10 seconds.
+
public StagefrightTest() {
}
@@ -96,14 +110,65 @@
doStagefrightTest(R.raw.cve_2015_6598);
}
+ public void testStagefright_bug_26366256() throws Exception {
+ doStagefrightTest(R.raw.bug_26366256);
+ }
+
+ public void testStagefright_bug_25765591() throws Exception {
+ doStagefrightTest(R.raw.bug_25765591);
+ }
+
+ public void testStagefright_bug_25812590() throws Exception {
+ doStagefrightTest(R.raw.bug_25812590);
+ }
+
+ public void testStagefright_bug_26070014() throws Exception {
+ doStagefrightTest(R.raw.bug_26070014);
+ }
+
private void doStagefrightTest(final int rid) throws Exception {
+ doStagefrightTestMediaPlayer(rid);
+ doStagefrightTestMediaCodec(rid);
+ }
+
+ private Surface getDummySurface() {
+ int[] textures = new int[1];
+ GLES20.glGenTextures(1, textures, 0);
+ GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
+ GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_MIN_FILTER,
+ GLES20.GL_NEAREST);
+ GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_MAG_FILTER,
+ GLES20.GL_LINEAR);
+ GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_WRAP_S,
+ GLES20.GL_CLAMP_TO_EDGE);
+ GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_WRAP_T,
+ GLES20.GL_CLAMP_TO_EDGE);
+ SurfaceTexture surfaceTex = new SurfaceTexture(textures[0]);
+ surfaceTex.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
+ @Override
+ public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+ Log.i(TAG, "new frame available");
+ }
+ });
+ return new Surface(surfaceTex);
+ }
+
+ private void doStagefrightTestMediaPlayer(final int rid) throws Exception {
class MediaPlayerCrashListener
implements MediaPlayer.OnErrorListener,
MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener {
@Override
public boolean onError(MediaPlayer mp, int newWhat, int extra) {
- what = newWhat;
+ Log.i(TAG, "error: " + newWhat);
+ // don't overwrite a more severe error with a less severe one
+ if (what != MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
+ what = newWhat;
+ }
lock.lock();
condition.signal();
lock.unlock();
@@ -118,7 +183,7 @@
@Override
public void onCompletion(MediaPlayer mp) {
- what = 0;
+ // preserve error condition, if any
lock.lock();
condition.signal();
lock.unlock();
@@ -126,8 +191,16 @@
public int waitForError() throws InterruptedException {
lock.lock();
- condition.await();
+ if (condition.awaitNanos(TIMEOUT_NS) <= 0) {
+ Log.d(TAG, "timed out on waiting for error");
+ }
lock.unlock();
+ if (what != 0) {
+ // Sometimes mediaserver signals a decoding error first, and *then* crashes
+ // due to additional in-flight buffers being processed, so wait a little
+ // and see if more errors show up.
+ SystemClock.sleep(1000);
+ }
return what;
}
@@ -136,6 +209,9 @@
int what;
}
+ String name = getInstrumentation().getContext().getResources().getResourceEntryName(rid);
+ Log.i(TAG, "start mediaplayer test for: " + name);
+
final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
Thread t = new Thread(new Runnable() {
@@ -147,6 +223,8 @@
mp.setOnErrorListener(mpcl);
mp.setOnPreparedListener(mpcl);
mp.setOnCompletionListener(mpcl);
+ Surface surface = getDummySurface();
+ mp.setSurface(surface);
try {
AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
.openRawResourceFd(rid);
@@ -165,10 +243,84 @@
});
t.start();
- String name = getInstrumentation().getContext().getResources().getResourceEntryName(rid);
String cve = name.replace("_", "-").toUpperCase();
assertFalse("Device *IS* vulnerable to " + cve,
mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
t.interrupt();
}
+
+ private void doStagefrightTestMediaCodec(final int rid) throws Exception {
+ Resources resources = getInstrumentation().getContext().getResources();
+ AssetFileDescriptor fd = resources.openRawResourceFd(rid);
+ MediaExtractor ex = new MediaExtractor();
+ ex.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ int numtracks = ex.getTrackCount();
+ String rname = resources.getResourceEntryName(rid);
+ Log.i(TAG, "start mediacodec test for: " + rname + ", which has " + numtracks + " tracks");
+ for (int t = 0; t < numtracks; t++) {
+ // find all the available decoders for this format
+ ArrayList<String> matchingCodecs = new ArrayList<String>();
+ MediaFormat format = ex.getTrackFormat(t);
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ for (MediaCodecInfo info: codecList.getCodecInfos()) {
+ if (info.isEncoder()) {
+ continue;
+ }
+ try {
+ MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
+ if (caps != null && caps.isFormatSupported(format)) {
+ matchingCodecs.add(info.getName());
+ }
+ } catch (IllegalArgumentException e) {
+ // type is not supported
+ }
+ }
+
+ if (matchingCodecs.size() == 0) {
+ Log.w(TAG, "no codecs for track " + t + ", type " + mime);
+ }
+ // decode this track once with each matching codec
+ ex.selectTrack(t);
+ for (String codecName: matchingCodecs) {
+ Log.i(TAG, "Decoding track " + t + " using codec " + codecName);
+ ex.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+ MediaCodec codec = MediaCodec.createByCodecName(codecName);
+ Surface surface = null;
+ if (mime.startsWith("video/")) {
+ surface = getDummySurface();
+ }
+ codec.configure(format, surface, null, 0);
+ codec.start();
+ MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+ while (true) {
+ int flags = ex.getSampleFlags();
+ long time = ex.getSampleTime();
+ int bufidx = codec.dequeueInputBuffer(5000);
+ if (bufidx >= 0) {
+ int n = ex.readSampleData(codec.getInputBuffer(bufidx), 0);
+ if (n < 0) {
+ flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+ time = 0;
+ n = 0;
+ }
+ codec.queueInputBuffer(bufidx, 0, n, time, flags);
+ ex.advance();
+ }
+ int status = codec.dequeueOutputBuffer(info, 5000);
+ if (status >= 0) {
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ break;
+ }
+ if (info.presentationTimeUs > TIMEOUT_NS / 1000) {
+ Log.d(TAG, "stopping after 10 seconds worth of data");
+ break;
+ }
+ codec.releaseOutputBuffer(status, true);
+ }
+ }
+ codec.release();
+ }
+ }
+ }
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockVideoCallCallback.java b/tests/tests/telecom/src/android/telecom/cts/MockVideoCallCallback.java
index 07e159c..5e32cf7 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockVideoCallCallback.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockVideoCallCallback.java
@@ -31,6 +31,8 @@
private int mVideoQuality = MockVideoProvider.VIDEO_QUALITY_UNDEFINED;
private int mCallSessionEvent = MockVideoProvider.SESSION_EVENT_UNDEFINED;
private int mPeerWidth = MockVideoProvider.PEER_WIDTH_UNDEFINED;
+ private int mResponseStatus;
+ private VideoProfile mRequestedProfile = null;
private VideoProfile mResponseProfile = null;
private VideoProfile mRequestProfile = null;
@@ -58,6 +60,8 @@
@Override
public void onSessionModifyResponseReceived(int status, VideoProfile requestedProfile,
VideoProfile responseProfile) {
+ mResponseStatus = status;
+ mRequestedProfile = requestedProfile;
mResponseProfile = responseProfile;
}
@@ -164,7 +168,16 @@
}
/**
- * Returns the last received response video profile.
+ * Returns the last {@code requestedProfile} received via onSessionModifyResponseReceived.
+ *
+ * @return The video profile.
+ */
+ public VideoProfile getRequestedProfile() {
+ return mRequestedProfile;
+ }
+
+ /**
+ * Returns the last {@code responseProfile} received via onSessionModifyResponseReceived.
*
* @return The video profile.
*/
@@ -173,6 +186,15 @@
}
/**
+ * Returns the last {@code status} received via onSessionModifyResponseReceived..
+ *
+ * @return The response status.
+ */
+ public int getResponseStatus() {
+ return mResponseStatus;
+ }
+
+ /**
* Returns the last requested video profile.
*
* @return The video profile.
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockVideoProvider.java b/tests/tests/telecom/src/android/telecom/cts/MockVideoProvider.java
index a1b6b65..b19b5b7 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockVideoProvider.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockVideoProvider.java
@@ -170,6 +170,18 @@
super.receiveSessionModifyRequest(request);
}
+ /**
+ * Sends a mock session modify response from the provider.
+ *
+ * @param status The response status.
+ * @param requestProfile The request video profile.
+ * @param responseProfile The response video profile.
+ */
+ public void sendMockSessionModifyResponse(int status, VideoProfile requestProfile,
+ VideoProfile responseProfile) {
+ super.receiveSessionModifyResponse(status, requestProfile, responseProfile);
+ }
+
public int getDeviceOrientation() {
return mDeviceOrientation;
}
@@ -189,4 +201,8 @@
public VideoProfile getSessionModifyResponse() {
return mSessionModifyResponse;
}
+
+ public Uri getPauseImageUri() {
+ return mPauseImageUri;
+ }
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/VideoCallTest.java b/tests/tests/telecom/src/android/telecom/cts/VideoCallTest.java
index fbfa998..9f79628 100644
--- a/tests/tests/telecom/src/android/telecom/cts/VideoCallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/VideoCallTest.java
@@ -17,8 +17,10 @@
package android.telecom.cts;
import android.graphics.SurfaceTexture;
+import android.net.Uri;
import android.telecom.Call;
import android.telecom.Connection;
+import android.telecom.Connection.VideoProvider;
import android.telecom.InCallService;
import android.telecom.VideoProfile;
import android.util.Log;
@@ -168,6 +170,58 @@
}
/**
+ * Test handling of session modify responses.
+ */
+ public void testReceiveSessionModifyResponse() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ VideoProfile fromVideoProfile = new VideoProfile(VideoProfile.STATE_AUDIO_ONLY);
+ VideoProfile toVideoProfile = new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL);
+
+ placeAndVerifyCall(VideoProfile.STATE_AUDIO_ONLY);
+ final MockConnection connection = verifyConnectionForOutgoingCall();
+
+ final MockInCallService inCallService = mInCallCallbacks.getService();
+ final Call call = inCallService.getLastCall();
+ final MockVideoProvider mockVideoProvider = connection.getMockVideoProvider();
+ assertVideoCallbackRegistered(inCallService, call, true);
+
+ final MockVideoCallCallback callback = inCallService.getVideoCallCallback(call);
+
+ mockVideoProvider.sendMockSessionModifyResponse(
+ VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS, fromVideoProfile,
+ toVideoProfile);
+ assertRequestReceived(callback, VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS,
+ fromVideoProfile, toVideoProfile);
+
+ mockVideoProvider.sendMockSessionModifyResponse(
+ VideoProvider.SESSION_MODIFY_REQUEST_FAIL, fromVideoProfile,
+ toVideoProfile);
+ assertRequestReceived(callback, VideoProvider.SESSION_MODIFY_REQUEST_FAIL,
+ fromVideoProfile, toVideoProfile);
+
+ mockVideoProvider.sendMockSessionModifyResponse(
+ VideoProvider.SESSION_MODIFY_REQUEST_INVALID, fromVideoProfile,
+ toVideoProfile);
+ assertRequestReceived(callback, VideoProvider.SESSION_MODIFY_REQUEST_INVALID,
+ fromVideoProfile, toVideoProfile);
+
+ mockVideoProvider.sendMockSessionModifyResponse(
+ VideoProvider.SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE, fromVideoProfile,
+ toVideoProfile);
+ assertRequestReceived(callback, VideoProvider.SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE,
+ fromVideoProfile, toVideoProfile);
+
+ mockVideoProvider.sendMockSessionModifyResponse(
+ VideoProvider.SESSION_MODIFY_REQUEST_TIMED_OUT, fromVideoProfile,
+ toVideoProfile);
+ assertRequestReceived(callback, VideoProvider.SESSION_MODIFY_REQUEST_TIMED_OUT,
+ fromVideoProfile, toVideoProfile);
+ }
+
+ /**
* Tests ability to start a video call, delaying the creation of the provider until after
* the call has been initiated (rather than immediately when the call is created). This more
* closely mimics the lifespan of a {@code VideoProvider} instance as it is reasonable to
@@ -193,8 +247,8 @@
// registered.
assertVideoCallbackRegistered(inCallService, call, false);
- // Trigger delayed creation of video provider and registration of callbacks and assert that
- // it happened.
+ // Trigger delayed creation of video provider and registration of callbacks and assert
+ // that it happened.
connection.createMockVideoProvider();
assertVideoCallbackRegistered(inCallService, call, true);
@@ -340,6 +394,56 @@
Connection.VideoProvider.SESSION_EVENT_CAMERA_READY);
}
});
+
+ assertCallSessionEventReceived(inCallService.getVideoCallCallback(call),
+ Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE,
+ new Work() {
+ @Override
+ public void doWork() {
+ connection.sendMockCallSessionEvent(
+ Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE);
+ }
+ });
+
+ assertCallSessionEventReceived(inCallService.getVideoCallCallback(call),
+ Connection.VideoProvider.SESSION_EVENT_TX_START,
+ new Work() {
+ @Override
+ public void doWork() {
+ connection.sendMockCallSessionEvent(
+ Connection.VideoProvider.SESSION_EVENT_TX_START);
+ }
+ });
+
+ assertCallSessionEventReceived(inCallService.getVideoCallCallback(call),
+ Connection.VideoProvider.SESSION_EVENT_TX_STOP,
+ new Work() {
+ @Override
+ public void doWork() {
+ connection.sendMockCallSessionEvent(
+ Connection.VideoProvider.SESSION_EVENT_TX_STOP);
+ }
+ });
+
+ assertCallSessionEventReceived(inCallService.getVideoCallCallback(call),
+ Connection.VideoProvider.SESSION_EVENT_RX_PAUSE,
+ new Work() {
+ @Override
+ public void doWork() {
+ connection.sendMockCallSessionEvent(
+ Connection.VideoProvider.SESSION_EVENT_RX_PAUSE);
+ }
+ });
+
+ assertCallSessionEventReceived(inCallService.getVideoCallCallback(call),
+ Connection.VideoProvider.SESSION_EVENT_RX_RESUME,
+ new Work() {
+ @Override
+ public void doWork() {
+ connection.sendMockCallSessionEvent(
+ Connection.VideoProvider.SESSION_EVENT_RX_RESUME);
+ }
+ });
}
/**
@@ -469,6 +573,25 @@
call.disconnect();
}
+ public void testSetPauseImage() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
+ final MockConnection connection = verifyConnectionForOutgoingCall();
+
+ final MockInCallService inCallService = mInCallCallbacks.getService();
+ final Call call = inCallService.getLastCall();
+ assertVideoCallbackRegistered(inCallService, call, true);
+ final MockVideoProvider mockVideoProvider = connection.getMockVideoProvider();
+ final InCallService.VideoCall videoCall = call.getVideoCall();
+
+ final Uri pauseImageUri = Uri.fromParts("file", "test.png", "");
+ videoCall.setPauseImage(pauseImageUri);
+ assertPauseUriChanged(mockVideoProvider, pauseImageUri);
+ }
+
/**
* Asserts that a call video state is as expected.
*
@@ -760,6 +883,31 @@
}
/**
+ * Asserts whether the pause image URI has changed to the expected value.
+ *
+ * @param mockVideoProvider The mock video provider.
+ * @param expected The expected URI.
+ */
+ private void assertPauseUriChanged(final MockVideoProvider mockVideoProvider,
+ final Uri expected) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return expected;
+ }
+
+ @Override
+ public Object actual() {
+ return mockVideoProvider.getPauseImageUri();
+ }
+ },
+ TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Pause image URI should be " + expected
+ );
+ }
+
+ /**
* Asserts whether a response video profile has been received
*
* @param videoCallCallback The video call callback.
@@ -839,4 +987,60 @@
"Session modify response video state should be " + expected
);
}
+
+ /**
+ * Asserts whether a session modify response has been received with the expected values.
+ *
+ * @param videoCallCallback The video call callback.
+ * @param expectedResponseStatus The expected status.
+ * @param expectedFromProfile The expected from profile.
+ * @param expectedToProfile The expected to profile.
+ */
+ private void assertRequestReceived(final MockVideoCallCallback videoCallCallback,
+ final int expectedResponseStatus, final VideoProfile expectedFromProfile,
+ final VideoProfile expectedToProfile) {
+
+ final String expected = buildRequestString(expectedResponseStatus, expectedFromProfile,
+ expectedToProfile);
+
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return expected;
+ }
+
+ @Override
+ public Object actual() {
+ int responseStatus = videoCallCallback.getResponseStatus();
+ VideoProfile fromProfile = videoCallCallback.getRequestedProfile();
+ VideoProfile toProfile = videoCallCallback.getResponseProfile();
+ return buildRequestString(responseStatus, fromProfile, toProfile);
+ }
+ },
+ TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Session modify response should match expected."
+ );
+ }
+
+ /**
+ * Creates a string representation of the parameters passed to
+ * {@link android.telecom.InCallService.VideoCall.Callback#onSessionModifyResponseReceived(int,
+ * VideoProfile, VideoProfile)}.
+ *
+ * @param status The status.
+ * @param fromProfile The from profile.
+ * @param toProfile The to profile.
+ * @return String representation.
+ */
+ private String buildRequestString(int status, VideoProfile fromProfile, VideoProfile toProfile) {
+ StringBuilder expectedSb = new StringBuilder();
+ expectedSb.append("Status: ");
+ expectedSb.append(status);
+ expectedSb.append(" From: ");
+ expectedSb.append(fromProfile);
+ expectedSb.append(" To: ");
+ expectedSb.append(toProfile);
+ return expectedSb.toString();
+ }
}
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/format/cts/DateFormatTest.java b/tests/tests/text/src/android/text/format/cts/DateFormatTest.java
index 8ca1fea..1808c85 100644
--- a/tests/tests/text/src/android/text/format/cts/DateFormatTest.java
+++ b/tests/tests/text/src/android/text/format/cts/DateFormatTest.java
@@ -28,6 +28,7 @@
import java.text.SimpleDateFormat;
import java.io.FileInputStream;
import java.io.InputStream;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@@ -257,4 +258,36 @@
checkFormat("12", "h", 24);
checkFormat( "0", "H", 24);
}
+
+ public void test_bug_82144() {
+ for (Locale locale : Locale.getAvailableLocales()) {
+ if (locale.toString().startsWith("haw")) {
+ // http://b/26397197 - remove this when fixed.
+ continue;
+ }
+ Locale.setDefault(locale);
+ char[] order = DateFormat.getDateFormatOrder(mContext);
+ boolean seenDay = false, seenMonth = false, seenYear = false;
+ for (char c : order) {
+ switch (c) {
+ case 'd':
+ seenDay = true;
+ break;
+ case 'M':
+ seenMonth = true;
+ break;
+ case 'y':
+ seenYear = true;
+ break;
+ default:
+ fail("Unknown character: " + c + " in " + Arrays.toString(order)
+ + " for " + locale);
+ break;
+ }
+ }
+ assertTrue(locale.toString() + " day not found", seenDay);
+ assertTrue(locale.toString() + " month not found", seenMonth);
+ assertTrue(locale.toString() + " year not found", seenYear);
+ }
+ }
}
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/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/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index e7d5ce2..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,9 +18,9 @@
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
import android.text.Spannable;
import android.text.SpannableString;
-import android.text.SpannableStringBuilder;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.text.util.Linkify.MatchFilter;
@@ -82,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));
@@ -92,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));
@@ -351,18 +351,213 @@
assertFalse(Linkify.addLinks((Spannable) null, 0));
}
- public void testAddLinks_acceptsUrlsWithCommasInRequestParameterValues() throws Exception {
- String url = "https://android.com/path?ll=37.4221,-122.0836&z=17&pll=37.4221,-122.0836";
- Spannable spannable = new SpannableString(url);
-
- Linkify.addLinks(spannable, Linkify.WEB_URLS);
-
- URLSpan[] urlSpans = spannable.getSpans(0, spannable.length(), URLSpan.class);
- assertEquals("Web URL parsing should accept commas", url, urlSpans[0].getURL());
- assertEquals("Spannable should start from beginning of the given URL", 0,
- spannable.getSpanStart(urlSpans[0]));
- assertEquals("Spannable should end at the end of the given URL", url.length(),
- spannable.getSpanEnd(urlSpans[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/util/src/android/util/cts/LocaleListTest.java b/tests/tests/util/src/android/util/cts/LocaleListTest.java
index f824aa8..83aeb9d 100644
--- a/tests/tests/util/src/android/util/cts/LocaleListTest.java
+++ b/tests/tests/util/src/android/util/cts/LocaleListTest.java
@@ -102,6 +102,20 @@
}
}
+ 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();
@@ -187,10 +201,90 @@
}
public void testGetDefault() {
- LocaleList ll = LocaleList.getDefault();
+ final LocaleList ll = LocaleList.getDefault();
assertNotNull(ll);
assertTrue(ll.size() >= 1);
- assertEquals(Locale.getDefault(), ll.getPrimary());
+
+ 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() {
@@ -325,4 +419,36 @@
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/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index f4d82cb..1b84aff 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -191,6 +191,14 @@
</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"
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/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml b/tests/tests/view/res/menu/menu_settings.xml
similarity index 64%
copy from hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
copy to tests/tests/view/res/menu/menu_settings.xml
index 4aca824..4f210d9 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
+++ b/tests/tests/view/res/menu/menu_settings.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<?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.
@@ -13,8 +13,9 @@
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>
+<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/AnimationTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
index bc1af11..a465824 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
@@ -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}.
*/
@@ -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/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/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/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 549466a..0191072 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -59,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;
@@ -347,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);
@@ -3591,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;
diff --git a/tests/tests/view/src/android/view/cts/WindowTest.java b/tests/tests/view/src/android/view/cts/WindowTest.java
index bc786af..a897af4 100644
--- a/tests/tests/view/src/android/view/cts/WindowTest.java
+++ b/tests/tests/view/src/android/view/cts/WindowTest.java
@@ -46,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;
@@ -62,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;
@@ -1046,6 +1048,10 @@
@Override
public void onMultiWindowModeChanged() {
}
+
+ @Override
+ public void reportActivityRelaunched() {
+ }
}
private class MockWindowCallback implements Window.Callback {
@@ -1149,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 69659a2..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 android.view.cts.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
@@ -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/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/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/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index a79e5ba..3f4fd92 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -2146,6 +2146,10 @@
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
}
+
+ // It is needed to make test pass on some devices.
+ mOnUiThread.setLayoutToMatchParent();
+
DisplayMetrics metrics = mOnUiThread.getDisplayMetrics();
final int dimension = 2 * Math.max(metrics.widthPixels, metrics.heightPixels);
String p = "<p style=\"height:" + dimension + "px;width:" + dimension + "px\"> </p>";
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/src/android/widget/cts/AbsSeekBarTest.java b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
index 9342d72..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 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;
@@ -46,13 +43,12 @@
}
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/MockPopupWindowCtsActivity.java b/tests/tests/widget/src/android/widget/cts/MockPopupWindowCtsActivity.java
old mode 100644
new mode 100755
diff --git a/tests/video/Android.mk b/tests/video/Android.mk
index 191b8b2..2d31e0f 100644
--- a/tests/video/Android.mk
+++ b/tests/video/Android.mk
@@ -25,7 +25,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestrunner
-LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni
+LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libnativehelper_compat_libc++
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
index 36fc9c2..d5db375 100644
--- a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
+++ b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
@@ -909,7 +909,7 @@
}
/**
- * run encoder benchmarking with encoded stream stored from encoding phase
+ * 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
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..7e67da63
--- /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..cc378df7
--- /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..7c14c374
--- /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-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
index 3f2f353..caea3d6 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
@@ -22,10 +22,12 @@
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.File;
+import java.io.FilenameFilter;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
@@ -37,6 +39,13 @@
*/
public class CtsApiCoverage {
+ private static final FilenameFilter SUPPORTED_FILE_NAME_FILTER = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ String fileName = name.toLowerCase();
+ return fileName.endsWith(".apk") || fileName.endsWith(".jar");
+ }
+ };
+
private static final int FORMAT_TXT = 0;
private static final int FORMAT_XML = 1;
@@ -101,7 +110,12 @@
printUsage();
}
} else {
- testApks.add(new File(args[i]));
+ File file = new File(args[i]);
+ if (file.isDirectory()) {
+ testApks.addAll(Arrays.asList(file.listFiles(SUPPORTED_FILE_NAME_FILTER)));
+ } else {
+ testApks.add(file);
+ }
}
}
diff --git a/tools/cts-tradefed/DynamicConfig.xml b/tools/cts-tradefed/DynamicConfig.xml
index b675082..6acffc0 100644
--- a/tools/cts-tradefed/DynamicConfig.xml
+++ b/tools/cts-tradefed/DynamicConfig.xml
@@ -14,4 +14,5 @@
-->
<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/res/config/cts.xml b/tools/cts-tradefed/res/config/cts.xml
index 87e678b..e6a75a0 100644
--- a/tools/cts-tradefed/res/config/cts.xml
+++ b/tools/cts-tradefed/res/config/cts.xml
@@ -21,6 +21,18 @@
<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">
diff --git a/tools/device-setup/TestDeviceSetup/Android.mk b/tools/device-setup/TestDeviceSetup/Android.mk
index 02c20d4..edb85d2 100644
--- a/tools/device-setup/TestDeviceSetup/Android.mk
+++ b/tools/device-setup/TestDeviceSetup/Android.mk
@@ -25,7 +25,8 @@
LOCAL_DEX_PREOPT := false
LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_SDK_VERSION := current
+# uncomment when b/13282254 is fixed
+#LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := TestDeviceSetup
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
index 856ba0f..c336d3c 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
@@ -76,4 +76,6 @@
public static final String MEMORY_CLASS = "memory_class";
public static final String LARGE_MEMORY_CLASS = "large_memory_class";
public static final String TOTAL_MEMORY = "total_memory";
+ public static final String REFERENCE_BUILD_FINGERPRINT =
+ "reference_build_fingerprint";
}
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java
index e565770..37f8558 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java
@@ -29,6 +29,7 @@
import android.os.Bundle;
import android.os.Environment;
import android.os.UserManager;
+import android.os.SystemProperties;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
@@ -80,6 +81,9 @@
addResult(BUILD_ABIS_64, TextUtils.join(",", Build.SUPPORTED_64_BIT_ABIS));
addResult(SERIAL_NUMBER, Build.SERIAL);
+ addResult(REFERENCE_BUILD_FINGERPRINT,
+ SystemProperties.get("ro.build.reference.fingerprint", ""));
+
addResult(VERSION_RELEASE, Build.VERSION.RELEASE);
addResult(VERSION_SDK, Build.VERSION.SDK);
addResult(VERSION_BASE_OS, Build.VERSION.BASE_OS);
@@ -457,7 +461,7 @@
private String getTotalMemory() {
ActivityManager activityManager = (ActivityManager) getContext()
.getSystemService(Context.ACTIVITY_SERVICE);
-
+
MemoryInfo memoryInfo = new MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return String.valueOf(memoryInfo.totalMem);
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index 9ccf468..30dfcd2 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -406,6 +406,7 @@
'android.rscpp' : [],
'android.rsg' : [],
'android.sax' : [],
+ 'android.server' : [],
'android.signature' : [],
'android.simplecpu' : [],
'android.speech' : [],