Merge "camera: Relax af scene mode change test"
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 6d3cd70..956d3a4 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -2210,6 +2210,28 @@
android:value="android.hardware.sensor.accelerometer" />
</activity>
+ <activity
+ android:name="com.android.cts.verifier.sensors.EventSanitizationTestActivity"
+ android:label="@string/snsr_event_sanitization_test"
+ android:screenOrientation="nosensor" >
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+
+ <meta-data
+ android:name="test_category"
+ android:value="@string/test_category_sensors">
+ </meta-data>
+
+ <meta-data
+ android:name="test_required_features"
+ android:value="android.hardware.sensor.proximity:android.hardware.sensor.accelerometer">
+ </meta-data>
+
+ </activity>
+
<receiver android:name=".widget.WidgetCtsProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 29339c2..c5b275a 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -948,6 +948,17 @@
You will need to walk to ensure that Significant Motion triggers. The screen will turn on and a sound will be played once the test completes.</string>
<string name="snsr_device_did_not_wake_up_at_trigger">Device did not wakeup at trigger time. wakeTime=%1$d ms triggerTime=%2$d ms</string>
+ <!-- Event sanitization for idle UIDs -->
+ <string name="snsr_event_sanitization_test">Event sanitization for idle UID test</string>
+ <string name="snsr_event_sanitization_test_setup">Run the \'adb shell cmd sensorservice set-uid-state com.android.cts.verifier idle\' shell command
+ to emulate the CtsVerifier UID being idle.</string>
+ <string name="snsr_event_sanitization_test_cleanup">Run the \'adb shell cmd sensorservice reset-uid-state com.android.cts.verifier\' shell command
+ to stop emulating the CtsVerifier UID being idle. Failing to do that would lead to other tests failing!</string>
+ <string name="snsr_significant_motion_test_uid_idle">Move around with the device to try triggering significant motion</string>
+ <string name="snsr_significant_motion_test_uid_idle_expectation">No trigger events should be generated while idle</string>
+ <string name="snsr_proximity_test_uid_idle">Touch the proximity sensor to try triggering it</string>
+ <string name="snsr_proximity_test_uid_idle_expectation">No on-change events should be generated while idle</string>
+
<!-- Low Latency Off-Body Detect -->
<string name="snsr_offbody_sensor_test">Off Body Sensor Tests</string>
<string name="snsr_offbody_sensor_registration">Registration failed for low latency offbody detect sensor.\n</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
index b7d9617..428d237 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
@@ -155,7 +155,7 @@
return executeTest(operation);
}
- private String executeTest(TestSensorOperation operation) throws InterruptedException {
+ private String executeTest(TestSensorOperation operation) throws Exception {
operation.addDefaultVerifications();
operation.execute(getCurrentTestNode());
return null;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/EventSanitizationTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/EventSanitizationTestActivity.java
new file mode 100644
index 0000000..4ebb5c6
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/EventSanitizationTestActivity.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.sensors;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.TriggerEvent;
+import android.hardware.TriggerEventListener;
+import android.hardware.cts.helpers.SensorNotSupportedException;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+import junit.framework.Assert;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests about event policy when the observer's UID is idle.
+ */
+public class EventSanitizationTestActivity extends SensorCtsVerifierTestActivity {
+ public EventSanitizationTestActivity() {
+ super(EventSanitizationTestActivity.class);
+ }
+
+ // time for the test to wait for an event
+ private static final int EVENT_TIMEOUT = 30;
+
+ @Override
+ protected void activitySetUp() throws Exception {
+ getTestLogger().logInstructions(R.string.snsr_event_sanitization_test_setup);
+ waitForUserToBegin();
+ }
+
+ @Override
+ protected void activityCleanUp() throws Exception {
+ getTestLogger().logInstructions(R.string.snsr_event_sanitization_test_cleanup);
+ waitForUserToContinue();
+ }
+
+ /**
+ * Test that no trigger events are triggered while the UID is idle.
+ */
+ public String testNoTriggerEventsWhileUidIdle() throws Exception {
+ // Not significant motion sensor, nothing to do.
+ final SensorManager sensorManager = getApplicationContext()
+ .getSystemService(SensorManager.class);
+ final Sensor sensor = sensorManager.getDefaultSensor(
+ Sensor.TYPE_SIGNIFICANT_MOTION);
+ if (sensor == null) {
+ throw new SensorNotSupportedException(Sensor.TYPE_SIGNIFICANT_MOTION);
+ }
+
+ // Let us begin.
+ final SensorTestLogger logger = getTestLogger();
+ logger.logInstructions(R.string.snsr_significant_motion_test_uid_idle);
+ waitForUserToBegin();
+
+ // Watch for the trigger event.
+ final CountDownLatch latch = new CountDownLatch(1);
+ final TriggerEventListener listener = new TriggerEventListener() {
+ @Override
+ public void onTrigger(TriggerEvent event) {
+ latch.countDown();
+ }
+ };
+ sensorManager.requestTriggerSensor(listener, sensor);
+
+ // Tell the user now when the test completes.
+ logger.logWaitForSound();
+
+ // We shouldn't be getting an event.
+ try {
+ Assert.assertFalse(getString(R.string
+ .snsr_significant_motion_test_uid_idle_expectation),
+ latch.await(EVENT_TIMEOUT, TimeUnit.SECONDS));
+ } finally {
+ sensorManager.cancelTriggerSensor(listener, sensor);
+ playSound();
+ }
+
+ return null;
+ }
+
+ /**
+ * Test that no on-change events are triggered while the UID is idle.
+ */
+ public String testNoOnChangeEventsWhileUidIdle() throws Exception {
+ // Not significant motion sensor, nothing to do.
+ final SensorManager sensorManager = getApplicationContext()
+ .getSystemService(SensorManager.class);
+ final Sensor sensor = sensorManager.getDefaultSensor(
+ Sensor.TYPE_PROXIMITY);
+ if (sensor == null) {
+ throw new SensorNotSupportedException(Sensor.TYPE_PROXIMITY);
+ }
+
+ // Let us begin.
+ final SensorTestLogger logger = getTestLogger();
+ logger.logInstructions(R.string.snsr_proximity_test_uid_idle);
+ waitForUserToBegin();
+
+ // Watch for the change event.
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SensorEventListener listener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ latch.countDown();
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ /* do nothing */
+ }
+ };
+ sensorManager.registerListener(listener, sensor,
+ sensor.getMinDelay(), sensor.getMaxDelay());
+
+ // Tell the user now when the test completes.
+ logger.logWaitForSound();
+
+ // We shouldn't be getting an event.
+ try {
+ Assert.assertFalse(getString(R.string
+ .snsr_proximity_test_uid_idle_expectation),
+ latch.await(EVENT_TIMEOUT, TimeUnit.SECONDS));
+ } finally {
+ sensorManager.unregisterListener(listener, sensor);
+ playSound();
+ }
+
+ return null;
+ }
+}
diff --git a/common/device-side/device-info/Android.mk b/common/device-side/device-info/Android.mk
index 4ab1ac6..df95d9a 100644
--- a/common/device-side/device-info/Android.mk
+++ b/common/device-side/device-info/Android.mk
@@ -25,13 +25,24 @@
android-support-test \
junit
-LOCAL_JAVA_LIBRARIES := android.test.base
+LOCAL_JAVA_LIBRARIES := \
+ android.test.base.stubs \
+ framework-stub-for-compatibility-device-info
LOCAL_MODULE := compatibility-device-info
-# uncomment when b/13282254 is fixed
-#LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := current
include $(BUILD_STATIC_JAVA_LIBRARY)
+include $(CLEAR_VARS)
+# This stub library provides some internal APIs (SystemProperties, VintfObject, etc.)
+# to compatibility-device-info library.
+LOCAL_MODULE := framework-stub-for-compatibility-device-info
+LOCAL_SRC_FILES := $(call all-java-files-under, src_stub)
+LOCAL_MODULE_TAGS := optional
+LOCAL_SDK_VERSION := current
+LOCAL_UNINSTALLABLE_MODULE := true
+include $(BUILD_JAVA_LIBRARY)
+
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/common/device-side/device-info/src_stub/android/os/SystemProperties.java b/common/device-side/device-info/src_stub/android/os/SystemProperties.java
new file mode 100644
index 0000000..2f8a051
--- /dev/null
+++ b/common/device-side/device-info/src_stub/android/os/SystemProperties.java
@@ -0,0 +1,9 @@
+/**
+ * This is a stub library for the runtime class at
+ * frameworks/base/core/java/android/os/SystemProperties.java
+ */
+package android.os;
+
+public class SystemProperties {
+ public static String get(String key, String def) { return null; }
+}
diff --git a/common/device-side/device-info/src_stub/android/os/VintfObject.java b/common/device-side/device-info/src_stub/android/os/VintfObject.java
new file mode 100644
index 0000000..42f1be2
--- /dev/null
+++ b/common/device-side/device-info/src_stub/android/os/VintfObject.java
@@ -0,0 +1,15 @@
+/**
+ * This is a stub library for the runtime class at
+ * frameworks/base/core/java/android/os/VintfObject.java
+ */
+
+package android.os;
+
+import java.util.Map;
+
+public class VintfObject {
+ public static Map<String, String[]> getVndkSnapshots() { return null; }
+ public static String getSepolicyVersion() { return null; }
+ public static String[] getHalNamesAndVersions() { return null; }
+ public static String[] report() { return null; }
+}
diff --git a/common/device-side/device-info/src_stub/android/os/VintfRuntimeInfo.java b/common/device-side/device-info/src_stub/android/os/VintfRuntimeInfo.java
new file mode 100644
index 0000000..20fa94c
--- /dev/null
+++ b/common/device-side/device-info/src_stub/android/os/VintfRuntimeInfo.java
@@ -0,0 +1,17 @@
+/**
+ * This is a stub library for the runtime class at
+ * frameworks/base/core/java/android/os/VintfRuntimeInfo.java
+ */
+package android.os;
+
+public class VintfRuntimeInfo {
+ public static String getBootAvbVersion() { return null; }
+ public static String getBootVbmetaAvbVersion() { return null; }
+ public static String getCpuInfo() { return null; }
+ public static String getHardwareId() { return null; }
+ public static String getKernelVersion() { return null; }
+ public static String getNodeName() { return null; }
+ public static String getOsName() { return null; }
+ public static String getOsRelease() { return null; }
+ public static String getOsVersion() { return null; }
+}
diff --git a/common/device-side/device-info/tests/Android.mk b/common/device-side/device-info/tests/Android.mk
index db4f250..cd057962 100644
--- a/common/device-side/device-info/tests/Android.mk
+++ b/common/device-side/device-info/tests/Android.mk
@@ -20,10 +20,12 @@
LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-info junit
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := compatibility-device-info-tests
+LOCAL_SDK_VERSION := current
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/common/device-side/util/Android.mk b/common/device-side/util/Android.mk
index fbf0ee4..bc54871 100644
--- a/common/device-side/util/Android.mk
+++ b/common/device-side/util/Android.mk
@@ -25,7 +25,9 @@
ub-uiautomator \
mockito-target-minus-junit4
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base.stubs
+LOCAL_JAVA_LIBRARIES := \
+ android.test.runner.stubs \
+ android.test.base.stubs
LOCAL_MODULE_TAGS := optional
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/BlockingBroadcastReceiver.java b/common/device-side/util/src/com/android/compatibility/common/util/BlockingBroadcastReceiver.java
index 4ac8403..3fbc2c5 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/BlockingBroadcastReceiver.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/BlockingBroadcastReceiver.java
@@ -79,6 +79,19 @@
return null;
}
+ /**
+ * Wait until the broadcast and return the received broadcast intent. {@code null} is returned
+ * if no broadcast with expected action is received within the given timeout.
+ */
+ public @Nullable Intent awaitForBroadcast(long timeoutMillis) {
+ try {
+ return mBlockingQueue.poll(timeoutMillis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "waitForBroadcast get interrupted: ", e);
+ }
+ return null;
+ }
+
public void unregisterQuietly() {
try {
mContext.unregisterReceiver(this);
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/devicepolicy/provisioning/SilentProvisioningTestManager.java b/common/device-side/util/src/com/android/compatibility/common/util/devicepolicy/provisioning/SilentProvisioningTestManager.java
index 19278d0..05edf1a 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/devicepolicy/provisioning/SilentProvisioningTestManager.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/devicepolicy/provisioning/SilentProvisioningTestManager.java
@@ -130,7 +130,9 @@
bundle.putParcelable(Intent.EXTRA_INTENT, intent);
bundle.putBinder(StartProvisioningActivity.EXTRA_BOOLEAN_CALLBACK,
mProvisioningResultCallback.asBinder());
- return new Intent(mContext, StartProvisioningActivity.class).putExtras(bundle);
+ return new Intent(mContext, StartProvisioningActivity.class)
+ .putExtras(bundle)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
private static void wakeUpAndDismissInsecureKeyguard() {
diff --git a/common/device-side/util/tests/Android.mk b/common/device-side/util/tests/Android.mk
index 12baeb7..a073b9a 100644
--- a/common/device-side/util/tests/Android.mk
+++ b/common/device-side/util/tests/Android.mk
@@ -24,4 +24,6 @@
LOCAL_MODULE := compatibility-device-util-tests
+LOCAL_SDK_VERSION := current
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/hostsidetests/api/src/com/android/cts/api/DexAnalyzer.java b/hostsidetests/api/src/com/android/cts/api/DexAnalyzer.java
index f4c45c9d..37d1759 100644
--- a/hostsidetests/api/src/com/android/cts/api/DexAnalyzer.java
+++ b/hostsidetests/api/src/com/android/cts/api/DexAnalyzer.java
@@ -440,19 +440,21 @@
return null;
}
- private static class SkipIfNeeded implements Predicate<MemberRef> {
+ private static class SkipIfNeeded implements Predicate<Ref> {
@Override
- public boolean test(MemberRef ref) {
- if (ref.getDefiningClass().endsWith("[]")) {
+ public boolean test(Ref ref) {
+ String className = (ref instanceof TypeRef) ?
+ ((TypeRef)ref).getName() : ((MemberRef)ref).getDefiningClass();
+ if (className.endsWith("[]")) {
// Reference to array type is skipped
return true;
}
- if (ref.getDefiningClass().startsWith("dalvik.annotation.")
- || ref.getDefiningClass().startsWith("javax.annotation.")) {
+ if (className.startsWith("dalvik.annotation.")
+ || className.startsWith("javax.annotation.")) {
// These annotation classes are not part of API but they are not explicitly used.
return true;
}
- if (ref.getDefiningClass().startsWith("java.lang.")) {
+ if (className.startsWith("java.lang.")) {
// core java libraries are exempted.
return true;
}
@@ -465,7 +467,8 @@
public Stream<TypeRef> collectUndefinedTypeReferences() {
return typeReferences.values().stream()
.filter(ref -> !definedClassesInDex.containsKey(ref.getName())
- && !approvedApis.getDefinedClasses().containsKey(ref.getName()));
+ && !approvedApis.getDefinedClasses().containsKey(ref.getName()))
+ .filter((new SkipIfNeeded()).negate());
}
public Stream<MethodRef> collectUndefinedMethodReferences() {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 5408115..7ba2eb9 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -42,12 +42,11 @@
private static final String TAG = "DirectBootHostTest";
private static final String PKG = "com.android.cts.encryptionapp";
- private static final String CLASS = ".EncryptionAppTest";
+ private static final String CLASS = PKG + ".EncryptionAppTest";
private static final String APK = "CtsEncryptionApp.apk";
private static final String OTHER_APK = "CtsSplitApp.apk";
private static final String OTHER_PKG = "com.android.cts.splitapp";
- private static final String OTHER_CLASS = ".SplitAppTest";
private static final String MODE_NATIVE = "native";
private static final String MODE_EMULATED = "emulated";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index 8cf385d..38e4dc2 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -49,16 +49,16 @@
private static final String NONE_APK = "CtsExternalStorageApp.apk";
private static final String NONE_PKG = "com.android.cts.externalstorageapp";
- private static final String NONE_CLASS = ".ExternalStorageTest";
+ private static final String NONE_CLASS = NONE_PKG + ".ExternalStorageTest";
private static final String READ_APK = "CtsReadExternalStorageApp.apk";
private static final String READ_PKG = "com.android.cts.readexternalstorageapp";
- private static final String READ_CLASS = ".ReadExternalStorageTest";
+ private static final String READ_CLASS = READ_PKG + ".ReadExternalStorageTest";
private static final String WRITE_APK = "CtsWriteExternalStorageApp.apk";
private static final String WRITE_PKG = "com.android.cts.writeexternalstorageapp";
- private static final String WRITE_CLASS = ".WriteExternalStorageTest";
+ private static final String WRITE_CLASS = WRITE_PKG + ".WriteExternalStorageTest";
private static final String MULTIUSER_APK = "CtsMultiUserStorageApp.apk";
private static final String MULTIUSER_PKG = "com.android.cts.multiuserstorageapp";
- private static final String MULTIUSER_CLASS = ".MultiUserStorageTest";
+ private static final String MULTIUSER_CLASS = MULTIUSER_PKG + ".MultiUserStorageTest";
private int[] mUsers;
@@ -159,14 +159,14 @@
// verify that the daemon correctly invalidates any caches.
assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
for (int user : mUsers) {
- runDeviceTests(WRITE_PKG, ".WriteGiftTest", user);
+ runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", user);
}
assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
for (int user : mUsers) {
- runDeviceTests(READ_PKG, ".ReadGiftTest", user);
- runDeviceTests(NONE_PKG, ".GiftTest", user);
+ runDeviceTests(READ_PKG, READ_PKG + ".ReadGiftTest", user);
+ runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", user);
}
} finally {
getDevice().uninstallPackage(NONE_PKG);
@@ -239,24 +239,24 @@
assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
for (int user : mUsers) {
- runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testFolderSetup", user);
+ runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testFolderSetup", user);
}
for (int user : mUsers) {
- runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testRWAccess", user);
+ runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testRWAccess", user);
}
for (int user : mUsers) {
- runDeviceTests(WRITE_PKG, ".WriteMultiViewTest", "testMoveAway", user);
+ runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteMultiViewTest", "testMoveAway", user);
}
for (int user : mUsers) {
- runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testROAccess", user);
+ runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testROAccess", user);
}
for (int user : mUsers) {
- runDeviceTests(WRITE_PKG, ".WriteMultiViewTest", "testMoveBack", user);
+ runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteMultiViewTest", "testMoveBack", user);
}
for (int user : mUsers) {
- runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testRWAccess", user);
+ runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testRWAccess", user);
}
} finally {
getDevice().uninstallPackage(NONE_PKG);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
index 3574191..02187fa 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
@@ -17,17 +17,15 @@
package android.appsecurity.cts;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
index b31f91a..6c0efd5 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
@@ -17,10 +17,10 @@
package android.appsecurity.cts;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
index 8bad048..3cde96f 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
@@ -18,12 +18,12 @@
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import java.util.Arrays;
import java.util.Map;
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteMultiViewTest.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteMultiViewTest.java
index db1c721..e48c319 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteMultiViewTest.java
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteMultiViewTest.java
@@ -21,10 +21,11 @@
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.PACKAGE_READ;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertFileReadWriteAccess;
+import android.os.SystemClock;
import android.system.Os;
import android.test.AndroidTestCase;
-
+import android.text.format.DateUtils;
import android.util.Log;
@@ -65,6 +66,9 @@
Os.rename(ourTestDir.getAbsolutePath(), otherTestDir.getAbsolutePath());
+ // Sit around long enough for VFS cache to expire
+ SystemClock.sleep(15 * DateUtils.SECOND_IN_MILLIS);
+
assertNotEqual(Os.getuid(), Os.stat(otherCache.getAbsolutePath()).st_uid);
assertNotEqual(Os.getuid(), Os.stat(otherTestDir.getAbsolutePath()).st_uid);
assertNotEqual(Os.getuid(), Os.stat(afterFile.getAbsolutePath()).st_uid);
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetSystemSettingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetSystemSettingTest.java
new file mode 100644
index 0000000..06e6149
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetSystemSettingTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.admin.DevicePolicyManager;
+import android.provider.Settings;
+
+/**
+ * Test {@link DevicePolicyManager#setSystemSetting}.
+ */
+public class SetSystemSettingTest extends BaseDeviceOwnerTest {
+
+ private static final String TEST_BRIGHTNESS_1 = "200";
+ private static final String TEST_BRIGHTNESS_2 = "100";
+
+ private void testSetBrightnessWithValue(String testBrightness) {
+ mDevicePolicyManager.setSystemSetting(getWho(),
+ Settings.System.SCREEN_BRIGHTNESS, testBrightness);
+ assertEquals(testBrightness, Settings.System.getString(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS));
+ }
+
+ public void testSetBrightness() {
+ testSetBrightnessWithValue(TEST_BRIGHTNESS_1);
+ testSetBrightnessWithValue(TEST_BRIGHTNESS_2);
+ }
+
+ public void testSetSystemSettingsFailsForNonWhitelistedSettings() throws Exception {
+ try {
+ mDevicePolicyManager.setSystemSetting(getWho(),
+ Settings.System.TEXT_AUTO_REPLACE, "0");
+ fail("Didn't throw security exception.");
+ } catch (SecurityException e) {
+ // Should throw SecurityException.
+ }
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetTimeTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetTimeTest.java
new file mode 100644
index 0000000..3ccbd9e
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetTimeTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.provider.Settings;
+
+import java.util.Calendar;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test {@link DevicePolicyManager#setTime} and @link {DevicePolicyManager#setTimeZone}
+ */
+public class SetTimeTest extends BaseDeviceOwnerTest {
+
+ private final long TEST_TIME_1 = 10000000;
+ private final long TEST_TIME_2 = 100000000;
+ private final String TEST_TIME_ZONE_1 = "America/New_York";
+ private final String TEST_TIME_ZONE_2 = "America/Los_Angeles";
+ private final long TIMEOUT_SEC = 10;
+
+ @Override
+ protected void tearDown() throws Exception {
+ mDevicePolicyManager.setGlobalSetting(getWho(), Settings.Global.AUTO_TIME, "1");
+ mDevicePolicyManager.setGlobalSetting(getWho(), Settings.Global.AUTO_TIME_ZONE, "1");
+ super.tearDown();
+ }
+
+ private void testSetTimeWithValue(long testTime) throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ latch.countDown();
+ }
+ };
+ mContext.registerReceiver(receiver, new IntentFilter(Intent.ACTION_TIME_CHANGED));
+
+ try {
+ assertTrue(mDevicePolicyManager.setTime(getWho(), testTime));
+ assertTrue(latch.await(TIMEOUT_SEC, TimeUnit.SECONDS));
+ assertTrue(System.currentTimeMillis() <= testTime + (TIMEOUT_SEC + 1) * 1000);
+ } finally {
+ mContext.unregisterReceiver(receiver);
+ }
+ }
+
+ public void testSetTime() throws Exception {
+ mDevicePolicyManager.setGlobalSetting(getWho(), Settings.Global.AUTO_TIME, "0");
+ testSetTimeWithValue(TEST_TIME_1);
+ testSetTimeWithValue(TEST_TIME_2);
+ }
+
+ public void testSetTimeFailWithAutoTimeOn() {
+ mDevicePolicyManager.setGlobalSetting(getWho(), Settings.Global.AUTO_TIME, "1");
+ assertFalse(mDevicePolicyManager.setTime(getWho(), TEST_TIME_1));
+ }
+
+ private void testSetTimeZoneWithValue(String testTimeZone) throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ latch.countDown();
+ }
+ };
+ mContext.registerReceiver(receiver, new IntentFilter(Intent.ACTION_TIMEZONE_CHANGED));
+
+ try {
+ assertTrue(mDevicePolicyManager.setTimeZone(getWho(), testTimeZone));
+ assertTrue(latch.await(TIMEOUT_SEC, TimeUnit.SECONDS));
+ assertEquals(testTimeZone, Calendar.getInstance().getTimeZone().getID());
+ } finally {
+ mContext.unregisterReceiver(receiver);
+ }
+ }
+
+ public void testSetTimeZone() throws Exception {
+ mDevicePolicyManager.setGlobalSetting(getWho(), Settings.Global.AUTO_TIME_ZONE, "0");
+ testSetTimeZoneWithValue(TEST_TIME_ZONE_1);
+ testSetTimeZoneWithValue(TEST_TIME_ZONE_2);
+ }
+
+ public void testSetTimeZoneFailWithAutoTimezoneOn() {
+ mDevicePolicyManager.setGlobalSetting(getWho(), Settings.Global.AUTO_TIME_ZONE, "1");
+ assertFalse(mDevicePolicyManager.setTimeZone(getWho(), TEST_TIME_ZONE_1));
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/PrintingApp/Android.mk b/hostsidetests/devicepolicy/app/PrintingApp/Android.mk
index 00c4678..be8f1f7 100644
--- a/hostsidetests/devicepolicy/app/PrintingApp/Android.mk
+++ b/hostsidetests/devicepolicy/app/PrintingApp/Android.mk
@@ -24,14 +24,11 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
LOCAL_PACKAGE_NAME := CtsDevicePolicyPrintingApp
LOCAL_SDK_VERSION := current
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := arcts cts vts general-tests
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index f88c380..3145247 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -19,9 +19,7 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -29,6 +27,8 @@
import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.util.FileUtil;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index fb343ea..df93564 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -612,6 +612,13 @@
executeDeviceOwnerTest("BluetoothRestrictionTest");
}
+ public void testSetTime() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ executeDeviceOwnerTest("SetTimeTest");
+ }
+
public void testDeviceOwnerProvisioning() throws Exception {
if (!mHasFeature) {
return;
@@ -754,6 +761,14 @@
executeDeviceOwnerTest("AirplaneModeRestrictionTest");
}
+ public void testSetSystemSetting() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ executeDeviceOwnerTest("SetSystemSettingTest");
+ }
+
+
private void executeDeviceOwnerTest(String testClassName) throws Exception {
if (!mHasFeature) {
return;
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/BaseDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/BaseDumpsysTest.java
index dd279d9..54c0dfb 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/BaseDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/BaseDumpsysTest.java
@@ -19,15 +19,15 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
diff --git a/hostsidetests/harmfulappwarning/Android.mk b/hostsidetests/harmfulappwarning/Android.mk
new file mode 100644
index 0000000..5ec2e99
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/Android.mk
@@ -0,0 +1,36 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE := CtsHarmfulAppWarningHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed
+
+
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+LOCAL_CTS_TEST_PACKAGE := android.host.harmfulappwarning
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/harmfulappwarning/AndroidTest.xml b/hostsidetests/harmfulappwarning/AndroidTest.xml
new file mode 100644
index 0000000..bb9a472
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<configuration description="Config for the CTS Harmful App Warning host test cases">
+ <option name="config-descriptor:metadata" key="component" value="art" />
+ <option name="test-suite-tag" value="cts" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsHarmfulAppWarningTestApp.apk" />
+ </target_preparer>
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsHarmfulAppWarningHostTestCases.jar" />
+ <option name="runtime-hint" value="10s" />
+ </test>
+</configuration>
diff --git a/hostsidetests/harmfulappwarning/sampleapp/Android.mk b/hostsidetests/harmfulappwarning/sampleapp/Android.mk
new file mode 100644
index 0000000..a0aba0d
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/sampleapp/Android.mk
@@ -0,0 +1,37 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+LOCAL_PACKAGE_NAME := CtsHarmfulAppWarningSampleApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/harmfulappwarning/sampleapp/AndroidManifest.xml b/hostsidetests/harmfulappwarning/sampleapp/AndroidManifest.xml
new file mode 100755
index 0000000..5bfbd24
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/sampleapp/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.harmfulappwarning.sampleapp">
+
+ <application>
+ <activity android:name=".SampleDeviceActivity" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
+
diff --git a/hostsidetests/harmfulappwarning/sampleapp/res/layout/sample_layout.xml b/hostsidetests/harmfulappwarning/sampleapp/res/layout/sample_layout.xml
new file mode 100644
index 0000000..b34e5a0
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/sampleapp/res/layout/sample_layout.xml
@@ -0,0 +1,19 @@
+<!-- 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+</RelativeLayout>
diff --git a/hostsidetests/harmfulappwarning/sampleapp/src/android/harmfulappwarning/sampleapp/SampleDeviceActivity.java b/hostsidetests/harmfulappwarning/sampleapp/src/android/harmfulappwarning/sampleapp/SampleDeviceActivity.java
new file mode 100644
index 0000000..d1b7869
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/sampleapp/src/android/harmfulappwarning/sampleapp/SampleDeviceActivity.java
@@ -0,0 +1,45 @@
+/*
+ * 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.harmfulappwarning.sampleapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * A simple activity which logs to Logcat.
+ *
+ * <p>This serves as a simple target application/activity to set a harmful app warning on.
+ */
+public class SampleDeviceActivity extends Activity {
+
+ private static final String ACTION_ACTIVITY_STARTED =
+ "android.harmfulappwarning.sampleapp.ACTIVITY_STARTED";
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.sample_layout);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ Intent intent = new Intent(ACTION_ACTIVITY_STARTED);
+ sendBroadcast(intent);
+ }
+}
diff --git a/hostsidetests/harmfulappwarning/src/android/harmfulappwarning/cts/HarmfulAppWarningTest.java b/hostsidetests/harmfulappwarning/src/android/harmfulappwarning/cts/HarmfulAppWarningTest.java
new file mode 100644
index 0000000..09cfd8b
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/src/android/harmfulappwarning/cts/HarmfulAppWarningTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.harmfulappwarning.cts;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.PackageInfo;
+import com.android.tradefed.result.InputStreamSource;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Scanner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Host-side tests for the harmful app launch warning
+ *
+ * <p>These tests have a few different components. This is the host-side part of the test, which is
+ * responsible for setting up the environment and passing off execution to the device-side part
+ * of the test.
+ *
+ * <p>The {@link HarmfulAppWarningDeviceTest} class is the device side of these tests. It attempts to launch
+ * the sample warned application, and verifies the correct behavior of the harmful app warning that
+ * is shown by the platform.
+ *
+ * <p>The third component is the sample app, which is just a placeholder app with a basic activity
+ * that only serves as a target for the harmful app warning.
+ *
+ * <p>Run with: atest CtsHarmfulAppWarningHostTestCases
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class HarmfulAppWarningTest extends BaseHostJUnit4Test {
+
+ private static final String TEST_APP_PACKAGE_NAME = "android.harmfulappwarning.sampleapp";
+ private static final String TEST_APP_ACTIVITY_CLASS_NAME = "SampleDeviceActivity";
+ private static final String TEST_APP_LAUNCHED_STRING = "Sample activity started.";
+
+ private static final String WARNING_MESSAGE = "This is a warning message.";
+ private static final String SET_HARMFUL_APP_WARNING_COMMAND = String.format(
+ "cmd package set-harmful-app-warning %s \"" + WARNING_MESSAGE + "\"",
+ TEST_APP_PACKAGE_NAME);
+
+ private static final String CLEAR_HARMFUL_APP_WARNING_COMMAND = String.format(
+ "cmd package set-harmful-app-warning %s", TEST_APP_PACKAGE_NAME);
+
+ private static final String GET_HARMFUL_APP_WARNING_COMMAND = String.format(
+ "cmd package get-harmful-app-warning %s", TEST_APP_PACKAGE_NAME);
+
+ private ITestDevice mDevice;
+
+ @Before
+ public void setUp() throws Exception {
+ installPackage("CtsHarmfulAppWarningSampleApp.apk");
+ mDevice = getDevice();
+ mDevice.clearLogcat();
+ }
+
+ private void runDeviceTest(String testName) throws DeviceNotAvailableException {
+ runDeviceTests("android.harmfulappwarning.testapp",
+ "android.harmfulappwarning.testapp.HarmfulAppWarningDeviceTest",
+ testName);
+ }
+
+ private void verifyHarmfulAppWarningSet() throws DeviceNotAvailableException {
+ String warning = getDevice().executeShellCommand(GET_HARMFUL_APP_WARNING_COMMAND);
+ assertEquals(WARNING_MESSAGE, warning.trim());
+ }
+
+ private void verifyHarmfulAppWarningUnset() throws DeviceNotAvailableException {
+ String warning = getDevice().executeShellCommand(GET_HARMFUL_APP_WARNING_COMMAND);
+ if (warning != null) {
+ warning = warning.trim();
+ }
+ assertTrue(warning == null || warning.length() == 0);
+ }
+
+ private void verifySampleAppUninstalled() throws DeviceNotAvailableException {
+ PackageInfo info = getDevice().getAppPackageInfo(TEST_APP_PACKAGE_NAME);
+ Assert.assertNull("Harmful application was not uninstalled", info);
+ }
+
+ private void verifySampleAppInstalled() throws DeviceNotAvailableException {
+ PackageInfo info = getDevice().getAppPackageInfo(TEST_APP_PACKAGE_NAME);
+ Assert.assertNotNull("Harmful application was uninstalled", info);
+ }
+
+ /**
+ * A basic smoke test to ensure that we're able to detect the launch of the activity when there
+ * is no warning.
+ */
+ @Test
+ public void testNormalLaunch() throws Exception {
+ runDeviceTest("testNormalLaunch");
+ }
+
+ /**
+ * Tests that when the user clicks "launch anyway" on the harmful app warning dialog, the
+ * warning is cleared and the activity is launched.
+ */
+ @Test
+ public void testLaunchAnyway() throws DeviceNotAvailableException {
+ mDevice.executeShellCommand(SET_HARMFUL_APP_WARNING_COMMAND);
+ runDeviceTest("testLaunchAnyway");
+
+ verifyHarmfulAppWarningUnset();
+ }
+
+ /**
+ * Tests that when the user clicks "uninstall" on the harmful app warning dialog, the
+ * application is uninstalled.
+ */
+ @Test
+ public void testUninstall() throws DeviceNotAvailableException {
+ mDevice.executeShellCommand(SET_HARMFUL_APP_WARNING_COMMAND);
+ runDeviceTest("testUninstall");
+ verifySampleAppUninstalled();
+ }
+
+ /**
+ * Tests that no action is taken when the user dismisses the harmful app warning
+ */
+ @Test
+ public void testDismissDialog() throws DeviceNotAvailableException {
+ mDevice.executeShellCommand(SET_HARMFUL_APP_WARNING_COMMAND);
+ runDeviceTest("testDismissDialog");
+ verifyHarmfulAppWarningSet();
+ verifySampleAppInstalled();
+ }
+}
diff --git a/hostsidetests/harmfulappwarning/testapp/Android.mk b/hostsidetests/harmfulappwarning/testapp/Android.mk
new file mode 100644
index 0000000..3ab50c4
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/testapp/Android.mk
@@ -0,0 +1,42 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ compatibility-device-util \
+ ub-uiautomator
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+LOCAL_PACKAGE_NAME := CtsHarmfulAppWarningTestApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/harmfulappwarning/testapp/AndroidManifest.xml b/hostsidetests/harmfulappwarning/testapp/AndroidManifest.xml
new file mode 100644
index 0000000..4f6bc69
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/testapp/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.harmfulappwarning.testapp">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.harmfulappwarning.testapp" />
+
+</manifest>
diff --git a/hostsidetests/harmfulappwarning/testapp/src/android/harmfulappwarning/testapp/HarmfulAppWarningDeviceTest.java b/hostsidetests/harmfulappwarning/testapp/src/android/harmfulappwarning/testapp/HarmfulAppWarningDeviceTest.java
new file mode 100644
index 0000000..3ee3374
--- /dev/null
+++ b/hostsidetests/harmfulappwarning/testapp/src/android/harmfulappwarning/testapp/HarmfulAppWarningDeviceTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.harmfulappwarning.testapp;
+
+import com.android.compatibility.common.util.BlockingBroadcastReceiver;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This is the device-side part of the tests for the harmful app launch warnings.
+ *
+ * <p>These tests are triggered by their counterparts in the {@link HarmfulAppWarningTest}
+ * host-side cts test.
+ */
+@RunWith(AndroidJUnit4.class)
+public class HarmfulAppWarningDeviceTest {
+
+ private static final long TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(1);
+
+ private static final String ACTION_ACTIVITY_STARTED =
+ "android.harmfulappwarning.sampleapp.ACTIVITY_STARTED";
+
+ private static final String TEST_APP_PACKAGE_NAME = "android.harmfulappwarning.sampleapp";
+ private static final String TEST_APP_ACTIVITY_CLASS_NAME =
+ "android.harmfulappwarning.sampleapp.SampleDeviceActivity";
+
+ private BlockingBroadcastReceiver mSampleActivityStartedReceiver;
+
+ protected static Instrumentation getInstrumentation() {
+ return InstrumentationRegistry.getInstrumentation();
+ }
+
+ protected static UiDevice getUiDevice() {
+ return UiDevice.getInstance(getInstrumentation());
+ }
+
+ private static void launchActivity(String packageName, String activityClassName) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(packageName, activityClassName);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getInstrumentation().getTargetContext().startActivity(intent, null);
+ }
+
+ private void verifyWarningShown() {
+ getUiDevice().wait(Until.findObject(By.res("android:id/message")), TIMEOUT_MILLIS);
+ UiObject2 obj = getUiDevice().findObject(By.res("android:id/message"));
+ Assert.assertEquals(obj.getText(), "This is a warning message.");
+ Assert.assertNotNull(obj);
+ }
+
+ private void verifySampleActivityLaunched() {
+ Assert.assertNotNull("Sample activity not launched.",
+ mSampleActivityStartedReceiver.awaitForBroadcast(TIMEOUT_MILLIS));
+ }
+
+ private void verifySampleActivityNotLaunched() {
+ Assert.assertNull("Sample activity was unexpectedly launched.",
+ mSampleActivityStartedReceiver.awaitForBroadcast(TIMEOUT_MILLIS));
+ }
+
+ private void clickLaunchAnyway() {
+ UiObject2 obj = getUiDevice().findObject(By.res("android:id/button1"));
+ Assert.assertNotNull(obj);
+ obj.click();
+ }
+
+ private void clickUninstall() {
+ UiObject2 obj = getUiDevice().findObject(By.res("android:id/button2"));
+ Assert.assertNotNull(obj);
+ obj.click();
+ }
+
+ @Before
+ public void setUp() {
+ mSampleActivityStartedReceiver = new BlockingBroadcastReceiver(
+ InstrumentationRegistry.getContext(), ACTION_ACTIVITY_STARTED);
+ mSampleActivityStartedReceiver.register();
+ }
+
+ @After
+ public void tearDown() {
+ mSampleActivityStartedReceiver.unregisterQuietly();
+ }
+
+ @Test
+ public void testNormalLaunch() throws Exception {
+ launchActivity(TEST_APP_PACKAGE_NAME, TEST_APP_ACTIVITY_CLASS_NAME);
+ verifySampleActivityLaunched();
+ }
+
+ @Test
+ public void testLaunchAnyway() throws Exception {
+ launchActivity(TEST_APP_PACKAGE_NAME, TEST_APP_ACTIVITY_CLASS_NAME);
+ verifyWarningShown();
+ clickLaunchAnyway();
+ verifySampleActivityLaunched();
+ }
+
+ @Test
+ public void testUninstall() throws Exception {
+ launchActivity(TEST_APP_PACKAGE_NAME, TEST_APP_ACTIVITY_CLASS_NAME);
+ verifyWarningShown();
+ clickUninstall();
+ verifySampleActivityNotLaunched();
+ }
+
+ @Test
+ public void testDismissDialog() throws Exception {
+ launchActivity(TEST_APP_PACKAGE_NAME, TEST_APP_ACTIVITY_CLASS_NAME);
+ verifyWarningShown();
+ getUiDevice().pressHome();
+ verifySampleActivityNotLaunched();
+ }
+}
diff --git a/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java b/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java
index d273033..dbb7e07 100644
--- a/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java
+++ b/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java
@@ -20,15 +20,15 @@
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingByteOutputReceiver;
import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
diff --git a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
index 3e44c4f..dcb1e5a 100644
--- a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
+++ b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
@@ -19,13 +19,13 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
diff --git a/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java b/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java
index c6df893..efc405f 100644
--- a/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java
+++ b/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java
@@ -20,12 +20,12 @@
import com.android.ddmlib.Log;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
diff --git a/hostsidetests/os/src/android/os/cts/OsHostTests.java b/hostsidetests/os/src/android/os/cts/OsHostTests.java
index 3b2e027..e36b1c7 100644
--- a/hostsidetests/os/src/android/os/cts/OsHostTests.java
+++ b/hostsidetests/os/src/android/os/cts/OsHostTests.java
@@ -26,12 +26,8 @@
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.util.AbiUtils;
-import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
diff --git a/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java b/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java
index ad27051..3a27c78 100644
--- a/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java
+++ b/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java
@@ -19,11 +19,12 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
-import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
@@ -496,7 +497,7 @@
StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
for (Map.Entry<TestIdentifier, TestResult> resultEntry :
result.getTestResults().entrySet()) {
- if (!resultEntry.getValue().getStatus().equals(TestResult.TestStatus.PASSED)) {
+ if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
errorBuilder.append(":\n");
errorBuilder.append(resultEntry.getValue().getStackTrace());
diff --git a/hostsidetests/security/src/android/security/cts/AdbUtils.java b/hostsidetests/security/src/android/security/cts/AdbUtils.java
index a7295b0..f04cc37 100644
--- a/hostsidetests/security/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/security/src/android/security/cts/AdbUtils.java
@@ -186,4 +186,12 @@
}
}
+ /**
+ * Utility function to help check the exit code of a shell command
+ */
+ public static int runCommandGetExitCode(String cmd, ITestDevice device) throws Exception {
+ return Integer.parseInt(
+ AdbUtils.runCommandLine( "(" + cmd + ") > /dev/null 2>&1; echo $?",
+ device).replaceAll("[^0-9]", ""));
+ }
}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index c005749..a75352c 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -719,6 +719,15 @@
}
/**
+ * Tests that all types on /vendor have the vendor_file_type attribute.
+ *
+ * @throws Exception
+ */
+ public void testVendorTypeViolators() throws Exception {
+ assertSepolicyTests("TestVendorTypeViolations", "/sepolicy_tests");
+ }
+
+ /**
* Tests that all domains with entrypoints on /system have the coredomain
* attribute, and that all domains with entrypoints on /vendor do not have the
* coredomain attribute.
diff --git a/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/BaseShortcutManagerHostTest.java b/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/BaseShortcutManagerHostTest.java
index 9b8d98a..c5d4f7f 100644
--- a/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/BaseShortcutManagerHostTest.java
+++ b/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/BaseShortcutManagerHostTest.java
@@ -18,13 +18,13 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
index 1b9d15f..9b758cf 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
@@ -315,6 +315,15 @@
}
}
+ @Test
+ public void testSimpleCpu() {
+ long timestamp = System.currentTimeMillis();
+ for (int i = 0; i < 10000; i ++) {
+ timestamp += i;
+ }
+ Log.i(TAG, "The answer is " + timestamp);
+ }
+
// ------- Helper methods
/** Puts the current thread to sleep. */
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
index 6242699..8561614 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
@@ -16,6 +16,7 @@
package android.cts.statsd.atom;
+import com.android.annotations.Nullable;
import com.android.internal.os.StatsdConfigProto.AtomMatcher;
import com.android.internal.os.StatsdConfigProto.EventMetric;
import com.android.internal.os.StatsdConfigProto.FieldFilter;
@@ -36,7 +37,6 @@
import com.android.os.StatsLog.StatsLogReport;
import com.android.tradefed.log.LogUtil;
import com.google.common.io.Files;
-import com.sun.istack.internal.Nullable;
import java.io.File;
import java.text.SimpleDateFormat;
@@ -501,6 +501,15 @@
}
/**
+ * TODO: Anomaly detection will be moved to general statsd device-side tests.
+ * Pulled atoms also should have a better way of constructing the config.
+ * Remove this config when that happens.
+ */
+ protected StatsdConfig.Builder getPulledAndAnomalyConfig() {
+ return StatsdConfig.newBuilder().setId(CONFIG_ID);
+ }
+
+ /**
* Determines if the device has the given feature.
* Prints a warning if its value differs from requiredAnswer.
*/
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
index cab6aea..2db4438 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
@@ -19,14 +19,14 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingByteOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
index 05d7659..ddb59d4 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
@@ -30,8 +30,6 @@
import com.android.os.AtomsProto.BatterySaverModeStateChanged;
import com.android.os.AtomsProto.ChargingStateChanged;
import com.android.os.AtomsProto.CpuTimePerFreq;
-import com.android.os.AtomsProto.CpuTimePerUid;
-import com.android.os.AtomsProto.CpuTimePerUidFreq;
import com.android.os.AtomsProto.DeviceIdleModeStateChanged;
import com.android.os.AtomsProto.KernelWakelock;
import com.android.os.AtomsProto.PluggedStateChanged;
@@ -55,8 +53,6 @@
// For tests that require incidentd. Keep as true until TESTS_ENABLED is permanently enabled.
private static final boolean INCIDENTD_TESTS_ENABLED = true;
- private static final long TEST_CONFIG_ID = "cts_test_config".hashCode();
-
public void testScreenStateChangedAtom() throws Exception {
if (!TESTS_ENABLED) {return;}
@@ -619,56 +615,6 @@
assertTrue(atom.getCpuTimePerFreq().getTimeMs() > 0);
}
- public void testCpuTimePerUidFreq() throws Exception {
- if (!TESTS_ENABLED) {return;}
- StatsdConfig.Builder config = getPulledAndAnomalyConfig();
- FieldMatcher.Builder dimension = FieldMatcher.newBuilder()
- .setField(Atom.CPU_TIME_PER_UID_FREQ_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder()
- .setField(CpuTimePerUidFreq.UID_FIELD_NUMBER));
- addGaugeAtom(config, Atom.CPU_TIME_PER_UID_FREQ_FIELD_NUMBER, dimension);
-
- turnScreenOff();
-
- uploadConfig(config);
-
- Thread.sleep(WAIT_TIME_LONG);
- turnScreenOn();
- Thread.sleep(WAIT_TIME_LONG);
-
- List<Atom> data = getGaugeMetricDataList();
-
- Atom atom = data.get(0);
- assertTrue(atom.getCpuTimePerUidFreq().getUid() > 0);
- assertTrue(atom.getCpuTimePerUidFreq().getFreqIdx() >= 0);
- assertTrue(atom.getCpuTimePerUidFreq().getTimeMs() > 0);
- }
-
- public void testCpuTimePerUid() throws Exception {
- if (!TESTS_ENABLED) {return;}
- StatsdConfig.Builder config = getPulledAndAnomalyConfig();
- FieldMatcher.Builder dimension = FieldMatcher.newBuilder()
- .setField(Atom.CPU_TIME_PER_UID_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder()
- .setField(CpuTimePerUid.UID_FIELD_NUMBER));
- addGaugeAtom(config, Atom.CPU_TIME_PER_UID_FIELD_NUMBER, dimension);
-
- turnScreenOff();
-
- uploadConfig(config);
-
- Thread.sleep(WAIT_TIME_LONG);
- turnScreenOn();
- Thread.sleep(WAIT_TIME_LONG);
-
- List<Atom> data = getGaugeMetricDataList();
-
- Atom atom = data.get(0);
- assertTrue(atom.getCpuTimePerUid().getUid() > 0);
- assertTrue(atom.getCpuTimePerUid().getUserTimeMs() > 0);
- assertTrue(atom.getCpuTimePerUid().getSysTimeMs() > 0);
- }
-
public void testSubsystemSleepState() throws Exception {
if (!TESTS_ENABLED) {return;}
StatsdConfig.Builder config = getPulledAndAnomalyConfig();
@@ -694,13 +640,4 @@
assertTrue(atom.getSubsystemSleepState().getTimeMs() >= 0);
}
}
-
- /**
- * TODO: Anomaly detection will be moved to general statsd device-side tests.
- * Pulled atoms also should have a better way of constructing the config.
- * Remove this config when that happens.
- */
- protected StatsdConfig.Builder getPulledAndAnomalyConfig() {
- return StatsdConfig.newBuilder().setId(TEST_CONFIG_ID);
- }
}
\ No newline at end of file
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index 196a231..f88f439 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -15,18 +15,20 @@
*/
package android.cts.statsd.atom;
+import com.android.internal.os.StatsdConfigProto.FieldMatcher;
import com.android.internal.os.StatsdConfigProto.StatsdConfig;
import com.android.os.AtomsProto.Atom;
+import com.android.os.AtomsProto.AudioStateChanged;
import com.android.os.AtomsProto.BleScanResultReceived;
import com.android.os.AtomsProto.BleScanStateChanged;
import com.android.os.AtomsProto.BleUnoptimizedScanStateChanged;
import com.android.os.AtomsProto.CameraStateChanged;
+import com.android.os.AtomsProto.CpuTimePerUid;
+import com.android.os.AtomsProto.CpuTimePerUidFreq;
import com.android.os.AtomsProto.FlashlightStateChanged;
-import com.android.os.AtomsProto.AudioStateChanged;
-import com.android.os.AtomsProto.MediaCodecActivityChanged;
import com.android.os.AtomsProto.GpsScanStateChanged;
+import com.android.os.AtomsProto.MediaCodecActivityChanged;
import com.android.os.AtomsProto.SyncStateChanged;
-import com.android.os.AtomsProto.WakeupAlarmOccurred;
import com.android.os.AtomsProto.WifiLockStateChanged;
import com.android.os.AtomsProto.WifiScanStateChanged;
import com.android.os.StatsLog.EventMetricData;
@@ -142,6 +144,80 @@
atom -> atom.getCameraStateChanged().getState().getNumber());
}
+ public void testCpuTimePerUid() throws Exception {
+ if (!TESTS_ENABLED) {return;}
+ StatsdConfig.Builder config = getPulledAndAnomalyConfig();
+ FieldMatcher.Builder dimension = FieldMatcher.newBuilder()
+ .setField(Atom.CPU_TIME_PER_UID_FIELD_NUMBER)
+ .addChild(FieldMatcher.newBuilder()
+ .setField(CpuTimePerUid.UID_FIELD_NUMBER));
+ addGaugeAtom(config, Atom.CPU_TIME_PER_UID_FIELD_NUMBER, dimension);
+
+ uploadConfig(config);
+
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testSimpleCpu");
+
+ turnScreenOff();
+ Thread.sleep(WAIT_TIME_SHORT);
+ turnScreenOn();
+ Thread.sleep(WAIT_TIME_SHORT);
+ turnScreenOff();
+ Thread.sleep(WAIT_TIME_SHORT);
+ turnScreenOn();
+
+ List<Atom> atomList = getGaugeMetricDataList();
+
+ // TODO: We don't have atom matching on gauge yet. Let's refactor this after that feature is
+ // implemented.
+ boolean found = false;
+ int uid = getUid();
+ for (Atom atom : atomList) {
+ if (atom.getCpuTimePerUid().getUid() == uid) {
+ found = true;
+ assertTrue(atom.getCpuTimePerUid().getUserTimeMs() > 0);
+ assertTrue(atom.getCpuTimePerUid().getSysTimeMs() > 0);
+ }
+ }
+ assertTrue("found uid " + uid, found);
+ }
+
+ public void testCpuTimePerUidFreq() throws Exception {
+ if (!TESTS_ENABLED) {return;}
+ StatsdConfig.Builder config = getPulledAndAnomalyConfig();
+ FieldMatcher.Builder dimension = FieldMatcher.newBuilder()
+ .setField(Atom.CPU_TIME_PER_UID_FREQ_FIELD_NUMBER)
+ .addChild(FieldMatcher.newBuilder()
+ .setField(CpuTimePerUidFreq.UID_FIELD_NUMBER));
+ addGaugeAtom(config, Atom.CPU_TIME_PER_UID_FREQ_FIELD_NUMBER, dimension);
+
+ uploadConfig(config);
+
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testSimpleCpu");
+
+ turnScreenOff();
+ Thread.sleep(WAIT_TIME_SHORT);
+ turnScreenOn();
+ Thread.sleep(WAIT_TIME_SHORT);
+ turnScreenOff();
+ Thread.sleep(WAIT_TIME_SHORT);
+ turnScreenOn();
+
+ List<Atom> atomList = getGaugeMetricDataList();
+
+ // TODO: We don't have atom matching on gauge yet. Let's refactor this after that feature is
+ // implemented.
+ boolean found = false;
+ int uid = getUid();
+ for (Atom atom : atomList) {
+ if (atom.getCpuTimePerUidFreq().getUid() == uid) {
+ found = true;
+ assertTrue(atom.getCpuTimePerUidFreq().getFreqIdx() >= 0);
+ assertTrue(atom.getCpuTimePerUidFreq().getTimeMs() > 0);
+ }
+ }
+ assertTrue("found uid " + uid, found);
+ }
+
public void testFlashlightState() throws Exception {
if (!TESTS_ENABLED)
return;
@@ -322,8 +398,19 @@
createAndUploadConfig(atomTag, true); // True: uses attribution.
Thread.sleep(WAIT_TIME_SHORT);
- turnScreenOn();
+ runVideoPlayerApp();
+
+ // 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.getMediaCodecActivityChanged().getState().getNumber());
+ }
+
+ private void runVideoPlayerApp() throws Exception {
+ turnScreenOn();
getDevice().executeShellCommand(
"am start -n com.android.server.cts.device.statsd/.VideoPlayerActivity");
@@ -332,12 +419,5 @@
"am force-stop com.android.server.cts.device.statsd");
Thread.sleep(WAIT_TIME_SHORT);
-
- // 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.getMediaCodecActivityChanged().getState().getNumber());
}
}
diff --git a/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java b/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
index 1b49eca8..03a581d 100644
--- a/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
+++ b/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
@@ -25,7 +25,6 @@
import com.android.compatibility.common.util.Stat;
import com.android.ddmlib.Log;
import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
diff --git a/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java b/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
index 9cfd957..acf9972 100644
--- a/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
+++ b/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
@@ -21,10 +21,10 @@
import com.android.compatibility.common.util.ReportLog;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
diff --git a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
index 47efe85..8a686cc 100644
--- a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
+++ b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
@@ -17,11 +17,11 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
diff --git a/hostsidetests/webkit/src/com/android/cts/webkit/WebViewHostSideStartupTest.java b/hostsidetests/webkit/src/com/android/cts/webkit/WebViewHostSideStartupTest.java
index 5953c5d..6a0d3fa 100644
--- a/hostsidetests/webkit/src/com/android/cts/webkit/WebViewHostSideStartupTest.java
+++ b/hostsidetests/webkit/src/com/android/cts/webkit/WebViewHostSideStartupTest.java
@@ -17,10 +17,10 @@
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestResult;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import java.util.Collection;
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
index 486e4fa..fc71a79 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
@@ -134,6 +134,16 @@
waitForIdle();
}
+ @MediumTest
+ public void testPerformActionScreenshot() throws Exception {
+ // Action should succeed
+ assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
+ AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT));
+ // Ideally should verify that we actually have a screenshot, but it's also possible
+ // for the screenshot to fail
+ waitForIdle();
+ }
+
private void waitForIdle() throws TimeoutException {
getInstrumentation().getUiAutomation().waitForIdle(
TIMEOUT_ACCESSIBILITY_STATE_IDLE,
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
index fe4dd07..d01f5c0 100644
--- a/tests/autofillservice/AndroidManifest.xml
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -36,11 +36,11 @@
</activity>
<activity android:name=".PreFilledLoginActivity" />
<activity android:name=".LoginWithStringsActivity" />
- <activity android:name=".WelcomeActivity"/>
+ <activity android:name=".WelcomeActivity" android:taskAffinity=".WelcomeActivity"/>
<activity android:name=".ViewAttributesTestActivity" />
<activity android:name=".AuthenticationActivity" />
<activity android:name=".ManualAuthenticationActivity" />
- <activity android:name=".CheckoutActivity"/>
+ <activity android:name=".CheckoutActivity" android:taskAffinity=".CheckoutActivity"/>
<activity android:name=".InitializedCheckoutActivity" />
<activity android:name=".DatePickerCalendarActivity" />
<activity android:name=".DatePickerSpinnerActivity" />
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
index 43bc24f..9262808 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
@@ -42,6 +42,9 @@
* Tests that the session finishes when the views and fragments go away
*/
public class AutoFinishSessionTest extends AutoFillServiceTestCase {
+
+ private static final String ID_BUTTON = "button";
+
@Rule
public final AutofillActivityTestRule<FragmentContainerActivity> mActivityRule =
new AutofillActivityTestRule<>(FragmentContainerActivity.class);
@@ -229,7 +232,7 @@
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_GENERIC);
// Remove previously started activity from top
- mUiBot.selectById("android.autofillservice.cts:id/button");
+ mUiBot.selectByRelativeId(ID_BUTTON);
mActivity.waitUntilResumed();
if (removeInForeGroup != null) {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java
index 7b8a42c..6890d7eb 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java
@@ -232,8 +232,10 @@
TAP_YES_ON_SAVE_UI
}
- protected final void startActivity(Class<?> clazz) {
- mContext.startActivity(new Intent(mContext, clazz));
+ protected final void startActivityOnNewTask(Class<?> clazz) {
+ final Intent intent = new Intent(mContext, clazz);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
}
protected RemoteViews newTemplate() {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DisableAutofillTest.java b/tests/autofillservice/src/android/autofillservice/cts/DisableAutofillTest.java
index c41b9f1..34c226a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/DisableAutofillTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/DisableAutofillTest.java
@@ -38,14 +38,16 @@
}
private SimpleSaveActivity startSimpleSaveActivity() throws Exception {
- final Intent intent = new Intent(mContext, SimpleSaveActivity.class);
+ final Intent intent = new Intent(mContext, SimpleSaveActivity.class)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
mUiBot.assertShownByRelativeId(SimpleSaveActivity.ID_LABEL);
return SimpleSaveActivity.getInstance();
}
private PreSimpleSaveActivity startPreSimpleSaveActivity() throws Exception {
- final Intent intent = new Intent(mContext, PreSimpleSaveActivity.class);
+ final Intent intent = new Intent(mContext, PreSimpleSaveActivity.class)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
mUiBot.assertShownByRelativeId(PreSimpleSaveActivity.ID_PRE_LABEL);
return PreSimpleSaveActivity.getInstance();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FieldsClassificationTest.java b/tests/autofillservice/src/android/autofillservice/cts/FieldsClassificationTest.java
index 24bc2a3..bffce78 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/FieldsClassificationTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/FieldsClassificationTest.java
@@ -156,8 +156,7 @@
// Assert results
final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
- assertFillEventForFieldsClassification(events.get(0), fieldId, "myId", 1,
- getDefaultAlgorithm());
+ assertFillEventForFieldsClassification(events.get(0), fieldId, "myId", 1);
}
@Test
@@ -198,17 +197,15 @@
// Assert results
final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
- final String algorithm = getDefaultAlgorithm();
- final String[] algorithms = { algorithm, algorithm };
// Best match is 0.66 (4 of 6), worst is 0.5 (3 of 6)
if (firstMatch) {
assertFillEventForFieldsClassification(events.get(0), new FieldClassificationResult[] {
new FieldClassificationResult(fieldId, new String[] { "1stId", "2ndId" },
- new float[] { 0.66F, 0.5F }, algorithms)});
+ new float[] { 0.66F, 0.5F })});
} else {
assertFillEventForFieldsClassification(events.get(0), new FieldClassificationResult[] {
new FieldClassificationResult(fieldId, new String[] { "2ndId", "1stId" },
- new float[] { 0.66F, 0.5F }, algorithms) });
+ new float[] { 0.66F, 0.5F }) });
}
}
@@ -244,11 +241,10 @@
// Assert results
final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
- final String algorithm = getDefaultAlgorithm();
assertFillEventForFieldsClassification(events.get(0),
new FieldClassificationResult[] {
- new FieldClassificationResult(fieldId1, "myId", 1.0F, algorithm),
- new FieldClassificationResult(fieldId2, "myId", 1.0F, algorithm),
+ new FieldClassificationResult(fieldId1, "myId", 1.0F),
+ new FieldClassificationResult(fieldId2, "myId", 1.0F),
});
}
@@ -292,19 +288,17 @@
mAfm.commit();
// Assert results
- final String algorithm = getDefaultAlgorithm();
- final String[] algorithms = { algorithm, algorithm };
final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
assertFillEventForFieldsClassification(events.get(0),
new FieldClassificationResult[] {
new FieldClassificationResult(fieldId1, new String[] { "myId", "otherId" },
- new float[] { 1.0F, 0.2F }, algorithms),
+ new float[] { 1.0F, 0.2F }),
new FieldClassificationResult(fieldId2, new String[] { "otherId", "myId" },
- new float[] { 1.0F, 0.2F }, algorithms),
+ new float[] { 1.0F, 0.2F }),
new FieldClassificationResult(fieldId3, new String[] { "myId", "otherId" },
- new float[] { 0.6F, 0.2F }, algorithms),
+ new float[] { 0.6F, 0.2F }),
new FieldClassificationResult(fieldId4, new String[] { "otherId", "myId"},
- new float[] { 0.80F, 0.2F }, algorithms)});
+ new float[] { 0.80F, 0.2F })});
}
@Test
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java b/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java
index 85574a0..3acce91 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java
@@ -390,7 +390,7 @@
assertDeprecatedClientState(selectionA, "activity", "A");
// Launch activity B
- mContext.startActivity(new Intent(mContext, CheckoutActivity.class));
+ mActivity.startActivity(new Intent(mActivity, CheckoutActivity.class));
mUiBot.assertShownByRelativeId(ID_CC_NUMBER);
// Trigger autofill on activity B
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 741c029..08265c4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -992,8 +992,6 @@
.that(match.getRemoteId()).isEqualTo(expectedResult.remoteIds[j]);
assertWithMessage("Wrong score at (%s, %s): %s", i, j, match)
.that(match.getScore()).isWithin(expectedResult.scores[j]);
- assertWithMessage("Wrong algorithm at (%s, %s): %s", i, j, match)
- .that(match.getAlgorithm()).isEqualTo(expectedResult.algorithms[j]);
}
}
@@ -1081,11 +1079,10 @@
}
public static void assertFillEventForFieldsClassification(@NonNull FillEventHistory.Event event,
- @NonNull AutofillId fieldId, @NonNull String remoteId, float score,
- @NonNull String algorithm) {
+ @NonNull AutofillId fieldId, @NonNull String remoteId, float score) {
assertFillEvent(event, TYPE_CONTEXT_COMMITTED, null, null, null,
new FieldClassificationResult[] {
- new FieldClassificationResult(fieldId, remoteId, score, algorithm)
+ new FieldClassificationResult(fieldId, remoteId, score)
});
}
@@ -1130,19 +1127,16 @@
public final AutofillId id;
public final String[] remoteIds;
public final float[] scores;
- public final String[] algorithms;
- FieldClassificationResult(@NonNull AutofillId id, @NonNull String remoteId, float score,
- String algorithm) {
- this(id, new String[] { remoteId }, new float[] { score }, new String[] { algorithm });
+ FieldClassificationResult(@NonNull AutofillId id, @NonNull String remoteId, float score) {
+ this(id, new String[] { remoteId }, new float[] { score });
}
FieldClassificationResult(@NonNull AutofillId id, @NonNull String[] remoteIds,
- float[] scores, String[] algorithms) {
+ float[] scores) {
this.id = id;
this.remoteIds = remoteIds;
this.scores = scores;
- this.algorithms = algorithms;
}
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index 7b8fc4a..9d36e64 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -399,9 +399,14 @@
*
* <p>Typically called at the end of a test case, to assert the initial request.
*/
- FillRequest getNextFillRequest() throws InterruptedException {
- final FillRequest request =
- mFillRequests.poll(FILL_TIMEOUT.ms(), TimeUnit.MILLISECONDS);
+ FillRequest getNextFillRequest() {
+ FillRequest request;
+ try {
+ request = mFillRequests.poll(FILL_TIMEOUT.ms(), TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("Interrupted", e);
+ }
if (request == null) {
throw new RetryableException(FILL_TIMEOUT, "onFillRequest() not called");
}
@@ -441,9 +446,14 @@
*
* <p>Typically called at the end of a test case, to assert the initial request.
*/
- SaveRequest getNextSaveRequest() throws InterruptedException {
- final SaveRequest request =
- mSaveRequests.poll(SAVE_TIMEOUT.ms(), TimeUnit.MILLISECONDS);
+ SaveRequest getNextSaveRequest() {
+ SaveRequest request;
+ try {
+ request = mSaveRequests.poll(SAVE_TIMEOUT.ms(), TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("Interrupted", e);
+ }
if (request == null) {
throw new RetryableException(SAVE_TIMEOUT, "onSaveRequest() not called");
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 706fe2b..6069177 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -107,6 +107,10 @@
public final AutofillActivityTestRule<LoginActivity> mActivityRule =
new AutofillActivityTestRule<LoginActivity>(LoginActivity.class);
+ @Rule
+ public final AutofillActivityTestRule<CheckoutActivity> mCheckoutActivityRule =
+ new AutofillActivityTestRule<CheckoutActivity>(CheckoutActivity.class, false);
+
private LoginActivity mActivity;
@Before
@@ -1429,10 +1433,9 @@
}
private void startCheckoutActivityAsNewTask() throws Exception {
- final Intent intent = new Intent(mContext, CheckoutActivity.class);
- intent.setFlags(
- Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
- mContext.startActivity(intent);
+ final Intent intent = new Intent(mContext, CheckoutActivity.class)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
+ mCheckoutActivityRule.launchActivity(intent);
mUiBot.assertShownByRelativeId(CheckoutActivity.ID_ADDRESS);
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/OutOfProcessLoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/OutOfProcessLoginActivity.java
index d37cca6..8fecba0c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/OutOfProcessLoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/OutOfProcessLoginActivity.java
@@ -39,9 +39,7 @@
setContentView(R.layout.login_activity);
- findViewById(R.id.login).setOnClickListener((v) -> {
- finish();
- });
+ findViewById(R.id.login).setOnClickListener((v) -> finish());
}
@Override
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PreSimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PreSimpleSaveActivityTest.java
index 97a5cc5..28a9974 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PreSimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PreSimpleSaveActivityTest.java
@@ -54,7 +54,7 @@
final Intent intent = new Intent(mContext, PreSimpleSaveActivity.class);
if (remainOnRecents) {
intent.setFlags(
- Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+ Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS | Intent.FLAG_ACTIVITY_NEW_TASK);
}
mActivity = mActivityRule.launchActivity(intent);
}
@@ -255,12 +255,12 @@
mUiBot.assertShownByRelativeId(ID_INPUT);
break;
case LAUNCH_PREVIOUS_ACTIVITY:
- startActivity(PreSimpleSaveActivity.class);
+ startActivityOnNewTask(PreSimpleSaveActivity.class);
mUiBot.assertShownByRelativeId(ID_INPUT);
break;
case LAUNCH_NEW_ACTIVITY:
// Launch a 3rd activity...
- startActivity(LoginActivity.class);
+ startActivityOnNewTask(LoginActivity.class);
mUiBot.assertShownByRelativeId(ID_USERNAME_CONTAINER);
// ...then go back
mUiBot.pressBack();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
index 0df508b..9b8fd68 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
@@ -51,20 +51,17 @@
* Test the lifecycle of a autofill session
*/
public class SessionLifecycleTest extends AutoFillServiceTestCase {
- private static final String USERNAME_FULL_ID = "android.autofillservice.cts:id/" + ID_USERNAME;
- private static final String PASSWORD_FULL_ID = "android.autofillservice.cts:id/" + ID_PASSWORD;
- private static final String LOGIN_FULL_ID = "android.autofillservice.cts:id/" + ID_LOGIN;
- private static final String BUTTON_FULL_ID = "android.autofillservice.cts:id/button";
- private static final String CANCEL_FULL_ID = "android.autofillservice.cts:id/cancel";
+ private static final String ID_BUTTON = "button";
+ private static final String ID_CANCEL = "cancel";
/**
* Delay for activity start/stop.
- * TODO figure out a better way to wait without using sleep().
*/
+ // TODO: figure out a better way to wait without using sleep().
private static final long WAIT_ACTIVITY_MS = 1000;
private static final Timeout SESSION_LIFECYCLE_TIMEOUT = new Timeout(
- "SESSION_LIFECYCLE_TIMEOUT", 500, 2F, 5000);
+ "SESSION_LIFECYCLE_TIMEOUT", 2000, 2F, 5000);
/**
* Runs an {@code assertion}, retrying until {@code timeout} is reached.
@@ -115,8 +112,8 @@
}
private void startAndWaitExternalActivity() throws Exception {
- Intent outOfProcessAcvitityStartIntent = new Intent(getContext(),
- OutOfProcessLoginActivity.class);
+ final Intent outOfProcessAcvitityStartIntent = new Intent(getContext(),
+ OutOfProcessLoginActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getStartedMarker(getContext()).delete();
getContext().startActivity(outOfProcessAcvitityStartIntent);
eventually("getStartedMarker()", () -> {
@@ -125,6 +122,8 @@
getStartedMarker(getContext()).delete();
// Even if we wait the activity started, UiObject still fails. Have to wait a little bit.
SystemClock.sleep(WAIT_ACTIVITY_MS);
+
+ mUiBot.assertShownByRelativeId(ID_USERNAME);
}
@Test
@@ -159,7 +158,7 @@
sReplier.addResponse(response);
// Trigger autofill on username
- mUiBot.selectById(USERNAME_FULL_ID);
+ mUiBot.selectByRelativeId(ID_USERNAME);
// Wait for fill request to be processed
sReplier.getNextFillRequest();
@@ -170,9 +169,10 @@
// Change orientation which triggers a destroy -> create in the app as the activity
// cannot deal with such situations
mUiBot.setScreenOrientation(LANDSCAPE);
+ mUiBot.setScreenOrientation(PORTRAIT);
// Wait context and Views being recreated in rotation
- mUiBot.assertShownById(USERNAME_FULL_ID);
+ mUiBot.assertShownByRelativeId(ID_USERNAME);
// Delete stopped marker
getStoppedMarker(getContext()).delete();
@@ -188,7 +188,7 @@
mUiBot.setScreenOrientation(PORTRAIT);
// Approve authentication
- mUiBot.selectById(BUTTON_FULL_ID);
+ mUiBot.selectByRelativeId(ID_BUTTON);
// Wait for dataset to be shown
mUiBot.assertDatasets("dataset");
@@ -201,24 +201,24 @@
mUiBot.selectDataset("dataset");
// Check the results.
- eventually("getTextById(" + USERNAME_FULL_ID + ")", () -> {
- return mUiBot.getTextById(USERNAME_FULL_ID).equals("autofilled username");
+ eventually("getTextById(" + ID_USERNAME + ")", () -> {
+ return mUiBot.getTextByRelativeId(ID_USERNAME).equals("autofilled username");
});
// Set password
- mUiBot.setTextById(PASSWORD_FULL_ID, "new password");
+ mUiBot.setTextByRelativeId(ID_PASSWORD, "new password");
// Login
- mUiBot.selectById(LOGIN_FULL_ID);
+ mUiBot.selectByRelativeId(ID_LOGIN);
// Wait for save UI to be shown
- mUiBot.assertShownById("android:id/autofill_save_yes");
+ mUiBot.assertSaveShowing(SAVE_DATA_TYPE_PASSWORD);
// Change orientation to make sure save UI can handle this
mUiBot.setScreenOrientation(PORTRAIT);
// Tap "Save".
- mUiBot.selectById("android:id/autofill_save_yes");
+ mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
// Get save request
InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();
@@ -237,6 +237,7 @@
final String extraValue = saveRequest.data.getString("numbers");
assertWithMessage("extras not passed on save").that(extraValue).isEqualTo("4815162342");
+ // TODO: refactor or remove call below
eventually("assert dangling sessions", () -> {
return Helper.listSessions().isEmpty();
});
@@ -262,7 +263,7 @@
sReplier.addResponse(response);
// Trigger autofill on username
- mUiBot.selectById(USERNAME_FULL_ID);
+ mUiBot.selectByRelativeId(ID_USERNAME);
// Wait for fill request to be processed
sReplier.getNextFillRequest();
@@ -302,7 +303,7 @@
sReplier.addResponse(response);
// Trigger autofill on username
- mUiBot.selectById(USERNAME_FULL_ID);
+ mUiBot.selectByRelativeId(ID_USERNAME);
// Wait for fill request to be processed
sReplier.getNextFillRequest();
@@ -346,7 +347,7 @@
sReplier.addResponse(response);
// Trigger autofill on username
- mUiBot.selectById(USERNAME_FULL_ID);
+ mUiBot.selectByRelativeId(ID_USERNAME);
// Wait for fill request to be processed
sReplier.getNextFillRequest();
@@ -374,7 +375,7 @@
killOfProcessLoginActivityProcess();
// Trigger autofill on username in nested activity
- mUiBot.selectById(USERNAME_FULL_ID);
+ mUiBot.selectByRelativeId(ID_USERNAME);
// Wait for fill request to be processed
sReplier.getNextFillRequest();
@@ -383,7 +384,7 @@
mUiBot.assertDatasets("dataset2");
// Tap "Cancel".
- mUiBot.selectById(CANCEL_FULL_ID);
+ mUiBot.selectByRelativeId(ID_CANCEL);
// Dataset should still be shown
mUiBot.assertDatasets("dataset1");
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
index cc95917..d1fc581 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
@@ -59,6 +59,10 @@
public final AutofillActivityTestRule<SimpleSaveActivity> mActivityRule =
new AutofillActivityTestRule<SimpleSaveActivity>(SimpleSaveActivity.class, false);
+ @Rule
+ public final AutofillActivityTestRule<WelcomeActivity> mWelcomeActivityRule =
+ new AutofillActivityTestRule<WelcomeActivity>(WelcomeActivity.class, false);
+
private SimpleSaveActivity mActivity;
private void startActivity() {
@@ -69,7 +73,7 @@
final Intent intent = new Intent(mContext, SimpleSaveActivity.class);
if (remainOnRecents) {
intent.setFlags(
- Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+ Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS | Intent.FLAG_ACTIVITY_NEW_TASK);
}
mActivity = mActivityRule.launchActivity(intent);
}
@@ -78,7 +82,7 @@
final Intent intent = new Intent(mContext.getApplicationContext(),
SimpleSaveActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
- mContext.startActivity(intent);
+ mActivity.startActivity(intent);
}
@Test
@@ -499,10 +503,9 @@
}
private void startWelcomeActivityOnNewTask() throws Exception {
- final Intent intent = new Intent(mContext, WelcomeActivity.class);
- intent.setFlags(
- Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
- mContext.startActivity(intent);
+ final Intent intent = new Intent(mContext, WelcomeActivity.class)
+ .setFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS | Intent.FLAG_ACTIVITY_NEW_TASK);
+ mWelcomeActivityRule.launchActivity(intent);
WelcomeActivity.assertShowingDefaultMessage(mUiBot);
}
@@ -702,11 +705,11 @@
mUiBot.switchAppsUsingRecents();
break;
case LAUNCH_PREVIOUS_ACTIVITY:
- startActivity(SimpleSaveActivity.class);
+ startActivityOnNewTask(SimpleSaveActivity.class);
break;
case LAUNCH_NEW_ACTIVITY:
// Launch a 3rd activity...
- startActivity(LoginActivity.class);
+ startActivityOnNewTask(LoginActivity.class);
mUiBot.assertShownByRelativeId(ID_USERNAME_CONTAINER);
// ...then go back
mUiBot.pressBack();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java b/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
index d0ec21a..fd175c2 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
@@ -44,7 +44,7 @@
/**
* Timeout for expected save requests.
*/
- static final Timeout SAVE_TIMEOUT = new Timeout("SAVE_TIMEOUT", 1000, 2F, 5000);
+ static final Timeout SAVE_TIMEOUT = new Timeout("SAVE_TIMEOUT", 2000, 3F, 5000);
/**
* Time to wait if a UI change is not expected
@@ -54,12 +54,12 @@
/**
* Timeout for UI operations. Typically used by {@link UiBot}.
*/
- static final Timeout UI_TIMEOUT = new Timeout("UI_TIMEOUT", 500, 2F, 2000);
+ static final Timeout UI_TIMEOUT = new Timeout("UI_TIMEOUT", 1000, 2F, 2000);
/**
* Timeout for webview operations. Typically used by {@link UiBot}.
*/
- static final Timeout WEBVIEW_TIMEOUT = new Timeout("UI_TIMEOUT", 8000, 2F, 16000);
+ static final Timeout WEBVIEW_TIMEOUT = new Timeout("WEBVIEW_TIMEOUT", 8000, 2F, 16000);
/**
* Timeout for showing the autofill dataset picker UI.
@@ -70,7 +70,7 @@
* <p>Typically used by {@link UiBot}.
*/
static final Timeout UI_DATASET_PICKER_TIMEOUT =
- new Timeout("UI_DATASET_PICKER_TIMEOUT", 500, 2F, 4000);
+ new Timeout("UI_DATASET_PICKER_TIMEOUT", 2000, 2F, 4000);
/**
* Timeout (in milliseconds) for an activity to be brought out to top.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index d4f77ca..6646665 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -251,11 +251,9 @@
/**
* Selects a view by id.
*/
- void selectById(String id) throws Exception {
- Log.v(TAG, "selectById(): " + id);
-
- final UiObject2 view = waitForObject(By.res(id), mDefaultTimeout);
- view.click();
+ void selectByRelativeId(String id) throws Exception {
+ Log.v(TAG, "selectByRelativeId(): " + id);
+ waitForObject(By.res(mPackageName, id)).click();
}
/**
@@ -312,9 +310,8 @@
/**
* Gets the text set on a view.
*/
- String getTextById(String id) throws Exception {
- final UiObject2 obj = waitForObject(By.res(id));
- return obj.getText();
+ String getTextByRelativeId(String id) throws Exception {
+ return waitForObject(By.res(mPackageName, id)).getText();
}
/**
@@ -327,9 +324,8 @@
/**
* Sets a new text on a view.
*/
- void setTextById(String id, String newText) throws Exception {
- UiObject2 view = waitForObject(By.res(id));
- view.setText(newText);
+ void setTextByRelativeId(String id, String newText) throws Exception {
+ waitForObject(By.res(mPackageName, id)).setText(newText);
}
/**
diff --git a/tests/camera/Android.mk b/tests/camera/Android.mk
index 4160f84..d440a9d 100644
--- a/tests/camera/Android.mk
+++ b/tests/camera/Android.mk
@@ -45,7 +45,8 @@
ctstestrunner \
mockito-target-minus-junit4 \
android-ex-camera2 \
- CtsCameraUtils
+ CtsCameraUtils \
+ truth-prebuilt
LOCAL_JNI_SHARED_LIBRARIES := \
libctscamera2_jni \
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 05a642c..1a27fd9 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -1080,9 +1080,15 @@
SurfaceTexture output2 = new SurfaceTexture(2);
Surface output2Surface = new Surface(output2);
- List<Surface> outputSurfaces = new ArrayList<>(
- Arrays.asList(output1Surface, output2Surface));
- mCamera.createCaptureSession(outputSurfaces, mSessionMockListener, mHandler);
+ ArrayList<OutputConfiguration> outConfigs = new ArrayList<OutputConfiguration> ();
+ outConfigs.add(new OutputConfiguration(output1Surface));
+ outConfigs.add(new OutputConfiguration(output2Surface));
+ SessionConfiguration sessionConfig = new SessionConfiguration(
+ SessionConfiguration.SESSION_REGULAR, outConfigs, mSessionMockListener,
+ mHandler);
+ CaptureRequest.Builder r = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ sessionConfig.setSessionParameters(r.build());
+ mCamera.createCaptureSession(sessionConfig);
mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
@@ -1123,7 +1129,7 @@
// Use output1
- CaptureRequest.Builder r = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ r = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
r.addTarget(output1Surface);
mSession.capture(r.build(), null, null);
@@ -1143,7 +1149,7 @@
mSessionMockListener = spy(new BlockingSessionCallback());
- outputSurfaces = new ArrayList<>(
+ ArrayList<Surface> outputSurfaces = new ArrayList<Surface>(
Arrays.asList(output1Surface, output3Surface));
mCamera.createCaptureSession(outputSurfaces, mSessionMockListener, mHandler);
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
index 3857b93..f84d520 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -426,6 +426,10 @@
result.get(CaptureResult.NOISE_REDUCTION_MODE));
} else if (key.equals(CaptureResult.REQUEST_PIPELINE_DEPTH)) {
+ } else if (key.equals(CaptureResult.STATISTICS_OIS_DATA_MODE)) {
+ mCollector.expectEquals(msg,
+ requestBuilder.get(CaptureRequest.STATISTICS_OIS_DATA_MODE),
+ result.get(CaptureResult.STATISTICS_OIS_DATA_MODE));
} else {
// Only do non-null check for the rest of keys.
mCollector.expectKeyValueNotNull(failMsg, result, key);
@@ -539,6 +543,13 @@
waiverKeys.add(CaptureResult.CONTROL_AF_SCENE_CHANGE);
}
+ if (!mStaticInfo.isOisDataModeSupported()) {
+ waiverKeys.add(CaptureResult.STATISTICS_OIS_DATA_MODE);
+ waiverKeys.add(CaptureResult.STATISTICS_OIS_TIMESTAMPS);
+ waiverKeys.add(CaptureResult.STATISTICS_OIS_X_SHIFTS);
+ waiverKeys.add(CaptureResult.STATISTICS_OIS_Y_SHIFTS);
+ }
+
if (mStaticInfo.isHardwareLevelAtLeastFull()) {
return waiverKeys;
}
@@ -818,6 +829,10 @@
resultKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
+ resultKeys.add(CaptureResult.STATISTICS_OIS_DATA_MODE);
+ resultKeys.add(CaptureResult.STATISTICS_OIS_TIMESTAMPS);
+ resultKeys.add(CaptureResult.STATISTICS_OIS_X_SHIFTS);
+ resultKeys.add(CaptureResult.STATISTICS_OIS_Y_SHIFTS);
resultKeys.add(CaptureResult.TONEMAP_CURVE);
resultKeys.add(CaptureResult.TONEMAP_MODE);
resultKeys.add(CaptureResult.TONEMAP_GAMMA);
diff --git a/tests/camera/src/android/hardware/camera2/cts/IdleUidTest.java b/tests/camera/src/android/hardware/camera2/cts/IdleUidTest.java
new file mode 100644
index 0000000..dd7053b
--- /dev/null
+++ b/tests/camera/src/android/hardware/camera2/cts/IdleUidTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.cts;
+
+import static org.junit.Assert.fail;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.io.IOException;
+
+/**
+ * Test for validating behaviors related to idle UIDs. Idle UIDs cannot
+ * access camera. If the UID has a camera handle and becomes idle it would
+ * get an error callback losing the camera handle. Similarly if the UID is
+ * already idle it cannot obtain a camera handle.
+ */
+@RunWith(AndroidJUnit4.class)
+public final class IdleUidTest {
+ private static final long CAMERA_OPERATION_TIMEOUT_MILLIS = 5000; // 5 sec
+
+ private static final HandlerThread sCallbackThread = new HandlerThread("Callback thread");
+
+ @BeforeClass
+ public static void startHandlerThread() {
+ sCallbackThread.start();
+ }
+
+ @AfterClass
+ public static void stopHandlerThread() {
+ sCallbackThread.quit();
+ }
+
+ /**
+ * Tests that a UID has access to the camera only in active state.
+ */
+ @Test
+ public void testCameraAccessForIdleUid() throws Exception {
+ final CameraManager cameraManager = InstrumentationRegistry.getTargetContext()
+ .getSystemService(CameraManager.class);
+ for (String cameraId : cameraManager.getCameraIdList()) {
+ testCameraAccessForIdleUidByCamera(cameraManager, cameraId,
+ new Handler(sCallbackThread.getLooper()));
+ }
+ }
+
+ /**
+ * Tests that a UID loses access to the camera if it becomes inactive.
+ */
+ @Test
+ public void testCameraAccessBecomingInactiveUid() throws Exception {
+ final CameraManager cameraManager = InstrumentationRegistry.getTargetContext()
+ .getSystemService(CameraManager.class);
+ for (String cameraId : cameraManager.getCameraIdList()) {
+ testCameraAccessBecomingInactiveUidByCamera(cameraManager, cameraId,
+ new Handler(sCallbackThread.getLooper()));
+ }
+
+ }
+
+ private void testCameraAccessForIdleUidByCamera(CameraManager cameraManager,
+ String cameraId, Handler handler) throws Exception {
+ // Can access camera from an active UID.
+ assertCameraAccess(cameraManager, cameraId, true, handler);
+
+ // Make our UID idle
+ makeMyPackageIdle();
+ try {
+ // Can not access camera from an idle UID.
+ assertCameraAccess(cameraManager, cameraId, false, handler);
+ } finally {
+ // Restore our UID as active
+ makeMyPackageActive();
+ }
+
+ // Can access camera from an active UID.
+ assertCameraAccess(cameraManager, cameraId, true, handler);
+ }
+
+ private static void assertCameraAccess(CameraManager cameraManager,
+ String cameraId, boolean hasAccess, Handler handler) {
+ // Mock the callback used to observe camera state.
+ final CameraDevice.StateCallback callback = mock(CameraDevice.StateCallback.class);
+
+ // Open the camera
+ try {
+ cameraManager.openCamera(cameraId, callback, handler);
+ } catch (CameraAccessException e) {
+ if (hasAccess) {
+ fail("Unexpected exception" + e);
+ } else {
+ assertThat(e.getReason()).isSameAs(CameraAccessException.CAMERA_DISABLED);
+ }
+ }
+
+ // Verify access
+ final ArgumentCaptor<CameraDevice> captor = ArgumentCaptor.forClass(CameraDevice.class);
+ try {
+ if (hasAccess) {
+ // The camera should open fine as we are in the foreground
+ verify(callback, timeout(CAMERA_OPERATION_TIMEOUT_MILLIS)
+ .times(1)).onOpened(captor.capture());
+ verifyNoMoreInteractions(callback);
+ } else {
+ // The camera should not open as we are in the background
+ verify(callback, timeout(CAMERA_OPERATION_TIMEOUT_MILLIS)
+ .times(1)).onError(captor.capture(),
+ eq(CameraDevice.StateCallback.ERROR_CAMERA_DISABLED));
+ verifyNoMoreInteractions(callback);
+ }
+ } finally {
+ final CameraDevice cameraDevice = captor.getValue();
+ assertThat(cameraDevice).isNotNull();
+ cameraDevice.close();
+ }
+ }
+
+ private void testCameraAccessBecomingInactiveUidByCamera(CameraManager cameraManager,
+ String cameraId, Handler handler) throws Exception {
+ // Mock the callback used to observe camera state.
+ final CameraDevice.StateCallback callback = mock(CameraDevice.StateCallback.class);
+
+ // Open the camera
+ try {
+ cameraManager.openCamera(cameraId, callback, handler);
+ } catch (CameraAccessException e) {
+ fail("Unexpected exception" + e);
+ }
+
+ // Verify access
+ final ArgumentCaptor<CameraDevice> captor = ArgumentCaptor.forClass(CameraDevice.class);
+ try {
+ // The camera should open fine as we are in the foreground
+ verify(callback, timeout(CAMERA_OPERATION_TIMEOUT_MILLIS)
+ .times(1)).onOpened(captor.capture());
+ verifyNoMoreInteractions(callback);
+
+ // Ready for a new verification
+ reset(callback);
+
+ // Now we are moving in the background
+ makeMyPackageIdle();
+
+ // The camera should be closed if the UID became idle
+ verify(callback, timeout(CAMERA_OPERATION_TIMEOUT_MILLIS)
+ .times(1)).onError(captor.capture(),
+ eq(CameraDevice.StateCallback.ERROR_CAMERA_DISABLED));
+ verifyNoMoreInteractions(callback);
+ } finally {
+ // Restore to active state
+ makeMyPackageActive();
+
+ final CameraDevice cameraDevice = captor.getValue();
+ assertThat(cameraDevice).isNotNull();
+ cameraDevice.close();
+ }
+ }
+
+ private static void makeMyPackageActive() throws IOException {
+ final String command = "cmd media.camera reset-uid-state "
+ + InstrumentationRegistry.getTargetContext().getPackageName();
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
+ }
+
+ private static void makeMyPackageIdle() throws IOException {
+ final String command = "cmd media.camera set-uid-state "
+ + InstrumentationRegistry.getTargetContext().getPackageName() + " idle";
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
+ }
+}
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index 6f5ccfb..3a1eb33 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -1097,6 +1097,14 @@
updatePreviewSurfaceWithVideo(videoSz, profile.videoFrameRate);
prepareVideoSnapshot(videoSnapshotRequestBuilder, imageListener);
+ Range<Integer> fpsRange = Range.create(profile.videoFrameRate,
+ profile.videoFrameRate);
+ videoSnapshotRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
+ fpsRange);
+ if (mStaticInfo.isVideoStabilizationSupported()) {
+ videoSnapshotRequestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
+ CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON);
+ }
CaptureRequest request = videoSnapshotRequestBuilder.build();
// Start recording
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index c5483f9..7abb84d 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -1008,6 +1008,83 @@
}
}
+ public void testOisDataMode() throws Exception {
+ final int NUM_FRAMES_VERIFIED = 3;
+
+ for (String id : mCameraIds) {
+ Log.i(TAG, String.format("Testing Camera %s for OIS mode", id));
+
+ StaticMetadata staticInfo =
+ new StaticMetadata(mCameraManager.getCameraCharacteristics(id));
+ if (!staticInfo.isOisDataModeSupported()) {
+ continue;
+ }
+
+ openDevice(id);
+
+ try {
+ SurfaceTexture preview = new SurfaceTexture(/*random int*/ 1);
+ Surface previewSurface = new Surface(preview);
+
+ CaptureRequest.Builder previewRequest = preparePreviewTestSession(preview);
+ SimpleCaptureCallback previewListener = new CameraTestUtils.SimpleCaptureCallback();
+
+ int[] availableOisDataModes = staticInfo.getCharacteristics().get(
+ CameraCharacteristics.STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES);
+
+ // Test each OIS data mode
+ for (int oisMode : availableOisDataModes) {
+ previewRequest.set(CaptureRequest.STATISTICS_OIS_DATA_MODE, oisMode);
+
+ int sequenceId = mCameraSession.setRepeatingRequest(previewRequest.build(),
+ previewListener, mHandler);
+
+ // Check OIS data in each mode.
+ for (int i = 0; i < NUM_FRAMES_VERIFIED; i++) {
+ TotalCaptureResult result =
+ previewListener.getTotalCaptureResult(CAPTURE_TIMEOUT);
+
+ long[] oisTimestamps = result.get(CaptureResult.STATISTICS_OIS_TIMESTAMPS);
+ float[] oisXShifts = result.get(CaptureResult.STATISTICS_OIS_X_SHIFTS);
+ float[] oisYShifts = result.get(CaptureResult.STATISTICS_OIS_Y_SHIFTS);
+
+ if (oisMode == CameraCharacteristics.STATISTICS_OIS_DATA_MODE_OFF) {
+ mCollector.expectKeyValueEquals(result,
+ CaptureResult.STATISTICS_OIS_DATA_MODE,
+ CaptureResult.STATISTICS_OIS_DATA_MODE_OFF);
+ mCollector.expectTrue("OIS timestamps reported in OIS_DATA_MODE_OFF",
+ oisTimestamps == null || oisTimestamps.length == 0);
+ mCollector.expectTrue("OIS x shifts reported in OIS_DATA_MODE_OFF",
+ oisXShifts == null || oisXShifts.length == 0);
+ mCollector.expectTrue("OIS y shifts reported in OIS_DATA_MODE_OFF",
+ oisYShifts == null || oisYShifts.length == 0);
+
+ } else if (oisMode == CameraCharacteristics.STATISTICS_OIS_DATA_MODE_ON) {
+ mCollector.expectKeyValueEquals(result,
+ CaptureResult.STATISTICS_OIS_DATA_MODE,
+ CaptureResult.STATISTICS_OIS_DATA_MODE_ON);
+ mCollector.expectTrue("OIS timestamps not reported in OIS_DATA_MODE_ON",
+ oisTimestamps != null && oisTimestamps.length != 0);
+ mCollector.expectTrue(
+ "Number of x shifts doesn't match number of OIS timetamps.",
+ oisXShifts != null && oisXShifts.length == oisTimestamps.length);
+ mCollector.expectTrue(
+ "Number of y shifts doesn't match number of OIS timetamps.",
+ oisYShifts != null && oisYShifts.length == oisTimestamps.length);
+ } else {
+ mCollector.addMessage(String.format("Invalid OIS mode: %d", oisMode));
+ }
+ }
+
+ mCameraSession.stopRepeating();
+ previewListener.getCaptureSequenceLastFrameNumber(sequenceId, CAPTURE_TIMEOUT);
+ previewListener.drain();
+ }
+ } finally {
+ closeDevice(id);
+ }
+ }
+ }
private CaptureRequest.Builder preparePreviewTestSession(SurfaceTexture preview)
throws Exception {
diff --git a/tests/camera/src/android/hardware/cts/CameraTest.java b/tests/camera/src/android/hardware/cts/CameraTest.java
index f5fff8e..b9655bc 100644
--- a/tests/camera/src/android/hardware/cts/CameraTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraTest.java
@@ -101,7 +101,6 @@
private static final String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
private static final String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
-
private PreviewCallback mPreviewCallback = new PreviewCallback();
private TestShutterCallback mShutterCallback = new TestShutterCallback();
private RawPictureCallback mRawPictureCallback = new RawPictureCallback();
@@ -3212,5 +3211,4 @@
}
}
}
-
}
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index 3c551f8..5921dda 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -2265,6 +2265,26 @@
}
/**
+ * Check if OIS data mode is supported.
+ */
+ public boolean isOisDataModeSupported() {
+ int[] availableOisDataModes = mCharacteristics.get(
+ CameraCharacteristics.STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES);
+
+ if (availableOisDataModes == null) {
+ return false;
+ }
+
+ for (int mode : availableOisDataModes) {
+ if (mode == CameraMetadata.STATISTICS_OIS_DATA_MODE_ON) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Get the value in index for a fixed-size array from a given key.
*
* <p>If the camera device is incorrectly reporting values, log a warning and return
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
index 51c5f0d..d73509d 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
@@ -613,6 +613,7 @@
/**
* Test that move-task works when moving between displays.
*/
+ @FlakyTest(bugId = 72231060)
@Presubmit
@Test
public void testMoveTaskBetweenDisplays() throws Exception {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
index c9b8b17..89ff760 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
@@ -35,7 +35,9 @@
import android.graphics.Point;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.FlakyTest;
import android.support.test.uiautomator.UiDevice;
import android.util.Log;
@@ -50,7 +52,8 @@
* Build: mmma -j32 cts/tests/framework/base
* Run: cts/tests/framework/base/activitymanager/util/run-test CtsWindowManagerDeviceTestCases android.server.wm.CrossAppDragAndDropTests
*/
-//@Presubmit b/68038788
+@Presubmit
+@FlakyTest(bugId = 65739235)
public class CrossAppDragAndDropTests {
private static final String TAG = "CrossAppDragAndDrop";
diff --git a/tests/sensor/src/android/hardware/cts/SensorTest.java b/tests/sensor/src/android/hardware/cts/SensorTest.java
index 11ead36..1751a8b 100644
--- a/tests/sensor/src/android/hardware/cts/SensorTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorTest.java
@@ -16,6 +16,9 @@
package android.hardware.cts;
+import android.hardware.cts.helpers.sensorverification.ContinuousEventSanitizedVerification;
+import android.support.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.SystemUtil;
import junit.framework.Assert;
import android.content.Context;
@@ -45,9 +48,9 @@
import android.platform.test.annotations.Presubmit;
import android.util.Log;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -307,14 +310,60 @@
assertFalse(result);
}
- // TODO: remove when parametized tests are supported and EventTimestampSynchronization
+ /**
+ * Verifies that if the UID is idle the continuous events are being reported
+ * but sanitized - all events are the same as the first one delivered except
+ * for their timestamps. From the point of view of an idle app these events are
+ * being properly generated but the sensor reading does not change - privacy.
+ */
+ // TODO: remove when parametrized tests are supported and EventTimestampSynchronization
+ public void testSanitizedContinuousEventsUidIdle() throws Exception {
+ ArrayList<Throwable> errorsFound = new ArrayList<>();
+ for (Sensor sensor : mAndroidSensorList) {
+ // If the UID is active no sanitization should be performed
+ verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
+ 5 /* duration */, TimeUnit.SECONDS, "continuous event",
+ false /* sanitized */, errorsFound);
+ verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
+ 5 /* duration */, TimeUnit.SECONDS, "continuous event",
+ false /* sanitized */, errorsFound);
+
+ // If the UID is idle sanitization should be performed
+ makeMyPackageIdle();
+ try {
+ verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
+ 5 /* duration */, TimeUnit.SECONDS, "continuous event",
+ true /* sanitized */, errorsFound);
+ verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
+ 5 /* duration */, TimeUnit.SECONDS, "continuous event",
+ true /* sanitized */, errorsFound);
+ } finally {
+ makeMyPackageActive();
+ }
+
+ // If the UID is active no sanitization should be performed
+ verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
+ 5 /* duration */, TimeUnit.SECONDS, "continuous event",
+ false /* sanitized */, errorsFound);
+ verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
+ 5 /* duration */, TimeUnit.SECONDS, "continuous event",
+ false /* sanitized */, errorsFound);
+ }
+ assertOnErrors(errorsFound);
+ }
+
+ // TODO: remove when parametrized tests are supported and EventTimestampSynchronization
// verification is added to default verifications
public void testSensorTimeStamps() throws Exception {
ArrayList<Throwable> errorsFound = new ArrayList<>();
for (Sensor sensor : mAndroidSensorList) {
// test both continuous and batching mode sensors
- verifyLongActivation(sensor, 0 /* maxReportLatencyUs */, errorsFound);
- verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10), errorsFound);
+ verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
+ 20 /* duration */, TimeUnit.SECONDS, "timestamp", false
+ /* sanitized */, errorsFound);
+ verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
+ 20 /* duration */, TimeUnit.SECONDS, "timestamp",
+ false /* sanitized */, errorsFound);
}
assertOnErrors(errorsFound);
}
@@ -324,7 +373,24 @@
SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
ArrayList<Throwable> errorsFound = new ArrayList<>();
for (Sensor sensor : mAndroidSensorList) {
- verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound);
+ verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound,
+ false /* flushWhileIdle */);
+ }
+ assertOnErrors(errorsFound);
+ }
+
+ /**
+ * Verifies that if the UID is idle flush events are reported. Since
+ * these events have no payload with private data they are working as
+ * for a non-idle UID.
+ */
+ // TODO: remove when parametized tests are supported and EventTimestampSynchronization
+ public void testBatchAndFlushUidIdle() throws Exception {
+ SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
+ ArrayList<Throwable> errorsFound = new ArrayList<>();
+ for (Sensor sensor : mAndroidSensorList) {
+ verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound,
+ true /* flushWhileIdle */);
}
assertOnErrors(errorsFound);
}
@@ -426,7 +492,8 @@
shouldEmulateSensorUnderLoad(),
SensorManager.SENSOR_DELAY_FASTEST,
maxReportLatencyUs);
- FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */);
+ FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */,
+ false /* flushWhileIdle */);
parallelSensorOperation.add(new TestSensorOperation(environment, executor));
builder.append(sensor.getName()).append(", ");
}
@@ -479,11 +546,15 @@
/**
* Verifies that a continuous sensor produces events that have timestamps synchronized with
- * {@link SystemClock#elapsedRealtimeNanos()}.
+ * {@link SystemClock#elapsedRealtimeNanos()} and that the events are sanitized/non-sanitized.
*/
private void verifyLongActivation(
Sensor sensor,
int maxReportLatencyUs,
+ long duration,
+ TimeUnit durationTimeUnit,
+ String testType,
+ boolean sanitized,
ArrayList<Throwable> errorsFound) throws InterruptedException {
if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
return;
@@ -496,14 +567,20 @@
shouldEmulateSensorUnderLoad(),
SensorManager.SENSOR_DELAY_FASTEST,
maxReportLatencyUs);
- TestSensorOperation operation =
- TestSensorOperation.createOperation(environment, 20, TimeUnit.SECONDS);
- operation.addVerification(EventGapVerification.getDefault(environment));
- operation.addVerification(EventOrderingVerification.getDefault(environment));
- operation.addVerification(
- EventTimestampSynchronizationVerification.getDefault(environment));
-
- Log.i(TAG, "Running timestamp test on: " + sensor.getName());
+ TestSensorOperation operation = TestSensorOperation.createOperation(
+ environment, duration, durationTimeUnit);
+ if (sanitized) {
+ final long verificationDelayNano = TimeUnit.NANOSECONDS.convert(
+ maxReportLatencyUs, TimeUnit.MICROSECONDS) * 2;
+ operation.addVerification(ContinuousEventSanitizedVerification
+ .getDefault(environment, verificationDelayNano));
+ } else {
+ operation.addVerification(EventGapVerification.getDefault(environment));
+ operation.addVerification(EventOrderingVerification.getDefault(environment));
+ operation.addVerification(EventTimestampSynchronizationVerification
+ .getDefault(environment));
+ }
+ Log.i(TAG, "Running " + testType + " test on: " + sensor.getName());
operation.execute(getCurrentTestNode());
} catch (InterruptedException e) {
// propagate so the test can stop
@@ -522,7 +599,8 @@
private void verifyRegisterListenerCallFlush(
Sensor sensor,
Handler handler,
- ArrayList<Throwable> errorsFound)
+ ArrayList<Throwable> errorsFound,
+ boolean flushWhileIdle)
throws InterruptedException {
if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
return;
@@ -535,7 +613,8 @@
shouldEmulateSensorUnderLoad(),
SensorManager.SENSOR_DELAY_FASTEST,
(int) TimeUnit.SECONDS.toMicros(10));
- FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */);
+ FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */,
+ flushWhileIdle);
TestSensorOperation operation = new TestSensorOperation(environment, executor, handler);
Log.i(TAG, "Running flush test on: " + sensor.getName());
@@ -559,6 +638,18 @@
}
}
+ private static void makeMyPackageActive() throws IOException {
+ final String command = "cmd sensorservice reset-uid-state "
+ + InstrumentationRegistry.getTargetContext().getPackageName();
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
+ }
+
+ private void makeMyPackageIdle() throws IOException {
+ final String command = "cmd sensorservice set-uid-state "
+ + InstrumentationRegistry.getTargetContext().getPackageName() + " idle";
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
+ }
+
/**
* A delegate that drives the execution of Batch/Flush tests.
* It performs several operations in order:
@@ -572,10 +663,13 @@
private class FlushExecutor implements TestSensorOperation.Executor {
private final TestSensorEnvironment mEnvironment;
private final int mEventCount;
+ private final boolean mFlushWhileIdle;
- public FlushExecutor(TestSensorEnvironment environment, int eventCount) {
+ public FlushExecutor(TestSensorEnvironment environment, int eventCount,
+ boolean flushWhileIdle) {
mEnvironment = environment;
mEventCount = eventCount;
+ mFlushWhileIdle = flushWhileIdle;
}
/**
@@ -588,17 +682,23 @@
*/
@Override
public void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
- throws InterruptedException {
+ throws Exception {
int sensorReportingMode = mEnvironment.getSensor().getReportingMode();
try {
CountDownLatch eventLatch = sensorManager.registerListener(listener, mEventCount);
if (sensorReportingMode == Sensor.REPORTING_MODE_CONTINUOUS) {
listener.waitForEvents(eventLatch, mEventCount, true);
}
+ if (mFlushWhileIdle) {
+ makeMyPackageIdle();
+ }
CountDownLatch flushLatch = sensorManager.requestFlush();
listener.waitForFlushComplete(flushLatch, true);
} finally {
sensorManager.unregisterListener();
+ if (mFlushWhileIdle) {
+ makeMyPackageActive();
+ }
}
}
}
diff --git a/tests/sensor/src/android/hardware/cts/helpers/SensorStats.java b/tests/sensor/src/android/hardware/cts/helpers/SensorStats.java
index 3892366..1ccf524 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/SensorStats.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/SensorStats.java
@@ -56,6 +56,7 @@
"event_time_wrong_clocksource_positions";
public static final String EVENT_COUNT_KEY = "event_count";
public static final String EVENT_COUNT_EXPECTED_KEY = "event_count_expected";
+ public static final String EVENT_NOT_SANITIZED_KEY = "event_not_sanitized";
public static final String EVENT_LOG_FILENAME = "event_log_filename";
public static final String WRONG_SENSOR_KEY = "wrong_sensor_observed";
public static final String FREQUENCY_KEY = "frequency";
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
index 436a7cf..7c9be9f 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
@@ -76,7 +76,7 @@
* {@inheritDoc}
*/
@Override
- public void execute(ISensorTestNode parent) throws InterruptedException {
+ public void execute(ISensorTestNode parent) throws Exception {
// Start alarm
IntentFilter intentFilter = new IntentFilter(ACTION);
BroadcastReceiver receiver = new BroadcastReceiver() {
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
index 8c52222..741dd63 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
@@ -48,7 +48,7 @@
* {@inheritDoc}
*/
@Override
- public void execute(ISensorTestNode parent) throws InterruptedException {
+ public void execute(ISensorTestNode parent) throws Exception {
SensorCtsHelper.sleep(mDelay, mTimeUnit);
mOperation.execute(asTestNode(parent));
}
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
index 5b333b8..8acfa7e 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
@@ -49,7 +49,7 @@
* one iterations, it is thrown and all subsequent iterations will not run.
*/
@Override
- public void execute(ISensorTestNode parent) throws InterruptedException {
+ public void execute(ISensorTestNode parent) throws Exception {
ISensorTestNode currentNode = asTestNode(parent);
for(int i = 0; i < mIterations; ++i) {
SensorOperation operation = mOperation.clone();
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperation.java b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperation.java
index 66604d3..fc12382 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperation.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperation.java
@@ -62,7 +62,7 @@
* - cleaning up on {@link InterruptedException}
* - propagating the exception down the stack
*/
- public abstract void execute(ISensorTestNode parent) throws InterruptedException;
+ public abstract void execute(ISensorTestNode parent) throws Exception;
/**
* @return The cloned {@link SensorOperation}.
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
index abfa692..568b015 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
@@ -44,7 +44,7 @@
* Test that the {@link FakeSensorOperation} functions correctly. Other tests in this class
* rely on this operation.
*/
- public void testFakeSensorOperation() throws InterruptedException {
+ public void testFakeSensorOperation() throws Exception {
final int opDurationMs = 100;
SensorOperation op = new FakeSensorOperation(opDurationMs, TimeUnit.MILLISECONDS);
@@ -69,7 +69,7 @@
/**
* Test that the {@link DelaySensorOperation} functions correctly.
*/
- public void testDelaySensorOperation() throws InterruptedException {
+ public void testDelaySensorOperation() throws Exception {
final int opDurationMs = 500;
final int subOpDurationMs = 100;
@@ -86,7 +86,7 @@
/**
* Test that the {@link ParallelSensorOperation} functions correctly.
*/
- public void testParallelSensorOperation() throws InterruptedException {
+ public void testParallelSensorOperation() throws Exception {
final int subOpCount = 100;
final int subOpDurationMs = 500;
@@ -127,7 +127,7 @@
* Test that the {@link ParallelSensorOperation} functions correctly if there is a failure in
* a child operation.
*/
- public void testParallelSensorOperation_fail() throws InterruptedException {
+ public void testParallelSensorOperation_fail() throws Exception {
final int subOpCount = 100;
ParallelSensorOperation op = new ParallelSensorOperation();
@@ -167,7 +167,7 @@
* Test that the {@link ParallelSensorOperation} functions correctly if a child exceeds the
* timeout.
*/
- public void testParallelSensorOperation_timeout() throws InterruptedException {
+ public void testParallelSensorOperation_timeout() throws Exception {
final int subOpCount = 100;
ParallelSensorOperation op = new ParallelSensorOperation(1, TimeUnit.SECONDS);
@@ -201,7 +201,7 @@
/**
* Test that the {@link RepeatingSensorOperation} functions correctly.
*/
- public void testRepeatingSensorOperation() throws InterruptedException {
+ public void testRepeatingSensorOperation() throws Exception {
final int iterations = 10;
final int subOpDurationMs = 100;
@@ -228,7 +228,7 @@
* Test that the {@link RepeatingSensorOperation} functions correctly if there is a failure in
* a child operation.
*/
- public void testRepeatingSensorOperation_fail() throws InterruptedException {
+ public void testRepeatingSensorOperation_fail() throws Exception {
final int iterations = 100;
final int failCount = 75;
@@ -286,7 +286,7 @@
/**
* Test that the {@link SequentialSensorOperation} functions correctly.
*/
- public void testSequentialSensorOperation() throws InterruptedException {
+ public void testSequentialSensorOperation() throws Exception {
final int subOpCount = 10;
final int subOpDurationMs = 100;
@@ -317,7 +317,7 @@
* Test that the {@link SequentialSensorOperation} functions correctly if there is a failure in
* a child operation.
*/
- public void testSequentialSensorOperation_fail() throws InterruptedException {
+ public void testSequentialSensorOperation_fail() throws Exception {
final int subOpCount = 100;
final int failCount = 75;
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
index 847c0f2..73ee68c 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
@@ -48,7 +48,7 @@
* in one operation, it is thrown and all subsequent operations will not run.
*/
@Override
- public void execute(ISensorTestNode parent) throws InterruptedException {
+ public void execute(ISensorTestNode parent) throws Exception {
ISensorTestNode currentNode = asTestNode(parent);
for (int i = 0; i < mOperations.size(); i++) {
SensorOperation operation = mOperations.get(i);
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
index ad2084d..878bb42 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
@@ -76,7 +76,7 @@
*/
public interface Executor {
void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
- throws InterruptedException;
+ throws Exception;
}
/**
@@ -124,7 +124,7 @@
* Collect the specified number of events from the sensor and run all enabled verifications.
*/
@Override
- public void execute(ISensorTestNode parent) throws InterruptedException {
+ public void execute(ISensorTestNode parent) throws Exception {
getStats().addValue("sensor_name", mEnvironment.getSensor().getName());
TestSensorEventListener listener = new TestSensorEventListener(mEnvironment, mHandler);
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
index 9f03f31..0ae5289 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
@@ -60,7 +60,7 @@
* {@inheritDoc}
*/
@Override
- public void execute(ISensorTestNode parent) throws InterruptedException {
+ public void execute(ISensorTestNode parent) throws Exception {
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock(mWakeLockFlags, TAG);
wakeLock.acquire();
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/ContinuousEventSanitizedVerification.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/ContinuousEventSanitizedVerification.java
new file mode 100644
index 0000000..4469c97
--- /dev/null
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/ContinuousEventSanitizedVerification.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+import android.os.SystemClock;
+import android.util.Log;
+import junit.framework.Assert;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A {@link ISensorVerification} which verifies that continuous events are sanitized
+ * when the UID is idle. In this case no events should be fired. We expect to receive
+ * events and stop receiving since some events may have been cached already.
+ */
+public class ContinuousEventSanitizedVerification extends AbstractSensorVerification {
+ public static final String PASSED_KEY = "continuous_event_sanitization_passed";
+
+ // Number of indices to print in assert message before truncating
+ private static final int TRUNCATE_MESSAGE_LENGTH = 3;
+
+ private final List<TestSensorEvent> mNonSanitizedEvents = new LinkedList<>();
+
+ private final long mVerificationStartTimeNano;
+
+ /**
+ * Get the default {@link ContinuousEventSanitizedVerification} for a sensor.
+ *
+ * @param environment the test environment
+ * @param verificationDelayNano After what delay to expect no events (nanoseconds).
+ * @return the verification or null if the verification does not apply to the sensor.
+ */
+ public static ContinuousEventSanitizedVerification getDefault(
+ TestSensorEnvironment environment, long verificationDelayNano) {
+ final int reportingMode = environment.getSensor().getReportingMode();
+ if (reportingMode == Sensor.REPORTING_MODE_CONTINUOUS) {
+ return new ContinuousEventSanitizedVerification(
+ SystemClock.elapsedRealtimeNanos() + verificationDelayNano);
+ }
+ return null;
+ }
+
+ private ContinuousEventSanitizedVerification(long verificationDelayNano) {
+ mVerificationStartTimeNano = verificationDelayNano;
+ }
+
+ /**
+ * Verify that the events are sanitized. Add {@value #PASSED_KEY} and
+ * {@value SensorStats#EVENT_NOT_SANITIZED_KEY} keys to {@link SensorStats}.
+ *
+ * @throws AssertionError if the verification failed.
+ */
+ @Override
+ public void verify(TestSensorEnvironment environment, SensorStats stats) {
+ final int count = mNonSanitizedEvents.size();
+ if (count > 0) {
+ stats.addValue(PASSED_KEY, false);
+ stats.addValue(SensorStats.EVENT_NOT_SANITIZED_KEY, mNonSanitizedEvents);
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append(mNonSanitizedEvents).append(" non-sanitized events: ");
+
+ for (int i = 0; i < Math.min(count, TRUNCATE_MESSAGE_LENGTH); i++) {
+ final TestSensorEvent event = mNonSanitizedEvents.get(i);
+ sb.append(String.format("sensor:%s", event.sensor.getName()));
+ sb.append(String.format("accuracy:%d", event.accuracy));
+ sb.append(String.format("values:%s", Arrays.toString(event.values)));
+
+ if (count > TRUNCATE_MESSAGE_LENGTH) {
+ sb.append(count - TRUNCATE_MESSAGE_LENGTH).append(" more");
+ } else {
+ // Delete the trailing "; "
+ sb.delete(sb.length() - 2, sb.length());
+ break;
+ }
+ }
+
+ Assert.fail(sb.toString());
+ } else {
+ stats.addValue(PASSED_KEY, true);
+ }
+ }
+
+ @Override
+ public ContinuousEventSanitizedVerification clone() {
+ return new ContinuousEventSanitizedVerification(mVerificationStartTimeNano);
+ }
+
+ @Override
+ protected void addSensorEventInternal(TestSensorEvent event) {
+ Log.i("OPALA", "event time: " + event.timestamp + " verif start:" + mVerificationStartTimeNano);
+ if (event.receivedTimestamp > mVerificationStartTimeNano) {
+ mNonSanitizedEvents.add(event);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
index b475cea..636a6b8 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
@@ -62,20 +62,36 @@
private static final int NETWORK_TAG = 0xf00d;
private static final long THRESHOLD_BYTES = 2 * 1024 * 1024; // 2 MB
- private interface NetworkInterfaceToTest {
- int getNetworkType();
- int getTransportType();
- boolean getMetered();
- void setMetered(boolean metered);
- String getSystemFeature();
- String getErrorMessage();
+ private abstract class NetworkInterfaceToTest {
+ private boolean mMetered;
+ private boolean mIsDefault;
+
+ abstract int getNetworkType();
+ abstract int getTransportType();
+
+ public boolean getMetered() {
+ return mMetered;
+ }
+
+ public void setMetered(boolean metered) {
+ this.mMetered = metered;
+ }
+
+ public boolean getIsDefault() {
+ return mIsDefault;
+ }
+
+ public void setIsDefault(boolean isDefault) {
+ mIsDefault = isDefault;
+ }
+
+ abstract String getSystemFeature();
+ abstract String getErrorMessage();
}
- private static final NetworkInterfaceToTest[] sNetworkInterfacesToTest =
+ private final NetworkInterfaceToTest[] mNetworkInterfacesToTest =
new NetworkInterfaceToTest[] {
new NetworkInterfaceToTest() {
- private boolean metered = false;
-
@Override
public int getNetworkType() {
return ConnectivityManager.TYPE_WIFI;
@@ -87,16 +103,6 @@
}
@Override
- public boolean getMetered() {
- return metered;
- }
-
- @Override
- public void setMetered(boolean metered) {
- this.metered = metered;
- }
-
- @Override
public String getSystemFeature() {
return PackageManager.FEATURE_WIFI;
}
@@ -107,7 +113,6 @@
}
},
new NetworkInterfaceToTest() {
- private boolean metered = false;
@Override
public int getNetworkType() {
return ConnectivityManager.TYPE_MOBILE;
@@ -119,15 +124,6 @@
}
@Override
- public boolean getMetered() {
- return metered;
- }
-
- @Override
- public void setMetered(boolean metered) {
- this.metered = metered;
- }
- @Override
public String getSystemFeature() {
return PackageManager.FEATURE_TELEPHONY;
}
@@ -266,18 +262,21 @@
private URL mUrl;
public boolean success;
public boolean metered;
+ public boolean isDefault;
NetworkCallback(long tolerance, URL url) {
mTolerance = tolerance;
mUrl = url;
success = false;
metered = false;
+ isDefault = false;
}
@Override
public void onAvailable(Network network) {
try {
mStartTime = System.currentTimeMillis() - mTolerance;
+ isDefault = network.equals(mCm.getActiveNetwork());
exerciseRemoteHost(network, mUrl);
mEndTime = System.currentTimeMillis() + mTolerance;
success = true;
@@ -296,13 +295,13 @@
private boolean shouldTestThisNetworkType(int networkTypeIndex, final long tolerance)
throws Exception {
boolean hasFeature = mPm.hasSystemFeature(
- sNetworkInterfacesToTest[networkTypeIndex].getSystemFeature());
+ mNetworkInterfacesToTest[networkTypeIndex].getSystemFeature());
if (!hasFeature) {
return false;
}
NetworkCallback callback = new NetworkCallback(tolerance, new URL(CHECK_CONNECTIVITY_URL));
mCm.requestNetwork(new NetworkRequest.Builder()
- .addTransportType(sNetworkInterfacesToTest[networkTypeIndex].getTransportType())
+ .addTransportType(mNetworkInterfacesToTest[networkTypeIndex].getTransportType())
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build(), callback);
synchronized(this) {
@@ -312,21 +311,22 @@
}
}
if (callback.success) {
- sNetworkInterfacesToTest[networkTypeIndex].setMetered(callback.metered);
+ mNetworkInterfacesToTest[networkTypeIndex].setMetered(callback.metered);
+ mNetworkInterfacesToTest[networkTypeIndex].setIsDefault(callback.isDefault);
return true;
}
// This will always fail at this point as we know 'hasFeature' is true.
- assertFalse (sNetworkInterfacesToTest[networkTypeIndex].getSystemFeature() +
+ assertFalse (mNetworkInterfacesToTest[networkTypeIndex].getSystemFeature() +
" is a reported system feature, " +
"however no corresponding connected network interface was found or the attempt " +
"to connect has timed out (timeout = " + TIMEOUT_MILLIS + "ms)." +
- sNetworkInterfacesToTest[networkTypeIndex].getErrorMessage(), hasFeature);
+ mNetworkInterfacesToTest[networkTypeIndex].getErrorMessage(), hasFeature);
return false;
}
private String getSubscriberId(int networkIndex) {
- int networkType = sNetworkInterfacesToTest[networkIndex].getNetworkType();
+ int networkType = mNetworkInterfacesToTest[networkIndex].getNetworkType();
if (ConnectivityManager.TYPE_MOBILE == networkType) {
TelephonyManager tm = (TelephonyManager) getInstrumentation().getContext()
.getSystemService(Context.TELEPHONY_SERVICE);
@@ -336,7 +336,7 @@
}
public void testDeviceSummary() throws Exception {
- for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+ for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
if (!shouldTestThisNetworkType(i, MINUTE/2)) {
continue;
}
@@ -344,7 +344,7 @@
NetworkStats.Bucket bucket = null;
try {
bucket = mNsm.querySummaryForDevice(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime);
} catch (RemoteException | SecurityException e) {
fail("testDeviceSummary fails with exception: " + e.toString());
@@ -354,10 +354,11 @@
assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
assertEquals(bucket.getUid(), NetworkStats.Bucket.UID_ALL);
assertEquals(bucket.getMetered(), NetworkStats.Bucket.METERED_ALL);
+ assertEquals(bucket.getDefaultNetwork(), NetworkStats.Bucket.DEFAULT_NETWORK_ALL);
setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
try {
bucket = mNsm.querySummaryForDevice(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime);
fail("negative testDeviceSummary fails: no exception thrown.");
} catch (RemoteException e) {
@@ -369,7 +370,7 @@
}
public void testUserSummary() throws Exception {
- for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+ for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
if (!shouldTestThisNetworkType(i, MINUTE/2)) {
continue;
}
@@ -377,7 +378,7 @@
NetworkStats.Bucket bucket = null;
try {
bucket = mNsm.querySummaryForUser(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime);
} catch (RemoteException | SecurityException e) {
fail("testUserSummary fails with exception: " + e.toString());
@@ -387,10 +388,11 @@
assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
assertEquals(bucket.getUid(), NetworkStats.Bucket.UID_ALL);
assertEquals(bucket.getMetered(), NetworkStats.Bucket.METERED_ALL);
+ assertEquals(bucket.getDefaultNetwork(), NetworkStats.Bucket.DEFAULT_NETWORK_ALL);
setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
try {
bucket = mNsm.querySummaryForUser(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime);
fail("negative testUserSummary fails: no exception thrown.");
} catch (RemoteException e) {
@@ -402,7 +404,7 @@
}
public void testAppSummary() throws Exception {
- for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+ for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
if (!shouldTestThisNetworkType(i, MINUTE/2)) {
continue;
}
@@ -410,7 +412,7 @@
NetworkStats result = null;
try {
result = mNsm.querySummary(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime);
assertTrue(result != null);
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
@@ -419,8 +421,12 @@
long totalTxBytes = 0;
long totalRxBytes = 0;
boolean hasCorrectMetering = false;
- int expectedMetering = sNetworkInterfacesToTest[i].getMetered() ?
+ boolean hasCorrectIsDefault = false;
+ int expectedMetering = mNetworkInterfacesToTest[i].getMetered() ?
NetworkStats.Bucket.METERED_YES : NetworkStats.Bucket.METERED_NO;
+ int expectedIsDefault = mNetworkInterfacesToTest[i].getIsDefault() ?
+ NetworkStats.Bucket.DEFAULT_NETWORK_YES :
+ NetworkStats.Bucket.DEFAULT_NETWORK_NO;
while (result.hasNextBucket()) {
assertTrue(result.getNextBucket(bucket));
assertTimestamps(bucket);
@@ -430,11 +436,14 @@
totalRxPackets += bucket.getRxPackets();
totalTxBytes += bucket.getTxBytes();
totalRxBytes += bucket.getRxBytes();
+ hasCorrectIsDefault |= bucket.getDefaultNetwork() == expectedIsDefault;
}
}
assertFalse(result.getNextBucket(bucket));
assertTrue("Incorrect metering for NetworkType: " +
- sNetworkInterfacesToTest[i].getNetworkType(), hasCorrectMetering);
+ mNetworkInterfacesToTest[i].getNetworkType(), hasCorrectMetering);
+ assertTrue("Incorrect isDefault for NetworkType: " +
+ mNetworkInterfacesToTest[i].getNetworkType(), hasCorrectIsDefault);
assertTrue("No Rx bytes usage for uid " + Process.myUid(), totalRxBytes > 0);
assertTrue("No Rx packets usage for uid " + Process.myUid(), totalRxPackets > 0);
assertTrue("No Tx bytes usage for uid " + Process.myUid(), totalTxBytes > 0);
@@ -449,7 +458,7 @@
setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
try {
result = mNsm.querySummary(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime);
fail("negative testAppSummary fails: no exception thrown.");
} catch (RemoteException e) {
@@ -461,7 +470,7 @@
}
public void testAppDetails() throws Exception {
- for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+ for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
// Relatively large tolerance to accommodate for history bucket size.
if (!shouldTestThisNetworkType(i, MINUTE * 120)) {
continue;
@@ -470,7 +479,7 @@
NetworkStats result = null;
try {
result = mNsm.queryDetails(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime);
assertTrue(result != null);
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
@@ -483,6 +492,8 @@
assertTimestamps(bucket);
assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
assertEquals(bucket.getMetered(), NetworkStats.Bucket.METERED_ALL);
+ assertEquals(bucket.getDefaultNetwork(),
+ NetworkStats.Bucket.DEFAULT_NETWORK_ALL);
if (bucket.getUid() == Process.myUid()) {
totalTxPackets += bucket.getTxPackets();
totalRxPackets += bucket.getRxPackets();
@@ -505,7 +516,7 @@
setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
try {
result = mNsm.queryDetails(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime);
fail("negative testAppDetails fails: no exception thrown.");
} catch (RemoteException e) {
@@ -517,7 +528,7 @@
}
public void testUidDetails() throws Exception {
- for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+ for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
// Relatively large tolerance to accommodate for history bucket size.
if (!shouldTestThisNetworkType(i, MINUTE * 120)) {
continue;
@@ -526,7 +537,7 @@
NetworkStats result = null;
try {
result = mNsm.queryDetailsForUid(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime, Process.myUid());
assertTrue(result != null);
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
@@ -539,6 +550,8 @@
assertTimestamps(bucket);
assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
assertEquals(bucket.getMetered(), NetworkStats.Bucket.METERED_ALL);
+ assertEquals(bucket.getDefaultNetwork(),
+ NetworkStats.Bucket.DEFAULT_NETWORK_ALL);
assertEquals(bucket.getUid(), Process.myUid());
totalTxPackets += bucket.getTxPackets();
totalRxPackets += bucket.getRxPackets();
@@ -560,7 +573,7 @@
setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
try {
result = mNsm.queryDetailsForUid(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime, Process.myUid());
fail("negative testUidDetails fails: no exception thrown.");
} catch (RemoteException e) {
@@ -572,7 +585,7 @@
}
public void testTagDetails() throws Exception {
- for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+ for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
// Relatively large tolerance to accommodate for history bucket size.
if (!shouldTestThisNetworkType(i, MINUTE * 120)) {
continue;
@@ -581,7 +594,7 @@
NetworkStats result = null;
try {
result = mNsm.queryDetailsForUidTag(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime, Process.myUid(), NETWORK_TAG);
assertTrue(result != null);
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
@@ -594,6 +607,8 @@
assertTimestamps(bucket);
assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
assertEquals(bucket.getMetered(), NetworkStats.Bucket.METERED_ALL);
+ assertEquals(bucket.getDefaultNetwork(),
+ NetworkStats.Bucket.DEFAULT_NETWORK_ALL);
assertEquals(bucket.getUid(), Process.myUid());
if (bucket.getTag() == NETWORK_TAG) {
totalTxPackets += bucket.getTxPackets();
@@ -620,7 +635,7 @@
setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
try {
result = mNsm.queryDetailsForUidTag(
- sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
mStartTime, mEndTime, Process.myUid(), NETWORK_TAG);
fail("negative testUidDetails fails: no exception thrown.");
} catch (SecurityException e) {
@@ -630,7 +645,7 @@
}
public void testCallback() throws Exception {
- for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+ for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
// Relatively large tolerance to accommodate for history bucket size.
if (!shouldTestThisNetworkType(i, MINUTE/2)) {
continue;
@@ -641,7 +656,7 @@
HandlerThread thread = new HandlerThread("callback-thread");
thread.start();
Handler handler = new Handler(thread.getLooper());
- mNsm.registerUsageCallback(sNetworkInterfacesToTest[i].getNetworkType(),
+ mNsm.registerUsageCallback(mNetworkInterfacesToTest[i].getNetworkType(),
getSubscriberId(i), THRESHOLD_BYTES, usageCallback, handler);
// TODO: Force traffic and check whether the callback is invoked.
diff --git a/tests/tests/bionic/Android.build.copy.libs.mk b/tests/tests/bionic/Android.build.copy.libs.mk
index 7db4b1d..2944911 100644
--- a/tests/tests/bionic/Android.build.copy.libs.mk
+++ b/tests/tests/bionic/Android.build.copy.libs.mk
@@ -84,6 +84,7 @@
libtest_relo_check_dt_needed_order_1.so \
libtest_relo_check_dt_needed_order_2.so \
libtest_simple.so \
+ libtest_thread_local_dtor.so \
libtest_two_parents_child.so \
libtest_two_parents_parent1.so \
libtest_two_parents_parent2.so \
diff --git a/tests/tests/carrierapi/AndroidManifest.xml b/tests/tests/carrierapi/AndroidManifest.xml
index 0338d99..95f55f4 100644
--- a/tests/tests/carrierapi/AndroidManifest.xml
+++ b/tests/tests/carrierapi/AndroidManifest.xml
@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.carrierapi.cts">
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
new file mode 100644
index 0000000..63f8347
--- /dev/null
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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.carrierapi.cts;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.NetworkScan;
+import android.telephony.NetworkScanRequest;
+import android.telephony.RadioAccessSpecifier;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.TelephonyManager;
+import android.telephony.TelephonyScanManager;
+import android.util.Log;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Build, install and run the tests by running the commands below:
+ * make cts -j64
+ * cts-tradefed run cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.NetworkScanApiTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class NetworkScanApiTest {
+ private TelephonyManager mTelephonyManager;
+ private static final String TAG = "NetworkScanApiTest";
+ private int mNetworkScanStatus;
+ private static final int EVENT_NETWORK_SCAN_START = 100;
+ private static final int EVENT_NETWORK_SCAN_RESULTS = 200;
+ private static final int EVENT_NETWORK_SCAN_ERROR = 300;
+ private static final int EVENT_NETWORK_SCAN_COMPLETED = 400;
+ private List<CellInfo> mScanResults = null;
+ private NetworkScanHandlerThread mTestHandlerThread;
+ private Handler mHandler;
+ private NetworkScanRequest mNetworkScanRequest;
+ private NetworkScanCallbackImpl mNetworkScanCallback;
+ private static final int MAX_INIT_WAIT_MS = 60000; // 60 seconds
+ private Object mLock = new Object();
+ private boolean mReady;
+ private int mErrorCode;
+
+ @Before
+ public void setUp() throws Exception {
+ mTelephonyManager = (TelephonyManager)
+ InstrumentationRegistry.getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ mTestHandlerThread = new NetworkScanHandlerThread(TAG);
+ mTestHandlerThread.start();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mTestHandlerThread.quit();
+ }
+
+ private void waitUntilReady() {
+ synchronized (mLock) {
+ try {
+ mLock.wait(MAX_INIT_WAIT_MS);
+ } catch (InterruptedException ie) {
+ }
+
+ if (!mReady) {
+ fail("NetworkScanApiTest failed to initialize");
+ }
+ }
+ }
+
+ private void setReady(boolean ready) {
+ synchronized (mLock) {
+ mReady = ready;
+ mLock.notifyAll();
+ }
+ }
+
+ private class NetworkScanHandlerThread extends HandlerThread {
+
+ public NetworkScanHandlerThread(String name) {
+ super(name);
+ }
+
+ @Override
+ public void onLooperPrepared() {
+ /* create a custom handler for the Handler Thread */
+ mHandler = new Handler(mTestHandlerThread.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_NETWORK_SCAN_START:
+ Log.d(TAG, "request network scan");
+ mTelephonyManager.requestNetworkScan(
+ mNetworkScanRequest, mNetworkScanCallback);
+ break;
+ default:
+ Log.d(TAG, "Unknown Event " + msg.what);
+ }
+ }
+ };
+ }
+ }
+
+ private class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback {
+ @Override
+ public void onResults(List<CellInfo> results) {
+ Log.d(TAG, "onResults: " + results.toString());
+ mNetworkScanStatus = EVENT_NETWORK_SCAN_RESULTS;
+ mScanResults = results;
+ }
+
+ @Override
+ public void onComplete() {
+ Log.d(TAG, "onComplete");
+ mNetworkScanStatus = EVENT_NETWORK_SCAN_COMPLETED;
+ setReady(true);
+ }
+
+ @Override
+ public void onError(int error) {
+ Log.d(TAG, "onError: " + String.valueOf(error));
+ mNetworkScanStatus = EVENT_NETWORK_SCAN_ERROR;
+ mErrorCode = error;
+ setReady(true);
+ }
+ }
+
+ private RadioAccessSpecifier getRadioAccessSpecifier(CellInfo cellInfo) {
+ RadioAccessSpecifier ras;
+ if (cellInfo instanceof CellInfoLte) {
+ int ranLte = AccessNetworkConstants.AccessNetworkType.EUTRAN;
+ int[] lteChannels = {((CellInfoLte) cellInfo).getCellIdentity().getEarfcn()};
+ ras = new RadioAccessSpecifier(ranLte, null /* bands */, lteChannels);
+ Log.d(TAG, "CellInfoLte channel: " + lteChannels[0]);
+ } else if (cellInfo instanceof CellInfoWcdma) {
+ int ranLte = AccessNetworkConstants.AccessNetworkType.UTRAN;
+ int[] wcdmaChannels = {((CellInfoWcdma) cellInfo).getCellIdentity().getUarfcn()};
+ ras = new RadioAccessSpecifier(ranLte, null /* bands */, wcdmaChannels);
+ Log.d(TAG, "CellInfoWcdma channel: " + wcdmaChannels[0]);
+ } else if (cellInfo instanceof CellInfoGsm) {
+ int ranGsm = AccessNetworkConstants.AccessNetworkType.GERAN;
+ int[] gsmChannels = {((CellInfoGsm) cellInfo).getCellIdentity().getArfcn()};
+ ras = new RadioAccessSpecifier(ranGsm, null /* bands */, gsmChannels);
+ Log.d(TAG, "CellInfoGsm channel: " + gsmChannels[0]);
+ } else {
+ ras = null;
+ }
+ return ras;
+ }
+
+ /**
+ * Tests that the device properly requests a network scan.
+ */
+ @Test
+ public void testRequestNetworkScan() throws InterruptedException {
+ if (!mTelephonyManager.hasCarrierPrivileges()) {
+ fail("This test requires a SIM card with carrier privilege rule on it.");
+ }
+
+ // Make sure that there should be at least one entry.
+ List<CellInfo> allCellInfo = mTelephonyManager.getAllCellInfo();
+ Log.d(TAG, "allCellInfo: " + allCellInfo.toString());
+ if (allCellInfo == null) {
+ fail("TelephonyManager.getAllCellInfo() returned NULL!");
+ }
+ if (allCellInfo.size() == 0) {
+ fail("TelephonyManager.getAllCellInfo() returned zero-length list!");
+ }
+
+ // Construct a NetworkScanRequest
+ List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>();
+ for (int i = 0; i < allCellInfo.size(); i++) {
+ RadioAccessSpecifier ras = getRadioAccessSpecifier(allCellInfo.get(i));
+ if (ras != null) {
+ radioAccessSpecifier.add(ras);
+ }
+ }
+ if (radioAccessSpecifier.size() == 0) {
+ RadioAccessSpecifier gsm = new RadioAccessSpecifier(
+ AccessNetworkConstants.AccessNetworkType.GERAN,
+ null /* bands */,
+ null /* channels */);
+ RadioAccessSpecifier lte = new RadioAccessSpecifier(
+ AccessNetworkConstants.AccessNetworkType.EUTRAN,
+ null /* bands */,
+ null /* channels */);
+ RadioAccessSpecifier wcdma = new RadioAccessSpecifier(
+ AccessNetworkConstants.AccessNetworkType.UTRAN,
+ null /* bands */,
+ null /* channels */);
+ radioAccessSpecifier.add(gsm);
+ radioAccessSpecifier.add(lte);
+ radioAccessSpecifier.add(wcdma);
+ }
+ RadioAccessSpecifier[] radioAccessSpecifierArray =
+ new RadioAccessSpecifier[radioAccessSpecifier.size()];
+ mNetworkScanRequest = new NetworkScanRequest(
+ NetworkScanRequest.SCAN_TYPE_ONE_SHOT /* scan type */,
+ radioAccessSpecifier.toArray(radioAccessSpecifierArray),
+ 5 /* search periodicity */,
+ 60 /* max search time */,
+ true /*enable incremental results*/,
+ 5 /* incremental results periodicity */,
+ null /* List of PLMN ids (MCC-MNC) */);
+
+ mNetworkScanCallback = new NetworkScanCallbackImpl();
+ Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_START);
+ setReady(false);
+ startNetworkScan.sendToTarget();
+ waitUntilReady();
+
+ Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus);
+ assertTrue("The final scan status is not ScanCompleted or ScanError with an error "
+ + "code ERROR_MODEM_UNAVAILABLE or ERROR_UNSUPPORTED",
+ isScanStatusValid());
+ }
+
+ private boolean isScanStatusValid() {
+ // TODO(b/72162885): test the size of ScanResults is not zero after the blocking bug fixed.
+ if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_COMPLETED) && (mScanResults != null)) {
+ // Scan complete.
+ return true;
+ }
+ if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_ERROR)
+ && ((mErrorCode == NetworkScan.ERROR_MODEM_UNAVAILABLE)
+ || (mErrorCode == NetworkScan.ERROR_UNSUPPORTED))) {
+ // Scan error but the error type is allowed.
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
index 95bf60c..6e11919 100644
--- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
+++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
@@ -16,6 +16,8 @@
package com.android.cts.content;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
@@ -39,8 +41,11 @@
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
+import android.util.Log;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -48,6 +53,7 @@
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.regex.Pattern;
@@ -62,6 +68,8 @@
public class CtsSyncAccountAccessOtherCertTestCases {
private static final long SYNC_TIMEOUT_MILLIS = 20000; // 20 sec
private static final long UI_TIMEOUT_MILLIS = 5000; // 5 sec
+ private static final String LOG_TAG =
+ CtsSyncAccountAccessOtherCertTestCases.class.getSimpleName();
private static final Pattern PERMISSION_REQUESTED = Pattern.compile(
"Permission Requested|Permission requested");
@@ -87,6 +95,7 @@
assumeTrue(hasNotificationSupport());
Intent intent = new Intent(getContext(), StubActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
AccountManager accountManager = getContext().getSystemService(AccountManager.class);
@@ -96,6 +105,7 @@
Account addedAccount = new Account(
result.getString(AccountManager.KEY_ACCOUNT_NAME),
result.getString(AccountManager.KEY_ACCOUNT_TYPE));
+ Log.i(LOG_TAG, "Added account " + addedAccount);
waitForSyncManagerAccountChangeUpdate();
@@ -114,9 +124,11 @@
.setManual(true)
.build();
ContentResolver.requestSync(request);
+ Log.i(LOG_TAG, "Sync requested " + request);
verify(adapter, timeout(SYNC_TIMEOUT_MILLIS).times(0)).onPerformSync(any(), any(),
any(), any(), any());
+ Log.i(LOG_TAG, "Did not get onPerformSync");
UiDevice uiDevice = getUiDevice();
if (isWatch()) {
@@ -124,21 +136,40 @@
notification.click();
} else {
uiDevice.openNotification();
- uiDevice.wait(Until.hasObject(By.text(PERMISSION_REQUESTED)),
- UI_TIMEOUT_MILLIS);
+ Log.i(LOG_TAG, "openNotification done");
+ try {
+ UiObject2 permissionRequest = uiDevice.wait(
+ Until.findObject(By.text(PERMISSION_REQUESTED)), UI_TIMEOUT_MILLIS);
- uiDevice.findObject(By.text(PERMISSION_REQUESTED)).click();
+ Log.i(LOG_TAG, "permissionRequest=" + permissionRequest);
+
+ permissionRequest.click();
+ } catch (Throwable t) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ getUiDevice().dumpWindowHierarchy(os);
+
+ Log.w(LOG_TAG, "Window hierarchy:");
+ for (String line : os.toString("UTF-8").split("\n")) {
+ Log.w(LOG_TAG, line);
+
+ // Do not overwhelm logging
+ Thread.sleep(10);
+ }
+
+ throw t;
+ }
}
- uiDevice.wait(Until.hasObject(By.text(ALLOW_SYNC)),
- UI_TIMEOUT_MILLIS);
+ Log.i(LOG_TAG, "Permission opened");
- uiDevice.findObject(By.text(ALLOW_SYNC)).click();
+ uiDevice.wait(Until.findObject(By.text(ALLOW_SYNC)), UI_TIMEOUT_MILLIS).click();
ContentResolver.requestSync(request);
+ Log.i(LOG_TAG, "Sync requested " + request);
verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onPerformSync(any(), any(), any(), any(),
any());
+ Log.i(LOG_TAG, "Got onPerformSync");
} finally {
// Ask the differently signed authenticator to drop all accounts
accountManager.getAuthToken(addedAccount, TOKEN_TYPE_REMOVE_ACCOUNTS,
diff --git a/tests/tests/content/src/android/content/cts/AccountAccessSameCertTest.java b/tests/tests/content/src/android/content/cts/AccountAccessSameCertTest.java
index 72785b5..db27352 100644
--- a/tests/tests/content/src/android/content/cts/AccountAccessSameCertTest.java
+++ b/tests/tests/content/src/android/content/cts/AccountAccessSameCertTest.java
@@ -16,6 +16,8 @@
package android.content.cts;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.timeout;
@@ -78,6 +80,7 @@
assumeTrue(hasNotificationSupport());
Intent intent = new Intent(getContext(), StubActivity.class);
+ intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
AccountManager accountManager = getContext().getSystemService(AccountManager.class);
diff --git a/tests/tests/dpi/Android.mk b/tests/tests/dpi/Android.mk
index 46deccb..d6380c5 100644
--- a/tests/tests/dpi/Android.mk
+++ b/tests/tests/dpi/Android.mk
@@ -43,9 +43,7 @@
# CTS tests, so drop it into a library that other tests can use.
include $(CLEAR_VARS)
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-LOCAL_JAVA_LIBRARIES := android.test.base
+LOCAL_JAVA_LIBRARIES := android.test.base.stubs
LOCAL_SRC_FILES := src/android/dpi/cts/DefaultManifestAttributesTest.java
@@ -53,4 +51,6 @@
LOCAL_MODULE := android.cts.dpi
+LOCAK_SDK_VERSION := current
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java
index 2e986cb..8fad002 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java
@@ -200,15 +200,17 @@
Arrays.fill(origWidth, max);
}
+ // NOTE: instrinsic W/H may already be a scaled and truncated value computed from the
+ // underlying asset (e.g. bitmap) so account for this previously applied scaling/truncation
+ // by applying a small delta to the asserts.
+
// Set density to half of original.
DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
final StateListDrawable halfDrawable =
(StateListDrawable) cs.newDrawable(res);
- // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
- final float approxHalf = (float)(densityDpi / 2) / densityDpi;
for (int i = 0; i < count; i++) {
halfDrawable.selectDrawable(i);
- assertEquals(Math.round(origWidth[i] * approxHalf), halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(origWidth[i] * 0.5f), halfDrawable.getIntrinsicWidth(), 1);
}
// Set density to double original.
@@ -217,7 +219,7 @@
(StateListDrawable) cs.newDrawable(res);
for (int i = 0; i < count; i++) {
doubleDrawable.selectDrawable(i);
- assertEquals(origWidth[i] * 2, doubleDrawable.getIntrinsicWidth());
+ assertEquals(origWidth[i] * 2, doubleDrawable.getIntrinsicWidth(), 1);
}
// Restore original configuration and metrics.
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
index eddcecc..536c16f 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
@@ -357,8 +357,8 @@
@Test
public void testGetIntrinsicSize() {
BitmapDrawable bitmapDrawable = new BitmapDrawable();
- assertEquals(0, bitmapDrawable.getIntrinsicWidth());
- assertEquals(0, bitmapDrawable.getIntrinsicHeight());
+ assertEquals(-1, bitmapDrawable.getIntrinsicWidth());
+ assertEquals(-1, bitmapDrawable.getIntrinsicHeight());
Bitmap bitmap = Bitmap.createBitmap(200, 300, Config.RGB_565);
bitmapDrawable = new BitmapDrawable(bitmap);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
index 6499594..c96a1ca 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
@@ -225,25 +225,28 @@
origWidth1 = tempWidth1;
}
+ // NOTE: instrinsic W/H may already be a scaled and truncated value computed from the
+ // underlying asset (e.g. bitmap) so account for this previously applied scaling/truncation
+ // by applying a small delta to the asserts.
+
// Set density to half of original.
DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
final StateListDrawable halfDrawable =
(StateListDrawable) preloadedConstantState.newDrawable(res);
- // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
- final float approxHalf = (float)(densityDpi / 2) / densityDpi;
halfDrawable.selectDrawable(0);
- assertEquals(Math.round(origWidth0 * approxHalf), halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(origWidth0 * 0.5f), halfDrawable.getIntrinsicWidth(), 1);
halfDrawable.selectDrawable(1);
- assertEquals(Math.round(origWidth1 * approxHalf), halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(origWidth1 * 0.5f), halfDrawable.getIntrinsicWidth(), 1);
// Set density to double original.
+ // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
final StateListDrawable doubleDrawable =
(StateListDrawable) preloadedConstantState.newDrawable(res);
doubleDrawable.selectDrawable(0);
- assertEquals(origWidth0 * 2, doubleDrawable.getIntrinsicWidth());
+ assertEquals(origWidth0 * 2, doubleDrawable.getIntrinsicWidth(), 1);
doubleDrawable.selectDrawable(1);
- assertEquals(origWidth1 * 2, doubleDrawable.getIntrinsicWidth());
+ assertEquals(origWidth1 * 2, doubleDrawable.getIntrinsicWidth(), 1);
// Restore original configuration and metrics.
DrawableTestUtils.setResourcesDensity(res, densityDpi);
diff --git a/tests/tests/jvmti/attaching/Android.mk b/tests/tests/jvmti/attaching/Android.mk
index dc13854..56169d4 100644
--- a/tests/tests/jvmti/attaching/Android.mk
+++ b/tests/tests/jvmti/attaching/Android.mk
@@ -25,7 +25,10 @@
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libjvmtiattachingtestagent
+LOCAL_JNI_SHARED_LIBRARIES := libjvmtiattachingtestagent1 \
+ libjvmtiattachingtestagent2 \
+ libjvmtiattachingtestagent3 \
+ libjvmtiattachingtestagent4 \
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/jvmti/attaching/jni/Android.mk b/tests/tests/jvmti/attaching/jni/Android.mk
index 8f364e2..b0d8376 100644
--- a/tests/tests/jvmti/attaching/jni/Android.mk
+++ b/tests/tests/jvmti/attaching/jni/Android.mk
@@ -18,9 +18,10 @@
LOCAL_PATH:= $(call my-dir)
+define jvmti-attaching-test-agent
include $(CLEAR_VARS)
-LOCAL_MODULE := libjvmtiattachingtestagent
+LOCAL_MODULE := libjvmtiattachingtestagent$1
LOCAL_MODULE_TAGS := optional
@@ -29,8 +30,15 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SDK_VERSION := current
-LOCAL_NDK_STL_VARIANT := c++_static
LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -DAGENT_NR=$1
+
include $(BUILD_SHARED_LIBRARY)
+endef
+
+$(eval $(call jvmti-attaching-test-agent,1))
+$(eval $(call jvmti-attaching-test-agent,2))
+$(eval $(call jvmti-attaching-test-agent,3))
+$(eval $(call jvmti-attaching-test-agent,4))
diff --git a/tests/tests/jvmti/attaching/jni/agent.c b/tests/tests/jvmti/attaching/jni/agent.c
index 1b1d6df..3ebca31 100644
--- a/tests/tests/jvmti/attaching/jni/agent.c
+++ b/tests/tests/jvmti/attaching/jni/agent.c
@@ -22,9 +22,7 @@
static bool sIsAttached = false;
jint
-Agent_OnAttach(JavaVM* vm,
- char* options,
- void* reserved) {
+Agent_OnAttach(JavaVM* vm, char* options, void* reserved) {
if (options != NULL && options[0] == 'a') {
sIsAttached = true;
return JNI_OK;
@@ -33,12 +31,18 @@
}
}
-JNIEXPORT jboolean JNICALL
-Java_android_jvmti_attaching_cts_AttachingTest_isAttached(JNIEnv *env,
- jclass klass) {
+#ifndef AGENT_NR
+#error "Missing AGENT_NR"
+#endif
+#define CONCAT(A,B) A ## B
+#define EVAL(A,B) CONCAT(A,B)
+#define NAME(BASE) EVAL(BASE,AGENT_NR)
+
+JNIEXPORT jboolean JNICALL NAME(Java_android_jvmti_attaching_cts_AttachingTest_isAttached) (
+ JNIEnv* env, jclass klass) {
if (sIsAttached) {
return JNI_TRUE;
} else {
return JNI_FALSE;
}
-}
\ No newline at end of file
+}
diff --git a/tests/tests/jvmti/attaching/src/android.jvmti.attaching.cts/AttachingTest.java b/tests/tests/jvmti/attaching/src/android.jvmti.attaching.cts/AttachingTest.java
index 27f4131..994681f 100644
--- a/tests/tests/jvmti/attaching/src/android.jvmti.attaching.cts/AttachingTest.java
+++ b/tests/tests/jvmti/attaching/src/android.jvmti.attaching.cts/AttachingTest.java
@@ -23,9 +23,11 @@
import dalvik.system.BaseDexClassLoader;
-import org.junit.BeforeClass;
+import org.junit.AfterClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
@@ -35,20 +37,110 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.concurrent.Callable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class AttachingTest {
- private static String sAgentFile;
+ // Some static stored state, for final cleanup.
+ private static Set<File> createdFiles = new HashSet<>();
- @BeforeClass
- public static void copyAgentToFile() throws Exception {
+ // Parameters for a test instance.
+
+ // The string to pass as the agent parameter.
+ private String agentString;
+ // The classloader to pass.
+ private ClassLoader classLoader;
+ // The attach-success function for the last test.
+ private Callable<Boolean> isAttachedFn;
+
+ public AttachingTest(String agentString, ClassLoader classLoader,
+ Callable<Boolean> isAttachedFn) {
+ this.agentString = agentString;
+ this.classLoader = classLoader;
+ this.isAttachedFn = isAttachedFn;
+ }
+
+ @Parameters
+ public static Collection<Object[]> data() {
+ Collection<Object[]> params = new ArrayList<>();
+
+ try {
+ // Test that an absolute path works w/o given classloader.
+ File agentExtracted = copyAgentToFile("jvmtiattachingtestagent1");
+ Callable<Boolean> success = AttachingTest::isAttached1;
+ params.add(new Object[] {
+ agentExtracted.getAbsolutePath(),
+ null,
+ success,
+ });
+ createdFiles.add(agentExtracted);
+ } catch (Exception exc) {
+ throw new RuntimeException(exc);
+ }
+
+ try {
+ // Test that an absolute path works w/ given classloader.
+ File agentExtracted = copyAgentToFile("jvmtiattachingtestagent2");
+ Callable<Boolean> success = AttachingTest::isAttached2;
+ params.add(new Object[] {
+ agentExtracted.getAbsolutePath(),
+ AttachingTest.class.getClassLoader(),
+ success,
+ });
+ createdFiles.add(agentExtracted);
+ } catch (Exception exc) {
+ throw new RuntimeException(exc);
+ }
+
+ {
+ // Test that a relative path works w/ given classloader.
+ Callable<Boolean> success = AttachingTest::isAttached3;
+ params.add(new Object[] {
+ "libjvmtiattachingtestagent3.so",
+ AttachingTest.class.getClassLoader(),
+ success,
+ });
+ }
+
+ try {
+ // The name part of an extracted lib should not work.
+ File agentExtracted = copyAgentToFile("jvmtiattachingtestagent4");
+ String name = agentExtracted.getName();
+ Callable<Boolean> success = () -> {
+ try {
+ isAttached4();
+ // Any result is a failure.
+ return false;
+ } catch (UnsatisfiedLinkError e) {
+ return true;
+ }
+ };
+ params.add(new Object[] {
+ name,
+ AttachingTest.class.getClassLoader(),
+ success,
+ });
+ createdFiles.add(agentExtracted);
+ } catch (Exception exc) {
+ throw new RuntimeException(exc);
+ }
+
+ return params;
+ }
+
+ private static File copyAgentToFile(String lib) throws Exception {
ClassLoader cl = AttachingTest.class.getClassLoader();
assertTrue(cl instanceof BaseDexClassLoader);
File copiedAgent = File.createTempFile("agent", ".so");
try (InputStream is = new FileInputStream(
- ((BaseDexClassLoader) cl).findLibrary("jvmtiattachingtestagent"))) {
+ ((BaseDexClassLoader) cl).findLibrary(lib))) {
try (OutputStream os = new FileOutputStream(copiedAgent)) {
byte[] buffer = new byte[64 * 1024];
@@ -62,45 +154,70 @@
}
}
- sAgentFile = copiedAgent.getAbsolutePath();
+ return copiedAgent;
}
+ @AfterClass
+ public static void cleanupExtractedAgents() throws Exception {
+ for (File f : createdFiles) {
+ f.delete();
+ }
+ createdFiles.clear();
+ }
+
+ // Tests.
+
+ // This will be repeated unnecessarily, but that's OK.
@Test(expected = IOException.class)
public void a_attachInvalidAgent() throws Exception {
- Debug.attachJvmtiAgent(File.createTempFile("badAgent", ".so").getAbsolutePath(), null);
+ File tmpFile = File.createTempFile("badAgent", ".so");
+ createdFiles.add(tmpFile);
+ Debug.attachJvmtiAgent(tmpFile.getAbsolutePath(), null, classLoader);
}
@Test(expected = IOException.class)
public void a_attachInvalidPath() throws Exception {
- Debug.attachJvmtiAgent(sAgentFile + ".invalid", null);
+ Debug.attachJvmtiAgent(agentString + ".invalid", null, classLoader);
}
@Test(expected = NullPointerException.class)
public void a_attachNullAgent() throws Exception {
- Debug.attachJvmtiAgent(null, null);
+ Debug.attachJvmtiAgent(null, null, classLoader);
}
+ // This will be repeated unnecessarily, but that's OK.
@Test(expected = IllegalArgumentException.class)
public void a_attachWithEquals() throws Exception {
- Debug.attachJvmtiAgent(File.createTempFile("=", ".so").getAbsolutePath(), null);
+ File tmpFile = File.createTempFile("=", ".so");
+ createdFiles.add(tmpFile);
+ Debug.attachJvmtiAgent(tmpFile.getAbsolutePath(), null, classLoader);
}
@Test(expected = IOException.class)
public void a_attachWithNullOptions() throws Exception {
- Debug.attachJvmtiAgent(sAgentFile, null);
+ Debug.attachJvmtiAgent(agentString, null, classLoader);
}
@Test(expected = IOException.class)
public void a_attachWithBadOptions() throws Exception {
- Debug.attachJvmtiAgent(sAgentFile, "b");
+ Debug.attachJvmtiAgent(agentString, "b", classLoader);
}
@Test
public void b_attach() throws Exception {
- Debug.attachJvmtiAgent(sAgentFile, "a");
+ try {
+ Debug.attachJvmtiAgent(agentString, "a", classLoader);
+ } catch (Throwable t) {
+ // Ignored.
+ }
- assertTrue(isAttached());
+ assertTrue(isAttachedFn.call());
}
- native static boolean isAttached();
+ // Functions the agents can bind to.
+
+ native static boolean isAttached1();
+ native static boolean isAttached2();
+ native static boolean isAttached3();
+ native static boolean isAttached4();
}
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 75c1f07..0aab327 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -70,11 +70,13 @@
LOCAL_PACKAGE_NAME := CtsMediaTestCases
-# uncomment when b/13249737 is fixed
+# This test uses private APIs
#LOCAL_SDK_VERSION := current
-LOCAL_JAVA_LIBRARIES += android.test.runner org.apache.http.legacy
-LOCAL_JAVA_LIBRARIES += android.test.base
+LOCAL_JAVA_LIBRARIES += \
+ org.apache.http.legacy \
+ android.test.base.stubs \
+ android.test.runner.stubs
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index 957e10d..25e35b2 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -20,7 +20,6 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
-import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioRecord.OnRecordPositionUpdateListener;
import android.media.AudioTimestamp;
@@ -32,17 +31,32 @@
import android.os.Message;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
-import com.android.compatibility.common.util.CtsAndroidTestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+import com.android.compatibility.common.util.SystemUtil;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import java.io.IOException;
import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
import java.util.ArrayList;
-public class AudioRecordTest extends CtsAndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class AudioRecordTest {
private final static String TAG = "AudioRecordTest";
private static final String REPORT_LOG_NAME = "CtsMediaTestCases";
private AudioRecord mAudioRecord;
@@ -62,10 +76,8 @@
}
};
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
+ @Before
+ public void setUp() throws Exception {
if (!hasMicrophone()) {
return;
}
@@ -101,13 +113,12 @@
assertNotNull(mAudioRecord);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
if (hasMicrophone()) {
mAudioRecord.release();
mLooper.quit();
}
- super.tearDown();
}
private void reset() {
@@ -116,6 +127,7 @@
mIsHandleMessageCalled = false;
}
+ @Test
public void testAudioRecordProperties() throws Exception {
if (!hasMicrophone()) {
return;
@@ -134,6 +146,7 @@
assertTrue(bufferSize > 0);
}
+ @Test
public void testAudioRecordOP() throws Exception {
if (!hasMicrophone()) {
return;
@@ -236,6 +249,7 @@
assertEquals(AudioRecord.STATE_UNINITIALIZED, mAudioRecord.getState());
}
+ @Test
public void testAudioRecordResamplerMono8Bit() throws Exception {
doTest("resampler_mono_8bit", true /*localRecord*/, false /*customHandler*/,
1 /*periodsPerSecond*/, 1 /*markerPeriodsPerSecond*/,
@@ -244,6 +258,7 @@
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_8BIT);
}
+ @Test
public void testAudioRecordResamplerStereo8Bit() throws Exception {
doTest("resampler_stereo_8bit", true /*localRecord*/, false /*customHandler*/,
0 /*periodsPerSecond*/, 3 /*markerPeriodsPerSecond*/,
@@ -253,6 +268,7 @@
}
@Presubmit
+ @Test
public void testAudioRecordLocalMono16BitShort() throws Exception {
doTest("local_mono_16bit_short", true /*localRecord*/, false /*customHandler*/,
30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/,
@@ -260,6 +276,8 @@
false /*auditRecording*/, false /*isChannelIndex*/, 8000 /*TEST_SR*/,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 500 /*TEST_TIME_MS*/);
}
+
+ @Test
public void testAudioRecordLocalMono16Bit() throws Exception {
doTest("local_mono_16bit", true /*localRecord*/, false /*customHandler*/,
30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/,
@@ -268,6 +286,7 @@
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
}
+ @Test
public void testAudioRecordStereo16Bit() throws Exception {
doTest("stereo_16bit", false /*localRecord*/, false /*customHandler*/,
2 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/,
@@ -276,6 +295,7 @@
AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
}
+ @Test
public void testAudioRecordMonoFloat() throws Exception {
doTest("mono_float", false /*localRecord*/, true /*customHandler*/,
30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/,
@@ -284,6 +304,7 @@
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_FLOAT);
}
+ @Test
public void testAudioRecordLocalNonblockingStereoFloat() throws Exception {
doTest("local_nonblocking_stereo_float", true /*localRecord*/, true /*customHandler*/,
2 /*periodsPerSecond*/, 0 /*markerPeriodsPerSecond*/,
@@ -293,6 +314,7 @@
}
// Audit modes work best with non-blocking mode
+ @Test
public void testAudioRecordAuditByteBufferResamplerStereoFloat() throws Exception {
if (isLowRamDevice()) {
return; // skip. FIXME: reenable when AF memory allocation is updated.
@@ -305,6 +327,7 @@
AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_FLOAT);
}
+ @Test
public void testAudioRecordAuditChannelIndexMonoFloat() throws Exception {
doTest("audit_channel_index_mono_float", true /*localRecord*/, true /*customHandler*/,
2 /*periodsPerSecond*/, 0 /*markerPeriodsPerSecond*/,
@@ -315,6 +338,7 @@
// Audit buffers can run out of space with high sample rate,
// so keep the channels and pcm encoding low
+ @Test
public void testAudioRecordAuditChannelIndex2() throws Exception {
if (isLowRamDevice()) {
return; // skip. FIXME: reenable when AF memory allocation is updated.
@@ -329,6 +353,7 @@
// Audit buffers can run out of space with high numbers of channels,
// so keep the sample rate low.
+ @Test
public void testAudioRecordAuditChannelIndex5() throws Exception {
doTest("audit_channel_index_5", true /*localRecord*/, true /*customHandler*/,
2 /*periodsPerSecond*/, 0 /*markerPeriodsPerSecond*/,
@@ -340,6 +365,7 @@
// Test AudioRecord.Builder to verify the observed configuration of an AudioRecord built with
// an empty Builder matches the documentation / expected values
+ @Test
public void testAudioRecordBuilderDefault() throws Exception {
if (!hasMicrophone()) {
return;
@@ -369,6 +395,7 @@
// Test AudioRecord.Builder to verify the observed configuration of an AudioRecord built with
// an incomplete AudioFormat matches the documentation / expected values
+ @Test
public void testAudioRecordBuilderPartialFormat() throws Exception {
if (!hasMicrophone()) {
return;
@@ -400,6 +427,7 @@
// Test AudioRecord.Builder to verify the observed configuration of an AudioRecord matches
// the parameters used in the builder
+ @Test
public void testAudioRecordBuilderParams() throws Exception {
if (!hasMicrophone()) {
return;
@@ -441,6 +469,7 @@
}
// Test AudioRecord to ensure we can build after a failure.
+ @Test
public void testAudioRecordBufferSize() throws Exception {
if (!hasMicrophone()) {
return;
@@ -476,6 +505,7 @@
assertTrue(TEST_NAME + ": buffer frame count", observedBufferSize2 > 0);
}
+ @Test
public void testTimestamp() throws Exception {
if (!hasMicrophone()) {
return;
@@ -571,6 +601,69 @@
}
}
+ @Test
+ public void testRecordNoDataForIdleUids() throws Exception {
+ if (!hasMicrophone()) {
+ return;
+ }
+
+ AudioRecord recorder = null;
+
+ // We will record audio for 20 sec from active and idle state expecting
+ // the recording from active state to have data while from idle silence.
+ try {
+ // Setup a recorder
+ final AudioRecord candidateRecorder = new AudioRecord.Builder()
+ .setAudioSource(MediaRecorder.AudioSource.MIC)
+ .setBufferSizeInBytes(1024)
+ .setAudioFormat(new AudioFormat.Builder()
+ .setSampleRate(8000)
+ .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+ .build())
+ .build();
+
+ // Unleash it :P
+ candidateRecorder.startRecording();
+ recorder = candidateRecorder;
+
+ final int sampleCount = AudioHelper.frameCountFromMsec(6000,
+ candidateRecorder.getFormat()) * candidateRecorder.getFormat()
+ .getChannelCount();
+ final ShortBuffer buffer = ShortBuffer.allocate(sampleCount);
+
+ // Read five seconds of data
+ readDataTimed(recorder, 5000, buffer);
+ // Ensure we read non-empty bytes
+ assertSilence(buffer, false);
+
+ // Start clean
+ buffer.clear();
+ // Force idle the package
+ makeMyPackageIdle();
+ // Read five seconds of data
+ readDataTimed(recorder, 5000, buffer);
+ // Ensure we read empty bytes
+ assertSilence(buffer, true);
+
+ // Start clean
+ buffer.clear();
+ // Reset to active
+ makeMyPackageActive();
+ // Read five seconds of data
+ readDataTimed(recorder, 5000, buffer);
+ // Ensure we read non-empty bytes
+ assertSilence(buffer, false);
+ } finally {
+ if (recorder != null) {
+ recorder.stop();
+ recorder.release();
+ }
+ makeMyPackageActive();
+ }
+ }
+
+ @Test
public void testSynchronizedRecord() throws Exception {
if (!hasMicrophone()) {
return;
@@ -1167,7 +1260,7 @@
ResultUnit.MS);
log.setSummary("unified_abs_diff", (periodicStat.getAvgAbs() + markerStat.getAvgAbs()) / 2,
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.submit(getInstrumentation());
+ log.submit(InstrumentationRegistry.getInstrumentation());
}
private class MockOnRecordPositionUpdateListener
@@ -1286,4 +1379,61 @@
private void printTimestamp(String s, AudioTimestamp ats) {
Log.d(TAG, s + ": pos: " + ats.framePosition + " time: " + ats.nanoTime);
}
+
+ private static void readDataTimed(AudioRecord recorder, long durationMillis,
+ ShortBuffer out) throws IOException {
+ final short[] buffer = new short[1024];
+ final long startTimeMillis = SystemClock.uptimeMillis();
+ final long stopTimeMillis = startTimeMillis + durationMillis;
+ while (SystemClock.uptimeMillis() < stopTimeMillis) {
+ final int readCount = recorder.read(buffer, 0, buffer.length);
+ if (readCount <= 0) {
+ return;
+ }
+ out.put(buffer, 0, readCount);
+ }
+ }
+
+ private static void assertSilence(ShortBuffer buffer, boolean silence) {
+ // Always need some bytes read
+ assertTrue("Buffer should have some data", buffer.position() > 0);
+
+ // It is possible that the transition from empty to non empty bytes
+ // happened in the middle of the read data due to the async nature of
+ // the system. Therefore, we look for the transitions from non-empty
+ // to empty and from empty to non-empty values for robustness.
+ int totalSilenceCount = 0;
+ final int valueCount = buffer.position();
+ for (int i = valueCount - 1; i >= 0; i--) {
+ final short value = buffer.get(i);
+ if (value == 0) {
+ totalSilenceCount++;
+ }
+ }
+ if (silence) {
+ if (totalSilenceCount < valueCount / 2) {
+ fail("Recording was not silenced while UID idle");
+ }
+ } else {
+ if (totalSilenceCount > valueCount / 2) {
+ fail("Recording was silenced while UID active");
+ }
+ }
+ }
+
+ private static void makeMyPackageActive() throws IOException {
+ final String command = "cmd media.audio_policy reset-uid-state "
+ + InstrumentationRegistry.getTargetContext().getPackageName();
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
+ }
+
+ private static void makeMyPackageIdle() throws IOException {
+ final String command = "cmd media.audio_policy set-uid-state "
+ + InstrumentationRegistry.getTargetContext().getPackageName() + " idle";
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
+ }
+
+ private static Context getContext() {
+ return InstrumentationRegistry.getInstrumentation().getTargetContext();
+ }
}
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerTest.java b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
index 401e2d5..4a1dc09 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
@@ -391,11 +391,21 @@
mMediaScannerConnection.connect();
checkConnectionState(true);
+ // test unlocalizable file
+ canonicalizeTest(R.raw.testmp3);
+
+ mMediaScannerConnectionClient.reset();
+
+ // test localizable file
+ canonicalizeTest(R.raw.testmp3_4);
+ }
+
+ private void canonicalizeTest(int resId) throws Exception {
// write file and scan to insert into database
String fileDir = Environment.getExternalStorageDirectory() + "/"
+ getClass().getCanonicalName() + "/canonicaltest-" + System.currentTimeMillis();
String fileName = fileDir + "/test.mp3";
- writeFile(R.raw.testmp3, fileName);
+ writeFile(resId, fileName);
mMediaScannerConnection.scanFile(fileName, MEDIA_TYPE);
checkMediaScannerConnection();
@@ -420,7 +430,7 @@
// write same file again and scan to insert into database
mMediaScannerConnectionClient.reset();
String fileName2 = fileDir + "/test2.mp3";
- writeFile(R.raw.testmp3, fileName2);
+ writeFile(resId, fileName2);
mMediaScannerConnection.scanFile(fileName2, MEDIA_TYPE);
checkMediaScannerConnection();
diff --git a/tests/tests/nativemedia/aaudio/jni/Android.mk b/tests/tests/nativemedia/aaudio/jni/Android.mk
index c6f0902..9795b70 100644
--- a/tests/tests/nativemedia/aaudio/jni/Android.mk
+++ b/tests/tests/nativemedia/aaudio/jni/Android.mk
@@ -22,6 +22,7 @@
LOCAL_SRC_FILES := \
test_aaudio.cpp \
+ test_aaudio_attributes.cpp \
test_aaudio_callback.cpp \
test_aaudio_mmap.cpp \
test_aaudio_misc.cpp \
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp
new file mode 100644
index 0000000..6143613
--- /dev/null
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+// Test AAudio attributes such as Usage, ContentType and InputPreset.
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <aaudio/AAudio.h>
+#include <gtest/gtest.h>
+
+constexpr int64_t kNanosPerSecond = 1000000000;
+constexpr int kNumFrames = 256;
+constexpr int kChannelCount = 2;
+
+constexpr int32_t DONT_SET = -1000;
+
+static void checkAttributes(aaudio_performance_mode_t perfMode,
+ aaudio_usage_t usage,
+ aaudio_content_type_t contentType,
+ aaudio_input_preset_t preset = DONT_SET,
+ aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT) {
+
+ float *buffer = new float[kNumFrames * kChannelCount];
+
+ AAudioStreamBuilder *aaudioBuilder = nullptr;
+ AAudioStream *aaudioStream = nullptr;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+ // Request stream properties.
+ AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+ AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
+
+ // Set the attribute in the builder.
+ if (usage != DONT_SET) {
+ AAudioStreamBuilder_setUsage(aaudioBuilder, usage);
+ }
+ if (contentType != DONT_SET) {
+ AAudioStreamBuilder_setContentType(aaudioBuilder, contentType);
+ }
+ if (preset != DONT_SET) {
+ AAudioStreamBuilder_setInputPreset(aaudioBuilder, preset);
+ }
+
+ // Create an AAudioStream using the Builder.
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+ AAudioStreamBuilder_delete(aaudioBuilder);
+
+ // Make sure we get the same attributes back from the stream.
+ aaudio_usage_t expectedUsage =
+ (usage == DONT_SET || usage == AAUDIO_UNSPECIFIED)
+ ? AAUDIO_USAGE_MEDIA // default
+ : usage;
+ EXPECT_EQ(expectedUsage, AAudioStream_getUsage(aaudioStream));
+
+ aaudio_content_type_t expectedContentType =
+ (contentType == DONT_SET || contentType == AAUDIO_UNSPECIFIED)
+ ? AAUDIO_CONTENT_TYPE_MUSIC // default
+ : contentType;
+ EXPECT_EQ(expectedContentType, AAudioStream_getContentType(aaudioStream));
+
+ aaudio_input_preset_t expectedPreset =
+ (preset == DONT_SET || preset == AAUDIO_UNSPECIFIED)
+ ? AAUDIO_INPUT_PRESET_VOICE_RECOGNITION // default
+ : preset;
+ EXPECT_EQ(expectedPreset, AAudioStream_getInputPreset(aaudioStream));
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
+
+ if (direction == AAUDIO_DIRECTION_INPUT) {
+ EXPECT_EQ(kNumFrames,
+ AAudioStream_read(aaudioStream, buffer, kNumFrames, kNanosPerSecond));
+ } else {
+ EXPECT_EQ(kNumFrames,
+ AAudioStream_write(aaudioStream, buffer, kNumFrames, kNanosPerSecond));
+ }
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
+ delete[] buffer;
+}
+
+static const aaudio_usage_t sUsages[] = {
+ DONT_SET,
+ AAUDIO_UNSPECIFIED,
+ AAUDIO_USAGE_MEDIA,
+ AAUDIO_USAGE_VOICE_COMMUNICATION,
+ AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ AAUDIO_USAGE_ALARM,
+ AAUDIO_USAGE_NOTIFICATION,
+ AAUDIO_USAGE_NOTIFICATION_RINGTONE,
+ AAUDIO_USAGE_NOTIFICATION_EVENT,
+ AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+ AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ AAUDIO_USAGE_ASSISTANCE_SONIFICATION,
+ AAUDIO_USAGE_GAME,
+ AAUDIO_USAGE_ASSISTANT
+};
+
+static const aaudio_content_type_t sContentypes[] = {
+ DONT_SET,
+ AAUDIO_UNSPECIFIED,
+ AAUDIO_CONTENT_TYPE_SPEECH,
+ AAUDIO_CONTENT_TYPE_MUSIC,
+ AAUDIO_CONTENT_TYPE_MOVIE,
+ AAUDIO_CONTENT_TYPE_SONIFICATION
+};
+
+static const aaudio_input_preset_t sInputPresets[] = {
+ DONT_SET,
+ AAUDIO_UNSPECIFIED,
+ AAUDIO_INPUT_PRESET_GENERIC,
+ AAUDIO_INPUT_PRESET_CAMCORDER,
+ AAUDIO_INPUT_PRESET_VOICE_RECOGNITION,
+ AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
+ AAUDIO_INPUT_PRESET_UNPROCESSED,
+};
+
+static void checkAttributesUsage(aaudio_performance_mode_t perfMode) {
+ for (aaudio_usage_t usage : sUsages) {
+ checkAttributes(perfMode, usage, DONT_SET);
+ }
+}
+
+static void checkAttributesContentType(aaudio_input_preset_t perfMode) {
+ for (aaudio_content_type_t contentType : sContentypes) {
+ checkAttributes(perfMode, DONT_SET, contentType);
+ }
+}
+
+static void checkAttributesInputPreset(aaudio_performance_mode_t perfMode) {
+ for (aaudio_input_preset_t inputPreset : sInputPresets) {
+ checkAttributes(perfMode,
+ DONT_SET,
+ DONT_SET,
+ inputPreset,
+ AAUDIO_DIRECTION_INPUT);
+ }
+}
+
+TEST(test_attributes, aaudio_usage_perfnone) {
+ checkAttributesUsage(AAUDIO_PERFORMANCE_MODE_NONE);
+}
+
+TEST(test_attributes, aaudio_content_type_perfnone) {
+ checkAttributesContentType(AAUDIO_PERFORMANCE_MODE_NONE);
+}
+
+TEST(test_attributes, aaudio_input_preset_perfnone) {
+ checkAttributesInputPreset(AAUDIO_PERFORMANCE_MODE_NONE);
+}
+
+TEST(test_attributes, aaudio_usage_lowlat) {
+ checkAttributesUsage(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
+
+TEST(test_attributes, aaudio_content_type_lowlat) {
+ checkAttributesContentType(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
+
+TEST(test_attributes, aaudio_input_preset_lowlat) {
+ checkAttributesInputPreset(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_misc.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_misc.cpp
index 42c9f42..01ed9f6 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_misc.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_misc.cpp
@@ -75,4 +75,28 @@
static_assert(0 == AAUDIO_CALLBACK_RESULT_CONTINUE, ENUM_CANNOT_CHANGE);
static_assert(1 == AAUDIO_CALLBACK_RESULT_STOP, ENUM_CANNOT_CHANGE);
+
+ static_assert(1 == AAUDIO_USAGE_MEDIA, ENUM_CANNOT_CHANGE);
+ static_assert(2 == AAUDIO_USAGE_VOICE_COMMUNICATION, ENUM_CANNOT_CHANGE);
+ static_assert(3 == AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING, ENUM_CANNOT_CHANGE);
+ static_assert(4 == AAUDIO_USAGE_ALARM, ENUM_CANNOT_CHANGE);
+ static_assert(5 == AAUDIO_USAGE_NOTIFICATION, ENUM_CANNOT_CHANGE);
+ static_assert(6 == AAUDIO_USAGE_NOTIFICATION_RINGTONE, ENUM_CANNOT_CHANGE);
+ static_assert(10 == AAUDIO_USAGE_NOTIFICATION_EVENT, ENUM_CANNOT_CHANGE);
+ static_assert(11 == AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY, ENUM_CANNOT_CHANGE);
+ static_assert(12 == AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, ENUM_CANNOT_CHANGE);
+ static_assert(13 == AAUDIO_USAGE_ASSISTANCE_SONIFICATION, ENUM_CANNOT_CHANGE);
+ static_assert(14 == AAUDIO_USAGE_GAME, ENUM_CANNOT_CHANGE);
+ static_assert(16 == AAUDIO_USAGE_ASSISTANT, ENUM_CANNOT_CHANGE);
+
+ static_assert(1 == AAUDIO_CONTENT_TYPE_SPEECH, ENUM_CANNOT_CHANGE);
+ static_assert(2 == AAUDIO_CONTENT_TYPE_MUSIC, ENUM_CANNOT_CHANGE);
+ static_assert(3 == AAUDIO_CONTENT_TYPE_MOVIE, ENUM_CANNOT_CHANGE);
+ static_assert(4 == AAUDIO_CONTENT_TYPE_SONIFICATION, ENUM_CANNOT_CHANGE);
+
+ static_assert(1 == AAUDIO_INPUT_PRESET_GENERIC, ENUM_CANNOT_CHANGE);
+ static_assert(5 == AAUDIO_INPUT_PRESET_CAMCORDER, ENUM_CANNOT_CHANGE);
+ static_assert(6 == AAUDIO_INPUT_PRESET_VOICE_RECOGNITION, ENUM_CANNOT_CHANGE);
+ static_assert(7 == AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION, ENUM_CANNOT_CHANGE);
+ static_assert(9 == AAUDIO_INPUT_PRESET_UNPROCESSED, ENUM_CANNOT_CHANGE);
}
diff --git a/tests/tests/slice/src/android/slice/cts/SliceBuilderTest.java b/tests/tests/slice/src/android/slice/cts/SliceBuilderTest.java
new file mode 100644
index 0000000..74ed881
--- /dev/null
+++ b/tests/tests/slice/src/android/slice/cts/SliceBuilderTest.java
@@ -0,0 +1,308 @@
+/*
+ * 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.slice.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.app.slice.Slice;
+import android.app.slice.SliceItem;
+import android.app.slice.SliceSpec;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArraySet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+@RunWith(AndroidJUnit4.class)
+public class SliceBuilderTest {
+
+ private static final Uri BASE_URI = Uri.parse("content://android.slice.cts/");
+ private final Context mContext = InstrumentationRegistry.getContext();
+
+ @Test
+ public void testInt() {
+ Slice s = new Slice.Builder(BASE_URI)
+ .addInt(0xff121212, "subtype", Slice.HINT_TITLE)
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_INT, item.getFormat());
+ assertEquals(0xff121212, item.getInt());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testIntList() {
+ Slice s = new Slice.Builder(BASE_URI)
+ .addInt(0xff121212, "subtype", Arrays.asList(Slice.HINT_TITLE))
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_INT, item.getFormat());
+ assertEquals(0xff121212, item.getInt());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testIcon() {
+ Icon i = Icon.createWithResource(mContext, R.drawable.size_48x48);
+ Slice s = new Slice.Builder(BASE_URI)
+ .addIcon(i, "subtype", Slice.HINT_TITLE)
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_IMAGE, item.getFormat());
+ assertEquals(i, item.getIcon());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testIconList() {
+ Icon i = Icon.createWithResource(mContext, R.drawable.size_48x48);
+ Slice s = new Slice.Builder(BASE_URI)
+ .addIcon(i, "subtype", Arrays.asList(Slice.HINT_TITLE))
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_IMAGE, item.getFormat());
+ assertEquals(i, item.getIcon());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testText() {
+ CharSequence i = "Some text";
+ Slice s = new Slice.Builder(BASE_URI)
+ .addText(i, "subtype", Slice.HINT_TITLE)
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_TEXT, item.getFormat());
+ assertEquals(i, item.getText());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testTextList() {
+ CharSequence i = "Some text";
+ Slice s = new Slice.Builder(BASE_URI)
+ .addText(i, "subtype", Arrays.asList(Slice.HINT_TITLE))
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_TEXT, item.getFormat());
+ assertEquals(i, item.getText());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testTimestamp() {
+ long i = 43L;
+ Slice s = new Slice.Builder(BASE_URI)
+ .addTimestamp(i, "subtype", Slice.HINT_TITLE)
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_TIMESTAMP, item.getFormat());
+ assertEquals(i, item.getTimestamp());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testTimestampList() {
+ long i = 43L;
+ Slice s = new Slice.Builder(BASE_URI)
+ .addTimestamp(i, "subtype", Arrays.asList(Slice.HINT_TITLE))
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_TIMESTAMP, item.getFormat());
+ assertEquals(i, item.getTimestamp());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testRemoteInput() {
+ RemoteInput i = new RemoteInput.Builder("key").build();
+ Slice s = new Slice.Builder(BASE_URI)
+ .addRemoteInput(i, "subtype", Slice.HINT_TITLE)
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_REMOTE_INPUT, item.getFormat());
+ assertEquals(i, item.getRemoteInput());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testRemoteInputList() {
+ RemoteInput i = new RemoteInput.Builder("key").build();
+ Slice s = new Slice.Builder(BASE_URI)
+ .addRemoteInput(i, "subtype", Arrays.asList(Slice.HINT_TITLE))
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_REMOTE_INPUT, item.getFormat());
+ assertEquals(i, item.getRemoteInput());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testBundle() {
+ Bundle i = new Bundle();
+ Slice s = new Slice.Builder(BASE_URI)
+ .addBundle(i, "subtype", Slice.HINT_TITLE)
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_BUNDLE, item.getFormat());
+ assertEquals(i, item.getBundle());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testBundleList() {
+ Bundle i = new Bundle();
+ Slice s = new Slice.Builder(BASE_URI)
+ .addBundle(i, "subtype", Arrays.asList(Slice.HINT_TITLE))
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_BUNDLE, item.getFormat());
+ assertEquals(i, item.getBundle());
+ assertEquals("subtype", item.getSubType());
+ assertTrue(item.hasHint(Slice.HINT_TITLE));
+ }
+
+ @Test
+ public void testAction() {
+ PendingIntent i = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+ Slice subSlice = new Slice.Builder(BASE_URI.buildUpon().appendPath("s").build()).build();
+ Slice s = new Slice.Builder(BASE_URI)
+ .addAction(i, subSlice)
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_ACTION, item.getFormat());
+ assertEquals(i, item.getAction());
+ assertEquals(null, item.getSubType());
+ assertEquals(subSlice, item.getSlice());
+ }
+
+ @Test
+ public void testActionSubtype() {
+ PendingIntent i = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+ Slice subSlice = new Slice.Builder(BASE_URI.buildUpon().appendPath("s").build()).build();
+ Slice s = new Slice.Builder(BASE_URI)
+ .addAction(i, subSlice, "subtype")
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_ACTION, item.getFormat());
+ assertEquals(i, item.getAction());
+ assertEquals("subtype", item.getSubType());
+ assertEquals(subSlice, item.getSlice());
+ }
+
+ @Test
+ public void testSubslice() {
+ Slice subSlice = new Slice.Builder(BASE_URI.buildUpon().appendPath("s").build()).build();
+ Slice s = new Slice.Builder(BASE_URI)
+ .addSubSlice(subSlice)
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_SLICE, item.getFormat());
+ assertEquals(null, item.getSubType());
+ assertEquals(subSlice, item.getSlice());
+ }
+
+ @Test
+ public void testSubsliceSubtype() {
+ Slice subSlice = new Slice.Builder(BASE_URI.buildUpon().appendPath("s").build()).build();
+ Slice s = new Slice.Builder(BASE_URI)
+ .addSubSlice(subSlice, "subtype")
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(1, s.getItems().size());
+
+ SliceItem item = s.getItems().get(0);
+ assertEquals(SliceItem.FORMAT_SLICE, item.getFormat());
+ assertEquals("subtype", item.getSubType());
+ assertEquals(subSlice, item.getSlice());
+ }
+
+ @Test
+ public void testSpec() {
+ Slice s = new Slice.Builder(BASE_URI)
+ .setSpec(new SliceSpec("spec", 3))
+ .build();
+ assertEquals(BASE_URI, s.getUri());
+ assertEquals(0, s.getItems().size());
+ assertEquals(new SliceSpec("spec", 3), s.getSpec());
+ }
+}
diff --git a/tests/tests/slice/src/android/slice/cts/SliceProvider.java b/tests/tests/slice/src/android/slice/cts/SliceProvider.java
index ce8417e..19968ab 100644
--- a/tests/tests/slice/src/android/slice/cts/SliceProvider.java
+++ b/tests/tests/slice/src/android/slice/cts/SliceProvider.java
@@ -17,14 +17,13 @@
import static java.util.stream.Collectors.toList;
import android.app.PendingIntent;
+import android.app.slice.Slice;
+import android.app.slice.Slice.Builder;
import android.app.slice.SliceSpec;
-import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.net.Uri;
-import android.app.slice.Slice;
-import android.app.slice.Slice.Builder;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -45,9 +44,13 @@
"/int",
"/timestamp",
"/hints",
- "/bundle"
+ "/bundle",
+ "/spec",
};
+ public static final String SPEC_TYPE = "android.cts.SliceType";
+ public static final int SPEC_REV = 4;
+
@Override
public boolean onCreate() {
return true;
@@ -100,6 +103,10 @@
Bundle b1 = new Bundle();
b1.putParcelable("a", new TestParcel());
return new Slice.Builder(sliceUri).addBundle(b1, "bundle").build();
+ case "/spec":
+ return new Slice.Builder(sliceUri)
+ .setSpec(new SliceSpec(SPEC_TYPE, SPEC_REV))
+ .build();
}
return new Slice.Builder(sliceUri).build();
}
diff --git a/tests/tests/slice/src/android/slice/cts/SliceTest.java b/tests/tests/slice/src/android/slice/cts/SliceTest.java
index 9a0dcef..f573bca 100644
--- a/tests/tests/slice/src/android/slice/cts/SliceTest.java
+++ b/tests/tests/slice/src/android/slice/cts/SliceTest.java
@@ -22,6 +22,7 @@
import android.app.PendingIntent.CanceledException;
import android.app.slice.SliceManager;
+import android.app.slice.SliceSpec;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -192,6 +193,15 @@
}
@Test
+ public void testHasHints() {
+ Uri uri = BASE_URI.buildUpon().appendPath("hints").build();
+ Slice s = mSliceManager.bindSlice(uri, Collections.emptyList());
+
+ assertTrue(s.getItems().get(0).hasHint(Slice.HINT_TITLE));
+ assertFalse(s.getItems().get(0).hasHint(Slice.HINT_LIST));
+ }
+
+ @Test
public void testBundle() {
Uri uri = BASE_URI.buildUpon().appendPath("bundle").build();
Slice s = mSliceManager.bindSlice(uri, Collections.emptyList());
@@ -217,4 +227,11 @@
assertEquals(0, mSliceManager.getSliceDescendants(
BASE_URI.buildUpon().appendPath("/nothing").build()).size());
}
+
+ @Test
+ public void testGetSliceSpec() {
+ Uri uri = BASE_URI.buildUpon().appendPath("spec").build();
+ Slice s = mSliceManager.bindSlice(uri, Collections.emptyList());
+ assertEquals(new SliceSpec(SliceProvider.SPEC_TYPE, SliceProvider.SPEC_REV), s.getSpec());
+ }
}
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index d0b219d..37fcb01 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -51,8 +51,14 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.List;
import java.util.regex.Pattern;
+/**
+ * Build, install and run the tests by running the commands below:
+ * make cts -j64
+ * cts-tradefed run cts -m CtsTelephonyTestCases --test android.telephony.cts.TelephonyManagerTest
+ */
@RunWith(AndroidJUnit4.class)
public class TelephonyManagerTest {
private TelephonyManager mTelephonyManager;
@@ -603,4 +609,32 @@
private static Context getContext() {
return InstrumentationRegistry.getContext();
}
+
+ /**
+ * Tests that the device properly sets the network selection mode to automatic.
+ * Expects a security exception since the caller does not have carrier privileges.
+ */
+ @Test
+ public void testSetNetworkSelectionModeAutomatic() {
+ try {
+ mTelephonyManager.setNetworkSelectionModeAutomatic();
+ fail("Expected SecurityException. App does not have carrier privileges.");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ /**
+ * Tests that the device properly asks the radio to connect to the input network and change
+ * selection mode to manual.
+ * Expects a security exception since the caller does not have carrier privileges.
+ */
+ @Test
+ public void testSetNetworkSelectionModeManual() {
+ try {
+ mTelephonyManager.setNetworkSelectionModeManual(
+ "" /* operatorNumeric */, false /* persistSelection */);
+ fail("Expected SecurityException. App does not have carrier privileges.");
+ } catch (SecurityException expected) {
+ }
+ }
}
diff --git a/tools/cts-api-coverage/proto/cts_report.proto b/tools/cts-api-coverage/proto/cts_report.proto
new file mode 100644
index 0000000..afb4338
--- /dev/null
+++ b/tools/cts-api-coverage/proto/cts_report.proto
@@ -0,0 +1,352 @@
+// 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.
+
+// Contains proto definition for storing CTS reports.
+
+syntax = "proto2";
+
+package com.android.cts.apicoverage;
+option java_package = "com.android.cts.apicoverage";
+option java_outer_classname = "CtsReportProto";
+
+// from common_report.proto
+// Information about the build on the phone. All the fields
+// correspond to values from android.os.Build.
+// Next Id: 20
+message BuildInfo {
+ optional string board = 1;
+ optional string brand = 2;
+ optional string device = 3;
+ optional string display = 4;
+ optional string fingerprint = 5;
+ optional string id = 6;
+ optional string model = 7;
+ optional string product = 8;
+ message Version {
+ optional string release = 1;
+ optional string sdk = 2;
+ }
+ optional Version version = 9;
+ optional string manufacturer = 10;
+ // This field is deprecated in android.os.Build. Use supported_abi instead.
+ optional string abi = 11 [deprecated = true];
+ // This field is deprecated in android.os.Build. Use supported_abi instead.
+ optional string abi2 = 12 [deprecated = true];
+ repeated string supported_abi = 13;
+ repeated string supported_32_bit_abi = 14;
+ repeated string supported_64_bit_abi = 15;
+ // Build.BASE_OS The base OS build the product is based on. See b/23003940
+ optional string base_os = 16;
+ // Build.SECURITY_PATCH The user-visible security patch level. See b/23003940
+ optional string security_patch = 17;
+ // A build fingerprint of the reference device. See go/apfe-reference-build
+ optional string reference_build_fingerprint = 18;
+ // RO Property set for the build.
+ map<string, string> ro_property_map = 19;
+}
+
+// Summary count of the test results.
+message Summary {
+ optional int32 failed = 1;
+ optional int32 not_executed = 2;
+ optional int32 pass = 3;
+ optional int32 timeout = 4;
+ optional int32 warning = 5;
+}
+
+// Information about the device's memory configuration
+message MemoryInfo {
+ // ActivityManager.isLowRamDevice
+ optional bool is_low_ram_device = 1;
+
+ // ActivityManager.getMemoryClass()
+ optional int32 memory_class = 2;
+
+ // ActivityManager.getLargeMemoryClass()
+ optional int32 large_memory_class = 3;
+
+ // MemoryInfo.totalMem
+ optional int64 total_memory = 4;
+}
+
+message CpuInfo {
+ // Runtime.availableProcessors
+ optional int32 available_processors = 1;
+}
+// from common_report.proto ends
+
+// Logical screen density
+// The numbers are in dpi and should match android.util.DisplayMetrics.DENSITY_*
+enum LogicalDensity {
+ LDPI = 120;
+ MDPI = 160;
+ TVDPI = 213;
+ HDPI = 240;
+ DENSITY_260 = 260;
+ DENSITY_280 = 280;
+ DENSITY_300 = 300;
+ XHDPI = 320;
+ DENSITY_340 = 340;
+ DENSITY_360 = 360;
+ // Intermediate density for screens that sit somewhere between DENSITY_XHIGH (320 dpi) and
+ // DENSITY_XXHIGH (480 dpi).
+ DENSITY_400 = 400;
+ DENSITY_420 = 420;
+ XXHDPI = 480;
+ // Intermediate density for screens that sit somewhere between DENSITY_XXHIGH (480 dpi) and
+ // DENSITY_XXXHIGH (640 dpi).
+ DENSITY_560 = 560;
+ XXXHDPI = 640;
+}
+
+// Logical screen size
+// The numbers should match
+// android.content.res.Configuration.SCREENLAYOUT_SIZE_*
+enum LogicalSize {
+ UNDEFINED = 0;
+ SMALL = 1;
+ NORMAL = 2;
+ LARGE = 3;
+ XLARGE = 4;
+}
+
+// Result type of PTS tests defined in:
+// cts/suite/pts/lib/commonutil/src/com/android/pts/util/ResultType.java
+enum ResultType {
+ LOWER_BETTER = 0;
+ HIGHER_BETTER = 1;
+ NEUTRAL = 2;
+ WARNING = 3;
+}
+
+// Result unit of PTS values defined in:
+// cts/suite/pts/lib/commonutil/src/com/android/pts/util/ResultUnit.java
+enum ResultUnit {
+ NONE = 0;
+ MS = 1;
+ FPS = 2;
+ OPS = 3;
+ KBPS = 4;
+ MBPS = 5;
+ BYTE = 6;
+ COUNT = 7;
+ SCORE = 8;
+}
+
+// A CtsReport message encapsulates the output of a Compatibility Test Suite
+// (CTS) run.
+message CtsReport {
+
+ // Test plan that was run, generally "CTS".
+ optional string test_plan = 1;
+
+ // Version of the CTS tool.
+ optional string version = 2;
+
+ optional int64 start_time = 3;
+ optional int64 end_time = 4;
+
+ // Fields describing the particular device under test.
+ // Next Id: 32
+ message DeviceInfo {
+
+ optional string screen_resolution = 1;
+ optional LogicalDensity logical_screen_density = 17;
+ optional LogicalSize logical_screen_size = 18;
+
+ optional string subscriber_id = 2 [deprecated = true];
+ optional string type = 3 [deprecated = true];
+ optional string device_id = 4 [deprecated = true];
+ optional string imei = 5 [deprecated = true];
+ optional string imsi = 6 [deprecated = true];
+ optional string keypad = 7;
+ repeated string locale = 8;
+ optional string navigation = 9;
+ optional string network = 10 [deprecated = true];
+ optional string touch = 11;
+ optional float x_dpi = 12;
+ optional float y_dpi = 13;
+ optional string opengl_es_version = 19;
+
+ // Use BuildInfo.supported_abi instead
+ optional string build_abi = 20 [deprecated = true];
+ // Use BuildInfo.supported_abi instead
+ optional string build_abi2 = 21 [deprecated = true];
+
+ optional BuildInfo build_info = 14;
+ optional MemoryInfo memory_info = 29;
+ optional CpuInfo cpu_info = 30;
+
+ // Filesystem partitions.
+ optional string partitions = 22;
+
+ repeated string system_library = 23;
+ // Deprecated. These values are found in the extension list
+ repeated string opengl_texture_format = 24 [deprecated = true];
+ // GLES20.GL_EXTENSIONS, GL10.GL_EXTENSIONS or GLES30.GL_EXTENSIONS
+ repeated string opengl_extension = 25;
+ // gl.glGetString(GL10.GL_VENDOR) or GLES20.glGetString(GLES20.GL_VENDOR)
+ // or GLES30.glGetString(GLES30.GL_VENDOR)
+ optional string opengl_vendor = 26;
+ // gl.glGetString(GL10.GL_RENDERER)
+ // or GLES20.glGetString(GLES20.GL_RENDERER)
+ // or GLES30.glGetString(GLES30.GL_RENDERER)
+ optional string opengl_renderer = 27;
+
+ // Hardware features that may be available on the device.
+ // This includes features such as camera, gps and compass.
+ message Feature {
+ optional string name = 1;
+ optional string type = 2;
+ optional bool available = 3;
+ optional int32 version = 4;
+ }
+ repeated Feature feature = 15;
+
+ // Running processes.
+ message Process {
+ optional string name = 1;
+ optional int32 uid = 2;
+ }
+ repeated Process process = 16;
+
+ // Configuration.smallestScreenWidthDp
+ optional int32 smallest_screen_width_dp = 28;
+
+ // The value reported from UserManager.getMaxSupportedUsers
+ optional int32 max_supported_users = 31;
+ }
+ optional DeviceInfo device_info = 5;
+
+ // Information about the host running the test suite.
+ message HostInfo {
+
+ // Hostname of the machine running the tests.
+ optional string hostname = 1;
+
+ // Operating system running on the host.
+ message Os {
+ optional string arch = 1;
+ optional string name = 2;
+ optional string version = 3;
+ }
+ optional Os os = 2;
+
+ // Information about the JRE used to run the tests.
+ message JavaEnv {
+ optional string name = 1;
+ optional string version = 2;
+ }
+ optional JavaEnv java_env = 3;
+
+ // CTS version and parameters during runtime.
+ message Cts {
+ optional string version = 1;
+
+ message Parameter {
+ optional string name = 1;
+ optional int32 value = 2;
+ }
+ repeated Parameter parameter = 2;
+ }
+ optional Cts cts = 4;
+ }
+ optional HostInfo host_info = 6;
+
+ optional Summary summary = 7;
+
+ // Group of test suites within a specific java package.
+ message TestPackage {
+
+ // Java package name.
+ optional string deprecated_app_package_name = 1 [deprecated = true];
+
+ // Unique name describing the test package within the java package.
+ optional string name = 2;
+ optional string deprecated_digest = 3 [deprecated = true];
+ optional bool deprecated_signature_check = 4 [deprecated = true];
+
+ // Group of test cases.
+ message TestSuite {
+
+ // Unique name describing the test suite within the test package.
+ optional string name = 1;
+
+ // Group of individual tests.
+ message TestCase {
+
+ // Unique name describing the test case within the test suite.
+ optional string name = 1;
+ optional string priority = 2;
+
+ // Smallest test unit, which ideally tests only one feature or function.
+ message Test {
+
+ // Unique name describing the test within the test case.
+ optional string name = 1;
+
+ // Result of the test run.
+ optional string result = 2;
+
+ // Bug id for known issues.
+ optional string deprecated_known_failure = 3 [deprecated = true];
+
+ // Time this test was started.
+ optional int64 deprecated_start_time = 4 [deprecated = true];
+
+ // Time this test completed.
+ optional int64 deprecated_end_time = 5 [deprecated = true];
+
+ // Captures an exception thrown during the test.
+ message FailedScene {
+ optional string exception_message = 1;
+ optional string stack_trace = 2;
+ }
+ repeated FailedScene failed_scene = 6;
+
+ // Summary of the PTS test.
+ message Summary {
+ optional string message = 1;
+ optional ResultType score_type = 2;
+ optional ResultUnit unit = 3;
+ optional double value = 4;
+ }
+ optional Summary summary = 7;
+
+ // Details of the PTS test.
+ message Details {
+
+ // Set of values captured when running the PTS test.
+ message ValueArray {
+ optional string source = 1;
+ optional string message = 2;
+ optional ResultType score_type = 3;
+ optional ResultUnit unit = 4;
+ repeated double value = 5;
+ }
+ repeated ValueArray value_array = 1;
+ }
+ optional Details details = 8;
+ }
+ repeated Test test = 3;
+ }
+ repeated TestCase test_case = 2;
+ }
+ repeated TestSuite test_suite = 5;
+
+ // abi specifies the ABI the test ran under like "armeabi".
+ optional string abi = 6;
+ }
+ repeated TestPackage test_package = 8;
+}
\ No newline at end of file
diff --git a/tools/cts-api-coverage/proto/testsuite.proto b/tools/cts-api-coverage/proto/testsuite.proto
index a0adb6f..c4f55d4 100644
--- a/tools/cts-api-coverage/proto/testsuite.proto
+++ b/tools/cts-api-coverage/proto/testsuite.proto
@@ -48,6 +48,68 @@
repeated TestClass test_classes = 5;
}
+message Annotation {
+ int32 visibility = 1;
+ string type = 2;
+
+ message Element {
+ string name = 1;
+ string value = 2;
+ }
+ repeated Element elements = 3;
+}
+
+message TestSuite {
+ string name = 1;
+
+ message Package {
+ string name = 1;
+
+ message Class {
+ string name = 1;
+ string type = 2;
+ string super_class = 3;
+ string interface = 4;
+
+ enum Type {
+ UNKNOWN = 0;
+ JUNIT3 = 1;
+ JUNIT4 = 2;
+ PARAMETERIZED = 3;
+ JAVAHOST = 4;
+ GTEST = 5;
+ DEQP = 6;
+ }
+ Type test_type = 5;
+ repeated Annotation annotations = 6;
+
+ message Method {
+ string defining_class = 1;
+ string name = 2;
+ string parameters = 3;
+ string return_type = 4;
+ int32 access_flags = 5;
+ repeated Annotation annotations = 6;
+ }
+ repeated Method methods = 7;
+
+ message Field {
+ string defining_class = 1;
+ string name = 2;
+ string type = 3;
+ int32 access_flags = 4;
+ string initial_value = 5;
+ repeated Annotation annotations = 6;
+ }
+ repeated Field fields = 8;
+ string apk = 9;
+ }
+ repeated Class classes = 2;
+ string op_codes = 3;
+ }
+ repeated Package packages = 2;
+}
+
// target File Metadata for e.g. config, apk, jar, exe, so
message FileMetadata {
string description = 1;
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsReportHandler.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsReportHandler.java
new file mode 100644
index 0000000..d0247e2
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsReportHandler.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.apicoverage;
+
+import com.android.cts.apicoverage.CtsReportProto.*;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * {@link DefaultHandler} that builds an empty {@link ApiCoverage} object from scanning
+ * TestModule.xml.
+ */
+class CtsReportHandler extends DefaultHandler {
+ private static final String MODULE_TAG = "Module";
+ private static final String TEST_CASE_TAG = "TestCase";
+ private static final String TEST_TAG = "Test";
+ private static final String NAME_TAG = "name";
+ private static final String RESULT_TAG = "result";
+ private static final String ABI_TAG = "abi";
+ private static final String DONE_TAG = "done";
+ private static final String PASS_TAG = "pass";
+ private static final String FAILED_TAG = "failed";
+ private static final String RUNTIME_TAG = "runtime";
+
+ private CtsReport.Builder mCtsReportBld;
+ private CtsReport.TestPackage.Builder mTestPackageBld;
+ private CtsReport.TestPackage.TestSuite.Builder mModuleBld;
+ private CtsReport.TestPackage.TestSuite.TestCase.Builder mTestCaseBld;
+
+ CtsReportHandler(String configFileName) {
+ mCtsReportBld = CtsReport.newBuilder();
+ mTestPackageBld = CtsReport.TestPackage.newBuilder();
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String name, Attributes attributes)
+ throws SAXException {
+ super.startElement(uri, localName, name, attributes);
+
+ try {
+ if (MODULE_TAG.equalsIgnoreCase(localName)) {
+ mModuleBld = CtsReport.TestPackage.TestSuite.newBuilder();
+ mModuleBld.setName(attributes.getValue(ABI_TAG)+","+attributes.getValue(NAME_TAG));
+ } else if (TEST_CASE_TAG.equalsIgnoreCase(localName)) {
+ mTestCaseBld = CtsReport.TestPackage.TestSuite.TestCase.newBuilder();
+ mTestCaseBld.setName(attributes.getValue(NAME_TAG));
+ } else if (TEST_TAG.equalsIgnoreCase(localName)) {
+ CtsReport.TestPackage.TestSuite.TestCase.Test.Builder testBld;
+ testBld = CtsReport.TestPackage.TestSuite.TestCase.Test.newBuilder();
+ testBld.setName(attributes.getValue(NAME_TAG));
+ testBld.setResult(attributes.getValue(RESULT_TAG));
+ mTestCaseBld.addTest(testBld);
+ }
+ } catch (Exception ex) {
+ System.err.println(localName + " " + name);
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String name) throws SAXException {
+ super.endElement(uri, localName, name);
+
+ if (MODULE_TAG.equalsIgnoreCase(localName)) {
+ mTestPackageBld.addTestSuite(mModuleBld);
+ mModuleBld = null;
+ } else if (TEST_CASE_TAG.equalsIgnoreCase(localName)) {
+ mModuleBld.addTestCase(mTestCaseBld);
+ mTestCaseBld = null;
+ }
+ }
+
+ public CtsReport getCtsReport() {
+ mCtsReportBld.addTestPackage(mTestPackageBld);
+ return mCtsReportBld.build();
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsReportParser.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsReportParser.java
new file mode 100644
index 0000000..e094a34
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsReportParser.java
@@ -0,0 +1,168 @@
+/*
+ * 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 com.android.cts.apicoverage;
+
+import com.android.cts.apicoverage.CtsReportProto.*;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+/**
+ * Class that outputs an XML report of the {@link ApiCoverage} collected. It can be viewed in a
+ * browser when used with the api-coverage.css and api-coverage.xsl files.
+ */
+class CtsReportParser {
+ public static final String TEST_RESULT_FILE_NAME = "test_result.xml";
+
+ private static void printUsage() {
+ System.out.println("Usage: CtsReportParser [OPTION]... [APK]...");
+ System.out.println();
+ System.out.println("Generates a report about what Android NDK methods.");
+ System.out.println();
+ System.out.println("Options:");
+ System.out.println(" -o FILE output file or standard out if not given");
+ System.out.println(" -i PATH path to the Test_Result.xml");
+ System.out.println();
+ System.exit(1);
+ }
+
+ private static CtsReport parseCtsReport(String testResultPath)
+ throws Exception {
+ XMLReader xmlReader = XMLReaderFactory.createXMLReader();
+ CtsReportHandler ctsReportXmlHandler =
+ new CtsReportHandler(testResultPath);
+ xmlReader.setContentHandler(ctsReportXmlHandler);
+ FileReader fileReader = null;
+ try {
+ fileReader = new FileReader(testResultPath);
+ xmlReader.parse(new InputSource(fileReader));
+ } finally {
+ if (fileReader != null) {
+ fileReader.close();
+ }
+ }
+ return ctsReportXmlHandler.getCtsReport();
+ }
+
+ private static void printCtsReport(CtsReport ctsReport) {
+ //Header
+ System.out.println("no,Abi,Module,Class,Test,Result");
+ int i = 1;
+ for (CtsReport.TestPackage tPkg : ctsReport.getTestPackageList()) {
+ for (CtsReport.TestPackage.TestSuite module : tPkg.getTestSuiteList()) {
+ for (CtsReport.TestPackage.TestSuite.TestCase testCase : module.getTestCaseList()) {
+ for (CtsReport.TestPackage.TestSuite.TestCase.Test test : testCase.getTestList()) {
+ System.out.printf("%d,%s,%s,%s,%s\n",
+ i++,
+ module.getName(),
+ testCase.getName(),
+ test.getName(),
+ test.getResult());
+ }
+ }
+ }
+ }
+ }
+
+ static void printCtsReportSummary(CtsReport ctsReport, String fName)
+ throws IOException{
+
+ FileWriter fWriter = new FileWriter(fName);
+ PrintWriter pWriter = new PrintWriter(fWriter);
+
+ //Header
+ pWriter.print("no,Module,Test#\n");
+
+ for (CtsReport.TestPackage tPkg : ctsReport.getTestPackageList()) {
+ int moduleCnt = 0;
+ for (CtsReport.TestPackage.TestSuite module : tPkg.getTestSuiteList()) {
+ int testCaseCnt = 0;
+ for (CtsReport.TestPackage.TestSuite.TestCase testCase : module.getTestCaseList()) {
+ for (CtsReport.TestPackage.TestSuite.TestCase.Test test : testCase.getTestList()) {
+ testCaseCnt++;
+ }
+ }
+ pWriter.printf("%d,%s,%d\n",
+ moduleCnt++,
+ module.getName(),
+ testCaseCnt);
+ }
+ }
+
+ pWriter.close();
+ }
+
+ public static void main(String[] args)
+ throws IOException, SAXException, Exception {
+ String testResultPath = "./test_result.xml";
+ String outputFileName = "./test_result.pb";
+ String outputSummaryFilePath = "./reportSummary.csv";
+ int numTestModule = 0;
+
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].startsWith("-")) {
+ if ("-o".equals(args[i])) {
+ outputFileName = getExpectedArg(args, ++i);
+ } else if ("-i".equals(args[i])) {
+ testResultPath = getExpectedArg(args, ++i);
+ } else if ("-s".equals(args[i])) {
+ outputSummaryFilePath = getExpectedArg(args, ++i);
+ } else {
+ printUsage();
+ }
+ } else {
+ printUsage();
+ }
+ }
+
+ // Read message from the file and print them out
+ CtsReport ctsReport = parseCtsReport(testResultPath);
+
+ printCtsReport(ctsReport);
+ printCtsReportSummary(ctsReport, outputSummaryFilePath);
+
+
+ // Write test case list message to disk.
+ FileOutputStream output = new FileOutputStream(outputFileName);
+ try {
+ ctsReport.writeTo(output);
+ } finally {
+ output.close();
+ }
+ }
+
+ /** Get the argument or print out the usage and exit. */
+ private static String getExpectedArg(String[] args, int index) {
+ if (index < args.length) {
+ return args[index];
+ } else {
+ printUsage();
+ return null; // Never will happen because printUsage will call exit(1)
+ }
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TestCaseReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TestCaseReport.java
new file mode 100644
index 0000000..7cc42b0
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TestCaseReport.java
@@ -0,0 +1,371 @@
+/*
+ * 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 com.android.cts.apicoverage;
+
+
+import com.android.cts.apicoverage.TestSuiteProto.*;
+
+import org.jf.dexlib2.AccessFlags;
+import org.jf.dexlib2.DexFileFactory;
+import org.jf.dexlib2.Opcodes;
+import org.jf.dexlib2.iface.Annotation;
+import org.jf.dexlib2.iface.AnnotationElement;
+import org.jf.dexlib2.iface.ClassDef;
+import org.jf.dexlib2.iface.DexFile;
+import org.jf.dexlib2.iface.Method;
+import org.jf.dexlib2.iface.value.StringEncodedValue;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.NoSuchAlgorithmException;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+class TestCaseReport {
+ // JUNIT3 Test suffix
+ private static final String TEST_TAG = "Test;";
+ private static final String TEST_PREFIX_TAG = "test";
+ private static final String RUN_WITH_ANNOTATION_TAG =
+ "Lorg/junit/runner/RunWith;";
+ private static final String TEST_ANNOTATION_TAG =
+ "Lorg/junit/Test;";
+ private static final String PARAMETERS_TAG =
+ "Lorg/junit/runners/Parameterized$Parameters";
+ private static final String ANDROID_JUNIT4_TEST_TAG =
+ "AndroidJUnit4.class";
+ private static final String PARAMETERIZED_TAG =
+ "Parameterized.class";
+
+ // configuration option
+ private static final String NOT_SHARDABLE_TAG = "not-shardable";
+ // test class option
+ private static final String RUNTIME_HIT_TAG = "runtime-hint";
+ // com.android.tradefed.testtype.AndroidJUnitTest option
+ private static final String PACKAGE_TAG = "package";
+ // com.android.compatibility.common.tradefed.testtype.JarHostTest option
+ private static final String JAR_NAME_TAG = "jar";
+ // com.android.tradefed.testtype.GTest option
+ private static final String NATIVE_TEST_DEVICE_PATH_TAG = "native-test-device-path";
+ private static final String MODULE_TAG = "module-name";
+
+ private static final String SUITE_API_INSTALLER_TAG = "com.android.tradefed.targetprep.suite.SuiteApkInstaller";
+ private static final String JAR_HOST_TEST_TAG = "com.android.compatibility.common.tradefed.testtype.JarHostTest";
+ // com.android.tradefed.targetprep.suite.SuiteApkInstaller option
+ private static final String TEST_FILE_NAME_TAG = "test-file-name";
+ // com.android.compatibility.common.tradefed.targetprep.FilePusher option
+ private static final String PUSH_TAG = "push";
+
+ // test class
+ private static final String ANDROID_JUNIT_TEST_TAG = "com.android.tradefed.testtype.AndroidJUnitTest";
+
+ // Target File Extensions
+ private static final String CONFIG_EXT_TAG = ".config";
+ private static final String CONFIG_REGEX = ".config$";
+ private static final String JAR_EXT_TAG = ".jar";
+ private static final String APK_EXT_TAG = ".apk";
+ private static final String SO_EXT_TAG = ".so";
+
+ private static void printUsage() {
+ System.out.println("Usage: test-suite-content-report [OPTION]...");
+ System.out.println();
+ System.out.println("Generates test test list protocal buffer message.");
+ System.out.println();
+ System.out.println(
+ "$ANDROID_HOST_OUT/bin/test-suite-content-report "
+ + "-i out/host/linux-x86/cts/android-cts/testcases "
+ + "-c ./cts-content.pb"
+ + "-o ./cts-list.pb");
+ System.out.println();
+ System.out.println("Options:");
+ System.out.println(" -i PATH path to the Test Suite Folder");
+ System.out.println(" -c FILE input file of Test Content Protocal Buffer");
+ System.out.println(" -o FILE output file of Test Case List Protocal Buffer");
+ System.out.println();
+ System.exit(1);
+ }
+
+ /** Get the argument or print out the usage and exit. */
+ private static String getExpectedArg(String[] args, int index) {
+ if (index < args.length) {
+ return args[index];
+ } else {
+ printUsage();
+ return null; // Never will happen because print Usage will call exit(1)
+ }
+ }
+
+ private static boolean hasAnnotation(Set<? extends Annotation> annotations, String tag) {
+ for (Annotation annotation : annotations) {
+ if (annotation.getType().equals(tag)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static TestSuite.Package.Class.Type chkTestType(ClassDef classDef) {
+ for (Annotation annotation : classDef.getAnnotations()) {
+ if (annotation.getType().equals(RUN_WITH_ANNOTATION_TAG)) {
+ for (AnnotationElement annotationEle : annotation.getElements()) {
+ String aName = annotationEle.getName();
+ if (aName.equals(ANDROID_JUNIT4_TEST_TAG)) {
+ return TestSuite.Package.Class.Type.JUNIT4;
+ } else if (aName.equals(PARAMETERIZED_TAG)) {
+ return TestSuite.Package.Class.Type.PARAMETERIZED;
+ }
+ }
+
+ return TestSuite.Package.Class.Type.JUNIT4;
+ }
+ }
+
+ if (classDef.getType().endsWith(TEST_TAG)) {
+ return TestSuite.Package.Class.Type.JUNIT3;
+ } else {
+ return TestSuite.Package.Class.Type.UNKNOWN;
+ }
+ }
+
+ private static boolean isTargetClass(List<String> pkgList, String className) {
+ boolean found = false;
+ for (String pkg : pkgList) {
+ if (className.startsWith(pkg)) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+ }
+
+ // Get test case list from an APK
+ private static TestSuite.Package.Builder parseApkTestCase(List<String> apkList,
+ List<String> classList, String tsPath, int api)
+ throws Exception {
+
+ TestSuite.Package.Builder tsPkgBuilder = TestSuite.Package.newBuilder();
+ for (String apkName : apkList) {
+ DexFile dexFile = null;
+ String apkPath = Paths.get(tsPath, apkName).toString();
+ try {
+ dexFile = DexFileFactory.loadDexFile(apkPath, Opcodes.forApi(api));
+ } catch (IOException | DexFileFactory.DexFileNotFoundException ex) {
+ System.err.println("Unable to load dex file: " + apkPath);
+ // ex.printStackTrace();
+ continue;
+ }
+
+ tsPkgBuilder.setName(apkName);
+ for (ClassDef classDef : dexFile.getClasses()) {
+ // adjust the format Lclass/y;
+ String className = classDef.getType().replace('/','.');
+ // remove L...;
+ if (className.length() > 2) {
+ className = className.substring(1, className.length() - 1);
+ }
+ if (isTargetClass(classList, className)){
+ if ((classDef.getAccessFlags() & AccessFlags.PUBLIC.getValue()) != 0) {
+ TestSuite.Package.Class.Builder tClassBuilder = TestSuite.Package.Class.newBuilder();
+ tClassBuilder.setTestType(chkTestType(classDef));
+ tClassBuilder.setApk(apkName);
+ tClassBuilder.setName(className);
+ if (TestSuite.Package.Class.Type.JUNIT3 == tClassBuilder.getTestType()) {
+ for (Method method : classDef.getMethods()) {
+ if ((method.getAccessFlags() & AccessFlags.PUBLIC.getValue()) != 0) {
+ String mName = method.getName();
+ if (mName.startsWith(TEST_PREFIX_TAG)) {
+ TestSuite.Package.Class.Method.Builder methodBuilder = TestSuite.Package.Class.Method.newBuilder();
+ methodBuilder.setName(mName);
+ tClassBuilder.addMethods(methodBuilder);
+ }
+ }
+ }
+ } else if (TestSuite.Package.Class.Type.JUNIT4 == tClassBuilder.getTestType()) {
+ for (Method method : classDef.getMethods()) {
+ if (hasAnnotation(method.getAnnotations(), TEST_ANNOTATION_TAG)) {
+ String mName = method.getName();
+ TestSuite.Package.Class.Method.Builder methodBuilder = TestSuite.Package.Class.Method.newBuilder();
+ methodBuilder.setName(mName);
+ tClassBuilder.addMethods(methodBuilder);
+ }
+ }
+ }
+ tsPkgBuilder.addClasses(tClassBuilder);
+ }
+ }
+ }
+ }
+ return tsPkgBuilder;
+ }
+
+ // Iterates though all test suite content and prints them.
+ static TestSuite.Builder listTestCases(TestSuiteContent tsContent, String tsPath)
+ throws Exception {
+ TestSuite.Builder tsBuilder = TestSuite.newBuilder();
+
+ int i = 1;
+ for (Entry entry: tsContent.getFileEntriesList()) {
+ if (Entry.EntryType.CONFIG == entry.getType()) {
+ ConfigMetadata config = entry.getFileMetadata().getConfigMetadata();
+
+ // getting package/class list from Test Module Configuration
+ ArrayList<String> testClassList = new ArrayList<String> ();
+ List<Option> optList;
+ List<ConfigMetadata.TestClass> testClassesList = config.getTestClassesList();
+ for (ConfigMetadata.TestClass tClass : testClassesList) {
+ optList = tClass.getOptionsList();
+ for (Option opt : optList) {
+ if (PACKAGE_TAG.equalsIgnoreCase(opt.getName())) {
+ testClassList.add(opt.getValue());
+ }
+ }
+ }
+
+ // getting apk list from Test Module Configuration
+ ArrayList<String> testApkList = new ArrayList<String> ();
+ List<ConfigMetadata.TargetPreparer> tPrepList = config.getTargetPreparersList();
+ for (ConfigMetadata.TargetPreparer tPrep : tPrepList) {
+ optList = tPrep.getOptionsList();
+ for (Option opt : optList) {
+ if (TEST_FILE_NAME_TAG.equalsIgnoreCase(opt.getName())) {
+ testApkList.add(opt.getValue());
+ }
+ }
+ }
+
+ TestSuite.Package.Builder tsPkgBuilder =
+ parseApkTestCase(testApkList, testClassList, tsPath, 27);
+ tsPkgBuilder.setName(entry.getName().replaceAll(CONFIG_REGEX, ""));
+ tsBuilder.addPackages(tsPkgBuilder);
+ }
+ }
+ return tsBuilder;
+ }
+
+ // Iterates though all test suite content and prints them.
+ static void printTestSuite(TestSuite ts) {
+ //Header
+ System.out.println("no,Module,Class,Test,Apk,Type");
+ int i = 1;
+ for (TestSuite.Package pkg : ts.getPackagesList()) {
+ for (TestSuite.Package.Class cls : pkg.getClassesList()) {
+ for (TestSuite.Package.Class.Method mtd : cls.getMethodsList()) {
+ System.out.printf("%d,%s,%s,%s,%s,%s\n",
+ i++,
+ pkg.getName(),
+ cls.getName(),
+ mtd.getName(),
+ cls.getApk(),
+ cls.getTestType());
+ }
+ }
+ }
+ }
+
+ // Iterates though all test suite content and prints them.
+ static void printTestSuiteSummary(TestSuite ts, String fName)
+ throws IOException{
+ FileWriter fWriter = new FileWriter(fName);
+ PrintWriter pWriter = new PrintWriter(fWriter);
+
+ //Header
+ pWriter.print("no,Module,Test#,Class#\n");
+
+ int i = 0;
+ for (TestSuite.Package pkg : ts.getPackagesList()) {
+ int classCnt = 0;
+ int methodCnt = 0;
+ for (TestSuite.Package.Class cls : pkg.getClassesList()) {
+ for (TestSuite.Package.Class.Method mtd : cls.getMethodsList()) {
+ methodCnt++;
+ }
+ classCnt++;
+ }
+ pWriter.printf("%d,%s,%d,%d\n",
+ i++,
+ pkg.getName(),
+ methodCnt,
+ classCnt);
+ }
+
+ pWriter.close();
+ }
+
+ public static void main(String[] args)
+ throws IOException, NoSuchAlgorithmException, Exception {
+ String tsContentFilePath = "./tsContentMessage.pb";
+ String outputTestCaseListFilePath = "./tsTestCaseList.pb";
+ String outputSummaryFilePath = "./tsSummary.csv";
+ String tsPath = "";
+
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].startsWith("-")) {
+ if ("-o".equals(args[i])) {
+ outputTestCaseListFilePath = getExpectedArg(args, ++i);
+ } else if ("-c".equals(args[i])) {
+ tsContentFilePath = getExpectedArg(args, ++i);
+ } else if ("-s".equals(args[i])) {
+ outputSummaryFilePath = getExpectedArg(args, ++i);
+ } else if ("-i".equals(args[i])) {
+ tsPath = getExpectedArg(args, ++i);
+ File file = new File(tsPath);
+ // Only acception a folder
+ if (!file.isDirectory()) {
+ printUsage();
+ }
+ } else {
+ printUsage();
+ }
+ }
+ }
+
+ // Read message from the file and print them out
+ TestSuiteContent tsContent =
+ TestSuiteContent.parseFrom(new FileInputStream(tsContentFilePath));
+
+ TestSuite ts = listTestCases(tsContent, tsPath).build();
+
+ // Write test case list message to disk.
+ FileOutputStream output = new FileOutputStream(outputTestCaseListFilePath);
+ try {
+ ts.writeTo(output);
+ } finally {
+ output.close();
+ }
+
+ // Read message from the file and print them out
+ TestSuite ts1 = TestSuite.parseFrom(new FileInputStream(outputTestCaseListFilePath));
+ printTestSuite(ts1);
+ printTestSuiteSummary(ts1, outputSummaryFilePath);
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TestSuiteContentReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TestSuiteContentReport.java
index 044acdc..dae80ed 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TestSuiteContentReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TestSuiteContentReport.java
@@ -19,6 +19,14 @@
import com.android.cts.apicoverage.TestSuiteProto.*;
+import org.jf.dexlib2.DexFileFactory;
+import org.jf.dexlib2.Opcodes;
+import org.jf.dexlib2.iface.Annotation;
+import org.jf.dexlib2.iface.AnnotationElement;
+import org.jf.dexlib2.iface.ClassDef;
+import org.jf.dexlib2.iface.DexFile;
+import org.jf.dexlib2.iface.Method;
+import org.jf.dexlib2.iface.value.StringEncodedValue;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
@@ -60,6 +68,9 @@
// com.android.compatibility.common.tradefed.targetprep.FilePusher option
private static final String PUSH_TAG = "push";
+ // test class
+ private static final String ANDROID_JUNIT_TEST_TAG = "com.android.tradefed.testtype.AndroidJUnitTest";
+
// Target File Extensions
private static final String CONFIG_EXT_TAG = ".config";
private static final String JAR_EXT_TAG = ".jar";
@@ -74,11 +85,13 @@
System.out.println(
"$ANDROID_HOST_OUT/bin/test-suite-content-report "
+ "-i out/host/linux-x86/cts/android-cts "
- + "-o ./cts-content.pb");
+ + "-o ./cts-content.pb"
+ + "-t ./cts-list.pb");
System.out.println();
System.out.println("Options:");
- System.out.println(" -o FILE output file or standard out if not given");
System.out.println(" -i PATH path to the Test Suite Folder");
+ System.out.println(" -o FILE output file of Test Content Protocal Buffer");
+ System.out.println(" -t FILE output file of Test Case List Protocal Buffer");
System.out.println();
System.exit(1);
}
@@ -246,7 +259,7 @@
}
// Iterates though all test suite content and prints them.
- static void Print(TestSuiteContent tsContent) {
+ static void printTestSuiteContent(TestSuiteContent tsContent) {
//Header
System.out.printf("no,type,name,size,relative path,id,content id,parent id,description,test class");
// test class header
@@ -262,6 +275,7 @@
i++, entry.getType(), entry.getName(), entry.getSize(),
entry.getRelativePath(), entry.getId(), entry.getContentId(),
entry.getParentId());
+
if (Entry.EntryType.CONFIG == entry.getType()) {
ConfigMetadata config = entry.getFileMetadata().getConfigMetadata();
System.out.printf(",%s", entry.getFileMetadata().getDescription());
@@ -315,18 +329,20 @@
public static void main(String[] args)
throws IOException, NoSuchAlgorithmException {
String outputFilePath = "./tsContentMessage.pb";
+ String outputTestCaseListFilePath = "./tsTestCaseList.pb";
String tsPath = "";
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("-")) {
if ("-o".equals(args[i])) {
outputFilePath = getExpectedArg(args, ++i);
+ } else if ("-t".equals(args[i])) {
+ outputTestCaseListFilePath = getExpectedArg(args, ++i);
} else if ("-i".equals(args[i])) {
tsPath = getExpectedArg(args, ++i);
File file = new File(tsPath);
- if (file.isDirectory()) {
- //
- } else {
+ // Only acception a folder
+ if (!file.isDirectory()) {
printUsage();
}
} else {
@@ -348,6 +364,6 @@
// Read message from the file and print them out
TestSuiteContent tsContent1 =
TestSuiteContent.parseFrom(new FileInputStream(outputFilePath));
- Print(tsContent1);
+ printTestSuiteContent(tsContent1);
}
}
diff --git a/tools/cts-device-info/src/com/android/cts/deviceinfo/CameraDeviceInfo.java b/tools/cts-device-info/src/com/android/cts/deviceinfo/CameraDeviceInfo.java
index 782e075..01917d3 100644
--- a/tools/cts-device-info/src/com/android/cts/deviceinfo/CameraDeviceInfo.java
+++ b/tools/cts-device-info/src/com/android/cts/deviceinfo/CameraDeviceInfo.java
@@ -468,6 +468,7 @@
charsKeyNames.add(CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES.getName());
charsKeyNames.add(CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES.getName());
charsKeyNames.add(CameraCharacteristics.LENS_FACING.getName());
+ charsKeyNames.add(CameraCharacteristics.LENS_POSE_REFERENCE.getName());
charsKeyNames.add(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES.getName());
charsKeyNames.add(CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES.getName());
charsKeyNames.add(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS.getName());
@@ -515,6 +516,7 @@
charsKeyNames.add(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT.getName());
charsKeyNames.add(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES.getName());
charsKeyNames.add(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES.getName());
+ charsKeyNames.add(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES.getName());
charsKeyNames.add(CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS.getName());
charsKeyNames.add(CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES.getName());
charsKeyNames.add(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL.getName());