Merge "cts: Set LOCAL_SDK_VERSION where possible."
diff --git a/apps/CameraITS/pymodules/its/image.py b/apps/CameraITS/pymodules/its/image.py
index d4776c7..1654faa8 100644
--- a/apps/CameraITS/pymodules/its/image.py
+++ b/apps/CameraITS/pymodules/its/image.py
@@ -414,7 +414,7 @@
return img
-def get_black_level(chan, props, cap_res):
+def get_black_level(chan, props, cap_res=None):
"""Return the black level to use for a given capture.
Uses a dynamic value from the capture result if available, else falls back
@@ -428,7 +428,7 @@
Returns:
The black level value for the specified channel.
"""
- if (cap_res.has_key('android.sensor.dynamicBlackLevel') and
+ if (cap_res is not None and cap_res.has_key('android.sensor.dynamicBlackLevel') and
cap_res['android.sensor.dynamicBlackLevel'] is not None):
black_levels = cap_res['android.sensor.dynamicBlackLevel']
else:
diff --git a/apps/CameraITS/tests/scene1/test_raw_exposure.py b/apps/CameraITS/tests/scene1/test_raw_exposure.py
new file mode 100644
index 0000000..3a0dcf6
--- /dev/null
+++ b/apps/CameraITS/tests/scene1/test_raw_exposure.py
@@ -0,0 +1,160 @@
+# Copyright 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import its.device
+import its.caps
+import its.objects
+import its.image
+import os.path
+import numpy as np
+from matplotlib import pylab
+import matplotlib.pyplot
+
+IMG_STATS_GRID = 9 # find used to find the center 11.11%
+NAME = os.path.basename(__file__).split(".")[0]
+NUM_ISO_STEPS = 5
+SATURATION_TOL = 0.01
+BLK_LVL_TOL = 0.1
+# Test 3 steps per 2x exposure
+EXP_MULT = pow(2, 1.0/3)
+INCREASING_THR = 0.99
+# slice captures into burst of SLICE_LEN requests
+SLICE_LEN = 10
+
+def main():
+ """Capture a set of raw images with increasing exposure time and measure the pixel values.
+ """
+
+ with its.device.ItsSession() as cam:
+
+ props = cam.get_camera_properties()
+ its.caps.skip_unless(its.caps.raw16(props) and
+ its.caps.manual_sensor(props) and
+ its.caps.read_3a(props) and
+ its.caps.per_frame_control(props))
+ debug = its.caps.debug_mode()
+
+ # Expose for the scene with min sensitivity
+ exp_min, exp_max = props["android.sensor.info.exposureTimeRange"]
+ sens_min, _ = props["android.sensor.info.sensitivityRange"]
+ # Digital gains might not be visible on RAW data
+ sens_max = props["android.sensor.maxAnalogSensitivity"]
+ sens_step = (sens_max - sens_min) / NUM_ISO_STEPS
+ white_level = float(props["android.sensor.info.whiteLevel"])
+ black_levels = [its.image.get_black_level(i,props) for i in range(4)]
+ # Get the active array width and height.
+ aax = props["android.sensor.info.activeArraySize"]["left"]
+ aay = props["android.sensor.info.activeArraySize"]["top"]
+ aaw = props["android.sensor.info.activeArraySize"]["right"]-aax
+ aah = props["android.sensor.info.activeArraySize"]["bottom"]-aay
+ raw_stat_fmt = {"format": "rawStats",
+ "gridWidth": aaw/IMG_STATS_GRID,
+ "gridHeight": aah/IMG_STATS_GRID}
+
+ e_test = []
+ mult = 1.0
+ while exp_min*mult < exp_max:
+ e_test.append(int(exp_min*mult))
+ mult *= EXP_MULT
+ if e_test[-1] < exp_max * INCREASING_THR:
+ e_test.append(int(exp_max))
+ e_test_ms = [e / 1000000.0 for e in e_test]
+
+ for s in range(sens_min, sens_max, sens_step):
+ means = []
+ means.append(black_levels)
+ reqs = [its.objects.manual_capture_request(s, e, 0) for e in e_test]
+ # Capture raw in debug mode, rawStats otherwise
+ caps = []
+ for i in range(len(reqs) / SLICE_LEN):
+ if debug:
+ caps += cam.do_capture(reqs[i*SLICE_LEN:(i+1)*SLICE_LEN], cam.CAP_RAW)
+ else:
+ caps += cam.do_capture(reqs[i*SLICE_LEN:(i+1)*SLICE_LEN], raw_stat_fmt)
+ last_n = len(reqs) % SLICE_LEN
+ if last_n == 1:
+ if debug:
+ caps += [cam.do_capture(reqs[-last_n:], cam.CAP_RAW)]
+ else:
+ caps += [cam.do_capture(reqs[-last_n:], raw_stat_fmt)]
+ elif last_n > 0:
+ if debug:
+ caps += cam.do_capture(reqs[-last_n:], cam.CAP_RAW)
+ else:
+ caps += cam.do_capture(reqs[-last_n:], raw_stat_fmt)
+
+ # Measure the mean of each channel.
+ # Each shot should be brighter (except underexposed/overexposed scene)
+ for i,cap in enumerate(caps):
+ if debug:
+ planes = its.image.convert_capture_to_planes(cap, props)
+ tiles = [its.image.get_image_patch(p, 0.445, 0.445, 0.11, 0.11) for p in planes]
+ mean = [m * white_level for tile in tiles
+ for m in its.image.compute_image_means(tile)]
+ img = its.image.convert_capture_to_rgb_image(cap, props=props)
+ its.image.write_image(img, "%s_s=%d_e=%05d.jpg" % (NAME, s, e_test))
+ else:
+ mean_image, _ = its.image.unpack_rawstats_capture(cap)
+ mean = mean_image[IMG_STATS_GRID/2, IMG_STATS_GRID/2]
+
+ print "ISO=%d, exposure time=%.3fms, mean=%s" % (
+ s, e_test[i] / 1000000.0, str(mean))
+ means.append(mean)
+
+
+ # means[0] is black level value
+ r = [m[0] for m in means[1:]]
+ gr = [m[1] for m in means[1:]]
+ gb = [m[2] for m in means[1:]]
+ b = [m[3] for m in means[1:]]
+
+ pylab.plot(e_test_ms, r, "r.-")
+ pylab.plot(e_test_ms, b, "b.-")
+ pylab.plot(e_test_ms, gr, "g.-")
+ pylab.plot(e_test_ms, gb, "k.-")
+ pylab.xscale('log')
+ pylab.yscale('log')
+ pylab.title("%s ISO=%d" % (NAME, s))
+ pylab.xlabel("Exposure time (ms)")
+ pylab.ylabel("Center patch pixel mean")
+ matplotlib.pyplot.savefig("%s_s=%d.png" % (NAME, s))
+ pylab.clf()
+
+ allow_under_saturated = True
+ for i in xrange(1, len(means)):
+ prev_mean = means[i-1]
+ mean = means[i]
+
+ if np.isclose(max(mean), white_level, rtol=SATURATION_TOL):
+ print "Saturated: white_level %f, max_mean %f"% (white_level, max(mean))
+ break;
+
+ if allow_under_saturated and np.allclose(mean, black_levels, rtol=BLK_LVL_TOL):
+ # All channel means are close to black level
+ continue
+
+ allow_under_saturated = False
+ # Check pixel means are increasing (with small tolerance)
+ channels = ["Red", "Gr", "Gb", "Blue"]
+ for chan in range(4):
+ err_msg = "ISO=%d, %s, exptime %3fms mean: %.2f, %s mean: %.2f, TOL=%.f%%" % (
+ s, channels[chan],
+ e_test_ms[i-1], mean[chan],
+ "black level" if i == 1 else "exptime %3fms"%e_test_ms[i-2],
+ prev_mean[chan],
+ INCREASING_THR*100)
+ assert mean[chan] > prev_mean[chan] * INCREASING_THR, err_msg
+
+if __name__ == "__main__":
+ main()
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
index 861af28..8345184 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
@@ -16,6 +16,7 @@
package com.android.cts.verifier.audio;
+import android.content.res.Resources;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
@@ -110,13 +111,15 @@
if (mIsPeripheralAttached && mSelectedProfile != null) {
ProfileButtonAttributes mButtonAttributes = mSelectedProfile.getButtonAttributes();
boolean match = mButtonAttributes != null;
+ boolean interceptedVolume = getResources().getBoolean(Resources.getSystem()
+ .getIdentifier("config_handleVolumeKeysInWindowManager", "bool", "android"));
if (match && mButtonAttributes.mHasBtnA != mHasBtnA) {
match = false;
}
- if (match && mButtonAttributes.mHasBtnB != mHasBtnB) {
+ if (match && mButtonAttributes.mHasBtnB != mHasBtnB && !interceptedVolume) {
match = false;
}
- if (match && mButtonAttributes.mHasBtnC != mHasBtnC) {
+ if (match && mButtonAttributes.mHasBtnC != mHasBtnC && !interceptedVolume) {
match = false;
}
Log.i(TAG, "match:" + match);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index 5dbbc79..81226a6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -1328,7 +1328,8 @@
int newCount = mCountCallbacksRemaining.get();
if (newCount == currentCount) {
- throw new ItsException("No callback received within timeout");
+ throw new ItsException("No callback received within timeout " +
+ timeoutMs + "ms");
}
currentCount = newCount;
}
@@ -1802,8 +1803,8 @@
logMsg.append(String.format(
"sens=%d, exp=%.1fms, dur=%.1fms, ",
result.get(CaptureResult.SENSOR_SENSITIVITY),
- result.get(CaptureResult.SENSOR_EXPOSURE_TIME).intValue() / 1000000.0f,
- result.get(CaptureResult.SENSOR_FRAME_DURATION).intValue() /
+ result.get(CaptureResult.SENSOR_EXPOSURE_TIME).longValue() / 1000000.0f,
+ result.get(CaptureResult.SENSOR_FRAME_DURATION).longValue() /
1000000.0f));
}
if (result.get(CaptureResult.COLOR_CORRECTION_GAINS) != null) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LockTaskUiTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LockTaskUiTestActivity.java
index a6e6b2f..5447536 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LockTaskUiTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LockTaskUiTestActivity.java
@@ -21,12 +21,11 @@
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_RECENTS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
import static com.android.cts.verifier.managedprovisioning.Utils.createInteractiveTestItem;
-import android.app.Activity;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -152,7 +151,7 @@
adapter.add(createSetLockTaskFeaturesTest(
TEST_ID_RECENTS,
- LOCK_TASK_FEATURE_RECENTS,
+ LOCK_TASK_FEATURE_OVERVIEW,
R.string.device_owner_lock_task_ui_recents_test,
R.string.device_owner_lock_task_ui_recents_test_info));
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
index db8a888..60400be 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
@@ -71,6 +71,9 @@
@Option(name="build-flavor", description="build flavor name to supply.")
private String mBuildFlavor = null;
+ @Option(name="build-target", description="build target name to supply.")
+ private String mBuildTarget = null;
+
@Option(name="build-attribute", description="build attributes to supply.")
private Map<String, String> mBuildAttributes = new HashMap<String,String>();
@@ -103,6 +106,9 @@
for (Map.Entry<String, String> entry : mBuildAttributes.entrySet()) {
buildInfo.addBuildAttribute(entry.getKey(), entry.getValue());
}
+ if (mTestTag != null) {
+ buildInfo.setTestTag(mTestTag);
+ }
}
/**
@@ -117,7 +123,7 @@
* {@inheritDoc}
*/
@Override
- public IBuildInfo getBuild() {
+ public IBuildInfo getBuild() throws BuildRetrievalError {
// Create a blank BuildInfo which will get populated later.
String version = null;
if (mBuildId != null) {
@@ -128,7 +134,7 @@
version = IBuildInfo.UNKNOWN_BUILD_ID;
}
}
- IBuildInfo ctsBuild = new DeviceBuildInfo(version, mTestTag);
+ IBuildInfo ctsBuild = new DeviceBuildInfo(version, mBuildTarget);
if (mBranch != null) {
ctsBuild.setBuildBranch(mBranch);
}
@@ -151,9 +157,18 @@
// build info fields
return getBuild();
} else {
- String buildId = device.getBuildId();
- String buildFlavor = device.getBuildFlavor();
- IBuildInfo info = new DeviceBuildInfo(buildId, mTestTag);
+ if (mBuildId == null) {
+ mBuildId = device.getBuildId();
+ }
+ if (mBuildFlavor == null) {
+ mBuildFlavor = device.getBuildFlavor();
+ }
+ if (mBuildTarget == null) {
+ String name = device.getProperty("ro.product.name");
+ String variant = device.getProperty("ro.build.type");
+ mBuildTarget = name + "-" + variant;
+ }
+ IBuildInfo info = new DeviceBuildInfo(mBuildId, mBuildTarget);
if (mBranch == null) {
// if branch is not specified via param, make a pseudo branch name based on platform
// version and product info from device
@@ -164,7 +179,7 @@
device.getProperty("ro.build.version.release"));
}
info.setBuildBranch(mBranch);
- info.setBuildFlavor(buildFlavor);
+ info.setBuildFlavor(mBuildFlavor);
String buildAlias = device.getBuildAlias();
if (RELEASE_BUILD.matcher(buildAlias).matches()) {
info.addBuildAttribute("build_alias", buildAlias);
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
index fe29c7f..5dcf2dd 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
@@ -22,6 +22,7 @@
import com.android.compatibility.common.util.IInvocationResult;
import com.android.compatibility.common.util.ResultHandler;
import com.android.compatibility.common.util.TestStatus;
+import com.android.tradefed.build.BuildRetrievalError;
import com.android.tradefed.command.Console;
import com.android.tradefed.config.ArgsOptionParser;
import com.android.tradefed.config.ConfigurationException;
@@ -426,8 +427,12 @@
private CompatibilityBuildHelper getBuildHelper() {
if (mBuildHelper == null) {
- CompatibilityBuildProvider buildProvider = new CompatibilityBuildProvider();
- mBuildHelper = new CompatibilityBuildHelper(buildProvider.getBuild());
+ try {
+ CompatibilityBuildProvider buildProvider = new CompatibilityBuildProvider();
+ mBuildHelper = new CompatibilityBuildHelper(buildProvider.getBuild());
+ } catch (BuildRetrievalError e) {
+ e.printStackTrace();
+ }
}
return mBuildHelper;
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/suite/CertificationSuiteResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/suite/CertificationSuiteResultReporter.java
index f57126d..7934abd 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/suite/CertificationSuiteResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/suite/CertificationSuiteResultReporter.java
@@ -60,7 +60,8 @@
import javax.xml.transform.stream.StreamSource;
/**
- * Extension of {@link SuiteResultReporter} to handle Compatibility specific format and operations.
+ * Extension of {@link XmlFormattedGeneratorReporter} and {@link SuiteResultReporter} to handle
+ * Compatibility specific format and operations.
*/
public class CertificationSuiteResultReporter extends XmlFormattedGeneratorReporter
implements ILogSaverListener, ITestSummaryListener {
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/retry/RetryFactoryTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/retry/RetryFactoryTest.java
index a95ebfb..1ac2014 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/retry/RetryFactoryTest.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/retry/RetryFactoryTest.java
@@ -199,6 +199,7 @@
test.setInvocationContext(mContext);
// reset the retry id - Ensure that retry of retry does not throw
test.resetRetryId();
+ test.isRetry();
// clean the helper
helper.tearDown();
return test;
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/suite/CompatibilityTestSuite.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/suite/CompatibilityTestSuite.java
index be64ccd..dd6a457 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/suite/CompatibilityTestSuite.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/suite/CompatibilityTestSuite.java
@@ -19,11 +19,13 @@
import com.android.compatibility.common.tradefed.testtype.ISubPlan;
import com.android.compatibility.common.tradefed.testtype.SubPlan;
import com.android.compatibility.common.tradefed.testtype.retry.RetryFactoryTest;
+import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.Option.Importance;
import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.suite.BaseTestSuite;
import com.android.tradefed.testtype.suite.SuiteModuleLoader;
@@ -59,6 +61,8 @@
private String mSubPlan;
private CompatibilityBuildHelper mBuildHelper;
+ /** Tag if the current instance is running as a retry from RetryFactory */
+ private boolean mIsRetry = false;
@Override
public void setBuild(IBuildInfo buildInfo) {
@@ -84,8 +88,8 @@
@Override
public LinkedHashMap<String, IConfiguration> loadTests() {
if (mRetrySessionId != null) {
- throw new IllegalArgumentException("--retry cannot be specified with cts-suite.xml. "
- + "Use 'run cts --retry <session id>' instead.");
+ throw new IllegalArgumentException("--retry cannot be specified with cts[*].xml. "
+ + "Use 'run retry --retry <session id>' instead.");
}
return super.loadTests();
}
@@ -125,6 +129,13 @@
}
/**
+ * Mark the instance of CompatibilityTestSuite as a retry.
+ */
+ public final void isRetry() {
+ mIsRetry = true;
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -136,9 +147,15 @@
getModuleLoader().loadConfigsFromDirectory(testsDir, abis, suitePrefix, suiteTag));
// Add an extra check in CTS since we never expect the config folder to be empty.
if (loadedConfigs.size() == 0) {
- throw new IllegalArgumentException(
- String.format("No config files found in %s or in resources.",
- testsDir.getAbsolutePath()));
+ if (mIsRetry) {
+ // Only log if it's a retry
+ CLog.logAndDisplay(LogLevel.DEBUG,
+ "No module that needed to run in retry were found. nothing to do.");
+ } else {
+ throw new IllegalArgumentException(
+ String.format("No config files found in %s or in resources.",
+ testsDir.getAbsolutePath()));
+ }
}
return loadedConfigs;
}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProviderTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProviderTest.java
index 0e02c02..f7116d7 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProviderTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProviderTest.java
@@ -85,6 +85,8 @@
EasyMock.expect(mMockDevice.getBuildId()).andReturn("8888");
EasyMock.expect(mMockDevice.getBuildFlavor()).andReturn("flavor");
EasyMock.expect(mMockDevice.getBuildAlias()).andReturn("alias");
+ EasyMock.expect(mMockDevice.getProperty("ro.product.name")).andReturn("product");
+ EasyMock.expect(mMockDevice.getProperty("ro.build.type")).andReturn("userdebug");
EasyMock.replay(mMockDevice);
IBuildInfo info = mProvider.getBuild(mMockDevice);
EasyMock.verify(mMockDevice);
diff --git a/common/util/src/com/android/compatibility/common/util/ResultHandler.java b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
index c394b8d..d85c678 100644
--- a/common/util/src/com/android/compatibility/common/util/ResultHandler.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
@@ -156,8 +156,9 @@
* @return an IInvocationResult for this result, or null upon error
*/
public static IInvocationResult getResultFromDir(File resultDir, Boolean useChecksum) {
+ File resultFile = null;
try {
- File resultFile = new File(resultDir, TEST_RESULT_FILE_NAME);
+ resultFile = new File(resultDir, TEST_RESULT_FILE_NAME);
if (!resultFile.exists()) {
return null;
}
@@ -277,6 +278,9 @@
parser.require(XmlPullParser.END_TAG, NS, RESULT_TAG);
return invocation;
} catch (XmlPullParserException | IOException e) {
+ System.out.println(
+ String.format("Exception when trying to load %s",
+ resultFile.getAbsolutePath()));
e.printStackTrace();
return null;
}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
index b9b652a..01f9c7d 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
@@ -51,6 +51,7 @@
}
@Ignore
+ @Test
public void testFail() throws Exception {
fail("Expected");
}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
index 6ef2ba1..8874660 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
@@ -20,7 +20,7 @@
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_RECENTS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
import static junit.framework.Assert.assertEquals;
@@ -191,7 +191,7 @@
LOCK_TASK_FEATURE_SYSTEM_INFO,
LOCK_TASK_FEATURE_NOTIFICATIONS,
LOCK_TASK_FEATURE_HOME,
- LOCK_TASK_FEATURE_RECENTS,
+ LOCK_TASK_FEATURE_OVERVIEW,
LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
LOCK_TASK_FEATURE_KEYGUARD
};
@@ -505,11 +505,11 @@
}
/**
- * Starts LockTaskUtilityActivity with {@link ActivityOptions#setLockTaskMode(boolean)}
+ * Starts LockTaskUtilityActivity with {@link ActivityOptions#setLockTaskEnabled(boolean)}
*/
private void startLockTaskWithOptions(String className) throws InterruptedException {
Intent intent = getLockTaskUtility(className);
- Bundle options = ActivityOptions.makeBasic().setLockTaskMode(true).toBundle();
+ Bundle options = ActivityOptions.makeBasic().setLockTaskEnabled(true).toBundle();
startAndWait(intent, options);
}
diff --git a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml b/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
index 8f23cd9..04c8c08 100644
--- a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
+++ b/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
@@ -43,6 +43,9 @@
<activity
android:name=".VideoPlayerActivity"
android:label="@string/app_name"
+ android:resizeableActivity="true"
+ android:supportsPictureInPicture="true"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java
index b15ec35..ea1fcec 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java
@@ -17,19 +17,71 @@
package com.android.server.cts.device.statsd;
import android.app.Activity;
+import android.content.Intent;
+import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.SystemClock;
+import android.util.Log;
import android.widget.VideoView;
public class VideoPlayerActivity extends Activity {
- /** Called when the activity is first created. */
+ private static final String TAG = VideoPlayerActivity.class.getSimpleName();
+
+ public static final String KEY_ACTION = "action";
+ public static final String ACTION_PLAY_VIDEO = "action.play_video";
+ public static final String ACTION_PLAY_VIDEO_PICTURE_IN_PICTURE_MODE =
+ "action.play_video_picture_in_picture_mode";
+
+ public static final int DELAY_MILLIS = 2000;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ Intent intent = this.getIntent();
+ if (intent == null) {
+ Log.e(TAG, "Intent was null.");
+ finish();
+ }
+
+ String action = intent.getStringExtra(KEY_ACTION);
+ Log.i(TAG, "Starting " + action + " from foreground activity.");
+
+ switch (action) {
+ case ACTION_PLAY_VIDEO:
+ playVideo();
+ break;
+ case ACTION_PLAY_VIDEO_PICTURE_IN_PICTURE_MODE:
+ playVideo();
+ this.enterPictureInPictureMode();
+ break;
+ default:
+ Log.e(TAG, "Intent had invalid action " + action);
+ finish();
+ }
+ delay();
+ }
+
+ private void playVideo() {
setContentView(R.layout.activity_main);
VideoView videoView = (VideoView)findViewById(R.id.video_player_view);
videoView.setVideoPath("android.resource://" + getPackageName() + "/" + R.raw.colors_video);
videoView.start();
}
+
+ private void delay() {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ SystemClock.sleep(DELAY_MILLIS);
+ return null;
+ }
+ @Override
+ protected void onPostExecute(Void nothing) {
+ finish();
+ }
+ }.execute();
+ }
}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java b/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
index 25cb53d..dc2da39 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
@@ -47,6 +47,8 @@
private static final boolean TESTS_ENABLED = false;
private static final boolean INCIDENTD_TESTS_ENABLED = true;
+ private static final int WAIT_AFTER_BREADCRUMB_MS = 2000;
+
// Config constants
private static final int APP_BREADCRUMB_REPORTED_MATCH_START_ID = 1;
private static final int APP_BREADCRUMB_REPORTED_MATCH_STOP_ID = 2;
@@ -109,7 +111,7 @@
if (INCIDENTD_TESTS_ENABLED) assertFalse("Incident", didIncidentdFireSince(markTime));
doAppBreadcrumbReportedStart(6); // count(label=6) -> 3 (anomaly, since "greater than 2"!)
- Thread.sleep(1000);
+ Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
List<EventMetricData> data = getEventMetricDataList();
assertEquals("Expected 1 anomaly", 1, data.size());
@@ -260,12 +262,12 @@
String markTime = getCurrentLogcatDate();
doAppBreadcrumbReportedStart(6); // value = 6, which is NOT > trigger
- Thread.sleep(2000);
+ Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
assertEquals("Premature anomaly", 0, getEventMetricDataList().size());
if (INCIDENTD_TESTS_ENABLED) assertFalse("Incident", didIncidentdFireSince(markTime));
doAppBreadcrumbReportedStart(14); // value = 14 > trigger
- Thread.sleep(2000);
+ Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
List<EventMetricData> data = getEventMetricDataList();
assertEquals("Expected 1 anomaly", 1, data.size());
@@ -274,42 +276,40 @@
if (INCIDENTD_TESTS_ENABLED) assertTrue("No incident", didIncidentdFireSince(markTime));
}
- // TODO: Removed until b/73091354 is solved, since it keeps crashing statsd. Update CTS later.
// Tests that anomaly detection for gauge works.
-// public void testGaugeAnomalyDetection() throws Exception {
-// if (!TESTS_ENABLED) return;
-// StatsdConfig.Builder config = getBaseConfig(1, 20, 6)
-// .addGaugeMetric(GaugeMetric.newBuilder()
-// .setId(METRIC_ID)
-// .setWhat(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
-// .setBucket(TimeUnit.ONE_MINUTE)
-// // Get the label field's value into the gauge:
-// .setGaugeFieldsFilter(
-// FieldFilter.newBuilder().setFields(FieldMatcher.newBuilder()
-// .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
-// .addChild(FieldMatcher.newBuilder()
-// .setField(AppBreadcrumbReported
-// .LABEL_FIELD_NUMBER))
-// )
-// )
-// );
-// uploadConfig(config);
-//
-// String markTime = getCurrentLogcatDate();
-// doAppBreadcrumbReportedStart(6); // gauge = 6, which is NOT > trigger
-// Thread.sleep(2000);
-// assertEquals("Premature anomaly", 0, getEventMetricDataList().size());
-// if (INCIDENTD_TESTS_ENABLED) assertFalse("Incident", didIncidentdFireSince(markTime));
-//
-// doAppBreadcrumbReportedStart(14); // gauge = 6+1 > trigger
-// Thread.sleep(2000);
-//
-// List<EventMetricData> data = getEventMetricDataList();
-// assertEquals("Expected 1 anomaly", 1, data.size());
-// AnomalyDetected a = data.get(0).getAtom().getAnomalyDetected();
-// assertEquals("Wrong alert_id", ALERT_ID, a.getAlertId());
-// if (INCIDENTD_TESTS_ENABLED) assertTrue("No incident", didIncidentdFireSince(markTime));
-// }
+ public void testGaugeAnomalyDetection() throws Exception {
+ StatsdConfig.Builder config = getBaseConfig(1, 20, 6 /* threshold: value > 6 */)
+ .addGaugeMetric(GaugeMetric.newBuilder()
+ .setId(METRIC_ID)
+ .setWhat(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
+ .setBucket(TimeUnit.CTS)
+ // Get the label field's value into the gauge:
+ .setGaugeFieldsFilter(
+ FieldFilter.newBuilder().setFields(FieldMatcher.newBuilder()
+ .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
+ .addChild(FieldMatcher.newBuilder()
+ .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER))
+ )
+ )
+ );
+ uploadConfig(config);
+
+ String markTime = getCurrentLogcatDate();
+ doAppBreadcrumbReportedStart(6); // gauge = 6, which is NOT > trigger
+ Thread.sleep(Math.max(WAIT_AFTER_BREADCRUMB_MS, 1_100)); // Must be >1s to push next bucket.
+ assertEquals("Premature anomaly", 0, getEventMetricDataList().size());
+ if (INCIDENTD_TESTS_ENABLED) assertFalse("Incident", didIncidentdFireSince(markTime));
+
+ // We waited for >1s above, so we are now in the next bucket (which is essential).
+ doAppBreadcrumbReportedStart(14); // gauge = 14 > trigger
+ Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
+
+ List<EventMetricData> data = getEventMetricDataList();
+ assertEquals("Expected 1 anomaly", 1, data.size());
+ AnomalyDetected a = data.get(0).getAtom().getAnomalyDetected();
+ assertEquals("Wrong alert_id", ALERT_ID, a.getAlertId());
+ if (INCIDENTD_TESTS_ENABLED) assertTrue("No incident", didIncidentdFireSince(markTime));
+ }
private final StatsdConfig.Builder getBaseConfig(int numBuckets,
int refractorySecs,
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
index c0f194c..c3c209f 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
@@ -178,10 +178,21 @@
/**
* Runs the specified activity for WAIT_TME_LONG.
*/
- protected void runActivity(String activity) throws Exception {
+ protected void runActivity(String activity, String actionKey, String actionValue)
+ throws Exception {
+ String intentString = null;
+ if (actionKey != null && actionValue != null) {
+ intentString = actionKey + " " + actionValue;
+ }
turnScreenOn();
- getDevice().executeShellCommand(
- "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity);
+ if (intentString == null) {
+ getDevice().executeShellCommand(
+ "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity);
+ } else {
+ getDevice().executeShellCommand(
+ "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity + " -e " +
+ intentString);
+ }
Thread.sleep(WAIT_TIME_LONG);
getDevice().executeShellCommand(
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index 0a800f0..344ec44 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -15,6 +15,8 @@
*/
package android.cts.statsd.atom;
+import static org.junit.Assert.assertTrue;
+
import android.os.WakeLockLevelEnum;
import com.android.internal.os.StatsdConfigProto.FieldMatcher;
@@ -31,6 +33,7 @@
import com.android.os.AtomsProto.ForegroundServiceStateChanged;
import com.android.os.AtomsProto.GpsScanStateChanged;
import com.android.os.AtomsProto.MediaCodecActivityChanged;
+import com.android.os.AtomsProto.PictureInPictureStateChanged;
import com.android.os.AtomsProto.ScheduledJobStateChanged;
import com.android.os.AtomsProto.SyncStateChanged;
import com.android.os.AtomsProto.WakelockStateChanged;
@@ -45,6 +48,7 @@
import java.util.List;
import java.util.Set;
+
/**
* Statsd atom tests that are done via app, for atoms that report a uid.
*/
@@ -319,7 +323,7 @@
final int atomTag = Atom.DAVEY_OCCURRED_FIELD_NUMBER;
createAndUploadConfig(atomTag); // Does not have UID, but needs a device-side compnent.
- runActivity("DaveyActivity");
+ runActivity("DaveyActivity", null, null);
List<EventMetricData> data = getEventMetricDataList();
assertTrue(data.size() == 1);
@@ -548,7 +552,7 @@
createAndUploadConfig(atomTag, true); // True: uses attribution.
Thread.sleep(WAIT_TIME_SHORT);
- runActivity("VideoPlayerActivity");
+ runActivity("VideoPlayerActivity", "action", "action.play_video");
// Sorted list of events in order in which they occurred.
List<EventMetricData> data = getEventMetricDataList();
@@ -557,4 +561,26 @@
assertStatesOccurred(stateSet, data, WAIT_TIME_LONG,
atom -> atom.getMediaCodecActivityChanged().getState().getNumber());
}
+
+ public void testPictureInPictureState() throws Exception {
+ if (!TESTS_ENABLED) return;
+ final int atomTag = Atom.PICTURE_IN_PICTURE_STATE_CHANGED_FIELD_NUMBER;
+
+ Set<Integer> entered = new HashSet<>(
+ Arrays.asList(PictureInPictureStateChanged.State.ENTERED_VALUE));
+
+ // Add state sets to the list in order.
+ List<Set<Integer>> stateSet = Arrays.asList(entered);
+
+ createAndUploadConfig(atomTag, false);
+
+ runActivity("VideoPlayerActivity", "action", "action.play_video_picture_in_picture_mode");
+
+ // Sorted list of events in order in which they occurred.
+ List<EventMetricData> data = getEventMetricDataList();
+
+ // Assert that the events happened in the expected order.
+ assertStatesOccurred(stateSet, data, WAIT_TIME_LONG,
+ atom -> atom.getPictureInPictureStateChanged().getState().getNumber());
+ }
}
diff --git a/tests/app/src/android/app/cts/DialogTest.java b/tests/app/src/android/app/cts/DialogTest.java
index ee1836a..b2749c7 100755
--- a/tests/app/src/android/app/cts/DialogTest.java
+++ b/tests/app/src/android/app/cts/DialogTest.java
@@ -746,6 +746,7 @@
assertFalse(d.isOnContextMenuClosedCalled);
}
+ @Test
public void testOnSearchRequested() {
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 4d11050..7592408 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -730,6 +730,13 @@
}
/**
+ * Check if autofill window is fullscreen, see com.android.server.autofill.ui.FillUi
+ */
+ public static boolean isAutofillWindowFullScreen(Context context) {
+ return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
+ /**
* Uses Shell command to get the Autofill logging level.
*/
public static String getLoggingLevel() {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 6137b4b..95718ba 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -33,6 +33,7 @@
import static android.autofillservice.cts.Helper.assertValue;
import static android.autofillservice.cts.Helper.dumpStructure;
import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.Helper.getContext;
import static android.autofillservice.cts.Helper.setUserComplete;
import static android.autofillservice.cts.InstrumentedAutoFillService.SERVICE_CLASS;
import static android.autofillservice.cts.InstrumentedAutoFillService.SERVICE_PACKAGE;
@@ -113,10 +114,12 @@
new AutofillActivityTestRule<CheckoutActivity>(CheckoutActivity.class, false);
private LoginActivity mActivity;
+ private boolean mCanPassKeys;
@Before
public void setActivity() {
mActivity = mActivityRule.getActivity();
+ mCanPassKeys = !Helper.isAutofillWindowFullScreen(getContext());
}
/**
@@ -1184,6 +1187,66 @@
}
@Test
+ public void keyboardFilterResult() throws Exception {
+ if (!mCanPassKeys) {
+ return;
+ }
+
+ final String AA = "Two A's";
+ final String AB = "A and B";
+ final String B = "Only B";
+
+ enableService();
+
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "aa")
+ .setPresentation(createPresentation(AA))
+ .build())
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "ab")
+ .setPresentation(createPresentation(AB))
+ .build())
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "b")
+ .setPresentation(createPresentation(B))
+ .build())
+ .build());
+
+ // Trigger auto-fill.
+ requestFocusOnUsername();
+ sReplier.getNextFillRequest();
+
+ // With no filter text all datasets should be shown
+ mUiBot.assertDatasets(AA, AB, B);
+
+ // Only two datasets start with 'a'
+ runShellCommand("input keyevent KEYCODE_A");
+ mUiBot.assertDatasets(AA, AB);
+
+ // Only one dataset start with 'aa'
+ runShellCommand("input keyevent KEYCODE_A");
+ mUiBot.assertDatasets(AA);
+
+ // Only two datasets start with 'a'
+ runShellCommand("input keyevent KEYCODE_DEL");
+ mUiBot.assertDatasets(AA, AB);
+
+ // With no filter text all datasets should be shown
+ runShellCommand("input keyevent KEYCODE_DEL");
+ mUiBot.assertDatasets(AA, AB, B);
+
+ // No dataset start with 'aaa'
+ final MyAutofillCallback callback = mActivity.registerCallback();
+ runShellCommand("input keyevent KEYCODE_A");
+ runShellCommand("input keyevent KEYCODE_A");
+ runShellCommand("input keyevent KEYCODE_A");
+ callback.assertUiHiddenEvent(mActivity.getUsername());
+ mUiBot.assertNoDatasets();
+ }
+
+ @Test
public void filterText() throws Exception {
final String AA = "Two A's";
final String AB = "A and B";
diff --git a/tests/framework/base/activitymanager/Android.mk b/tests/framework/base/activitymanager/Android.mk
index 65fda92..25cfd6b 100644
--- a/tests/framework/base/activitymanager/Android.mk
+++ b/tests/framework/base/activitymanager/Android.mk
@@ -27,6 +27,7 @@
$(call all-named-files-under,Components.java, app) \
$(call all-named-files-under,Components.java, app27) \
$(call all-named-files-under,Components.java, appDebuggable) \
+ $(call all-named-files-under,Components.java, appDeprecatedSdk) \
$(call all-named-files-under,Components.java, appDisplaySize) \
$(call all-named-files-under,Components.java, appSecondUid) \
$(call all-named-files-under,Components.java, appThirdUid) \
diff --git a/tests/framework/base/activitymanager/AndroidManifest.xml b/tests/framework/base/activitymanager/AndroidManifest.xml
index 7afc2d4..1e79464 100644
--- a/tests/framework/base/activitymanager/AndroidManifest.xml
+++ b/tests/framework/base/activitymanager/AndroidManifest.xml
@@ -57,6 +57,10 @@
<activity android:name="android.server.am.lifecycle.ActivityLifecycleClientTestBase$SecondActivity"/>
+ <activity
+ android:name="android.server.am.lifecycle.ActivityLifecycleClientTestBase$TranslucentActivity"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+
<activity android:name="android.server.am.StartActivityTests$TestActivity2" />
</application>
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/BroadcastReceiverActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/BroadcastReceiverActivity.java
index 9e53e23..282d750 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/BroadcastReceiverActivity.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/BroadcastReceiverActivity.java
@@ -25,7 +25,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
-import android.server.am.util.ActivityLauncher;
import android.util.Log;
/**
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/Components.java b/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
index 30346bb..49bcae3 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
@@ -25,6 +25,7 @@
component("AlwaysFocusablePipActivity");
public static final ComponentName ANIMATION_TEST_ACTIVITY = component("AnimationTestActivity");
public static final ComponentName ASSISTANT_ACTIVITY = component("AssistantActivity");
+ public static final ComponentName BOTTOM_ACTIVITY = component("BottomActivity");
public static final ComponentName BOTTOM_LEFT_LAYOUT_ACTIVITY =
component("BottomLeftLayoutActivity");
public static final ComponentName BOTTOM_RIGHT_LAYOUT_ACTIVITY =
@@ -74,12 +75,15 @@
public static final ComponentName SPLASHSCREEN_ACTIVITY = component("SplashscreenActivity");
public static final ComponentName SWIPE_REFRESH_ACTIVITY = component("SwipeRefreshActivity");
public static final ComponentName TEST_ACTIVITY = component("TestActivity");
+ public static final ComponentName TOP_ACTIVITY = component("TopActivity");
public static final ComponentName TOP_LEFT_LAYOUT_ACTIVITY = component("TopLeftLayoutActivity");
public static final ComponentName TOP_RIGHT_LAYOUT_ACTIVITY =
component("TopRightLayoutActivity");
public static final ComponentName TRANSLUCENT_ACTIVITY = component("TranslucentActivity");
public static final ComponentName TRANSLUCENT_ASSISTANT_ACTIVITY =
component("TranslucentAssistantActivity");
+ public static final ComponentName TRANSLUCENT_TOP_ACTIVITY =
+ component("TranslucentTopActivity");
public static final ComponentName TURN_SCREEN_ON_ACTIVITY = component("TurnScreenOnActivity");
public static final ComponentName TURN_SCREEN_ON_ATTR_ACTIVITY =
component("TurnScreenOnAttrActivity");
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/LaunchBroadcastReceiver.java b/tests/framework/base/activitymanager/app/src/android/server/am/LaunchBroadcastReceiver.java
index 1e51cef..f3cb966 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/LaunchBroadcastReceiver.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/LaunchBroadcastReceiver.java
@@ -19,7 +19,6 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.server.am.util.ActivityLauncher;
import android.util.Log;
/** Broadcast receiver that can launch activities. */
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
index 8947a15..bf96af2 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
@@ -18,13 +18,15 @@
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
+import static android.server.am.ActivityLauncher.KEY_DISPLAY_ID;
+import static android.server.am.ActivityLauncher.KEY_LAUNCH_ACTIVITY;
+import static android.server.am.ActivityLauncher.KEY_TARGET_ACTIVITY;
import android.app.Activity;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.os.Bundle;
-import android.server.am.util.ActivityLauncher;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
@@ -227,9 +229,9 @@
private void launchActivity(String activityName, int displayId) {
final Bundle extras = new Bundle();
- extras.putBoolean("launch_activity", true);
- extras.putString("target_activity", activityName);
- extras.putInt("display_id", displayId);
+ extras.putBoolean(KEY_LAUNCH_ACTIVITY, true);
+ extras.putString(KEY_TARGET_ACTIVITY, activityName);
+ extras.putInt(KEY_DISPLAY_ID, displayId);
ActivityLauncher.launchActivityFromExtras(this, extras);
}
}
diff --git a/tests/framework/base/activitymanager/appDeprecatedSdk/Android.mk b/tests/framework/base/activitymanager/appDeprecatedSdk/Android.mk
index d28d30b..2b556f6 100644
--- a/tests/framework/base/activitymanager/appDeprecatedSdk/Android.mk
+++ b/tests/framework/base/activitymanager/appDeprecatedSdk/Android.mk
@@ -19,6 +19,8 @@
# don't include this package in any target
LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := cts-am-app-base
+
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := 16
diff --git a/tests/framework/base/activitymanager/appDeprecatedSdk/src/android/server/am/deprecatedsdk/Components.java b/tests/framework/base/activitymanager/appDeprecatedSdk/src/android/server/am/deprecatedsdk/Components.java
new file mode 100644
index 0000000..180738d
--- /dev/null
+++ b/tests/framework/base/activitymanager/appDeprecatedSdk/src/android/server/am/deprecatedsdk/Components.java
@@ -0,0 +1,9 @@
+package android.server.am.deprecatedsdk;
+
+import android.content.ComponentName;
+import android.server.am.component.ComponentsBase;
+
+public class Components extends ComponentsBase {
+
+ public static final ComponentName MAIN_ACTIVITY = component(Components.class, "MainActivity");
+}
diff --git a/tests/framework/base/activitymanager/appSecondUid/src/android/server/am/second/LaunchBroadcastReceiver.java b/tests/framework/base/activitymanager/appSecondUid/src/android/server/am/second/LaunchBroadcastReceiver.java
index caa9e9e..1b975ac 100644
--- a/tests/framework/base/activitymanager/appSecondUid/src/android/server/am/second/LaunchBroadcastReceiver.java
+++ b/tests/framework/base/activitymanager/appSecondUid/src/android/server/am/second/LaunchBroadcastReceiver.java
@@ -19,7 +19,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.server.am.util.ActivityLauncher;
+import android.server.am.ActivityLauncher;
import android.util.Log;
/** Broadcast receiver that can launch activities. */
diff --git a/tests/framework/base/activitymanager/app_base/Android.mk b/tests/framework/base/activitymanager/app_base/Android.mk
index c395f97..384d715 100644
--- a/tests/framework/base/activitymanager/app_base/Android.mk
+++ b/tests/framework/base/activitymanager/app_base/Android.mk
@@ -8,6 +8,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
android-support-v4 \
+ cts-amwm-util \
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
diff --git a/tests/framework/base/activitymanager/app_base/src/android/server/am/LaunchingActivity.java b/tests/framework/base/activitymanager/app_base/src/android/server/am/LaunchingActivity.java
index 2b8d3be..1eadf61 100644
--- a/tests/framework/base/activitymanager/app_base/src/android/server/am/LaunchingActivity.java
+++ b/tests/framework/base/activitymanager/app_base/src/android/server/am/LaunchingActivity.java
@@ -17,11 +17,8 @@
package android.server.am;
import android.os.Bundle;
-import android.server.am.util.ActivityLauncher;
import android.app.Activity;
import android.content.Intent;
-import android.server.am.util.ActivityLauncher;
-import android.util.Log;
/**
* Activity that launches another activities when new intent is received.
diff --git a/tests/framework/base/activitymanager/app_base/src/android/server/am/component/ComponentsBase.java b/tests/framework/base/activitymanager/app_base/src/android/server/am/component/ComponentsBase.java
index 2843c4c..f6c3471 100644
--- a/tests/framework/base/activitymanager/app_base/src/android/server/am/component/ComponentsBase.java
+++ b/tests/framework/base/activitymanager/app_base/src/android/server/am/component/ComponentsBase.java
@@ -16,24 +16,10 @@
package android.server.am.component;
-import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertThat;
-import android.app.Activity;
-import android.app.Service;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.Context;
-
-import org.hamcrest.Matchers;
-
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.stream.Collectors;
/**
* Base class for Components constants holding class.
diff --git a/tests/framework/base/activitymanager/app_base/src/android/server/am/util/ActivityLauncher.java b/tests/framework/base/activitymanager/app_base/src/android/server/am/util/ActivityLauncher.java
deleted file mode 100644
index 4f60e0a..0000000
--- a/tests/framework/base/activitymanager/app_base/src/android/server/am/util/ActivityLauncher.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.server.am.util;
-
-import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
-import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
-
-import android.app.ActivityOptions;
-import android.content.Intent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Bundle;
-import android.server.am.TestActivity;
-import android.text.TextUtils;
-import android.util.Log;
-
-/** Utility class which contains common code for launching activities. */
-public class ActivityLauncher {
- private static final String TAG = ActivityLauncher.class.getSimpleName();
-
- public static void launchActivityFromExtras(final Context context, Bundle extras) {
- if (extras == null || !extras.getBoolean("launch_activity")) {
- return;
- }
-
- Log.i(TAG, "launchActivityFromExtras: extras=" + extras);
-
- final Intent newIntent = new Intent();
- final String targetComponent = extras.getString("target_component");
- final String targetActivity = extras.getString("target_activity");
- if (!TextUtils.isEmpty(targetComponent)) {
- newIntent.setComponent(ComponentName.unflattenFromString(targetComponent));
- } else if (targetActivity != null) {
- final String extraPackageName = extras.getString("package_name");
- final String packageName = extraPackageName != null ? extraPackageName
- : context.getApplicationContext().getPackageName();
- newIntent.setComponent(new ComponentName(packageName,
- packageName + "." + targetActivity));
- } else {
- newIntent.setClass(context, TestActivity.class);
- }
-
- if (extras.getBoolean("launch_to_the_side")) {
- newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_LAUNCH_ADJACENT);
- if (extras.getBoolean("random_data")) {
- final Uri data = new Uri.Builder()
- .path(String.valueOf(System.currentTimeMillis()))
- .build();
- newIntent.setData(data);
- }
- }
- if (extras.getBoolean("multiple_task")) {
- newIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
- }
- if (extras.getBoolean("new_task")) {
- newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
- }
-
- if (extras.getBoolean("reorder_to_front")) {
- newIntent.addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT);
- }
-
- ActivityOptions options = null;
- final int displayId = extras.getInt("display_id", -1);
- if (displayId != -1) {
- options = ActivityOptions.makeBasic();
- options.setLaunchDisplayId(displayId);
- newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK);
- }
-
- final Context launchContext = extras.getBoolean("use_application_context") ?
- context.getApplicationContext() : context;
-
- try {
- launchContext.startActivity(newIntent, options != null ? options.toBundle() : null);
- } catch (SecurityException e) {
- Log.e(TAG, "SecurityException launching activity");
- } catch (Exception e) {
- if (extras.getBoolean("suppress_exceptions")) {
- Log.e(TAG, "Exception launching activity");
- } else {
- throw e;
- }
- }
- }
-}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
index 7874080..59a2509 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
@@ -51,6 +51,7 @@
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.FlakyTest;
+import org.junit.Ignore;
import org.junit.Test;
import java.util.ArrayList;
@@ -371,7 +372,8 @@
}
// TODO(b/70870253): This test seems malfunction.
- // @Test
+ @Ignore("b/70870253")
+ @Test
public void testNonFullscreenActivityProhibited() throws Exception {
// We do not wait for the activity as it should not launch based on the restrictions around
// specifying orientation. We instead start an activity known to launch immediately after
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
index d3f3ee3..ab1a820 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
@@ -79,6 +79,7 @@
testChangeFontScale(FONT_SCALE_ACTIVITY, true /* relaunch */);
}
+ @FlakyTest(bugId = 73812451)
@Presubmit
@Test
public void testChangeFontScaleNoRelaunch() throws Exception {
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
index 9c81e59..7c49d13 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
@@ -20,6 +20,9 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.server.am.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
+import static android.server.am.ActivityLauncher.KEY_LAUNCH_ACTIVITY;
+import static android.server.am.ActivityLauncher.KEY_NEW_TASK;
+import static android.server.am.ActivityLauncher.KEY_TARGET_ACTIVITY;
import static android.server.am.ActivityManagerDisplayTestBase.ReportedDisplayMetrics
.getDisplayMetrics;
import static android.server.am.ActivityManagerState.STATE_RESUMED;
@@ -248,8 +251,8 @@
mAmWmState.assertFocusedStack("Focus must be on the secondary display", frontStackId);
// Launch non-resizeable activity from secondary display.
- executeShellCommand("am broadcast -a trigger_broadcast --ez launch_activity true "
- + "--ez new_task true --es target_activity "
+ executeShellCommand("am broadcast -a trigger_broadcast --ez " + KEY_LAUNCH_ACTIVITY
+ + " true --ez " + KEY_NEW_TASK + " true --es " + KEY_TARGET_ACTIVITY + " "
+ getSimpleClassName(NON_RESIZEABLE_ACTIVITY));
mAmWmState.computeState(NON_RESIZEABLE_ACTIVITY);
@@ -1464,8 +1467,9 @@
assertEquals("Focus must be on primary display", DEFAULT_DISPLAY_ID,
focusedStack.mDisplayId);
- executeShellCommand("am broadcast -a trigger_broadcast --ez launch_activity true "
- + "--ez new_task true --es target_activity " + LAUNCHING_ACTIVITY);
+ executeShellCommand("am broadcast -a trigger_broadcast --ez " + KEY_LAUNCH_ACTIVITY
+ + " true --ez " + KEY_NEW_TASK + " true --es " + KEY_TARGET_ACTIVITY + " "
+ + LAUNCHING_ACTIVITY);
// Check that the third activity ends up in a new task in the same stack as the
// first activity
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
index c7e7381..b8885ac 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
@@ -244,6 +244,7 @@
@Test
@Presubmit
+ @FlakyTest(bugId = 73808815)
public void testLaunchToSideSingleInstance() throws Exception {
launchTargetToSide(SINGLE_INSTANCE_ACTIVITY, false);
}
@@ -482,6 +483,7 @@
}
}
+ @FlakyTest(bugId = 73813034)
@Test
@Presubmit
public void testFinishDockActivityWhileMinimized() throws Exception {
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java
index fe05359..925f9a4 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java
@@ -16,6 +16,9 @@
package android.server.am;
+import static android.server.am.Components.BOTTOM_ACTIVITY;
+import static android.server.am.Components.TOP_ACTIVITY;
+import static android.server.am.Components.TRANSLUCENT_TOP_ACTIVITY;
import static android.server.am.WindowManagerState.TRANSIT_ACTIVITY_CLOSE;
import static android.server.am.WindowManagerState.TRANSIT_ACTIVITY_OPEN;
import static android.server.am.WindowManagerState.TRANSIT_TASK_CLOSE;
@@ -27,6 +30,7 @@
import static org.junit.Assert.assertEquals;
+import android.content.ComponentName;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.FlakyTest;
@@ -48,12 +52,6 @@
@FlakyTest(bugId = 71792333)
public class ActivityManagerTransitionSelectionTests extends ActivityManagerTestBase {
- private static final String BOTTOM_ACTIVITY_NAME = "BottomActivity";
- private static final String TOP_ACTIVITY_NAME = "TopActivity";
- private static final String TRANSLUCENT_TOP_ACTIVITY_NAME = "TranslucentTopActivity";
-
- //------------------------------------------------------------------------//
-
// Test activity open/close under normal timing
@Test
public void testOpenActivity_NeitherWallpaper() throws Exception {
@@ -225,40 +223,46 @@
testTransitionSelection(true /*testOpen*/, false /*testNewTask*/,
bottomWallpaper, topWallpaper, false /*topTranslucent*/, slowStop, expectedTransit);
}
+
private void testCloseActivity(boolean bottomWallpaper,
boolean topWallpaper, boolean slowStop, String expectedTransit) throws Exception {
testTransitionSelection(false /*testOpen*/, false /*testNewTask*/,
bottomWallpaper, topWallpaper, false /*topTranslucent*/, slowStop, expectedTransit);
}
+
private void testOpenTask(boolean bottomWallpaper,
boolean topWallpaper, boolean slowStop, String expectedTransit) throws Exception {
testTransitionSelection(true /*testOpen*/, true /*testNewTask*/,
bottomWallpaper, topWallpaper, false /*topTranslucent*/, slowStop, expectedTransit);
}
+
private void testCloseTask(boolean bottomWallpaper,
boolean topWallpaper, boolean slowStop, String expectedTransit) throws Exception {
testTransitionSelection(false /*testOpen*/, true /*testNewTask*/,
bottomWallpaper, topWallpaper, false /*topTranslucent*/, slowStop, expectedTransit);
}
+
private void testCloseActivityTranslucent(boolean bottomWallpaper,
boolean topWallpaper, String expectedTransit) throws Exception {
testTransitionSelection(false /*testOpen*/, false /*testNewTask*/,
bottomWallpaper, topWallpaper, true /*topTranslucent*/,
false /*slowStop*/, expectedTransit);
}
+
private void testCloseTaskTranslucent(boolean bottomWallpaper,
boolean topWallpaper, String expectedTransit) throws Exception {
testTransitionSelection(false /*testOpen*/, true /*testNewTask*/,
bottomWallpaper, topWallpaper, true /*topTranslucent*/,
false /*slowStop*/, expectedTransit);
}
+
//------------------------------------------------------------------------//
private void testTransitionSelection(
boolean testOpen, boolean testNewTask,
boolean bottomWallpaper, boolean topWallpaper, boolean topTranslucent,
boolean testSlowStop, String expectedTransit) throws Exception {
- String bottomStartCmd = getAmStartCmd(BOTTOM_ACTIVITY_NAME);
+ String bottomStartCmd = getAmStartCmd(BOTTOM_ACTIVITY);
if (bottomWallpaper) {
bottomStartCmd += " --ez USE_WALLPAPER true";
}
@@ -267,11 +271,10 @@
}
executeShellCommand(bottomStartCmd);
- mAmWmState.computeState(new WaitForValidActivityState(BOTTOM_ACTIVITY_NAME));
+ mAmWmState.computeState(BOTTOM_ACTIVITY);
- final String topActivityName = topTranslucent ?
- TRANSLUCENT_TOP_ACTIVITY_NAME : TOP_ACTIVITY_NAME;
- String topStartCmd = getAmStartCmd(topActivityName);
+ final ComponentName topActivity = topTranslucent ? TRANSLUCENT_TOP_ACTIVITY : TOP_ACTIVITY;
+ String topStartCmd = getAmStartCmd(topActivity);
if (testNewTask) {
topStartCmd += " -f 0x18000000";
}
@@ -285,9 +288,9 @@
Thread.sleep(5000);
if (testOpen) {
- mAmWmState.computeState(new WaitForValidActivityState(topActivityName));
+ mAmWmState.computeState(topActivity);
} else {
- mAmWmState.computeState(new WaitForValidActivityState(BOTTOM_ACTIVITY_NAME));
+ mAmWmState.computeState(BOTTOM_ACTIVITY);
}
assertEquals("Picked wrong transition", expectedTransit,
diff --git a/tests/framework/base/activitymanager/src/android/server/am/AnimationBackgroundTests.java b/tests/framework/base/activitymanager/src/android/server/am/AnimationBackgroundTests.java
index fb56ce7..c8e3fa1 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/AnimationBackgroundTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/AnimationBackgroundTests.java
@@ -16,15 +16,16 @@
package android.server.am;
-
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.server.am.Components.ANIMATION_TEST_ACTIVITY;
+import static android.server.am.Components.LAUNCHING_ACTIVITY;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import static android.server.am.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
-
/**
* Build/Install/Run:
* atest CtsActivityManagerDeviceTestCases:AnimationBackgroundTests
@@ -33,9 +34,9 @@
@Test
public void testAnimationBackground_duringAnimation() throws Exception {
- launchActivityOnDisplay(LAUNCHING_ACTIVITY_NAME, DEFAULT_DISPLAY_ID);
+ launchActivityOnDisplay(LAUNCHING_ACTIVITY, DEFAULT_DISPLAY);
getLaunchActivityBuilder()
- .setTargetActivityName("AnimationTestActivity")
+ .setTargetActivity(ANIMATION_TEST_ACTIVITY)
.setWaitForLaunched(false)
.execute();
@@ -51,9 +52,9 @@
@Test
public void testAnimationBackground_gone() throws Exception {
- launchActivityOnDisplay(LAUNCHING_ACTIVITY_NAME, DEFAULT_DISPLAY_ID);
- getLaunchActivityBuilder().setTargetActivityName("AnimationTestActivity").execute();
- mAmWmState.computeState(new WaitForValidActivityState.Builder("AnimationTestActivity").build());
+ launchActivityOnDisplay(LAUNCHING_ACTIVITY, DEFAULT_DISPLAY);
+ getLaunchActivityBuilder().setTargetActivity(ANIMATION_TEST_ACTIVITY).execute();
+ mAmWmState.computeState(ANIMATION_TEST_ACTIVITY);
assertFalse("window animation background needs to be gone", mAmWmState.getWmState()
.getStandardStackByWindowingMode(WINDOWING_MODE_FULLSCREEN)
.isWindowAnimationBackgroundSurfaceShowing());
diff --git a/tests/framework/base/activitymanager/src/android/server/am/DeprecatedTargetSdkTest.java b/tests/framework/base/activitymanager/src/android/server/am/DeprecatedTargetSdkTest.java
index 42edc5f..167ba4b 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/DeprecatedTargetSdkTest.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/DeprecatedTargetSdkTest.java
@@ -16,8 +16,13 @@
package android.server.am;
+import static android.server.am.ComponentNameUtils.getWindowName;
+import static android.server.am.UiDeviceUtils.pressBackButton;
+import static android.server.am.deprecatedsdk.Components.MAIN_ACTIVITY;
+
import static org.junit.Assert.assertTrue;
+import android.content.ComponentName;
import android.support.test.runner.AndroidJUnit4;
import org.junit.After;
@@ -32,11 +37,10 @@
*/
@RunWith(AndroidJUnit4.class)
public class DeprecatedTargetSdkTest extends ActivityManagerTestBase {
- private static final String AM_START_COMMAND = "am start -n %s/%s.%s";
- private static final String AM_FORCE_STOP = "am force-stop %s";
- private static final int ACTIVITY_TIMEOUT_MILLIS = 1000;
- private static final int WINDOW_TIMEOUT_MILLIS = 1000;
+ /** @see com.android.server.am.DeprecatedTargetSdkVersionDialog */
+ private static final String DEPRECATED_TARGET_SDK_VERSION_DIALOG =
+ "DeprecatedTargetSdkVersionDialog";
@After
@Override
@@ -44,49 +48,31 @@
super.tearDown();
// Ensure app process is stopped.
- forceStopPackage("android.server.am.deprecatedsdk");
- forceStopPackage("android.server.am");
+ stopTestPackage(MAIN_ACTIVITY);
}
@Test
public void testCompatibilityDialog() throws Exception {
// Launch target app.
- startActivity("android.server.am.deprecatedsdk", "MainActivity");
- verifyWindowDisplayed("MainActivity", ACTIVITY_TIMEOUT_MILLIS);
- verifyWindowDisplayed("DeprecatedTargetSdkVersionDialog", WINDOW_TIMEOUT_MILLIS);
+ launchActivity(MAIN_ACTIVITY);
+ assertActivityDisplayed(MAIN_ACTIVITY);
+ assertWindowDisplayed(DEPRECATED_TARGET_SDK_VERSION_DIALOG);
// Go back to dismiss the warning dialog.
- executeShellCommand("input keyevent 4");
+ pressBackButton();
// Go back again to formally stop the app. If we just kill the process, it'll attempt to
// resume rather than starting from scratch (as far as ActivityStack is concerned) and it
// won't invoke the warning dialog.
- executeShellCommand("input keyevent 4");
+ pressBackButton();
}
- private void forceStopPackage(String packageName) {
- final String forceStopCmd = String.format(AM_FORCE_STOP, packageName);
- executeShellCommand(forceStopCmd);
+ private void assertActivityDisplayed(final ComponentName activityName) throws Exception {
+ assertWindowDisplayed(getWindowName(activityName));
}
- private void startActivity(String packageName, String activityName){
- executeShellCommand(getStartCommand(packageName, activityName));
- }
-
- private String getStartCommand(String packageName, String activityName) {
- return String.format(AM_START_COMMAND, packageName, packageName, activityName);
- }
-
- private void verifyWindowDisplayed(String windowName, long timeoutMillis) {
- boolean success = false;
-
- // Verify that compatibility dialog is shown within 1000ms.
- final long timeoutTimeMillis = System.currentTimeMillis() + timeoutMillis;
- while (!success && System.currentTimeMillis() < timeoutTimeMillis) {
- final String output = executeShellCommand("dumpsys window");
- success = output.contains(windowName);
- }
-
- assertTrue(windowName + " was not displayed", success);
+ private void assertWindowDisplayed(final String windowName) throws Exception {
+ mAmWmState.waitForValidState(WaitForValidActivityState.forWindow(windowName));
+ assertTrue(windowName + "is visible", mAmWmState.getWmState().isWindowVisible(windowName));
}
}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java
index a5673a6..421b542 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java
@@ -24,6 +24,9 @@
final ActivityTestRule mSecondActivityTestRule = new ActivityTestRule(SecondActivity.class,
true /* initialTouchMode */, false /* launchActivity */);
+ final ActivityTestRule mTranslucentActivityTestRule = new ActivityTestRule(
+ TranslucentActivity.class, true /* initialTouchMode */, false /* launchActivity */);
+
private final ActivityLifecycleMonitor mLifecycleMonitor = ActivityLifecycleMonitorRegistry
.getInstance();
private LifecycleLog mLifecycleLog;
@@ -80,4 +83,8 @@
// Test activity
public static class SecondActivity extends Activity {
}
+
+ // Translucent test activity
+ public static class TranslucentActivity extends Activity {
+ }
}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
index b785b6b..a70bc79 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
@@ -1,6 +1,7 @@
package android.server.am.lifecycle;
import static android.support.test.runner.lifecycle.Stage.DESTROYED;
+import static android.support.test.runner.lifecycle.Stage.PAUSED;
import static android.support.test.runner.lifecycle.Stage.RESUMED;
import static android.support.test.runner.lifecycle.Stage.STOPPED;
@@ -60,7 +61,7 @@
@FlakyTest(bugId = 72956507)
@Test
- public void testRelaunch() throws Exception {
+ public void testRelaunchResumed() throws Exception {
final Activity activity = mFirstActivityTestRule.launchActivity(new Intent());
waitAndAssertActivityStates(state(activity, RESUMED));
@@ -68,6 +69,38 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync(activity::recreate);
waitAndAssertActivityStates(state(activity, RESUMED));
- LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog());
+ LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(), RESUMED);
+ }
+
+ @FlakyTest(bugId = 72956507)
+ @Test
+ public void testRelaunchPaused() throws Exception {
+ final Activity pausedActivity = mFirstActivityTestRule.launchActivity(new Intent());
+ final Activity topTranslucentActivity =
+ mTranslucentActivityTestRule.launchActivity(new Intent());
+
+ waitAndAssertActivityStates(state(pausedActivity, PAUSED),
+ state(topTranslucentActivity, RESUMED));
+
+ getLifecycleLog().clear();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(pausedActivity::recreate);
+ waitAndAssertActivityStates(state(pausedActivity, PAUSED));
+
+ LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(), PAUSED);
+ }
+
+ @FlakyTest(bugId = 72956507)
+ @Test
+ public void testRelaunchStopped() throws Exception {
+ final Activity stoppedActivity = mFirstActivityTestRule.launchActivity(new Intent());
+ final Activity topActivity = mSecondActivityTestRule.launchActivity(new Intent());
+
+ waitAndAssertActivityStates(state(stoppedActivity, STOPPED), state(topActivity, RESUMED));
+
+ getLifecycleLog().clear();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(stoppedActivity::recreate);
+ waitAndAssertActivityStates(state(stoppedActivity, STOPPED));
+
+ LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(), STOPPED);
}
}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java
index bbb3ad8..094ce72 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java
@@ -71,13 +71,22 @@
}
static void assertRelaunchSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ LifecycleLog lifecycleLog, Stage startState) {
final List<Stage> observedTransitions = lifecycleLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "relaunch");
- final List<Stage> expectedTransitions =
- Arrays.asList(PAUSED, STOPPED, DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED);
+ final List<Stage> expectedTransitions;
+ if (startState == PAUSED) {
+ expectedTransitions = Arrays.asList(
+ STOPPED, DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED, PAUSED);
+ } else if (startState == STOPPED) {
+ expectedTransitions = Arrays.asList(
+ DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED, PAUSED, STOPPED);
+ } else {
+ expectedTransitions = Arrays.asList(
+ PAUSED, STOPPED, DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED);
+ }
assertEquals(errorMessage, expectedTransitions, observedTransitions);
}
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityLauncher.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityLauncher.java
new file mode 100644
index 0000000..1be32de
--- /dev/null
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityLauncher.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.server.am;
+
+import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
+
+import android.app.ActivityOptions;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+
+/** Utility class which contains common code for launching activities. */
+public class ActivityLauncher {
+ private static final String TAG = ActivityLauncher.class.getSimpleName();
+
+ /** Key for boolean extra, indicates whether it should launch an activity. */
+ public static final String KEY_LAUNCH_ACTIVITY = "launch_activity";
+ /**
+ * Key for boolean extra, indicates whether it the activity should be launched to side in
+ * split-screen.
+ */
+ public static final String KEY_LAUNCH_TO_SIDE = "launch_to_the_side";
+ /**
+ * Key for boolean extra, indicates if launch intent should include random data to be different
+ * from other launch intents.
+ */
+ public static final String KEY_RANDOM_DATA = "random_data";
+ /**
+ * Key for boolean extra, indicates if launch intent should have
+ * {@link Intent#FLAG_ACTIVITY_NEW_TASK}.
+ */
+ public static final String KEY_NEW_TASK = "new_task";
+ /**
+ * Key for boolean extra, indicates if launch intent should have
+ * {@link Intent#FLAG_ACTIVITY_MULTIPLE_TASK}.
+ */
+ public static final String KEY_MULTIPLE_TASK = "multiple_task";
+ /**
+ * Key for boolean extra, indicates if launch intent should have
+ * {@link Intent#FLAG_ACTIVITY_REORDER_TO_FRONT}.
+ */
+ public static final String KEY_REORDER_TO_FRONT = "reorder_to_front";
+ /**
+ * Key for string extra with string representation of target component.
+ */
+ public static final String KEY_TARGET_COMPONENT = "target_component";
+ /**
+ * Key for string extra with target activity name.
+ */
+ public static final String KEY_TARGET_ACTIVITY = "target_activity";
+ /**
+ * Key for string extra with target package name. If {@link #KEY_TARGET_ACTIVITY} is provided
+ * and this extra is not, then current application's package name will be used.
+ */
+ public static final String KEY_TARGET_PACKAGE = "target_package";
+ /**
+ * Key for int extra with target display id where the activity should be launched. Adding this
+ * automatically applies {@link Intent#FLAG_ACTIVITY_NEW_TASK} and
+ * {@link Intent#FLAG_ACTIVITY_MULTIPLE_TASK} to the intent.
+ */
+ public static final String KEY_DISPLAY_ID = "display_id";
+ /**
+ * Key for boolean extra, indicates if launch should be done from application context of the one
+ * passed in {@link #launchActivityFromExtras(Context, Bundle)}.
+ */
+ public static final String KEY_USE_APPLICATION_CONTEXT = "use_application_context";
+ /**
+ * Key for boolean extra, indicates if instrumentation context will be used for launch. This
+ * means that {@link PendingIntent} should be used instead of a regular one, because application
+ * switch will not be allowed otherwise.
+ */
+ public static final String KEY_USE_INSTRUMENTATION = "use_instrumentation";
+ /**
+ * Key for boolean extra, indicates if any exceptions thrown during launch other then
+ * {@link SecurityException} should be suppressed. A {@link SecurityException} is never thrown,
+ * it's always written to logs.
+ */
+ public static final String KEY_SUPPRESS_EXCEPTIONS = "suppress_exceptions";
+
+
+ /** Perform an activity launch configured by provided extras. */
+ public static void launchActivityFromExtras(final Context context, Bundle extras) {
+ if (extras == null || !extras.getBoolean(KEY_LAUNCH_ACTIVITY)) {
+ return;
+ }
+
+ Log.i(TAG, "launchActivityFromExtras: extras=" + extras);
+
+ final Intent newIntent = new Intent();
+ final String targetComponent = extras.getString(KEY_TARGET_COMPONENT);
+ final String targetActivity = extras.getString(KEY_TARGET_ACTIVITY);
+ if (!TextUtils.isEmpty(targetComponent)) {
+ newIntent.setComponent(ComponentName.unflattenFromString(targetComponent));
+ } else if (targetActivity != null) {
+ final String extraPackageName = extras.getString(KEY_TARGET_PACKAGE);
+ final String packageName = extraPackageName != null ? extraPackageName
+ : context.getApplicationContext().getPackageName();
+ newIntent.setComponent(new ComponentName(packageName,
+ packageName + "." + targetActivity));
+ } else {
+ newIntent.setComponent(new ComponentName("android.server.am",
+ "android.server.am.TestActivity"));
+ }
+
+ if (extras.getBoolean(KEY_LAUNCH_TO_SIDE)) {
+ newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_LAUNCH_ADJACENT);
+ if (extras.getBoolean(KEY_RANDOM_DATA)) {
+ final Uri data = new Uri.Builder()
+ .path(String.valueOf(System.currentTimeMillis()))
+ .build();
+ newIntent.setData(data);
+ }
+ }
+ if (extras.getBoolean(KEY_MULTIPLE_TASK)) {
+ newIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+ }
+ if (extras.getBoolean(KEY_NEW_TASK)) {
+ newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
+ }
+
+ if (extras.getBoolean(KEY_REORDER_TO_FRONT)) {
+ newIntent.addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT);
+ }
+
+ ActivityOptions options = null;
+ final int displayId = extras.getInt(KEY_DISPLAY_ID, -1);
+ if (displayId != -1) {
+ options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(displayId);
+ newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK);
+ }
+ final Bundle optionsBundle = options != null ? options.toBundle() : null;
+
+ final Context launchContext = extras.getBoolean(KEY_USE_APPLICATION_CONTEXT) ?
+ context.getApplicationContext() : context;
+
+ try {
+ if (extras.getBoolean(KEY_USE_INSTRUMENTATION)) {
+ // Using PendingIntent for Instrumentation launches, because otherwise we won't
+ // be allowed to switch the current activity with ours with different uid.
+ // android.permission.STOP_APP_SWITCHES is needed to do this directly.
+ final PendingIntent pendingIntent = PendingIntent.getActivity(launchContext, 0,
+ newIntent, 0, optionsBundle);
+ pendingIntent.send();
+ } else {
+ launchContext.startActivity(newIntent, optionsBundle);
+ }
+ } catch (SecurityException e) {
+ Log.e(TAG, "SecurityException launching activity");
+ } catch (PendingIntent.CanceledException e) {
+ if (extras.getBoolean(KEY_SUPPRESS_EXCEPTIONS)) {
+ Log.e(TAG, "Exception launching activity with pending intent");
+ } else {
+ throw new RuntimeException(e);
+ }
+ Log.e(TAG, "SecurityException launching activity");
+ } catch (Exception e) {
+ if (extras.getBoolean(KEY_SUPPRESS_EXCEPTIONS)) {
+ Log.e(TAG, "Exception launching activity");
+ } else {
+ throw e;
+ }
+ }
+ }
+}
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
index 9ff84cb..18bbb5b 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
@@ -33,6 +33,20 @@
import static android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT;
import static android.content.pm.PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE;
import static android.content.pm.PackageManager.FEATURE_WATCH;
+import static android.server.am.ActivityLauncher.KEY_DISPLAY_ID;
+import static android.server.am.ActivityLauncher.KEY_LAUNCH_ACTIVITY;
+import static android.server.am.ActivityLauncher.KEY_LAUNCH_TO_SIDE;
+import static android.server.am.ActivityLauncher.KEY_MULTIPLE_TASK;
+import static android.server.am.ActivityLauncher.KEY_NEW_TASK;
+import static android.server.am.ActivityLauncher.KEY_RANDOM_DATA;
+import static android.server.am.ActivityLauncher.KEY_REORDER_TO_FRONT;
+import static android.server.am.ActivityLauncher.KEY_SUPPRESS_EXCEPTIONS;
+import static android.server.am.ActivityLauncher.KEY_TARGET_ACTIVITY;
+import static android.server.am.ActivityLauncher.KEY_TARGET_COMPONENT;
+import static android.server.am.ActivityLauncher.KEY_TARGET_PACKAGE;
+import static android.server.am.ActivityLauncher.KEY_USE_APPLICATION_CONTEXT;
+import static android.server.am.ActivityLauncher.KEY_USE_INSTRUMENTATION;
+import static android.server.am.ActivityLauncher.launchActivityFromExtras;
import static android.server.am.ComponentNameUtils.getActivityName;
import static android.server.am.ComponentNameUtils.getLogTag;
import static android.server.am.ComponentNameUtils.getSimpleClassName;
@@ -58,6 +72,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Bitmap;
+import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.provider.Settings;
@@ -504,16 +519,10 @@
protected void launchActivitiesInSplitScreen(LaunchActivityBuilder primaryActivity,
LaunchActivityBuilder secondaryActivity) throws Exception {
// Launch split-screen primary.
- String tmpLaunchingActivityName = primaryActivity.mLaunchingActivityName;
primaryActivity
- // TODO(b/70618153): Work around issues with the activity launch builder where
- // launching activity doesn't work. We don't really need launching activity in this
- // case and should probably change activity launcher to work without a launching
- // activity.
- .setLaunchingActivityName(primaryActivity.mTargetActivityName)
+ .setUseInstrumentation()
.setWaitForLaunched(true)
.execute();
- primaryActivity.setLaunchingActivityName(tmpLaunchingActivityName);
final int taskId = mAmWmState.getAmState().getTaskByActivityName(
primaryActivity.mTargetActivityName).mTaskId;
@@ -523,17 +532,13 @@
mAmWmState.waitForRecentsActivityVisible();
// Launch split-screen secondary
- tmpLaunchingActivityName = secondaryActivity.mLaunchingActivityName;
+ // Recents become focused, so we can just launch new task in focused stack
secondaryActivity
- // TODO(b/70618153): Work around issues with the activity launch builder where
- // launching activity doesn't work. We don't really need launching activity in this
- // case and should probably change activity launcher to work without a launching
- // activity.
- .setLaunchingActivityName(secondaryActivity.mTargetActivityName)
+ .setUseInstrumentation()
.setWaitForLaunched(true)
- .setToSide(true)
+ .setNewTask(true)
+ .setMultipleTask(true)
.execute();
- secondaryActivity.setLaunchingActivityName(tmpLaunchingActivityName);
}
protected void setActivityTaskWindowingMode(final ComponentName activityName,
@@ -1462,6 +1467,11 @@
private String mBroadcastReceiverPackage;
private String mBroadcastReceiverAction;
+ private enum LauncherType {
+ INSTRUMENTATION, LAUNCHING_ACTIVITY, BROADCAST_RECEIVER
+ }
+ private LauncherType mLauncherType = LauncherType.LAUNCHING_ACTIVITY;
+
public LaunchActivityBuilder(ActivityAndWindowManagersState amWmState) {
mAmWmState = amWmState;
mWaitForLaunched = true;
@@ -1521,11 +1531,13 @@
@Deprecated
public LaunchActivityBuilder setLaunchingActivityName(String name) {
mLaunchingActivityName = name;
+ mLauncherType = LauncherType.LAUNCHING_ACTIVITY;
return this;
}
public LaunchActivityBuilder setLaunchingActivity(ComponentName component) {
mLaunchingActivity = component;
+ mLauncherType = LauncherType.LAUNCHING_ACTIVITY;
return this;
}
@@ -1534,11 +1546,21 @@
return this;
}
- /** Use broadcast receiver instead of launching activity. */
+ /** Use broadcast receiver as a launchpad for activities. */
public LaunchActivityBuilder setUseBroadcastReceiver(final ComponentName broadcastReceiver,
final String broadcastAction) {
mBroadcastReceiverPackage = broadcastReceiver.getPackageName();
mBroadcastReceiverAction = broadcastAction;
+ mLauncherType = LauncherType.BROADCAST_RECEIVER;
+ return this;
+ }
+
+ /** Use {@link android.app.Instrumentation} as a launchpad for activities. */
+ public LaunchActivityBuilder setUseInstrumentation() {
+ mLauncherType = LauncherType.INSTRUMENTATION;
+ // Calling startActivity() from outside of an Activity context requires the
+ // FLAG_ACTIVITY_NEW_TASK flag.
+ setNewTask(true);
return this;
}
@@ -1548,6 +1570,44 @@
}
public void execute() throws Exception {
+ switch (mLauncherType) {
+ case INSTRUMENTATION:
+ launchUsingInstrumentation();
+ break;
+ case LAUNCHING_ACTIVITY:
+ case BROADCAST_RECEIVER:
+ launchUsingShellCommand();
+ }
+
+ if (mWaitForLaunched) {
+ mAmWmState.waitForValidState(false /* compareTaskAndStackBounds */, mTargetPackage,
+ new WaitForValidActivityState.Builder(mTargetActivityName).build());
+ }
+ }
+
+ /** Launch an activity using instrumentation. */
+ private void launchUsingInstrumentation() {
+ final Bundle b = new Bundle();
+ b.putBoolean(KEY_USE_INSTRUMENTATION, true);
+ b.putBoolean(KEY_LAUNCH_ACTIVITY, true);
+ b.putBoolean(KEY_LAUNCH_TO_SIDE, mToSide);
+ b.putBoolean(KEY_RANDOM_DATA, mRandomData);
+ b.putBoolean(KEY_NEW_TASK, mNewTask);
+ b.putBoolean(KEY_MULTIPLE_TASK, mMultipleTask);
+ b.putBoolean(KEY_REORDER_TO_FRONT, mReorderToFront);
+ b.putString(KEY_TARGET_ACTIVITY, mTargetActivityName);
+ b.putString(KEY_TARGET_PACKAGE, mTargetPackage);
+ b.putInt(KEY_DISPLAY_ID, mDisplayId);
+ b.putBoolean(KEY_USE_APPLICATION_CONTEXT, mUseApplicationContext);
+ b.putString(KEY_TARGET_COMPONENT, mComponent != null ? getActivityName(mComponent)
+ : null);
+ b.putBoolean(KEY_SUPPRESS_EXCEPTIONS, mSuppressExceptions);
+ final Context context = InstrumentationRegistry.getContext();
+ launchActivityFromExtras(context, b);
+ }
+
+ /** Build and execute a shell command to launch an activity. */
+ private void launchUsingShellCommand() {
StringBuilder commandBuilder = new StringBuilder();
if (mBroadcastReceiverPackage != null && mBroadcastReceiverAction != null) {
// Use broadcast receiver to launch the target.
@@ -1566,51 +1626,47 @@
}
// Add a flag to ensure we actually mean to launch an activity.
- commandBuilder.append(" --ez launch_activity true");
+ commandBuilder.append(" --ez " + KEY_LAUNCH_ACTIVITY + " true");
if (mToSide) {
- commandBuilder.append(" --ez launch_to_the_side true");
+ commandBuilder.append(" --ez " + KEY_LAUNCH_TO_SIDE + " true");
}
if (mRandomData) {
- commandBuilder.append(" --ez random_data true");
+ commandBuilder.append(" --ez " + KEY_RANDOM_DATA + " true");
}
if (mNewTask) {
- commandBuilder.append(" --ez new_task true");
+ commandBuilder.append(" --ez " + KEY_NEW_TASK + " true");
}
if (mMultipleTask) {
- commandBuilder.append(" --ez multiple_task true");
+ commandBuilder.append(" --ez " + KEY_MULTIPLE_TASK + " true");
}
if (mReorderToFront) {
- commandBuilder.append(" --ez reorder_to_front true");
+ commandBuilder.append(" --ez " + KEY_REORDER_TO_FRONT + " true");
}
if (mTargetActivityName != null) {
- commandBuilder.append(" --es target_activity ").append(mTargetActivityName);
- commandBuilder.append(" --es package_name ").append(mTargetPackage);
+ commandBuilder.append(" --es " + KEY_TARGET_ACTIVITY + " ")
+ .append(mTargetActivityName);
+ commandBuilder.append(" --es " + KEY_TARGET_PACKAGE + " ").append(mTargetPackage);
}
if (mDisplayId != INVALID_DISPLAY_ID) {
- commandBuilder.append(" --ei display_id ").append(mDisplayId);
+ commandBuilder.append(" --ei " + KEY_DISPLAY_ID + " ").append(mDisplayId);
}
if (mUseApplicationContext) {
- commandBuilder.append(" --ez use_application_context true");
+ commandBuilder.append(" --ez " + KEY_USE_APPLICATION_CONTEXT + " true");
}
if (mComponent != null) {
// {@link ActivityLauncher} parses this extra string by
// {@link ComponentName#unflattenFromString(String)}.
- commandBuilder.append(" --es target_component ")
+ commandBuilder.append(" --es " + KEY_TARGET_COMPONENT + " ")
.append(getActivityName(mComponent));
}
if (mSuppressExceptions) {
- commandBuilder.append(" --ez suppress_exceptions true");
+ commandBuilder.append(" --ez " + KEY_SUPPRESS_EXCEPTIONS + " true");
}
executeShellCommand(commandBuilder.toString());
-
- if (mWaitForLaunched) {
- mAmWmState.waitForValidState(false /* compareTaskAndStackBounds */, mTargetPackage,
- new WaitForValidActivityState(mTargetActivityName));
- }
}
}
}
diff --git a/tests/framework/base/windowmanager/frametestapp/src/android/server/wm/frametestapp/DialogTestActivity.java b/tests/framework/base/windowmanager/frametestapp/src/android/server/wm/frametestapp/DialogTestActivity.java
index e303f66..8410a8f 100644
--- a/tests/framework/base/windowmanager/frametestapp/src/android/server/wm/frametestapp/DialogTestActivity.java
+++ b/tests/framework/base/windowmanager/frametestapp/src/android/server/wm/frametestapp/DialogTestActivity.java
@@ -19,15 +19,11 @@
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
-import android.graphics.Rect;
-import android.os.Bundle;
import android.view.Gravity;
-import android.view.View;
import android.view.Window;
-import android.view.WindowInsets;
import android.view.WindowManager;
-public class DialogTestActivity extends Activity implements View.OnApplyWindowInsetsListener{
+public class DialogTestActivity extends Activity {
private static final String DIALOG_WINDOW_NAME = "TestDialog";
@@ -39,28 +35,16 @@
private AlertDialog mDialog;
- private Rect mOutsets = new Rect();
-
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- View content = new View(this);
- content.setOnApplyWindowInsetsListener(this);
- setContentView(content);
- }
-
@Override
protected void onStop() {
super.onStop();
mDialog.dismiss();
}
- public WindowInsets onApplyWindowInsets(View v, WindowInsets in) {
- if (in.isRound()) {
- mOutsets = new Rect(in.getSystemWindowInsetLeft(), in.getSystemWindowInsetTop(),
- in.getSystemWindowInsetRight(), in.getSystemWindowInsetBottom());
- }
+ @Override
+ protected void onResume() {
+ super.onResume();
setupTest(getIntent());
- return in;
}
private void setupTest(Intent intent) {
@@ -141,23 +125,23 @@
private void testExplicitSize() {
doLayoutParamTest((WindowManager.LayoutParams params) -> {
- params.width = 200 - mOutsets.left - mOutsets.right;
- params.height = 200 - mOutsets.bottom - mOutsets.top;
+ params.width = 200;
+ params.height = 200;
});
}
private void testExplicitSizeTopLeftGravity() {
doLayoutParamTest((WindowManager.LayoutParams params) -> {
- params.width = 200 - mOutsets.left - mOutsets.right;
- params.height = 200 - mOutsets.bottom - mOutsets.top;
+ params.width = 200;
+ params.height = 200;
params.gravity = Gravity.TOP | Gravity.LEFT;
});
}
private void testExplicitSizeBottomRightGravity() {
doLayoutParamTest((WindowManager.LayoutParams params) -> {
- params.width = 200 - mOutsets.left - mOutsets.right;
- params.height = 200 - mOutsets.bottom - mOutsets.top;
+ params.width = 200;
+ params.height = 200;
params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
});
}
@@ -182,6 +166,8 @@
doLayoutParamTest((WindowManager.LayoutParams params) -> {
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.MATCH_PARENT;
+ params.x = 100;
+ params.y = 100;
});
}
@@ -191,6 +177,8 @@
params.height = WindowManager.LayoutParams.MATCH_PARENT;
params.gravity = Gravity.LEFT | Gravity.TOP;
params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+ params.x = 100;
+ params.y = 100;
});
}
@@ -204,9 +192,9 @@
doLayoutParamTest((WindowManager.LayoutParams params) -> {
params.gravity = Gravity.LEFT | Gravity.TOP;
params.horizontalMargin = .25f;
- params.verticalMargin = .25f;
- params.width = 200 - mOutsets.left - mOutsets.right;
- params.height = 200 - mOutsets.bottom - mOutsets.top;
+ params.verticalMargin = .35f;
+ params.width = 200;
+ params.height = 200;
params.x = 0;
params.y = 0;
});
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEvent.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEvent.java
index 7c605f4..b9126ab 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEvent.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEvent.java
@@ -16,19 +16,53 @@
package com.android.cts.mockime;
+import android.inputmethodservice.AbstractInputMethodService;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.view.View;
/**
* An immutable object that stores event happened in the {@link MockIme}.
*/
public final class ImeEvent {
+ private enum ReturnType {
+ Null,
+ KnownUnsupportedType,
+ Boolean,
+ }
+
+ private static ReturnType getReturnTypeFromObject(@Nullable Object object) {
+ if (object == null) {
+ return ReturnType.Null;
+ }
+ if (object instanceof AbstractInputMethodService.AbstractInputMethodImpl) {
+ return ReturnType.KnownUnsupportedType;
+ }
+ if (object instanceof View) {
+ return ReturnType.KnownUnsupportedType;
+ }
+ if (object instanceof Boolean) {
+ return ReturnType.Boolean;
+ }
+ throw new UnsupportedOperationException("Unsupported return type=" + object);
+ }
+
ImeEvent(@NonNull String eventName, int nestLevel, @NonNull String threadName, int threadId,
boolean isMainThread, long enterTimestamp, long exitTimestamp, long enterWallTime,
long exitWallTime, @NonNull ImeState enterState, @Nullable ImeState exitState,
- @NonNull Bundle arguments) {
+ @NonNull Bundle arguments, @Nullable Object returnValue) {
+ this(eventName, nestLevel, threadName, threadId, isMainThread, enterTimestamp,
+ exitTimestamp, enterWallTime, exitWallTime, enterState, exitState, arguments,
+ returnValue, getReturnTypeFromObject(returnValue));
+ }
+
+ private ImeEvent(@NonNull String eventName, int nestLevel, @NonNull String threadName,
+ int threadId, boolean isMainThread, long enterTimestamp, long exitTimestamp,
+ long enterWallTime, long exitWallTime, @NonNull ImeState enterState,
+ @Nullable ImeState exitState, @NonNull Bundle arguments, @Nullable Object returnValue,
+ @NonNull ReturnType returnType) {
mEventName = eventName;
mNestLevel = nestLevel;
mThreadName = threadName;
@@ -41,6 +75,8 @@
mEnterState = enterState;
mExitState = exitState;
mArguments = arguments;
+ mReturnValue = returnValue;
+ mReturnType = returnType;
}
@NonNull
@@ -58,6 +94,7 @@
bundle.putBundle("mEnterState", mEnterState.toBundle());
bundle.putBundle("mExitState", mExitState != null ? mExitState.toBundle() : null);
bundle.putBundle("mArguments", mArguments);
+ bundle.putString("mReturnType", mReturnType.name());
return bundle;
}
@@ -75,9 +112,22 @@
final ImeState enterState = ImeState.fromBundle(bundle.getBundle("mEnterState"));
final ImeState exitState = ImeState.fromBundle(bundle.getBundle("mExitState"));
final Bundle arguments = bundle.getBundle("mArguments");
+ final Object result;
+ final ReturnType returnType = ReturnType.valueOf(bundle.getString("mReturnType"));
+ switch (returnType) {
+ case Null:
+ case KnownUnsupportedType:
+ result = null;
+ break;
+ case Boolean:
+ result = bundle.getBoolean("mReturnValue");
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported type=" + returnType);
+ }
return new ImeEvent(eventName, nestLevel, threadName,
threadId, isMainThread, enterTimestamp, exitTimestamp, enterWallTime, exitWallTime,
- enterState, exitState, arguments);
+ enterState, exitState, arguments, result, returnType);
}
/**
@@ -183,6 +233,22 @@
}
/**
+ * @return result value of this event.
+ * @throws NullPointerException if the return value is {@code null}
+ * @throws ClassCastException if the return value is non-{@code null} object that is different
+ * from {@link Boolean}
+ */
+ public boolean getReturnBooleanValue() {
+ if (mReturnType == ReturnType.Null) {
+ throw new NullPointerException();
+ }
+ if (mReturnType != ReturnType.Boolean) {
+ throw new ClassCastException();
+ }
+ return (Boolean) mReturnValue;
+ }
+
+ /**
* @return {@code true} if the event is issued when the event starts, not when the event
* finishes.
*/
@@ -207,4 +273,8 @@
private final ImeState mExitState;
@NonNull
private final Bundle mArguments;
+ @Nullable
+ private final Object mReturnValue;
+ @NonNull
+ private final ReturnType mReturnType;
}
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index 7196f5b..ac46df3 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -46,6 +46,7 @@
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
+import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
@@ -410,6 +411,11 @@
getTracer().onFinishInput(() -> super.onFinishInput());
}
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return getTracer().onKeyDown(keyCode, event, () -> super.onKeyDown(keyCode, event));
+ }
+
@CallSuper
public boolean onEvaluateInputViewShown() {
return getTracer().onEvaluateInputViewShown(() -> {
@@ -544,7 +550,7 @@
// Send enter event
sendEventInternal(new ImeEvent(eventName, nestLevel, mThreadName,
mThreadId, mIsMainThread, enterTimestamp, 0, enterWallTime,
- 0, enterState, null, arguments));
+ 0, enterState, null, arguments, null));
++mNestLevel;
T result;
try {
@@ -558,7 +564,7 @@
// Send exit event
sendEventInternal(new ImeEvent(eventName, nestLevel, mThreadName,
mThreadId, mIsMainThread, enterTimestamp, exitTimestamp, enterWallTime,
- exitWallTime, enterState, exitState, arguments));
+ exitWallTime, enterState, exitState, arguments, result));
return result;
}
@@ -612,6 +618,13 @@
recordEventInternal("onFinishInput", runnable);
}
+ public boolean onKeyDown(int keyCode, KeyEvent event, @NonNull BooleanSupplier supplier) {
+ final Bundle arguments = new Bundle();
+ arguments.putInt("keyCode", keyCode);
+ arguments.putParcelable("event", event);
+ return recordEventInternal("onKeyDown", supplier::getAsBoolean, arguments);
+ }
+
public boolean onShowInputRequested(int flags, boolean configChange,
@NonNull BooleanSupplier supplier) {
final Bundle arguments = new Bundle();
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
index da6cacf..0754e7f 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
@@ -33,6 +33,7 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.inputmethod.cts.util.EndToEndImeTestBase;
import android.view.inputmethod.cts.util.TestActivity;
@@ -40,6 +41,7 @@
import android.widget.LinearLayout;
import com.android.cts.mockime.ImeCommand;
+import com.android.cts.mockime.ImeEvent;
import com.android.cts.mockime.ImeEventStream;
import com.android.cts.mockime.ImeSettings;
import com.android.cts.mockime.MockImeSession;
@@ -50,6 +52,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.function.Predicate;
/**
* Tests for {@link InputMethodService} methods.
@@ -62,6 +65,23 @@
private Instrumentation mInstrumentation;
+ private static Predicate<ImeEvent> backKeyDownMatcher(boolean expectedReturnValue) {
+ return event -> {
+ if (!event.isEnterEvent()) {
+ // Skip enter event since we are interested in the return value.
+ return false;
+ }
+ if (!TextUtils.equals("onKeyDown", event.getEventName())) {
+ return false;
+ }
+ final int keyCode = event.getArguments().getInt("keyCode");
+ if (keyCode != KeyEvent.KEYCODE_BACK) {
+ return false;
+ }
+ return event.getReturnBooleanValue() == expectedReturnValue;
+ };
+ }
+
@Before
public void setup() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -102,6 +122,10 @@
(long) getOnMainSync(() -> testActivity.getOnBackPressedCallCount()));
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ // InputMethodService#onKeyDown() should handle back key event.
+ // TODO: Also check InputMethodService#requestHideSelf()
+ expectEvent(stream, backKeyDownMatcher(true), TIMEOUT);
+
// keyboard will hide
expectEvent(stream, event -> "hideSoftInput".equals(event.getEventName()), TIMEOUT);
@@ -136,6 +160,10 @@
(long) getOnMainSync(() -> testActivity.getOnBackPressedCallCount()));
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ // InputMethodService#onKeyDown() will not handle back key event.
+ // TODO: Also check InputMethodService#requestHideSelf()
+ expectEvent(stream, backKeyDownMatcher(false), TIMEOUT);
+
// keyboard will not hide
notExpectEvent(stream, event -> "hideSoftInput".equals(event.getEventName()),
EXPECTED_TIMEOUT);
diff --git a/tests/signature/api-check/Android.mk b/tests/signature/api-check/Android.mk
index 888ace3..9ee92c9 100644
--- a/tests/signature/api-check/Android.mk
+++ b/tests/signature/api-check/Android.mk
@@ -22,7 +22,7 @@
# don't include this package in any target
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src/java)
LOCAL_MODULE := cts-api-signature-test
@@ -37,4 +37,13 @@
include $(BUILD_STATIC_JAVA_LIBRARY)
+include $(CLEAR_VARS)
+LOCAL_MODULE := libclassdescriptors
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := src/jni/classdescriptors.cpp
+LOCAL_HEADER_LIBRARIES := jni_headers libopenjdkjvmti_headers
+LOCAL_SDK_VERSION := current
+LOCAL_NDK_STL_VARIANT := c++_static
+include $(BUILD_SHARED_LIBRARY)
+
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/signature/api-check/android-test-base-27-api/AndroidManifest.xml b/tests/signature/api-check/android-test-base-27-api/AndroidManifest.xml
index 684872f..877e911 100644
--- a/tests/signature/api-check/android-test-base-27-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-base-27-api/AndroidManifest.xml
@@ -22,7 +22,7 @@
<uses-sdk android:minSdkVersion="25" android:targetSdkVersion="27"/>
- <application/>
+ <application android:debuggable="true"/>
<instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
android:targetPackage="android.signature.cts.api.android_test_base_27"
diff --git a/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml b/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml
index 5c88521..f0fc8e1 100644
--- a/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml
@@ -20,7 +20,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <application>
+ <application android:debuggable="true">
<uses-library android:name="android.test.mock"/>
</application>
diff --git a/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml b/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml
index 61de501..f81665e 100644
--- a/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml
@@ -20,7 +20,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <application>
+ <application android:debuggable="true">
<uses-library android:name="android.test.runner"/>
</application>
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml b/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml
index eaf118b..f0fb7d8 100644
--- a/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml
@@ -20,7 +20,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <application/>
+ <application android:debuggable="true"/>
<instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
android:targetPackage="android.signature.cts.api.apache_http_legacy_current"
diff --git a/tests/signature/api-check/build_signature_apk.mk b/tests/signature/api-check/build_signature_apk.mk
index 3b0afd2..1bae842 100644
--- a/tests/signature/api-check/build_signature_apk.mk
+++ b/tests/signature/api-check/build_signature_apk.mk
@@ -21,7 +21,7 @@
# the list of api files needed
# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
@@ -30,9 +30,15 @@
LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
+LOCAL_JNI_SHARED_LIBRARIES := libclassdescriptors
+LOCAL_MULTILIB := both
+
LOCAL_ADDITIONAL_DEPENDENCIES += \
$(addprefix $(COMPATIBILITY_TESTCASES_OUT_cts)/,$(LOCAL_SIGNATURE_API_FILES))
+LOCAL_DEX_PREOPT := false
+LOCAL_PROGUARD_ENABLED := disabled
+
include $(BUILD_CTS_PACKAGE)
LOCAL_SIGNATURE_API_FILES :=
diff --git a/tests/signature/api-check/current-api/AndroidManifest.xml b/tests/signature/api-check/current-api/AndroidManifest.xml
index 7dc5730..d6f474b 100644
--- a/tests/signature/api-check/current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/current-api/AndroidManifest.xml
@@ -20,7 +20,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <application/>
+ <application android:debuggable="true"/>
<instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
android:targetPackage="android.signature.cts.api.current"
diff --git a/tests/signature/api-check/src/android/signature/cts/api/BootClassPathClassesProvider.java b/tests/signature/api-check/src/android/signature/cts/api/BootClassPathClassesProvider.java
deleted file mode 100644
index 02bd72e..0000000
--- a/tests/signature/api-check/src/android/signature/cts/api/BootClassPathClassesProvider.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.signature.cts.api;
-
-import android.signature.cts.ClassProvider;
-import dalvik.system.DexFile;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.stream.Stream;
-
-@SuppressWarnings("deprecation")
-public class BootClassPathClassesProvider extends ClassProvider {
- @Override
- public Stream<Class<?>> getAllClasses() {
- Stream.Builder<Class<?>> builder = Stream.builder();
- for (String file : getBootJarPaths()) {
- try {
- DexFile dexFile = new DexFile(file);
- Enumeration<String> entries = dexFile.entries();
- while (entries.hasMoreElements()) {
- String className = entries.nextElement();
- Class<?> clazz = getClass(className);
- if (clazz != null) {
- builder.add(clazz);
- }
- }
- } catch (IOException e) {
- throw new RuntimeException("Failed to parse dex in " + file, e);
- } catch (ClassNotFoundException e) {
- throw new RuntimeException("Error while loading class in " + file, e);
- }
- }
- return builder.build();
- }
-
- private String[] getBootJarPaths() {
- return System.getProperty("java.boot.class.path").split(":");
- }
-}
\ No newline at end of file
diff --git a/tests/signature/api-check/src/android/signature/cts/api/AbstractApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
similarity index 100%
rename from tests/signature/api-check/src/android/signature/cts/api/AbstractApiTest.java
rename to tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
diff --git a/tests/signature/api-check/src/android/signature/cts/api/AnnotationTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/AnnotationTest.java
similarity index 100%
rename from tests/signature/api-check/src/android/signature/cts/api/AnnotationTest.java
rename to tests/signature/api-check/src/java/android/signature/cts/api/AnnotationTest.java
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/BootClassPathClassesProvider.java b/tests/signature/api-check/src/java/android/signature/cts/api/BootClassPathClassesProvider.java
new file mode 100644
index 0000000..95f46df
--- /dev/null
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/BootClassPathClassesProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.signature.cts.api;
+
+import android.os.Debug;
+import android.signature.cts.ClassProvider;
+import dalvik.system.BaseDexClassLoader;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+@SuppressWarnings("deprecation")
+public class BootClassPathClassesProvider extends ClassProvider {
+ private static boolean sJvmtiAttached = false;
+
+ @Override
+ public Stream<Class<?>> getAllClasses() {
+ if (!sJvmtiAttached) {
+ try {
+ Debug.attachJvmtiAgent(copyAgentToFile("classdescriptors").getAbsolutePath(), null,
+ BootClassPathClassesProvider.class.getClassLoader());
+ sJvmtiAttached = true;
+ initialize();
+ } catch (Exception e) {
+ throw new RuntimeException("Error while attaching JVMTI agent", e);
+ }
+ }
+ return Arrays.stream(getClassloaderDescriptors(Object.class.getClassLoader()))
+ .map(descriptor -> {
+ System.err.println("Class name = " + descriptor);
+ String classname = descriptor.replace('/', '.');
+ // omit L and ; at the front and at the end
+ return classname.substring(1, classname.length() - 1);
+ })
+ .map(classname -> {
+ try {
+ return getClass(classname);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Cannot load " + classname, e);
+ }
+ });
+ }
+
+ private static File copyAgentToFile(String lib) throws Exception {
+ ClassLoader cl = BootClassPathClassesProvider.class.getClassLoader();
+
+ File copiedAgent = File.createTempFile("agent", ".so");
+ try (InputStream is = new FileInputStream(
+ ((BaseDexClassLoader) cl).findLibrary(lib))) {
+ try (OutputStream os = new FileOutputStream(copiedAgent)) {
+ byte[] buffer = new byte[64 * 1024];
+
+ while (true) {
+ int numRead = is.read(buffer);
+ if (numRead == -1) {
+ break;
+ }
+ os.write(buffer, 0, numRead);
+ }
+ }
+ }
+ return copiedAgent;
+ }
+
+ private static native void initialize();
+
+ private static native String[] getClassloaderDescriptors(ClassLoader loader);
+}
diff --git a/tests/signature/api-check/src/android/signature/cts/api/SignatureTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
similarity index 100%
rename from tests/signature/api-check/src/android/signature/cts/api/SignatureTest.java
rename to tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
diff --git a/tests/signature/api-check/src/android/signature/cts/api/TestResultObserver.java b/tests/signature/api-check/src/java/android/signature/cts/api/TestResultObserver.java
similarity index 100%
rename from tests/signature/api-check/src/android/signature/cts/api/TestResultObserver.java
rename to tests/signature/api-check/src/java/android/signature/cts/api/TestResultObserver.java
diff --git a/tests/signature/api-check/src/jni/classdescriptors.cpp b/tests/signature/api-check/src/jni/classdescriptors.cpp
new file mode 100644
index 0000000..3da66f1
--- /dev/null
+++ b/tests/signature/api-check/src/jni/classdescriptors.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+#include <jvmti.h>
+
+#include <string.h>
+
+namespace android {
+namespace signature {
+namespace cts {
+namespace api {
+
+static jvmtiEnv* jvmti_env;
+static jvmtiError (*get_descriptor_list)(jvmtiEnv* env, jobject loader, jint* cnt, char*** descs);
+
+template <typename T>
+static void Dealloc(T* t) {
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(t));
+}
+
+template <typename T, typename ...Rest>
+static void Dealloc(T* t, Rest... rs) {
+ Dealloc(t);
+ Dealloc(rs...);
+}
+
+static void DeallocParams(jvmtiParamInfo* params, jint n_params) {
+ for (jint i = 0; i < n_params; i++) {
+ Dealloc(params[i].name);
+ }
+}
+
+static void Cleanup(char** data, jint cnt) {
+ for (jint i = 0; i < cnt; i++) {
+ Dealloc(data[i]);
+ }
+ Dealloc(data);
+}
+
+extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm,
+ __attribute__((unused)) char* options,
+ __attribute__((unused)) void* reserved) {
+ jint jvmError = vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_2);
+ if (jvmError != JNI_OK) {
+ return jvmError;
+ }
+ return JVMTI_ERROR_NONE;
+}
+
+extern "C" JNIEXPORT jobjectArray JNICALL Java_android_signature_cts_api_BootClassPathClassesProvider_getClassloaderDescriptors(
+ JNIEnv* env, jclass, jobject loader) {
+ if (get_descriptor_list == nullptr) {
+ jclass rt_exception = env->FindClass("java/lang/RuntimeException");
+ env->ThrowNew(rt_exception, "get_class_loader_class_descriptor extension is not ready.");
+ return nullptr;
+ }
+ char** classes = nullptr;
+ jint cnt = -1;
+ jvmtiError error = get_descriptor_list(jvmti_env, loader, &cnt, &classes);
+ if (error != JVMTI_ERROR_NONE) {
+ jclass rt_exception = env->FindClass("java/lang/RuntimeException");
+ env->ThrowNew(rt_exception, "Error while executing get_class_loader_class_descriptor.");
+ return nullptr;
+ }
+
+ jobjectArray arr = env->NewObjectArray(cnt, env->FindClass("java/lang/String"), nullptr);
+ if (env->ExceptionCheck()) {
+ Cleanup(classes, cnt);
+ return nullptr;
+ }
+
+ for (jint i = 0; i < cnt; i++) {
+ env->SetObjectArrayElement(arr, i, env->NewStringUTF(classes[i]));
+ if (env->ExceptionCheck()) {
+ Cleanup(classes, cnt);
+ return nullptr;
+ }
+ }
+ Cleanup(classes, cnt);
+ return arr;
+}
+
+extern "C" JNIEXPORT void JNICALL Java_android_signature_cts_api_BootClassPathClassesProvider_initialize(JNIEnv* env, jclass) {
+ jint functionInfosCount = 0;
+ jvmtiExtensionFunctionInfo* functionInfos = nullptr;
+
+ jvmtiError err = jvmti_env->GetExtensionFunctions(&functionInfosCount, &functionInfos);
+ if (err != JVMTI_ERROR_NONE) {
+ jclass rt_exception = env->FindClass("java/lang/RuntimeException");
+ env->ThrowNew(rt_exception, "Failed to get JVMTI extension APIs");
+ return;
+ }
+
+ for (jint i = 0; i < functionInfosCount; i++) {
+ jvmtiExtensionFunctionInfo* curInfo = &functionInfos[i];
+ if (strcmp("com.android.art.class.get_class_loader_class_descriptors", curInfo->id) == 0) {
+ get_descriptor_list = reinterpret_cast<jvmtiError (*)(jvmtiEnv*, jobject, jint*, char***)>(curInfo->func);
+ }
+ DeallocParams(curInfo->params, curInfo->param_count);
+ Dealloc(curInfo->id, curInfo->short_description, curInfo->params, curInfo->errors);
+ }
+ Dealloc(functionInfos);
+
+ if (get_descriptor_list == nullptr) {
+ jclass rt_exception = env->FindClass("java/lang/RuntimeException");
+ env->ThrowNew(rt_exception, "Failed to find get_class_loader_class_descriptors extension");
+ return;
+ }
+}
+
+} // namespace api
+} // namespace cts
+} // namespace signature
+} // namespace android
diff --git a/tests/signature/api-check/system-annotation/AndroidManifest.xml b/tests/signature/api-check/system-annotation/AndroidManifest.xml
index 55318ed..7753fb9 100644
--- a/tests/signature/api-check/system-annotation/AndroidManifest.xml
+++ b/tests/signature/api-check/system-annotation/AndroidManifest.xml
@@ -20,7 +20,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <application/>
+ <application android:debuggable="true"/>
<instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
android:targetPackage="android.signature.cts.api.system_annotation"
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 110534f..d90179a 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -16,7 +16,9 @@
package android.app.usage.cts;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.app.Activity;
import android.app.AppOpsManager;
@@ -38,7 +40,6 @@
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.Until;
-import android.test.InstrumentationTestCase;
import android.util.SparseLongArray;
import org.junit.Before;
@@ -209,6 +210,16 @@
assertTrue(found);
}
+ @Test
+ public void testGetAppStandbyBuckets() throws Exception {
+ mUiDevice.executeShellCommand("am set-standby-bucket " + mTargetPackage + " rare");
+ Map<String, Integer> bucketMap = mUsageStatsManager.getAppStandbyBuckets();
+ assertTrue("No bucket data returned", bucketMap.size() > 0);
+ final int bucket = bucketMap.getOrDefault(mTargetPackage, -1);
+ assertEquals("Incorrect bucket returned for " + mTargetPackage, bucket,
+ UsageStatsManager.STANDBY_BUCKET_RARE);
+ }
+
/**
* We can't run this test because we are unable to change the system time.
* It would be nice to add a shell command or other to allow the shell user
diff --git a/tests/tests/graphics/res/drawable/animatedimagedrawable_automirrored.xml b/tests/tests/graphics/res/drawable/animatedimagedrawable_automirrored.xml
new file mode 100644
index 0000000..3d5b0cf
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/animatedimagedrawable_automirrored.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<animated-image xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/animated"
+ android:autoMirrored="true"
+ />
+
diff --git a/tests/tests/graphics/res/drawable/animatedimagedrawable_nosrc.xml b/tests/tests/graphics/res/drawable/animatedimagedrawable_nosrc.xml
new file mode 100644
index 0000000..0f7ac8f
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/animatedimagedrawable_nosrc.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<animated-image xmlns:android="http://schemas.android.com/apk/res/android"
+ />
+
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
index b87fd92..4fb6e19 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
@@ -90,6 +90,11 @@
mActivity = mActivityRule.getActivity();
}
+ @Test
+ public void testEmptyConstructor() {
+ new AnimatedImageDrawable();
+ }
+
private AnimatedImageDrawable createFromImageDecoder(int resId) {
Uri uri = null;
try {
@@ -504,4 +509,37 @@
assertNotNull(drawable);
assertTrue(drawable instanceof AnimatedImageDrawable);
}
+
+ @Test(expected=XmlPullParserException.class)
+ public void testMissingSrcInflate() throws XmlPullParserException, IOException {
+ XmlPullParser parser = mRes.getXml(R.drawable.animatedimagedrawable_nosrc);
+ Drawable drawable = Drawable.createFromXml(mRes, parser);
+ }
+
+ @Test
+ public void testAutoMirrored() {
+ AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+ assertFalse(drawable.isAutoMirrored());
+
+ drawable.setAutoMirrored(true);
+ assertTrue(drawable.isAutoMirrored());
+
+ drawable.setAutoMirrored(false);
+ assertFalse(drawable.isAutoMirrored());
+ }
+
+ @Test
+ public void testAutoMirroredFromXml() throws XmlPullParserException, IOException {
+ XmlPullParser parser = mRes.getXml(R.drawable.animatedimagedrawable_tag);
+ Drawable drawable = Drawable.createFromXml(mRes, parser);
+ assertNotNull(drawable);
+ assertTrue(drawable instanceof AnimatedImageDrawable);
+ assertFalse(drawable.isAutoMirrored());
+
+ parser = mRes.getXml(R.drawable.animatedimagedrawable_automirrored);
+ drawable = Drawable.createFromXml(mRes, parser);
+ assertNotNull(drawable);
+ assertTrue(drawable instanceof AnimatedImageDrawable);
+ assertTrue(drawable.isAutoMirrored());
+ }
}
diff --git a/tests/tests/permission/src/android/permission/cts/AppOpsTest.java b/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
index 970ada7..7285fd0 100644
--- a/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
+++ b/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
@@ -27,8 +27,14 @@
import static com.android.compatibility.common.util.AppOpsUtils.rejectedOperationLogged;
import static com.android.compatibility.common.util.AppOpsUtils.setOpMode;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
import android.Manifest.permission;
import android.app.AppOpsManager;
+import android.app.AppOpsManager.OnOpChangedListener;
import android.content.Context;
import android.os.Process;
import android.test.InstrumentationTestCase;
@@ -159,12 +165,12 @@
}
}
- public void testCheckPackagePassesTest() throws Exception {
+ public void testCheckPackagePassesCheck() throws Exception {
mAppOps.checkPackage(mMyUid, mOpPackageName);
mAppOps.checkPackage(Process.SYSTEM_UID, "android");
}
- public void testCheckPackageDoesntPassTest() throws Exception {
+ public void testCheckPackageDoesntPassCheck() throws Exception {
try {
// Package name doesn't match UID.
mAppOps.checkPackage(Process.SYSTEM_UID, mOpPackageName);
@@ -187,6 +193,41 @@
}
}
+ public void testWatchingMode() throws Exception {
+ OnOpChangedListener watcher = mock(OnOpChangedListener.class);
+ try {
+ setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ALLOWED);
+
+ mAppOps.startWatchingMode(OPSTR_READ_SMS, mOpPackageName, watcher);
+
+ // Make a change to the app op's mode.
+ reset(watcher);
+ setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ERRORED);
+ verify(watcher).onOpChanged(OPSTR_READ_SMS, mOpPackageName);
+
+ // Make another change to the app op's mode.
+ reset(watcher);
+ setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ALLOWED);
+ verify(watcher).onOpChanged(OPSTR_READ_SMS, mOpPackageName);
+
+ // Set mode to the same value as before - expect no call to the listener.
+ reset(watcher);
+ setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ALLOWED);
+ verifyZeroInteractions(watcher);
+
+ mAppOps.stopWatchingMode(watcher);
+
+ // Make a change to the app op's mode. Since we already stopped watching the mode, the
+ // listener shouldn't be called.
+ reset(watcher);
+ setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ERRORED);
+ verifyZeroInteractions(watcher);
+ } finally {
+ // Clean up registered watcher.
+ mAppOps.stopWatchingMode(watcher);
+ }
+ }
+
@SmallTest
public void testAllOpsHaveOpString() {
Set<String> opStrs = new HashSet<>();
diff --git a/tests/tests/security/res/raw/cve_2016_6764.mp4 b/tests/tests/security/res/raw/cve_2016_6764.mp4
new file mode 100644
index 0000000..46c1214
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2016_6764.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 9a3b940..6af1d56 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -526,6 +526,11 @@
***********************************************************/
@SecurityTest
+ public void testStagefright_cve_2016_6764() throws Exception {
+ doStagefrightTest(R.raw.cve_2016_6764);
+ }
+
+ @SecurityTest
public void testStagefright_cve_2017_13214() throws Exception {
doStagefrightTest(R.raw.cve_2017_13214);
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
index d93d431..c9e0c56 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
@@ -211,7 +211,6 @@
}
public static boolean waitForUnBinding() {
- sServiceUnBoundLatch = TestUtils.waitForLock(sServiceUnBoundLatch);
- return sServiceUnBoundLatch != null;
+ return TestUtils.waitForLatchCountDown(sServiceUnBoundLatch);
}
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java
index b057648..e6070ce 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java
@@ -198,7 +198,7 @@
* timeout expired without the lock being released.
*/
public boolean waitForUpdate(int lock) {
- mLocks[lock] = waitForLock(mLocks[lock]);
+ mLocks[lock] = TestUtils.waitForLock(mLocks[lock]);
return mLocks[lock] != null;
}
@@ -207,31 +207,7 @@
* @return {@code true} if binding happened within the time limit, or {@code false} otherwise.
*/
public static boolean waitForBinding() {
- sBindingLock = waitForLock(sBindingLock);
- return sBindingLock != null;
- }
-
- /**
- * Given a {@link CountDownLatch}, wait for the latch to reach zero for 5 seconds. If the lock
- * was released, return a new instance. Otherwise, return null to indicate that the timeout
- * expired without the lock being released.
- *
- * @param lock The lock to wait on.
- * @return {@code true} if the lock was released, and {@code false} if it failed to be released.
- */
- private static CountDownLatch waitForLock(CountDownLatch lock) {
- boolean success;
- try {
- success = lock.await(5000, TimeUnit.MILLISECONDS);
- } catch (InterruptedException ie) {
- return null;
- }
-
- if (success) {
- return new CountDownLatch(1);
- } else {
- return null;
- }
+ return TestUtils.waitForLatchCountDown(sBindingLock);
}
public TestUtils.InvokeCounter getOnCreateIncomingHandoverConnectionCounter() {
diff --git a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
index 3980f7f..31000de 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
@@ -255,17 +255,36 @@
}
}
- public static CountDownLatch waitForLock(CountDownLatch lock) {
- boolean success;
- try {
- if (lock == null) {
- return null;
- }
- success = lock.await(5000, TimeUnit.MILLISECONDS);
- } catch (InterruptedException ie) {
- return null;
+ /**
+ * Waits for the {@link CountDownLatch} to count down to 0 and then returns without reseting
+ * the latch.
+ * @param lock the latch that the system will wait on.
+ * @return true if the latch was released successfully, false if the latch timed out before
+ * resetting.
+ */
+ public static boolean waitForLatchCountDown(CountDownLatch lock) {
+ if (lock == null) {
+ return false;
}
+ boolean success;
+ try {
+ success = lock.await(5000, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException ie) {
+ return false;
+ }
+
+ return success;
+ }
+
+ /**
+ * Waits for the {@link CountDownLatch} to count down to 0 and then returns a new reset latch.
+ * @param lock The lock that will await a countDown to 0.
+ * @return a new reset {@link CountDownLatch} if the lock successfully counted down to 0 or
+ * null if the operation timed out.
+ */
+ public static CountDownLatch waitForLock(CountDownLatch lock) {
+ boolean success = waitForLatchCountDown(lock);
if (success) {
return new CountDownLatch(1);
} else {
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadFlowTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadFlowTest.java
index 5089381..e6a97ed 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadFlowTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadFlowTest.java
@@ -21,6 +21,7 @@
import android.os.Bundle;
import android.telephony.MbmsDownloadSession;
import android.telephony.cts.embmstestapp.CtsDownloadService;
+import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.MbmsDownloadReceiver;
import java.io.File;
@@ -29,14 +30,16 @@
public class MbmsDownloadFlowTest extends MbmsDownloadTestBase {
private File tempFileRootDir;
- private String tempFileRootDirPath;
+ private DownloadRequest testDownloadRequest;
@Override
public void setUp() throws Exception {
super.setUp();
+ testDownloadRequest = downloadRequestTemplate
+ .setAppIntent(new Intent(MbmsDownloadReceiverTest.APP_INTENT_ACTION))
+ .build();
tempFileRootDir = new File(mContext.getFilesDir(), "CtsTestDir");
tempFileRootDir.mkdir();
- tempFileRootDirPath = tempFileRootDir.getCanonicalPath();
mDownloadSession.setTempFileRootDirectory(tempFileRootDir);
}
@@ -49,15 +52,15 @@
public void testFileDownloadFlow() throws Exception {
MbmsDownloadReceiverTest.AppIntentCapture captor =
- new MbmsDownloadReceiverTest.AppIntentCapture(mContext, mCallbackHandler);
- mDownloadSession.download(MbmsDownloadReceiverTest.TEST_DOWNLOAD_REQUEST);
+ new MbmsDownloadReceiverTest.AppIntentCapture(mContext, mHandler);
+ mDownloadSession.download(testDownloadRequest);
mMiddlewareControl.actuallyStartDownloadFlow();
Intent downloadDoneIntent = captor.getIntent();
assertEquals(MbmsDownloadReceiverTest.APP_INTENT_ACTION, downloadDoneIntent.getAction());
assertEquals(MbmsDownloadSession.RESULT_SUCCESSFUL,
downloadDoneIntent.getIntExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, -1));
- assertEquals(MbmsDownloadReceiverTest.TEST_DOWNLOAD_REQUEST,
+ assertEquals(testDownloadRequest,
downloadDoneIntent.getParcelableExtra(
MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST));
assertEquals(CtsDownloadService.FILE_INFO,
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java
index 0d88f13..8232271 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java
@@ -47,9 +47,6 @@
public static final String APP_INTENT_ACTION =
"android.telephony.embms.cts.ACTION_TEST_DOWNLOAD_COMPLETE";
- public static final DownloadRequest TEST_DOWNLOAD_REQUEST = DOWNLOAD_REQUEST_TEMPLATE
- .setAppIntent(new Intent(APP_INTENT_ACTION))
- .build();
public static class AppIntentCapture {
private final BlockingQueue<Intent> mReceivedIntent = new LinkedBlockingQueue<>();
@@ -82,10 +79,14 @@
private MbmsDownloadReceiver mReceiver;
private File tempFileRootDir;
private String tempFileRootDirPath;
+ private DownloadRequest testDownloadRequest;
@Override
public void setUp() throws Exception {
super.setUp();
+ testDownloadRequest = downloadRequestTemplate
+ .setAppIntent(new Intent(APP_INTENT_ACTION))
+ .build();
mReceiver = new MbmsDownloadReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL);
@@ -140,9 +141,9 @@
intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT,
MbmsDownloadSession.RESULT_CANCELLED);
intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST,
- TEST_DOWNLOAD_REQUEST);
+ testDownloadRequest);
- AppIntentCapture intentCaptor = new AppIntentCapture(mContext, mCallbackHandler);
+ AppIntentCapture intentCaptor = new AppIntentCapture(mContext, mHandler);
sendBroadcastAndValidate(intentForReceiverTest, MbmsDownloadReceiver.RESULT_OK);
Intent receivedIntent = intentCaptor.getIntent();
@@ -150,7 +151,7 @@
assertEquals(MbmsDownloadSession.RESULT_CANCELLED,
receivedIntent.getIntExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, -1));
- assertEquals(TEST_DOWNLOAD_REQUEST,
+ assertEquals(testDownloadRequest,
receivedIntent.getParcelableExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST));
}
@@ -162,7 +163,7 @@
intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT,
MbmsDownloadSession.RESULT_SUCCESSFUL);
intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST,
- TEST_DOWNLOAD_REQUEST);
+ testDownloadRequest);
intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO,
CtsDownloadService.FILE_INFO);
intentForReceiverTest.putExtra(VendorUtils.EXTRA_FINAL_URI,
@@ -230,7 +231,7 @@
receivedExtras.add(getResultExtras(true));
receivedCode.add(getResultCode());
}
- }, mCallbackHandler, -1, null, null);
+ }, mHandler, -1, null, null);
try {
assertEquals(expectedCode,
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
index 29e70bb..5e70828 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
@@ -33,7 +33,7 @@
public void testDuplicateSession() throws Exception {
try {
MbmsDownloadSession failure = MbmsDownloadSession.create(
- mContext, mCallback, mCallbackHandler);
+ mContext, mCallbackExecutor, mCallback);
fail("Duplicate create should've thrown an exception");
} catch (IllegalStateException e) {
// Succeed
@@ -139,7 +139,7 @@
}
public void testResetDownloadKnowledge() throws Exception {
- DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
+ DownloadRequest request = downloadRequestTemplate.build();
mDownloadSession.resetDownloadKnowledge(request);
List<Bundle> resetDownloadKnowledgeCalls =
@@ -150,7 +150,7 @@
}
public void testGetDownloadStatus() throws Exception {
- DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
+ DownloadRequest request = downloadRequestTemplate.build();
mDownloadSession.requestDownloadState(request, CtsDownloadService.FILE_INFO);
List<Bundle> getDownloadStatusCalls =
@@ -163,7 +163,7 @@
}
public void testCancelDownload() throws Exception {
- DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
+ DownloadRequest request = downloadRequestTemplate.build();
mDownloadSession.cancelDownload(request);
List<Bundle> cancelDownloadCalls =
@@ -174,7 +174,11 @@
}
public void testListPendingDownloads() throws Exception {
- DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.setAppIntent(new Intent()).build();
+ File tempFileRootDir = new File(mContext.getFilesDir(), "CtsTestDir");
+ tempFileRootDir.mkdir();
+ mDownloadSession.setTempFileRootDirectory(tempFileRootDir);
+
+ DownloadRequest request = downloadRequestTemplate.setAppIntent(new Intent()).build();
mDownloadSession.download(request);
List<DownloadRequest> downloads = mDownloadSession.listPendingDownloads();
@@ -194,14 +198,12 @@
assertNotSame(mDownloadSession.getTempFileRootDirectory(), tempFileDirName);
}
- public void testDownloadRequestOpacity() throws Exception {
+ public void testDownloadRequestSerialization() throws Exception {
Intent intent = new Intent("sample_intent_action");
- DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.setAppIntent(intent).build();
- DownloadRequest newRequest = new DownloadRequest.Builder(request.getSourceUri())
- .setServiceId(request.getFileServiceId())
- .setSubscriptionId(request.getSubscriptionId())
- .setOpaqueData(request.getOpaqueData())
- .build();
+ DownloadRequest request = downloadRequestTemplate.setAppIntent(intent).build();
+ DownloadRequest newRequest =
+ DownloadRequest.Builder.fromSerializedRequest(request.toByteArray())
+ .build();
assertEquals(request, newRequest);
}
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadStateCallbackTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadStateCallbackTest.java
index a5cc2d0..c01de7c 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadStateCallbackTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadStateCallbackTest.java
@@ -83,8 +83,8 @@
public void testFullCallback() throws Exception {
int sampleInt = 10;
TestDSCallback callback = new TestDSCallback(DownloadStateCallback.ALL_UPDATES);
- DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
- mDownloadSession.registerStateCallback(request, callback, mCallbackHandler);
+ DownloadRequest request = downloadRequestTemplate.build();
+ mDownloadSession.registerStateCallback(request, mCallbackExecutor, callback);
mMiddlewareControl.fireOnProgressUpdated(request, CtsDownloadService.FILE_INFO,
sampleInt, sampleInt, sampleInt, sampleInt);
SomeArgs progressArgs = callback.waitOnProgressUpdated(ASYNC_TIMEOUT);
@@ -104,8 +104,8 @@
public void testDeregistration() throws Exception {
TestDSCallback callback = new TestDSCallback(DownloadStateCallback.ALL_UPDATES);
- DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
- mDownloadSession.registerStateCallback(request, callback, mCallbackHandler);
+ DownloadRequest request = downloadRequestTemplate.build();
+ mDownloadSession.registerStateCallback(request, mCallbackExecutor, callback);
mDownloadSession.unregisterStateCallback(request, callback);
mMiddlewareControl.fireOnStateUpdated(null, null, 0);
@@ -116,8 +116,8 @@
public void testCallbackFiltering1() throws Exception {
TestDSCallback callback = new TestDSCallback(DownloadStateCallback.PROGRESS_UPDATES);
- DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
- mDownloadSession.registerStateCallback(request, callback, mCallbackHandler);
+ DownloadRequest request = downloadRequestTemplate.build();
+ mDownloadSession.registerStateCallback(request, mCallbackExecutor, callback);
mMiddlewareControl.fireOnStateUpdated(null, null, 0);
assertNull(callback.waitOnStateUpdated(SHORT_TIMEOUT));
@@ -127,8 +127,8 @@
public void testCallbackFiltering2() throws Exception {
TestDSCallback callback = new TestDSCallback(DownloadStateCallback.STATE_UPDATES);
- DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
- mDownloadSession.registerStateCallback(request, callback, mCallbackHandler);
+ DownloadRequest request = downloadRequestTemplate.build();
+ mDownloadSession.registerStateCallback(request, mCallbackExecutor, callback);
mMiddlewareControl.fireOnStateUpdated(null, null, 0);
assertNotNull(callback.waitOnStateUpdated(SHORT_TIMEOUT));
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java
index 9da5f04..bde9de6 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -41,6 +42,7 @@
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -107,13 +109,12 @@
}
}
- static final DownloadRequest.Builder DOWNLOAD_REQUEST_TEMPLATE =
- new DownloadRequest.Builder(CtsDownloadService.DOWNLOAD_SOURCE_URI)
- .setServiceInfo(CtsDownloadService.FILE_SERVICE_INFO);
+ DownloadRequest.Builder downloadRequestTemplate;
Context mContext;
HandlerThread mHandlerThread;
- Handler mCallbackHandler;
+ Handler mHandler;
+ Executor mCallbackExecutor;
ICtsDownloadMiddlewareControl mMiddlewareControl;
MbmsDownloadSession mDownloadSession;
TestCallback mCallback = new TestCallback();
@@ -123,8 +124,16 @@
mContext = getInstrumentation().getContext();
mHandlerThread = new HandlerThread("EmbmsCtsTestWorker");
mHandlerThread.start();
- mCallbackHandler = new Handler(mHandlerThread.getLooper());
+ mHandler = new Handler(mHandlerThread.getLooper());
+ mCallbackExecutor = mHandler::post;
mCallback = new TestCallback();
+
+ File destinationDirectory = new File(mContext.getFilesDir(), "downloads");
+ destinationDirectory.mkdirs();
+ Uri destinationDirectoryUri = Uri.fromFile(destinationDirectory);
+ downloadRequestTemplate = new DownloadRequest.Builder(
+ CtsDownloadService.DOWNLOAD_SOURCE_URI, destinationDirectoryUri)
+ .setServiceInfo(CtsDownloadService.FILE_SERVICE_INFO);
getControlBinder();
setupDownloadSession();
}
@@ -138,7 +147,7 @@
private void setupDownloadSession() throws Exception {
mDownloadSession = MbmsDownloadSession.create(
- mContext, mCallback, mCallbackHandler);
+ mContext, mCallbackExecutor, mCallback);
assertNotNull(mDownloadSession);
assertTrue(mCallback.waitOnMiddlewareReady());
assertEquals(0, mCallback.getNumErrorCalls());
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingServiceTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingServiceTest.java
index 42e5618..835a6e4 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingServiceTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingServiceTest.java
@@ -127,7 +127,7 @@
public void testStartStreaming() throws Exception {
StreamingService streamingService = mStreamingSession.startStreaming(
CtsStreamingService .STREAMING_SERVICE_INFO,
- mStreamingServiceCallback, mCallbackHandler);
+ mCallbackExecutor, mStreamingServiceCallback);
assertNotNull(streamingService);
assertEquals(CtsStreamingService.STREAMING_SERVICE_INFO, streamingService.getInfo());
@@ -145,7 +145,7 @@
public void testGetPlaybackUri() throws Exception {
StreamingService streamingService = mStreamingSession.startStreaming(
CtsStreamingService .STREAMING_SERVICE_INFO,
- mStreamingServiceCallback, mCallbackHandler);
+ mCallbackExecutor, mStreamingServiceCallback);
assertEquals(CtsStreamingService.STREAMING_URI, streamingService.getPlaybackUri());
List<List<Object>> getPlaybackUriCalls =
@@ -158,8 +158,8 @@
public void testStopStreaming() throws Exception {
StreamingService streamingService = mStreamingSession.startStreaming(
CtsStreamingService .STREAMING_SERVICE_INFO,
- mStreamingServiceCallback, mCallbackHandler);
- streamingService.stopStreaming();
+ mCallbackExecutor, mStreamingServiceCallback);
+ streamingService.close();
List<List<Object>> stopStreamingCalls =
getMiddlewareCalls(CtsStreamingService.METHOD_STOP_STREAMING);
assertEquals(1, stopStreamingCalls.size());
@@ -170,7 +170,7 @@
public void testStreamingCallbacks() throws Exception {
mStreamingSession.startStreaming(
CtsStreamingService .STREAMING_SERVICE_INFO,
- mStreamingServiceCallback, mCallbackHandler);
+ mCallbackExecutor, mStreamingServiceCallback);
mMiddlewareControl.fireErrorOnStream(
MbmsErrors.StreamingErrors.ERROR_UNABLE_TO_START_SERVICE, "");
@@ -194,7 +194,7 @@
mMiddlewareControl.forceErrorCode(
MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE);
mStreamingSession.startStreaming(CtsStreamingService.STREAMING_SERVICE_INFO,
- mStreamingServiceCallback, mCallbackHandler);
+ mCallbackExecutor, mStreamingServiceCallback);
assertEquals(MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE,
mCallback.waitOnError().arg1);
}
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java
index 92b3fc9..0aeb734 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java
@@ -29,7 +29,7 @@
public void testDuplicateSession() throws Exception {
try {
MbmsStreamingSession failure = MbmsStreamingSession.create(
- mContext, mCallback, mCallbackHandler);
+ mContext, mCallbackExecutor, mCallback);
fail("Duplicate create should've thrown an exception");
} catch (IllegalStateException e) {
// Succeed
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java
index e170998..e4bb27b 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java
@@ -21,6 +21,7 @@
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -87,7 +88,7 @@
Context mContext;
HandlerThread mHandlerThread;
- Handler mCallbackHandler;
+ Executor mCallbackExecutor;
ICtsStreamingMiddlewareControl mMiddlewareControl;
MbmsStreamingSession mStreamingSession;
TestCallback mCallback = new TestCallback();
@@ -97,7 +98,7 @@
mContext = getInstrumentation().getContext();
mHandlerThread = new HandlerThread("EmbmsCtsTestWorker");
mHandlerThread.start();
- mCallbackHandler = new Handler(mHandlerThread.getLooper());
+ mCallbackExecutor = (new Handler(mHandlerThread.getLooper()))::post;
mCallback = new TestCallback();
getControlBinder();
setupStreamingSession();
@@ -112,7 +113,7 @@
private void setupStreamingSession() throws Exception {
mStreamingSession = MbmsStreamingSession.create(
- mContext, mCallback, mCallbackHandler);
+ mContext, mCallbackExecutor, mCallback);
assertNotNull(mStreamingSession);
assertTrue(mCallback.waitOnMiddlewareReady());
assertEquals(0, mCallback.getNumErrorCalls());
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
index ee46601..abaf96e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
@@ -39,7 +39,7 @@
@Test
public void testScreenshot() {
for (int i = 0 ; i < 500 ; i ++) {
- takeScreenshot(new Point());
+ takeScreenshot(new TestPositionInfo(new Point(), new Point()));
System.gc();
}
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
index 741c35c..2e1ce85 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
@@ -15,17 +15,13 @@
*/
package android.uirendering.cts.testclasses;
-import com.android.compatibility.common.util.SynchronousPixelCopy;
-
import android.animation.ObjectAnimator;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Point;
import android.graphics.Rect;
import android.support.test.filters.LargeTest;
-import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
@@ -40,6 +36,8 @@
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
+import com.android.compatibility.common.util.SynchronousPixelCopy;
+
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -111,9 +109,11 @@
mAnimator.cancel();
}
};
- Screenshotter screenshotter = testOffset -> {
+ Screenshotter screenshotter = testPositionInfo -> {
Bitmap source = getInstrumentation().getUiAutomation().takeScreenshot();
- return Bitmap.createBitmap(source, testOffset.x, testOffset.y, TEST_WIDTH, TEST_HEIGHT);
+ return Bitmap.createBitmap(source,
+ testPositionInfo.screenOffset.x, testPositionInfo.screenOffset.y,
+ TEST_WIDTH, TEST_HEIGHT);
};
createTest()
.addLayout(R.layout.frame_layout, initializer, true)
@@ -131,7 +131,7 @@
}
@Override
- public Bitmap takeScreenshot(Point point /* ignored */) {
+ public Bitmap takeScreenshot(TestPositionInfo testPositionInfo) {
SynchronousPixelCopy copy = new SynchronousPixelCopy();
Bitmap dest = Bitmap.createBitmap(
TEST_WIDTH, TEST_HEIGHT, Config.ARGB_8888);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
index 99f2780..f94047d 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -118,26 +118,25 @@
}
}
- public Bitmap takeScreenshot(Point testOffset) {
+ public Bitmap takeScreenshot(TestPositionInfo testPositionInfo) {
if (mScreenshotter == null) {
SynchronousPixelCopy copy = new SynchronousPixelCopy();
Bitmap dest = Bitmap.createBitmap(
TEST_WIDTH, TEST_HEIGHT,
getActivity().getWindow().isWideColorGamut()
? Config.RGBA_F16 : Config.ARGB_8888);
- Rect srcRect = new Rect(testOffset.x, testOffset.y,
- testOffset.x + TEST_WIDTH, testOffset.y + TEST_HEIGHT);
- Log.d("UiRendering", "capturing screenshot of " + srcRect.toShortString());
+ Rect srcRect = new Rect(0, 0, TEST_WIDTH, TEST_HEIGHT);
+ srcRect.offset(testPositionInfo.surfaceOffset.x, testPositionInfo.surfaceOffset.y);
+ Log.d(TAG, "capturing screenshot of " + srcRect.toShortString());
int copyResult = copy.request(getActivity().getWindow(), srcRect, dest);
Assert.assertEquals(PixelCopy.SUCCESS, copyResult);
return dest;
} else {
- return mScreenshotter.takeScreenshot(testOffset);
+ return mScreenshotter.takeScreenshot(testPositionInfo);
}
}
-
- protected Point runRenderSpec(TestCase testCase) {
- Point testOffset = getActivity().enqueueRenderSpecAndWait(
+ protected TestPositionInfo runRenderSpec(TestCase testCase) {
+ TestPositionInfo testPositionInfo = getActivity().enqueueRenderSpecAndWait(
testCase.layoutID, testCase.canvasClient,
testCase.viewInitializer, testCase.useHardware, testCase.usePicture);
testCase.wasTestRan = true;
@@ -148,15 +147,14 @@
throw new RuntimeException("readyFence didn't signal within 5 seconds");
}
}
- return testOffset;
+ return testPositionInfo;
}
/**
* Used to execute a specific part of a test and get the resultant bitmap
*/
protected Bitmap captureRenderSpec(TestCase testCase) {
- Point testOffset = runRenderSpec(testCase);
- return takeScreenshot(testOffset);
+ return takeScreenshot(runRenderSpec(testCase));
}
protected TestCaseBuilder createTest() {
@@ -165,8 +163,28 @@
return mTestCaseBuilder;
}
+ public static class TestPositionInfo {
+ /**
+ * Position of capture area in surface space - use this offset for e.g.
+ * PixelCopy from a window's surface.
+ */
+ public final Point surfaceOffset;
+
+ /**
+ * Position of capture area in screen space - use this offset for e.g.
+ * {@code getInstrumentation().getUiAutomation().takeScreenshot()},
+ * since those screenshots are captured in screen space.
+ */
+ public final Point screenOffset;
+
+ public TestPositionInfo(Point surfaceOffset, Point screenOffset) {
+ this.surfaceOffset = surfaceOffset;
+ this.screenOffset = screenOffset;
+ }
+ }
+
public interface Screenshotter {
- Bitmap takeScreenshot(Point point);
+ Bitmap takeScreenshot(TestPositionInfo params);
}
/**
@@ -230,7 +248,7 @@
}
for (TestCase testCase : mTestCases) {
- Point testOffset = runRenderSpec(testCase);
+ TestPositionInfo testPositionInfo = runRenderSpec(testCase);
for (int i = 0; i < VERIFY_ANIMATION_LOOP_COUNT; i++) {
try {
@@ -238,7 +256,7 @@
} catch (InterruptedException e) {
e.printStackTrace();
}
- Bitmap testCaseBitmap = takeScreenshot(testOffset);
+ Bitmap testCaseBitmap = takeScreenshot(testPositionInfo);
mBitmapAsserter.assertBitmapIsVerified(testCaseBitmap, bitmapVerifier,
getName(), testCase.getDebugString());
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
index 48c4a95..b12390e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
@@ -47,7 +47,8 @@
static final String EXTRA_WIDE_COLOR_GAMUT = "DrawActivity.WIDE_COLOR_GAMUT";
private final static long TIME_OUT_MS = 10000;
- private final Point mLock = new Point();
+ private final Object mLock = new Object();
+ private ActivityTestBase.TestPositionInfo mPositionInfo;
private Handler mHandler;
private View mView;
@@ -72,11 +73,11 @@
return mOnTv;
}
- public Point enqueueRenderSpecAndWait(int layoutId, CanvasClient canvasClient,
- @Nullable ViewInitializer viewInitializer, boolean useHardware, boolean usePicture) {
+ public ActivityTestBase.TestPositionInfo enqueueRenderSpecAndWait(int layoutId,
+ CanvasClient canvasClient, @Nullable ViewInitializer viewInitializer,
+ boolean useHardware, boolean usePicture) {
((RenderSpecHandler) mHandler).setViewInitializer(viewInitializer);
int arg2 = (useHardware ? View.LAYER_TYPE_NONE : View.LAYER_TYPE_SOFTWARE);
- Point point = new Point();
synchronized (mLock) {
if (canvasClient != null) {
mHandler.obtainMessage(RenderSpecHandler.CANVAS_MSG, usePicture ? 1 : 0,
@@ -87,12 +88,11 @@
try {
mLock.wait(TIME_OUT_MS);
- point.set(mLock.x, mLock.y);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
- return point;
+ return mPositionInfo;
}
public void reset() {
@@ -187,8 +187,6 @@
}
private class DrawCounterListener implements ViewTreeObserver.OnDrawListener {
- private final int[] mLocationInWindow = new int[2];
-
@Override
public void onDraw() {
long vsyncMillis = mView.getDrawingTime();
@@ -196,9 +194,14 @@
mView.post(() -> mView.getViewTreeObserver().removeOnDrawListener(this));
mDrawMonitor.notifyWhenDrawn(vsyncMillis, () -> {
+ final int[] location = new int[2];
+ mViewWrapper.getLocationInWindow(location);
+ Point surfaceOffset = new Point(location[0], location[1]);
+ mViewWrapper.getLocationOnScreen(location);
+ Point screenOffset = new Point(location[0], location[1]);
synchronized (mLock) {
- mViewWrapper.getLocationInWindow(mLocationInWindow);
- mLock.set(mLocationInWindow[0], mLocationInWindow[1]);
+ mPositionInfo = new ActivityTestBase.TestPositionInfo(
+ surfaceOffset, screenOffset);
mLock.notify();
}
});
diff --git a/tests/tests/widget/src/android/widget/cts/MagnifierTest.java b/tests/tests/widget/src/android/widget/cts/MagnifierTest.java
index fc54362..5c7c47e 100644
--- a/tests/tests/widget/src/android/widget/cts/MagnifierTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MagnifierTest.java
@@ -22,11 +22,9 @@
import static org.junit.Assume.assumeTrue;
import android.app.Activity;
-import android.app.Instrumentation;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
@@ -38,6 +36,7 @@
import android.widget.Magnifier;
import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.WidgetTestUtils;
import org.junit.Before;
import org.junit.Rule;
@@ -46,6 +45,8 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Tests for {@link Magnifier}.
@@ -53,7 +54,9 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class MagnifierTest {
- private Instrumentation mInstrumentation;
+ private static final String TIME_LIMIT_EXCEEDED =
+ "Completing the magnifier operation took too long";
+
private Activity mActivity;
private LinearLayout mLayout;
private Magnifier mMagnifier;
@@ -64,7 +67,6 @@
@Before
public void setup() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mActivity = mActivityRule.getActivity();
PollingCheck.waitFor(mActivity::hasWindowFocus);
mLayout = mActivity.findViewById(R.id.magnifier_activity_basic_layout);
@@ -141,25 +143,31 @@
}
@Test
- public void testWindowContent() {
+ public void testWindowContent() throws Throwable {
prepareFourQuadrantsScenario();
+ final CountDownLatch latch = new CountDownLatch(1);
+ mMagnifier.setOnOperationCompleteCallback(latch::countDown);
+
// Show the magnifier at the center of the activity.
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
mMagnifier.show(mLayout.getWidth() / 2, mLayout.getHeight() / 2);
});
- mInstrumentation.waitForIdleSync();
+ assertTrue(TIME_LIMIT_EXCEEDED, latch.await(1, TimeUnit.SECONDS));
assertFourQuadrants(mMagnifier.getContent());
}
@Test
- public void testWindowPosition() {
+ public void testWindowPosition() throws Throwable {
prepareFourQuadrantsScenario();
+ final CountDownLatch latch = new CountDownLatch(1);
+ mMagnifier.setOnOperationCompleteCallback(latch::countDown);
+
// Show the magnifier at the center of the activity.
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
mMagnifier.show(mLayout.getWidth() / 2, mLayout.getHeight() / 2);
});
- mInstrumentation.waitForIdleSync();
+ assertTrue(TIME_LIMIT_EXCEEDED, latch.await(1, TimeUnit.SECONDS));
// Assert that the magnifier position represents a valid rectangle on screen.
final Rect position = mMagnifier.getWindowPositionOnScreen();
@@ -169,27 +177,33 @@
}
@Test
- public void testWindowContent_modifiesAfterUpdate() {
+ public void testWindowContent_modifiesAfterUpdate() throws Throwable {
prepareFourQuadrantsScenario();
+
// Show the magnifier at the center of the activity.
- mInstrumentation.runOnMainSync(() -> {
+ final CountDownLatch latchForShow = new CountDownLatch(1);
+ mMagnifier.setOnOperationCompleteCallback(latchForShow::countDown);
+ mActivityRule.runOnUiThread(() -> {
mMagnifier.show(mLayout.getWidth() / 2, mLayout.getHeight() / 2);
});
- mInstrumentation.waitForIdleSync();
+ assertTrue(TIME_LIMIT_EXCEEDED, latchForShow.await(1, TimeUnit.SECONDS));
final Bitmap initialBitmap = mMagnifier.getContent()
.copy(mMagnifier.getContent().getConfig(), true);
assertFourQuadrants(initialBitmap);
// Make the one quadrant white.
- mInstrumentation.runOnMainSync(() -> {
- mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout_quadrant_1)
- .setBackground(null);
+ final View quadrant1 =
+ mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout_quadrant_1);
+ WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, quadrant1, () -> {
+ quadrant1.setBackground(null);
});
- mInstrumentation.waitForIdleSync();
+
// Update the magnifier.
- mInstrumentation.runOnMainSync(mMagnifier::update);
- mInstrumentation.waitForIdleSync();
+ final CountDownLatch latchForUpdate = new CountDownLatch(1);
+ mMagnifier.setOnOperationCompleteCallback(latchForUpdate::countDown);
+ mActivityRule.runOnUiThread(mMagnifier::update);
+ assertTrue(TIME_LIMIT_EXCEEDED, latchForUpdate.await(1, TimeUnit.SECONDS));
final Bitmap newBitmap = mMagnifier.getContent();
assertFourQuadrants(newBitmap);
@@ -200,13 +214,13 @@
* Sets the activity to contain four equal quadrants coloured differently and
* instantiates a magnifier. This method should not be called on the UI thread.
*/
- private void prepareFourQuadrantsScenario() {
- mInstrumentation.runOnMainSync(() -> {
+ private void prepareFourQuadrantsScenario() throws Throwable {
+ WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
mActivity.setContentView(R.layout.magnifier_activity_four_quadrants_layout);
mLayout = mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout);
mMagnifier = new Magnifier(mLayout);
- });
- mInstrumentation.waitForIdleSync();
+ }, false);
+ WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mLayout, null);
}
/**
diff --git a/tools/cts-tradefed/res/config/retry.xml b/tools/cts-tradefed/res/config/retry.xml
index e488410..d425d8e 100644
--- a/tools/cts-tradefed/res/config/retry.xml
+++ b/tools/cts-tradefed/res/config/retry.xml
@@ -14,6 +14,8 @@
limitations under the License.
-->
<configuration description="Runs a retry of a previous CTS session.">
+ <option name="dynamic-sharding" value="true" />
+ <option name="disable-strict-sharding" value="true" />
<device_recovery class="com.android.tradefed.device.WaitDeviceRecovery" />
<build_provider class="com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider" />
@@ -21,6 +23,8 @@
<option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:rerun-from-file:true" />
<option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:fallback-to-serial-rerun:false" />
+ <option name="compatibility:test-arg" value="com.android.compatibility.testtype.LibcoreTest:rerun-from-file:true" />
+ <option name="compatibility:test-arg" value="com.android.compatibility.testtype.LibcoreTest:fallback-to-serial-rerun:false" />
<logger class="com.android.tradefed.log.FileLogger">
<option name="log-level-display" value="WARN" />
@@ -36,6 +40,16 @@
<option name="skip-device-info" value="true" />
<option name="enable-root" value="false" />
+ <!-- retain 200MB of host log -->
+ <option name="max-log-size" value="200" />
+ <!-- retain 200MB of logcat -->
+ <option name="max-tmp-logcat-file" value="209715200" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="settings put global package_verifier_enable 0" />
+ <option name="teardown-command" value="settings put global package_verifier_enable 1"/>
+ </target_preparer>
+
<result_reporter class="com.android.compatibility.common.tradefed.result.ConsoleReporter" />
<result_reporter class="com.android.compatibility.common.tradefed.result.ResultReporter" />