Merge "[CTSVerifier] Release virtual display when we are done with it" into marshmallow-cts-dev
am: 577bed408e
* commit '577bed408e8b200fb0ae547a380dc86d7bd8666e':
[CTSVerifier] Release virtual display when we are done with it
Change-Id: I121522ff808c60c10374c0997d8145f36cc4e39c
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 9e5a0b1..d8ac03a 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -106,7 +106,6 @@
CtsMonkeyApp2 \
CtsPackageInstallerApp \
CtsPermissionApp \
- CtsPreconditionsApp \
CtsSimpleApp \
CtsSimplePreMApp \
CtsSomeAccessibilityServices \
diff --git a/apps/CameraITS/tests/scene1/test_black_white.py b/apps/CameraITS/tests/scene1/test_black_white.py
index 56bc5ec..68d7de6 100644
--- a/apps/CameraITS/tests/scene1/test_black_white.py
+++ b/apps/CameraITS/tests/scene1/test_black_white.py
@@ -76,9 +76,9 @@
matplotlib.pyplot.savefig("%s_plot_means.png" % (NAME))
for val in black_means:
- assert(val < 0.035)
+ assert(val < 0.025)
for val in white_means:
- assert(val > 0.965)
+ assert(val > 0.975)
if __name__ == '__main__':
main()
diff --git a/apps/CameraITS/tests/scene1/test_exposure.py b/apps/CameraITS/tests/scene1/test_exposure.py
index e448f80..dc4a790 100644
--- a/apps/CameraITS/tests/scene1/test_exposure.py
+++ b/apps/CameraITS/tests/scene1/test_exposure.py
@@ -61,9 +61,8 @@
mults.append(m)
s_test = round(s*m)
e_test = s_e_product / s_test
- print "Testsing s:", s_test, "e:", e_test
- req = its.objects.manual_capture_request(
- s_test, e_test, True, props)
+ print "Testing s:", s_test, "e:", e_test
+ req = its.objects.manual_capture_request(s_test, e_test, True, props)
cap = cam.do_capture(req)
s_res = cap["metadata"]["android.sensor.sensitivity"]
e_res = cap["metadata"]["android.sensor.exposureTime"]
@@ -113,4 +112,3 @@
if __name__ == '__main__':
main()
-
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 18ef8dd..ad78a59 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -41,7 +41,7 @@
LOCAL_PACKAGE_NAME := CtsVerifier
-LOCAL_JNI_SHARED_LIBRARIES := libctsverifier_jni libaudioloopback_jni
+LOCAL_JNI_SHARED_LIBRARIES := libctsverifier_jni
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 954f093..913c1f0 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.verifier"
android:versionCode="5"
- android:versionName="6.0_r6">
+ android:versionName="6.0_r201602s">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23"/>
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
index be44243..c74ed3a 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
@@ -20,4 +20,6 @@
* class instead of DeviceInfoActivity.
*/
public abstract class DeviceInfo extends DeviceInfoActivity {
+
}
+
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AdoptableHostTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AdoptableHostTest.java
index 6bf2a01..2ae2e10 100644
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AdoptableHostTest.java
@@ -26,7 +26,6 @@
import com.android.cts.appsecurity.SplitTests.BaseInstallMultiple;
import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
@@ -34,7 +33,6 @@
import com.android.tradefed.testtype.IBuildReceiver;
import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
/**
* Set of tests that verify behavior of adopted storage media, if supported.
@@ -149,10 +147,7 @@
final LocalVolumeInfo vol = getAdoptionVolume();
// Move storage there and verify that data went along for ride
- final CollectingOutputReceiver out = new CollectingOutputReceiver();
- getDevice().executeShellCommand("pm move-primary-storage " + vol.uuid, out, 2,
- TimeUnit.HOURS, 1);
- assertSuccess(out.getOutput());
+ assertSuccess(getDevice().executeShellCommand("pm move-primary-storage " + vol.uuid));
runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WifiTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WifiTest.java
index 685ad82..c4c02e8 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WifiTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WifiTest.java
@@ -44,7 +44,7 @@
private static final String NETWORK_SSID = "com.android.cts.xwde7ktvh8rmjuhr";
// Time duration to allow before assuming that a WiFi operation failed and ceasing to wait.
- private static final long UPDATE_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(5);
+ private static final long UPDATE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(30);
private static final long UPDATE_INTERVAL_MS = TimeUnit.SECONDS.toMillis(1);
// Shared WifiManager instance.
diff --git a/libs/testserver/src/android/webkit/cts/CtsTestServer.java b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
index 321b44d..de88f3b 100644
--- a/libs/testserver/src/android/webkit/cts/CtsTestServer.java
+++ b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
@@ -54,31 +54,34 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
+import java.net.URLConnection;
+import java.security.KeyManagementException;
import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.Vector;
+import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
@@ -112,6 +115,7 @@
private static final String COOKIE_PREFIX = "/cookie";
private static final String LINKED_SCRIPT_PREFIX = "/linkedscriptprefix";
private static final String AUTH_PREFIX = "/auth";
+ private static final String SHUTDOWN_PREFIX = "/shutdown";
public static final String NOLENGTH_POSTFIX = "nolength";
private static final int DELAY_MILLIS = 2000;
@@ -219,13 +223,74 @@
* Terminate the http server.
*/
public void shutdown() {
- mServerThread.shutDownOnClientThread();
-
try {
+ // Avoid a deadlock between two threads where one is trying to call
+ // close() and the other one is calling accept() by sending a GET
+ // request for shutdown and having the server's one thread
+ // sequentially call accept() and close().
+ URL url = new URL(mServerUri + SHUTDOWN_PREFIX);
+ if (url.getProtocol().equalsIgnoreCase("http")) {
+ // Use Socket instead of HttpURLConnection when the server is in cleartext HTTP mode
+ // to avoid the request being blocked by NetworkSecurityPolicy.
+ Socket socket = null;
+ try {
+ socket = new Socket(url.getHost(), url.getPort());
+ socket.getOutputStream().write(
+ ("GET " + SHUTDOWN_PREFIX + " HTTP/1.0\r\n\r\n").getBytes("US-ASCII"));
+ socket.getOutputStream().flush();
+ } finally {
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (Exception ignored) {}
+ }
+ }
+ } else {
+ URLConnection connection = openConnection(url);
+ connection.connect();
+
+ // Read the input from the stream to send the request.
+ InputStream is = connection.getInputStream();
+ is.close();
+ }
+
// Block until the server thread is done shutting down.
mServerThread.join();
+
+ } catch (MalformedURLException e) {
+ throw new IllegalStateException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalStateException(e);
+ } catch (KeyManagementException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private URLConnection openConnection(URL url)
+ throws IOException, NoSuchAlgorithmException, KeyManagementException {
+ if (mSsl == SslMode.INSECURE) {
+ return url.openConnection();
+ } else {
+ // Install hostname verifiers and trust managers that don't do
+ // anything in order to get around the client not trusting
+ // the test server due to a lack of certificates.
+
+ HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+ connection.setHostnameVerifier(new CtsHostnameVerifier());
+
+ SSLContext context = SSLContext.getInstance("TLS");
+ try {
+ context.init(ServerThread.getKeyManagers(), getTrustManagers(), null);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ connection.setSSLSocketFactory(context.getSocketFactory());
+
+ return connection;
}
}
@@ -710,6 +775,11 @@
response.setEntity(createPage(agent, agent));
} else if (path.equals(TEST_DOWNLOAD_PATH)) {
response = createTestDownloadResponse(Uri.parse(uriString));
+ } else if (path.equals(SHUTDOWN_PREFIX)) {
+ response = createResponse(HttpStatus.SC_OK);
+ // We cannot close the socket here, because we need to respond.
+ // Status must be set to OK, or else the test will fail due to
+ // a RunTimeException.
} else if (path.equals(APPCACHE_PATH)) {
response = createResponse(HttpStatus.SC_OK);
response.setEntity(createEntity("<!DOCTYPE HTML>" +
@@ -854,12 +924,9 @@
private CtsTestServer mServer;
private ServerSocket mSocket;
private SslMode mSsl;
- private boolean mWillShutDown = false;
+ private boolean mIsCancelled;
private SSLContext mSslContext;
private ExecutorService mExecutorService = Executors.newFixedThreadPool(20);
- private Object mLock = new Object();
- // All the sockets bound to an open connection.
- private Set<Socket> mSockets = new HashSet<Socket>();
/**
* Defines the keystore contents for the server, BKS version. Holds just a
@@ -945,14 +1012,10 @@
}
public void run() {
- while (!mWillShutDown) {
+ while (!mIsCancelled) {
try {
Socket socket = mSocket.accept();
- synchronized(mLock) {
- mSockets.add(socket);
- }
-
DefaultHttpServerConnection conn = mServer.createHttpServerConnection();
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
@@ -962,17 +1025,17 @@
// parsing the response since conn.close() will crash
// for SSL requests due to UnsupportedOperationException.
HttpRequest request = conn.receiveRequestHeader();
+ if (isShutdownRequest(request)) {
+ mIsCancelled = true;
+ }
if (request instanceof HttpEntityEnclosingRequest) {
conn.receiveRequestEntity( (HttpEntityEnclosingRequest) request);
}
- mExecutorService.execute(new HandleResponseTask(conn, request, socket));
+ mExecutorService.execute(new HandleResponseTask(conn, request));
} catch (IOException e) {
// normal during shutdown, ignore
Log.w(TAG, e);
- } catch (RejectedExecutionException e) {
- // normal during shutdown, ignore.
- Log.w(TAG, e);
} catch (HttpException e) {
Log.w(TAG, e);
} catch (UnsupportedOperationException e) {
@@ -981,26 +1044,10 @@
Log.w(TAG, e);
}
}
- }
-
- /**
- * Shutdown the socket and the executor service.
- * Note this method is called on the client thread, instead of the server thread.
- */
- public void shutDownOnClientThread() {
try {
- mWillShutDown = true;
mExecutorService.shutdown();
mExecutorService.awaitTermination(1L, TimeUnit.MINUTES);
mSocket.close();
- // To prevent the server thread from being blocked on read from socket,
- // which is called when the server tries to receiveRequestHeader,
- // close all the sockets here.
- synchronized(mLock) {
- for (Socket socket : mSockets) {
- socket.close();
- }
- }
} catch (IOException ignored) {
// safe to ignore
} catch (InterruptedException e) {
@@ -1008,19 +1055,24 @@
}
}
+ private static boolean isShutdownRequest(HttpRequest request) {
+ RequestLine requestLine = request.getRequestLine();
+ String uriString = requestLine.getUri();
+ URI uri = URI.create(uriString);
+ String path = uri.getPath();
+ return path.equals(SHUTDOWN_PREFIX);
+ }
+
private class HandleResponseTask implements Runnable {
private DefaultHttpServerConnection mConnection;
private HttpRequest mRequest;
- private Socket mSocket;
-
public HandleResponseTask(DefaultHttpServerConnection connection,
- HttpRequest request, Socket socket) {
+ HttpRequest request) {
this.mConnection = connection;
this.mRequest = request;
- this.mSocket = socket;
}
@Override
@@ -1030,10 +1082,6 @@
mConnection.sendResponseHeader(response);
mConnection.sendResponseEntity(response);
mConnection.close();
-
- synchronized(mLock) {
- ServerThread.this.mSockets.remove(mSocket);
- }
} catch (Exception e) {
Log.e(TAG, "Error handling request:", e);
}
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 30847ac..89cc897 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -359,25 +359,5 @@
description: "Still investigating this, root cause unknown yet",
bug: 27578806,
names: ["com.android.cts.cpptools.RunAsHostTest#testRunAs"]
-},
-{
- description: "Sensor tests not working",
- bug: 28159339,
- names: [
- "android.hardware.cts.helpers.sensorverification.TimestampClockSourceVerificationTest#testVerify_fail",
- "android.hardware.cts.helpers.sensorverification.TimestampClockSourceVerificationTest#testVerify_jitter_fail",
- "android.hardware.cts.helpers.sensorverification.TimestampClockSourceVerificationTest#testVerify_jitter_pass",
- "android.hardware.cts.helpers.sensorverification.TimestampClockSourceVerificationTest#testVerify_missing_events_fail",
- "android.hardware.cts.helpers.sensorverification.TimestampClockSourceVerificationTest#testVerify_missing_events_pass",
- "android.hardware.cts.helpers.sensorverification.TimestampClockSourceVerificationTest#testVerify_no_events_fail",
- "android.hardware.cts.helpers.sensorverification.TimestampClockSourceVerificationTest#testVerify_pass"
- ]
-},
-{
- description: "Permission Policy unaltered not working in M",
- bug: 27599613,
- names: [
- "android.permission2.cts.PermissionPolicyTest#testPlatformPermissionPolicyUnaltered"
- ]
}
]
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index 9d7f566..f5b29cf 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -332,7 +332,6 @@
.setTicker(message)
.setContentTitle("")
.setContentText("")
- .setPriority(Notification.PRIORITY_MAX)
// Mark the notification as "interruptive" by specifying a vibration pattern. This
// ensures it's announced properly on watch-type devices.
.setVibrate(new long[] {})
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index 2c185d9..7d7858a 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -23,7 +23,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner services.core
# Resource unit tests use a private locale and some densities
LOCAL_AAPT_FLAGS = -c xx_YY -c cs -c small -c normal -c large -c xlarge \
diff --git a/tests/tests/content/src/android/content/cts/SyncStorageEngineTest.java b/tests/tests/content/src/android/content/cts/SyncStorageEngineTest.java
new file mode 100644
index 0000000..c53107f
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/SyncStorageEngineTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.cts;
+
+import android.accounts.Account;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.PeriodicSync;
+import android.content.res.Resources;
+import android.content.SyncStatusInfo;
+import android.os.Bundle;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.test.RenamingDelegatingContext;
+import android.test.mock.MockContentResolver;
+import android.test.mock.MockContext;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import com.android.server.content.SyncStorageEngine;
+import com.android.internal.os.AtomicFile;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.List;
+
+public class SyncStorageEngineTest extends AndroidTestCase {
+ public void testMalformedAuthority() throws Exception {
+ Looper.prepare();
+ // Authority id is non integer. It should be discarded by SyncStorageEngine.
+ byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<accounts>\n"
+ + "<listenForTickles user=\"0\" enabled=\"false\" />"
+ + "<listenForTickles user=\"1\" enabled=\"true\" />"
+ + "<authority id=\"nonint\" user=\"0\" account=\"account1\" type=\"type1\""
+ + " authority=\"auth1\" />\n"
+ + "</accounts>\n").getBytes();
+
+ File syncDir = getSyncDir();
+ syncDir.mkdirs();
+ AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
+ FileOutputStream fos = accountInfoFile.startWrite();
+ fos.write(accountsFileData);
+ accountInfoFile.finishWrite(fos);
+
+ SyncStorageEngine engine = SyncStorageEngine.newTestInstance(getContext());
+ Account account = new Account("account1", "type1");
+ SyncStorageEngine.EndPoint endPoint = new SyncStorageEngine.EndPoint(account, "auth1", 0);
+ SyncStatusInfo info = engine.getStatusByAuthority(endPoint);
+ assertNull(info);
+ }
+
+ private File getSyncDir() {
+ return new File(new File(getContext().getFilesDir(), "system"), "sync");
+ }
+}
diff --git a/tests/tests/os/src/android/os/cts/SecurityPatchTest.java b/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
index f35af2e..57ef804 100644
--- a/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
+++ b/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
@@ -32,7 +32,7 @@
private static final String SECURITY_PATCH_DATE_ERROR =
"ro.build.version.security_patch should be \"%d-%02d\" or later. Found \"%s\"";
private static final int SECURITY_PATCH_YEAR = 2016;
- private static final int SECURITY_PATCH_MONTH = 05;
+ private static final int SECURITY_PATCH_MONTH = 06;
private boolean mSkipTests = false;
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 820b586..804a177 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -32,29 +32,17 @@
android_security_cts_MMapExecutableTest.cpp \
android_security_cts_AudioPolicyBinderTest.cpp \
android_security_cts_EncryptionTest.cpp \
- android_security_cts_MediaCryptoTest.cpp \
android_security_cts_MediaPlayerInfoLeakTest.cpp \
- android_security_cts_AudioFlingerBinderTest.cpp \
android_security_cts_AudioEffectBinderTest.cpp \
+ android_security_cts_AudioFlingerBinderTest.cpp \
+ android_security_cts_StagefrightFoundationTest.cpp \
+ android_security_cts_GraphicBufferInfoLeakTest.cpp \
android_security_cts_IDRMInfoLeakTest.cpp
-LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE) \
- system/core/include \
- frameworks/base/media/jni \
- frameworks/native/include/media/openmax
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) \
+ $(TOP)/frameworks/native/include/media/openmax
-LOCAL_SHARED_LIBRARIES := \
- libnativehelper \
- liblog \
- libbinder \
- libutils \
- libmedia \
- libselinux \
- libdl \
- libcutils \
- libcrypto \
- libstagefright_foundation
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libselinux libdl libcutils libcrypto libstagefright_foundation
LOCAL_C_INCLUDES += ndk/sources/cpufeatures
LOCAL_STATIC_LIBRARIES := cpufeatures
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index bd35bc4..3a1144c 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -29,6 +29,8 @@
extern int register_android_security_cts_EncryptionTest(JNIEnv* env);
extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
extern int register_android_security_cts_AudioEffectBinderTest(JNIEnv* env);
+extern int register_android_security_cts_StagefrightFoundationTest(JNIEnv* env);
+extern int register_android_security_cts_GraphicBufferInfoLeakTest(JNIEnv* env);
extern int register_android_security_cts_IDRMInfoLeakTest(JNIEnv* env);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
@@ -86,6 +88,14 @@
return JNI_ERR;
}
+ if (register_android_security_cts_StagefrightFoundationTest(env)) {
+ return JNI_ERR;
+ }
+
+ if (register_android_security_cts_GraphicBufferInfoLeakTest(env)) {
+ return JNI_ERR;
+ }
+
if (register_android_security_cts_IDRMInfoLeakTest(env)) {
return JNI_ERR;
}
diff --git a/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp b/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp
index 1e3fc86..6011920 100644
--- a/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp
@@ -152,12 +152,12 @@
return false;
}
- status_t status = aps->isStreamActive((audio_stream_type_t)(-1), 0);
- if (status == NO_ERROR) {
+ bool status = aps->isStreamActive((audio_stream_type_t)(-1), 0);
+ if (status) {
return false;
}
status = aps->isStreamActive((audio_stream_type_t)AUDIO_STREAM_CNT, 0);
- if (status == NO_ERROR) {
+ if (status) {
return false;
}
return true;
diff --git a/tests/tests/security/jni/android_security_cts_GraphicBufferInfoLeakTest.cpp b/tests/tests/security/jni/android_security_cts_GraphicBufferInfoLeakTest.cpp
new file mode 100644
index 0000000..d0cd347
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_GraphicBufferInfoLeakTest.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "GraphicBufferInfoLeakTest-JNI"
+
+#include <jni.h>
+#include <JNIHelp.h>
+
+#include <binder/Parcel.h>
+#include <binder/IServiceManager.h>
+
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <media/IMediaPlayerService.h>
+#include <media/IMediaRecorder.h>
+#include <media/IOMX.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+using namespace android;
+
+static sp<IMediaPlayerService> getMediaPlayerService()
+{
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> mediaPlayerService = sm->checkService(String16("media.player"));
+
+ sp<IMediaPlayerService> iMPService = IMediaPlayerService::asInterface(mediaPlayerService);
+ return iMPService;
+}
+
+jint android_security_cts_GraphicBuffer_test_attachBufferInfoLeak(JNIEnv* env,
+ jobject thiz __unused)
+{
+ sp<IMediaPlayerService> iMPService = getMediaPlayerService();
+
+ // get IOMX
+ // Keep synchronized with IMediaPlayerService.cpp!
+ enum {
+ GET_OMX = 4,
+ };
+
+ status_t err;
+ Parcel data, reply;
+ data.writeInterfaceToken(iMPService->getInterfaceDescriptor());
+ err = IMediaPlayerService::asBinder(iMPService)->transact(GET_OMX, data, &reply);
+ if (err != NO_ERROR) {
+ jniThrowException(env, "java/lang/RuntimeException", "GET_OMX failed");
+ }
+
+ // get IGraphicBufferConsumer
+ sp<IGraphicBufferProducer> iBufferProducer;
+ sp<IGraphicBufferConsumer> iBufferConsumer;
+ sp<IOMX> iOmx = interface_cast<IOMX>(reply.readStrongBinder());
+ err = iOmx->createPersistentInputSurface(&iBufferProducer, &iBufferConsumer);
+ if (err != NO_ERROR) {
+ jniThrowException(env, "java/lang/RuntimeException", "createPersistentInputSurface failed");
+ return err;
+ }
+
+ // Keep synchronized with IGraphicBufferConsumer.cpp!
+ enum {
+ ATTACH_BUFFER = 3,
+ };
+
+ for (;;) {
+ Parcel data2, reply2;
+ data2.writeInterfaceToken(iBufferConsumer->getInterfaceDescriptor());
+ err = IGraphicBufferConsumer::asBinder(iBufferConsumer)->transact(ATTACH_BUFFER, data2, &reply2);
+ if (err != NO_ERROR) {
+ jniThrowException(env, "java/lang/RuntimeException", "ATTACH_BUFFER failed");
+ }
+
+ int32_t slot = reply2.readInt32();
+ status_t result = reply2.readInt32();
+ ALOGV("slot %d", slot);
+ if (result != 0) {
+ // only check for leaked data in error case
+ return slot;
+ }
+ }
+}
+
+jint android_security_cts_GraphicBuffer_test_queueBufferInfoLeak(JNIEnv* env,
+ jobject thiz __unused)
+{
+ sp<IMediaPlayerService> iMPService = getMediaPlayerService();
+ sp<IMediaRecorder> recorder = iMPService->createMediaRecorder(String16("GraphicBufferInfoLeakTest"));
+
+ const char *fileName = "/dev/null";
+ int fd = open(fileName, O_RDWR | O_CREAT, 0744);
+ if (fd < 0) {
+ jniThrowException(env, "java/lang/RuntimeException", "open output failed");
+ return fd;
+ }
+
+ recorder->setVideoSource(2);
+ recorder->setOutputFile(fd, 0, 0);
+ recorder->setOutputFormat(0);
+ recorder->init();
+ recorder->prepare();
+ recorder->start();
+
+ //get IGraphicBufferProducer
+ sp<IGraphicBufferProducer> iGBP = recorder->querySurfaceMediaSource();
+ ALOGV("fd %d, Get iGBP instance, 0x%08x\n", fd, iGBP.get());
+
+ // Keep synchronized with IGraphicBufferProducer.cpp!
+ enum {
+ QUEUE_BUFFER = 7,
+ };
+
+ for (;;) {
+ status_t err;
+ Parcel data, reply;
+ data.writeInterfaceToken(iGBP->getInterfaceDescriptor());
+ data.writeInt32(-1);
+ err = IGraphicBufferProducer::asBinder(iGBP)->transact(QUEUE_BUFFER, data, &reply);
+ if (err != NO_ERROR) {
+ recorder->stop();
+ recorder->release();
+ jniThrowException(env, "java/lang/RuntimeException", "QUEUE_BUFFER failed");
+ return err;
+ }
+
+ size_t len = reply.dataAvail();
+ int32_t result; // last sizeof(int32_t) bytes of Parcel
+ ALOGV("dataAvail = %zu\n", len);
+ if (len < sizeof(result)) {
+ // must contain result
+ recorder->stop();
+ recorder->release();
+ jniThrowException(env, "java/lang/RuntimeException", "reply malformed");
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t *reply_data = (uint8_t *)reply.data();
+ memcpy(&result, reply_data + len - sizeof(result), sizeof(result));
+ if (result == NO_ERROR) {
+ // only check for leaked data in error case
+ continue;
+ }
+
+ uint8_t leaked_data = 0;
+ for (size_t i = 0; i < len - sizeof(result); ++i) {
+ ALOGV("IGraphicBufferProducer_InfoLeak reply_data[%d] = 0x%08x", i, reply_data[i]);
+ if (reply_data[i]) {
+ leaked_data = reply_data[i];
+ break;
+ }
+ }
+
+ recorder->stop();
+ recorder->release();
+ return leaked_data;
+ }
+}
+
+static JNINativeMethod gMethods[] = {
+ { "native_test_attachBufferInfoLeak", "()I",
+ (void *) android_security_cts_GraphicBuffer_test_attachBufferInfoLeak },
+ { "native_test_queueBufferInfoLeak", "()I",
+ (void *) android_security_cts_GraphicBuffer_test_queueBufferInfoLeak },
+};
+
+int register_android_security_cts_GraphicBufferInfoLeakTest(JNIEnv* env)
+{
+ jclass clazz = env->FindClass("android/security/cts/GraphicBufferInfoLeakTest");
+ return env->RegisterNatives(clazz, gMethods,
+ sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
new file mode 100644
index 0000000..d16bd38
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioEffectBinderTest-JNI"
+
+#include <cstdio>
+#include <jni.h>
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+using namespace android;
+
+/*
+ * Native methods used by
+ * cts/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
+ */
+
+static jboolean android_security_cts_StagefrightFoundation_test_aMessageFromParcel(
+ JNIEnv* env __unused, jobject thiz __unused)
+{
+ const int kMaxNumItems = 64;
+ const int kNumItems = kMaxNumItems + 1 + 1000;
+ char name[128];
+
+ Parcel data;
+ data.writeInt32(0); // what
+ data.writeInt32(kNumItems); // numItems
+ for (int i = 0; i < kMaxNumItems; ++i) {
+ snprintf(name, sizeof(name), "item-%d", i);
+ data.writeCString(name); // name
+ data.writeInt32(0); // kTypeInt32
+ data.writeInt32(i); // value
+ }
+ data.writeCString("evil"); // name
+ data.writeInt32(0); // kTypeInt32
+ data.writeInt32(0); // value
+ // NOTE: This could overwrite mNumItems!
+
+ for (int i = 0; i < 1000; ++i) {
+ snprintf(name, sizeof(name), "evil-%d", i);
+ data.writeCString(name); // name
+ data.writeInt32(0); // kTypeInt32
+ data.writeInt32(0); // value
+ }
+
+ data.setDataPosition(0);
+ sp<AMessage> msg = AMessage::FromParcel(data);
+
+ for (int i = 0; i < kMaxNumItems; ++i) {
+ snprintf(name, sizeof(name), "item-%d", i);
+ int32_t value;
+ if (!msg->findInt32(name, &value)) {
+ ALOGE("cannot find value for %s", name);
+ return JNI_FALSE;
+ }
+ if (value != i) {
+ ALOGE("value is changed: expected %d actual %d", i, value);
+ return JNI_FALSE;
+ }
+ }
+ return JNI_TRUE;
+}
+
+int register_android_security_cts_StagefrightFoundationTest(JNIEnv *env)
+{
+ static JNINativeMethod methods[] = {
+ { "native_test_aMessageFromParcel", "()Z",
+ (void *) android_security_cts_StagefrightFoundation_test_aMessageFromParcel},
+ };
+
+ jclass clazz = env->FindClass("android/security/cts/StagefrightFoundationTest");
+ return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
+}
diff --git a/tests/tests/security/res/raw/bug_25765591.mp2 b/tests/tests/security/res/raw/bug_25765591.mp2
new file mode 100644
index 0000000..200f575
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_25765591.mp2
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/ClonedSecureRandomTest.java b/tests/tests/security/src/android/security/cts/ClonedSecureRandomTest.java
index f8f4949..4ee1480 100644
--- a/tests/tests/security/src/android/security/cts/ClonedSecureRandomTest.java
+++ b/tests/tests/security/src/android/security/cts/ClonedSecureRandomTest.java
@@ -26,7 +26,8 @@
import android.security.cts.activity.ISecureRandomService;
import android.security.cts.activity.SecureRandomService;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.cts.util.TimeoutReq;
import java.io.BufferedReader;
import java.io.EOFException;
@@ -37,7 +38,6 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-@LargeTest
public class ClonedSecureRandomTest extends AndroidTestCase {
private static final int MAX_SHUTDOWN_TRIES = 50;
@@ -93,6 +93,7 @@
* sees two newly started processes with the same PID and compares their
* output.
*/
+ @TimeoutReq(minutes=15)
public void testCheckForDuplicateOutput() throws Exception {
assertEquals("Only supports up to " + MAX_PID + " because of memory requirements",
Integer.toString(MAX_PID), getFirstLineFromFile("/proc/sys/kernel/pid_max"));
diff --git a/tests/tests/security/src/android/security/cts/GraphicBufferInfoLeakTest.java b/tests/tests/security/src/android/security/cts/GraphicBufferInfoLeakTest.java
new file mode 100644
index 0000000..6005e37
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/GraphicBufferInfoLeakTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import junit.framework.TestCase;
+
+public class GraphicBufferInfoLeakTest extends TestCase {
+
+ static {
+ System.loadLibrary("ctssecurity_jni");
+ }
+
+ /**
+ * Check that IGraphicBufferConsumer::attachBuffer does not leak info in error case
+ */
+ public void test_attachBufferInfoLeak() throws Exception {
+ int slot = native_test_attachBufferInfoLeak();
+ assertTrue(String.format("Leaked slot 0x%08X", slot), slot == -1);
+ }
+
+ /**
+ * Check that IGraphicBufferProducer::queueBuffer does not leak info in error case
+ */
+ public void test_queueBufferInfoLeak() throws Exception {
+ int data = native_test_queueBufferInfoLeak();
+ assertTrue(String.format("Leaked buffer data 0x%08X", data), data == 0);
+ }
+
+ private static native int native_test_attachBufferInfoLeak();
+ private static native int native_test_queueBufferInfoLeak();
+}
diff --git a/tests/tests/security/src/android/security/cts/ListeningPortsTest.java b/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
index 87e957d..54fa406 100644
--- a/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
+++ b/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
@@ -18,11 +18,14 @@
import android.content.pm.PackageManager;
import android.test.AndroidTestCase;
+import android.util.Log;
import junit.framework.AssertionFailedError;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -37,15 +40,31 @@
* is considered a security best practice.
*/
public class ListeningPortsTest extends AndroidTestCase {
+ private static final String TAG = "ListeningPortsTest";
+
+ private static final int CONN_TIMEOUT_IN_MS = 5000;
/** Ports that are allowed to be listening. */
private static final List<String> EXCEPTION_PATTERNS = new ArrayList<String>(6);
static {
// IPv4 exceptions
- EXCEPTION_PATTERNS.add("0.0.0.0:5555"); // emulator port
- EXCEPTION_PATTERNS.add("10.0.2.15:5555"); // net forwarding for emulator
- EXCEPTION_PATTERNS.add("127.0.0.1:5037"); // adb daemon "smart sockets"
+ // Patterns containing ":" are allowed address port combinations
+ // Pattterns contains " " are allowed address UID combinations
+ // Patterns containing both are allowed address, port, and UID combinations
+ EXCEPTION_PATTERNS.add("0.0.0.0:5555"); // emulator port
+ EXCEPTION_PATTERNS.add("0.0.0.0:9101"); // verified ports
+ EXCEPTION_PATTERNS.add("0.0.0.0:9551"); // verified ports
+ EXCEPTION_PATTERNS.add("0.0.0.0:9552"); // verified ports
+ EXCEPTION_PATTERNS.add("10.0.2.15:5555"); // net forwarding for emulator
+ EXCEPTION_PATTERNS.add("127.0.0.1:5037"); // adb daemon "smart sockets"
+ EXCEPTION_PATTERNS.add("0.0.0.0 1020"); // used by the cast receiver
+ EXCEPTION_PATTERNS.add("0.0.0.0 10000"); // used by the cast receiver
+ EXCEPTION_PATTERNS.add("127.0.0.1 10000"); // used by the cast receiver
+ EXCEPTION_PATTERNS.add(":: 1002"); // used by remote control
+ EXCEPTION_PATTERNS.add(":: 1020"); // used by remote control
+ //no current patterns involve address, port and UID combinations
+ //Example for when necessary: EXCEPTION_PATTERNS.add("0.0.0.0:5555 10000")
}
/**
@@ -185,10 +204,16 @@
List<ParsedProcEntry> entries = ParsedProcEntry.parse(procFilePath);
for (ParsedProcEntry entry : entries) {
String addrPort = entry.localAddress.getHostAddress() + ':' + entry.port;
+ String addrUid = entry.localAddress.getHostAddress() + ' ' + entry.uid;
+ String addrPortUid = addrPort + ' ' + entry.uid;
if (isPortListening(entry.state, isTcp)
- && !isException(addrPort)
- && (!entry.localAddress.isLoopbackAddress() ^ loopback)) {
+ && !(isException(addrPort) || isException(addrUid) || isException(addrPortUid))
+ && (!entry.localAddress.isLoopbackAddress() ^ loopback)) {
+ if (isTcp && !isTcpConnectable(entry.localAddress, entry.port)) {
+ continue;
+ }
+
errors += "\nFound port listening on addr="
+ entry.localAddress.getHostAddress() + ", port="
+ entry.port + ", UID=" + entry.uid
@@ -210,6 +235,33 @@
return Arrays.asList(packages).toString();
}
+ private boolean isTcpConnectable(InetAddress address, int port) {
+ Socket socket = new Socket();
+
+ try {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Trying to connect " + address + ":" + port);
+ }
+ socket.connect(new InetSocketAddress(address, port), CONN_TIMEOUT_IN_MS);
+ } catch (IOException ioe) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Unable to connect:" + ioe);
+ }
+ return false;
+ } finally {
+ try {
+ socket.close();
+ } catch (IOException closeError) {
+ Log.e(TAG, "Unable to close socket: " + closeError);
+ }
+ }
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, address + ":" + port + " is connectable.");
+ }
+ return true;
+ }
+
private static boolean isException(String localAddress) {
return isPatternMatch(EXCEPTION_PATTERNS, localAddress);
}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
new file mode 100644
index 0000000..9999d88
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import junit.framework.TestCase;
+
+public class StagefrightFoundationTest extends TestCase {
+
+ static {
+ System.loadLibrary("ctssecurity_jni");
+ }
+
+ /**
+ * Checks that IEffect::command() cannot leak data.
+ */
+ public void test_aMessageFromParcel() throws Exception {
+ assertTrue(native_test_aMessageFromParcel());
+ }
+
+ private static native boolean native_test_aMessageFromParcel();
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index e41dd6d..c9c8e87 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -24,12 +24,24 @@
import android.content.Context;
import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.graphics.SurfaceTexture;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
import android.media.MediaPlayer;
+import android.opengl.GLES20;
+import android.opengl.GLES11Ext;
import android.os.Looper;
+import android.os.SystemClock;
import android.test.InstrumentationTestCase;
import android.util.Log;
+import android.view.Surface;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -100,6 +112,18 @@
doStagefrightTest(R.raw.bug_26366256);
}
+ public void testStagefright_bug_25765591() throws Exception {
+ doStagefrightTest(R.raw.bug_25765591);
+ }
+
+ public void testStagefright_bug_25812590() throws Exception {
+ doStagefrightTest(R.raw.bug_25812590);
+ }
+
+ public void testStagefright_bug_26070014() throws Exception {
+ doStagefrightTest(R.raw.bug_26070014);
+ }
+
public void testStagefright_cve_2015_3867() throws Exception {
doStagefrightTest(R.raw.cve_2015_3867);
}
@@ -127,23 +151,50 @@
public void testStagefright_cve_2015_3873_b_21814993() throws Exception {
doStagefrightTest(R.raw.cve_2015_3873_b_21814993);
}
-
- public void testStagefright_bug_25812590() throws Exception {
- doStagefrightTest(R.raw.bug_25812590);
- }
-
- public void testStagefright_bug_26070014() throws Exception {
- doStagefrightTest(R.raw.bug_26070014);
- }
private void doStagefrightTest(final int rid) throws Exception {
+ doStagefrightTestMediaPlayer(rid);
+ doStagefrightTestMediaCodec(rid);
+ }
+
+ private Surface getDummySurface() {
+ int[] textures = new int[1];
+ GLES20.glGenTextures(1, textures, 0);
+ GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
+ GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_MIN_FILTER,
+ GLES20.GL_NEAREST);
+ GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_MAG_FILTER,
+ GLES20.GL_LINEAR);
+ GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_WRAP_S,
+ GLES20.GL_CLAMP_TO_EDGE);
+ GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_WRAP_T,
+ GLES20.GL_CLAMP_TO_EDGE);
+ SurfaceTexture surfaceTex = new SurfaceTexture(textures[0]);
+ surfaceTex.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
+ @Override
+ public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+ Log.i(TAG, "new frame available");
+ }
+ });
+ return new Surface(surfaceTex);
+ }
+
+ private void doStagefrightTestMediaPlayer(final int rid) throws Exception {
class MediaPlayerCrashListener
implements MediaPlayer.OnErrorListener,
MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener {
@Override
public boolean onError(MediaPlayer mp, int newWhat, int extra) {
- what = newWhat;
+ Log.i(TAG, "error: " + newWhat);
+ // don't overwrite a more severe error with a less severe one
+ if (what != MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
+ what = newWhat;
+ }
lock.lock();
condition.signal();
lock.unlock();
@@ -158,7 +209,7 @@
@Override
public void onCompletion(MediaPlayer mp) {
- what = 0;
+ // preserve error condition, if any
lock.lock();
condition.signal();
lock.unlock();
@@ -170,6 +221,12 @@
Log.d(TAG, "timed out on waiting for error");
}
lock.unlock();
+ if (what != 0) {
+ // Sometimes mediaserver signals a decoding error first, and *then* crashes
+ // due to additional in-flight buffers being processed, so wait a little
+ // and see if more errors show up.
+ SystemClock.sleep(1000);
+ }
return what;
}
@@ -178,6 +235,9 @@
int what;
}
+ String name = getInstrumentation().getContext().getResources().getResourceEntryName(rid);
+ Log.i(TAG, "start mediaplayer test for: " + name);
+
final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
Thread t = new Thread(new Runnable() {
@@ -189,6 +249,8 @@
mp.setOnErrorListener(mpcl);
mp.setOnPreparedListener(mpcl);
mp.setOnCompletionListener(mpcl);
+ Surface surface = getDummySurface();
+ mp.setSurface(surface);
try {
AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
.openRawResourceFd(rid);
@@ -207,10 +269,84 @@
});
t.start();
- String name = getInstrumentation().getContext().getResources().getResourceEntryName(rid);
String cve = name.replace("_", "-").toUpperCase();
assertFalse("Device *IS* vulnerable to " + cve,
mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
t.interrupt();
}
+
+ private void doStagefrightTestMediaCodec(final int rid) throws Exception {
+ Resources resources = getInstrumentation().getContext().getResources();
+ AssetFileDescriptor fd = resources.openRawResourceFd(rid);
+ MediaExtractor ex = new MediaExtractor();
+ ex.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ int numtracks = ex.getTrackCount();
+ String rname = resources.getResourceEntryName(rid);
+ Log.i(TAG, "start mediacodec test for: " + rname + ", which has " + numtracks + " tracks");
+ for (int t = 0; t < numtracks; t++) {
+ // find all the available decoders for this format
+ ArrayList<String> matchingCodecs = new ArrayList<String>();
+ MediaFormat format = ex.getTrackFormat(t);
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ for (MediaCodecInfo info: codecList.getCodecInfos()) {
+ if (info.isEncoder()) {
+ continue;
+ }
+ try {
+ MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
+ if (caps != null && caps.isFormatSupported(format)) {
+ matchingCodecs.add(info.getName());
+ }
+ } catch (IllegalArgumentException e) {
+ // type is not supported
+ }
+ }
+
+ if (matchingCodecs.size() == 0) {
+ Log.w(TAG, "no codecs for track " + t + ", type " + mime);
+ }
+ // decode this track once with each matching codec
+ ex.selectTrack(t);
+ for (String codecName: matchingCodecs) {
+ Log.i(TAG, "Decoding track " + t + " using codec " + codecName);
+ ex.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+ MediaCodec codec = MediaCodec.createByCodecName(codecName);
+ Surface surface = null;
+ if (mime.startsWith("video/")) {
+ surface = getDummySurface();
+ }
+ codec.configure(format, surface, null, 0);
+ codec.start();
+ MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+ while (true) {
+ int flags = ex.getSampleFlags();
+ long time = ex.getSampleTime();
+ int bufidx = codec.dequeueInputBuffer(5000);
+ if (bufidx >= 0) {
+ int n = ex.readSampleData(codec.getInputBuffer(bufidx), 0);
+ if (n < 0) {
+ flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+ time = 0;
+ n = 0;
+ }
+ codec.queueInputBuffer(bufidx, 0, n, time, flags);
+ ex.advance();
+ }
+ int status = codec.dequeueOutputBuffer(info, 5000);
+ if (status >= 0) {
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ break;
+ }
+ if (info.presentationTimeUs > TIMEOUT_NS / 1000) {
+ Log.d(TAG, "stopping after 10 seconds worth of data");
+ break;
+ }
+ codec.releaseOutputBuffer(status, true);
+ }
+ }
+ codec.release();
+ }
+ }
+ }
}
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index 359923d..b57e0b6 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -42,7 +42,6 @@
<service android:name="android.telecom.cts.MockInCallService"
android:permission="android.permission.BIND_INCALL_SERVICE" >
- <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
index 052e820..d874dbf 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -297,7 +297,6 @@
if (mInCallCallbacks.getService() != null) {
currentCallCount = mInCallCallbacks.getService().getCallCount();
}
- int currentConnectionCount = getNumberOfConnections();
placeNewCallWithPhoneAccount(extras, videoState);
try {
@@ -312,20 +311,6 @@
assertEquals("InCallService should contain 1 more call after adding a call.",
currentCallCount + 1,
mInCallCallbacks.getService().getCallCount());
-
- // The connectionService.lock is released in
- // MockConnectionService#onCreateOutgoingConnection, however the connection will not
- // actually be added to the list of connections in the ConnectionService until shortly
- // afterwards. So there is still a potential for the lock to be released before it would
- // be seen by calls to ConnectionService#getAllConnections().
- // We will wait here until the list of connections includes one more connection to ensure
- // that placing the call has fully completed.
- final int expectedConnectionCount = currentConnectionCount + 1;
- assertCSConnections(expectedConnectionCount);
- }
-
- int getNumberOfConnections() {
- return CtsConnectionService.getAllConnectionsFromTelecom().size();
}
MockConnection verifyConnectionForOutgoingCall() {
@@ -535,24 +520,6 @@
);
}
- void assertCSConnections(final int numConnections) {
- waitUntilConditionIsTrueOrTimeout(new Condition() {
- @Override
- public Object expected() {
- return numConnections;
- }
-
- @Override
- public Object actual() {
- return CtsConnectionService
- .getAllConnectionsFromTelecom()
- .size();
- }
- },
- WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
- "ConnectionService should contain " + numConnections + " connections."
- );
- }
void assertNumConnections(final MockConnectionService connService, final int numConnections) {
waitUntilConditionIsTrueOrTimeout(new Condition() {
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
index e820e10..2364986 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
@@ -29,7 +29,6 @@
import android.util.Log;
import java.util.Collection;
-import java.util.Collections;
/**
* This is the official ConnectionService for Telecom's CTS App. Since telecom requires that a
@@ -155,9 +154,6 @@
public static Collection<Connection> getAllConnectionsFromTelecom() {
synchronized(sLock) {
- if (sTelecomConnectionService == null) {
- return Collections.EMPTY_LIST;
- }
return sTelecomConnectionService.getAllConnections();
}
}
diff --git a/tests/tests/uirendering/res/layout/simple_shadow_layout.xml b/tests/tests/uirendering/res/layout/simple_shadow_layout.xml
index f97974b..2f21df0 100644
--- a/tests/tests/uirendering/res/layout/simple_shadow_layout.xml
+++ b/tests/tests/uirendering/res/layout/simple_shadow_layout.xml
@@ -23,4 +23,4 @@
android:translationY="25px"
android:elevation="10dp"
android:background="#fff" />
-</FrameLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
index 5c06f0f..ffcbf30 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
@@ -27,10 +27,10 @@
public class ShadowTests extends ActivityTestBase {
@SmallTest
public void testShadowLayout() {
- int shadowColorValue = 0xD7;
+ int shadowColorValue = 0xDB;
// Android TV theme overrides shadow opacity to be darker.
if (getActivity().getOnTv()) {
- shadowColorValue = 0xB7;
+ shadowColorValue = 0xBB;
}
// Use a higher threshold (36) than default value (20);
SamplePointVerifier verifier = new SamplePointVerifier(
@@ -53,4 +53,4 @@
.addLayout(R.layout.simple_shadow_layout, null, true/* HW only */)
.runWithVerifier(verifier);
}
-}
+}
\ No newline at end of file
diff --git a/tests/tests/webkit/assets/webkit/jsunload.html b/tests/tests/webkit/assets/webkit/jsunload.html
index f016eb7..fb0673e 100644
--- a/tests/tests/webkit/assets/webkit/jsunload.html
+++ b/tests/tests/webkit/assets/webkit/jsunload.html
@@ -19,7 +19,7 @@
</head>
<script type="text/javascript">
function fireUnload() {
- return "this message will be a hardcoded string in chrome.";
+ return "testOnJsBeforeUnload";
}
window.onbeforeunload = fireUnload;
</script>
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
index 424d856..150fd86 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
@@ -198,7 +198,7 @@
runWindowTest(false);
}
- public void testOnJsBeforeUnloadIsCalled() throws Exception {
+ public void testOnJsBeforeUnload() throws Exception {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
}
@@ -221,6 +221,7 @@
return webChromeClient.hadOnJsBeforeUnload();
}
}.run();
+ assertEquals(webChromeClient.getMessage(), "testOnJsBeforeUnload");
}
public void testOnJsAlert() throws Exception {
diff --git a/tools/Android.mk b/tools/Android.mk
index 8cb90db..8377036 100644
--- a/tools/Android.mk
+++ b/tools/Android.mk
@@ -19,13 +19,12 @@
TF_JAR := $(HOST_OUT_JAVA_LIBRARIES)/tradefed-prebuilt.jar
CTS_TF_JAR := $(HOST_OUT_JAVA_LIBRARIES)/cts-tradefed.jar
CTS_TF_EXEC_PATH ?= $(HOST_OUT_EXECUTABLES)/cts-tradefed
-PRECONDITIONS_APK := $(CTS_TESTCASES_OUT)/CtsPreconditionsApp.apk
cts_prebuilt_jar := $(HOST_OUT)/cts/android-cts/tools/cts-prebuilt.jar
$(cts_prebuilt_jar): PRIVATE_TESTS_DIR := $(HOST_OUT)/cts/android-cts/repository/testcases
$(cts_prebuilt_jar): PRIVATE_PLANS_DIR := $(HOST_OUT)/cts/android-cts/repository/plans
$(cts_prebuilt_jar): PRIVATE_TOOLS_DIR := $(HOST_OUT)/cts/android-cts/tools
-$(cts_prebuilt_jar): $(JUNIT_HOST_JAR) $(HOSTTESTLIB_JAR) $(TF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(ADDITIONAL_TF_JARS) $(PRECONDITIONS_APK) | $(ACP) $(HOST_OUT_EXECUTABLES)/adb
+$(cts_prebuilt_jar): $(JUNIT_HOST_JAR) $(HOSTTESTLIB_JAR) $(TF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(ADDITIONAL_TF_JARS) | $(ACP) $(HOST_OUT_EXECUTABLES)/adb
mkdir -p $(PRIVATE_TESTS_DIR)
mkdir -p $(PRIVATE_PLANS_DIR)
mkdir -p $(PRIVATE_TOOLS_DIR)
diff --git a/tools/tradefed-host/preconditions/Android.mk b/tools/tradefed-host/preconditions/Android.mk
deleted file mode 100644
index bcd7b49..0000000
--- a/tools/tradefed-host/preconditions/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# 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
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsPreconditionsApp
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tools/tradefed-host/preconditions/AndroidManifest.xml b/tools/tradefed-host/preconditions/AndroidManifest.xml
deleted file mode 100644
index 02b3534..0000000
--- a/tools/tradefed-host/preconditions/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.preconditions">
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <!-- self-instrumenting test package. -->
- <instrumentation
- android:name="android.support.test.runner.AndroidJUnitRunner"
- android:label="CTS device-side preconditions test"
- android:targetPackage="com.android.cts.preconditions" >
- </instrumentation>
-</manifest>
diff --git a/tools/tradefed-host/preconditions/src/com/android/cts/preconditions/PreconditionsTest.java b/tools/tradefed-host/preconditions/src/com/android/cts/preconditions/PreconditionsTest.java
deleted file mode 100644
index f1576a3..0000000
--- a/tools/tradefed-host/preconditions/src/com/android/cts/preconditions/PreconditionsTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.preconditions;
-
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Environment;
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-/**
- * An AndroidTestCase class to verify that device-side preconditions are met for CTS
- */
-public class PreconditionsTest extends AndroidTestCase {
-
- private static final String TAG = "PreconditionsTest";
-
- /**
- * Test if device has no screen lock
- * @throws Exception
- */
- public void testScreenUnlocked() throws Exception {
- PackageManager pm = getContext().getPackageManager();
- if (pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
- || pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
- || pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
- Log.i(TAG, "Skipping screen lock precondition for this device type");
- return; // do not test for unlocked screen on devices with no screen lock
- }
- KeyguardManager km =
- (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
- assertFalse("Device must have screen lock disabled", km.isDeviceSecure());
- }
-
- /**
- * Test if device has accessible external storage
- * @throws Exception
- */
- public void testExternalStoragePresent() throws Exception {
- String state = Environment.getExternalStorageState();
- assertTrue("Device must have writable external storage mounted in order to run CTS",
- Environment.MEDIA_MOUNTED.equals(state));
- }
-
-}
diff --git a/tools/tradefed-host/res/config/cts.xml b/tools/tradefed-host/res/config/cts.xml
index a5665be..416b400 100644
--- a/tools/tradefed-host/res/config/cts.xml
+++ b/tools/tradefed-host/res/config/cts.xml
@@ -19,8 +19,6 @@
<option name="enable-root" value="false" />
<build_provider class="com.android.cts.tradefed.build.CtsBuildProvider" />
<device_recovery class="com.android.tradefed.device.WaitDeviceRecovery" />
- <target_preparer class="com.android.cts.tradefed.targetprep.DevicePreconditionPreparer" />
- <target_preparer class="com.android.cts.tradefed.targetprep.HostPreconditionPreparer" />
<test class="com.android.cts.tradefed.testtype.CtsTest" />
<logger class="com.android.tradefed.log.FileLogger" />
<result_reporter class="com.android.cts.tradefed.result.CtsXmlResultReporter" />
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index a578088..4505635 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
@Option(name="cts-install-path", description="the path to the cts installation to use")
private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
- public static final String CTS_BUILD_VERSION = "6.0_r6";
+ public static final String CTS_BUILD_VERSION = "6.0_r201606s";
public static final String CTS_PACKAGE = "com.android.cts.tradefed.testtype";
/**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/DevicePreconditionPreparer.java b/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/DevicePreconditionPreparer.java
deleted file mode 100644
index 1c0f193..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/DevicePreconditionPreparer.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.tradefed.targetprep;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.tradefed.testtype.Abi;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.build.IFolderBuildInfo;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.result.TestSummary;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.InstrumentationTest;
-import com.android.tradefed.targetprep.BuildError;
-import com.android.tradefed.targetprep.ITargetPreparer;
-import com.android.tradefed.targetprep.TargetSetupError;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * A {@link ITargetPreparer} that performs precondition checks on the device-side for CTS.
- * <p/>
- * This class instruments an APK containing tests verifying that the device meets CTS
- * preconditions. At present, the APK contains tests to ensure that the device's screen is not
- * locked, and that the device's external storage is present and writable. The test lives under
- * //cts/tools/tradefed-host/preconditions, and can be modified to perform further checks and tasks
- * from the device-side.
- */
-@OptionClass(alias="device-precondition-preparer")
-public class DevicePreconditionPreparer implements ITargetPreparer {
-
- /* This option also exists in the HostPreconditionPreparer */
- @Option(name = "skip-preconditions",
- description = "Whether to skip precondition checks and automation")
- protected boolean mSkipPreconditions = false;
-
- /* Constants for the InstrumentationTest */
- private static final String APK_NAME = "CtsPreconditionsApp.apk";
- private static final String PACKAGE_NAME = "com.android.cts.preconditions";
- private static final String RUNNER_NAME = "android.support.test.runner.AndroidJUnitRunner";
-
- private static final String LOG_TAG = DevicePreconditionPreparer.class.getSimpleName();
-
- /* Map used to track test failures */
- private ConcurrentHashMap<TestIdentifier, String> testFailures = new ConcurrentHashMap<>();
-
- /* Helper that logs a message with LogLevel.WARN */
- private static void printWarning(String msg) {
- LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG, msg);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
- BuildError, DeviceNotAvailableException {
- if (mSkipPreconditions) {
- return; // skipping device-side preconditions
- }
-
- try {
- if (!instrument(device, buildInfo)) {
- printWarning("Not all device-side preconditions met, " +
- "CTS tests may fail as a result.");
- }
- } catch (FileNotFoundException e) {
- throw new TargetSetupError(
- String.format("Couldn't find %s to instrument", APK_NAME), e);
- }
- }
-
- /* Instruments the APK on the device, and logs precondition test failures, if any are found.
- * Returns true if all tests pass, and otherwise returns false */
- private boolean instrument(ITestDevice device, IBuildInfo buildInfo)
- throws DeviceNotAvailableException, FileNotFoundException {
- ITestInvocationListener listener = new PreconditionPreparerListener();
- CtsBuildHelper mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- File apkFile = mCtsBuild.getTestApp(APK_NAME); // get the APK file with the CtsBuildHelper
- InstrumentationTest instrTest = new InstrumentationTest();
- instrTest.setDevice(device);
- instrTest.setInstallFile(apkFile);
- instrTest.setPackageName(PACKAGE_NAME);
- instrTest.setRunnerName(RUNNER_NAME);
- instrTest.run(listener);
- boolean success = true;
- if (!testFailures.isEmpty()) {
- success = false; // at least one precondition has failed
- for (TestIdentifier test : testFailures.keySet()) {
- String trace = testFailures.get(test);
- printWarning(String.format(
- "Precondition test %s failed.\n%s", test.getTestName(), trace));
- }
- }
- return success;
- }
-
- /**
- * The PreconditionPreparerListener is an implementation of ITestInvocationListener
- * that adds entries to the ConcurrentHashMap 'testFailures' of the outer class whenever
- * a test fails. The listener also logs information if the test run fails, for debugging
- * purposes.
- */
- public class PreconditionPreparerListener implements ITestInvocationListener {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testFailed(TestIdentifier test, String trace) {
- testFailures.put(test, trace);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testRunFailed(String errorMessage) {
- printWarning(String.format(
- "Device-side preconditions test run failed: %s", errorMessage));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testEnded(TestIdentifier test, Map<String, String> metrics) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void invocationStarted(IBuildInfo buildInfo) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void invocationEnded(long elapsedTime) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void invocationFailed(Throwable cause) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public TestSummary getSummary() {
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testRunStarted(String runName, int testCount) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testStarted(TestIdentifier test) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testAssumptionFailure(TestIdentifier test, String trace) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testIgnored(TestIdentifier test) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testRunStopped(long elapsedTime) {}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testRunEnded(long elapsedTime, Map<String, String> runMetrics) {}
- }
-}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/HostPreconditionPreparer.java b/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/HostPreconditionPreparer.java
deleted file mode 100644
index 2b85660..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/HostPreconditionPreparer.java
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.tradefed.targetprep;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil;
-import com.android.tradefed.targetprep.BuildError;
-import com.android.tradefed.targetprep.ITargetPreparer;
-import com.android.tradefed.targetprep.TargetSetupError;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.ZipUtil;
-
-import java.awt.Dimension;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.zip.ZipFile;
-
-/**
- * A {@link ITargetPreparer} that performs steps on the host-side to meet the preconditions of CTS.
- * <p/>
- * This class is intended for runs of CTS against a device running a user build.
- * <p/>
- * This class performs checks to verify that the location services are on, WiFi is connected,
- * the device locale is set to 'en-US', and that the device runs a user build. The class also
- * performs automation to ensure that 3rd party app installs are enabled, the 'Stay Awake' setting
- * is turned on, and that the appropriate media files are pushed to the device for the media tests.
- * Additionally, options are provided for automatically connecting to a specific WiFi network.
- */
-@OptionClass(alias="host-precondition-preparer")
-public class HostPreconditionPreparer implements ITargetPreparer {
-
- /* This option also exists in the DevicePreconditionPreparer */
- @Option(name = "skip-preconditions",
- description = "Whether to skip precondition checks and automation")
- protected boolean mSkipPreconditions = false;
-
- @Option(name = "wifi-ssid", description = "Name of the WiFi network with which to connect")
- protected String mWifiSsid = null;
-
- @Option(name = "wifi-psk", description = "The WPA-PSK associated with option 'wifi-ssid'")
- protected String mWifiPsk = null;
-
- @Option(name = "skip-media-download",
- description = "Whether to skip verifying/downloading media files")
- protected boolean mSkipMediaDownload = false;
-
- @Option(name = "skip-wifi-check",
- description = "Whether to skip verification of network connection")
- protected boolean mSkipWifiCheck = false;
-
- @Option(name = "local-media-path",
- description = "Absolute path of the media files directory on the host, containing" +
- "'bbb_short' and 'bbb_full' directories")
- protected String mLocalMediaPath = null;
-
- private static final String LOG_TAG = HostPreconditionPreparer.class.getSimpleName();
-
- private static final String WIFI_FEATURE = "android.hardware.wifi";
- private static final String LOCATION_GPS_FEATURE = "android.hardware.location.gps";
- private static final String LOCATION_NETWORK_FEATURE = "android.hardware.location.network";
-
- /* Constants found in android.provider.Settings */
- protected static final String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
- protected static final String PACKAGE_VERIFIER_INCLUDE_ADB = "verifier_verify_adb_installs";
- protected static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
- /* Constant from android.os.BatteryManager */
- private static final int BATTERY_PLUGGED_ANY = 7;
-
- /* Name and expected value of the device's locale property */
- private static final String LOCALE_PROPERTY_STRING = "ro.product.locale";
- private static final String US_EN_LOCALE_STRING = "en-US";
- /* Name and expected value of the device's build type property */
- private static final String BUILD_TYPE_PROPERTY_STRING = "ro.build.type";
- private static final String USER_BUILD_STRING = "user";
-
- /* Logged if the preparer fails to identify the device's maximum video playback resolution */
- private static final String MAX_PLAYBACK_RES_FAILURE_MSG =
- "Unable to parse maximum video playback resolution, pushing all media files";
-
- /*
- * The URL from which to download the compressed media files
- * TODO: Find a way to retrieve this programmatically
- */
- private static final String MEDIA_URL_STRING =
- "https://dl.google.com/dl/android/cts/android-cts-media-1.1.zip";
-
- /*
- * A default name for the local directory into which media files will be downloaded, if option
- * "local-media-path" is not provided. This name is intentionally predetermined and final, so
- * that when running CTS repeatedly, media files downloaded to the host in a previous run of
- * CTS can be found in this directory, which will live inside the local temp directory.
- */
- private static final String MEDIA_FOLDER_NAME = "android-cts-media";
-
- /* Constants identifying video playback resolutions of the media files to be copied */
- protected static final int RES_176_144 = 0; // 176x144 resolution
- protected static final int RES_DEFAULT = 1; // 480x360, the default max playback resolution
- protected static final int RES_720_480 = 2; // 720x480 resolution
- protected static final int RES_1280_720 = 3; // 1280x720 resolution
- protected static final int RES_1920_1080 = 4; // 1920x1080 resolution
-
- /* Array of Dimensions aligning with and corresponding to the resolution constants above */
- protected static final Dimension[] resolutions = {
- new Dimension(176, 144),
- new Dimension(480, 360),
- new Dimension(720, 480),
- new Dimension(1280, 720),
- new Dimension(1920, 1080)
- };
-
- /*********************************************************************************************
- * HELPER METHODS
- *********************************************************************************************/
-
- /* Helper that logs a message with LogLevel.INFO */
- private static void printInfo(String msg) {
- LogUtil.printLog(Log.LogLevel.INFO, LOG_TAG, msg);
- }
-
- /* Helper that logs a message with LogLevel.WARN */
- private static void printWarning(String msg) {
- LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG, msg);
- }
-
- /* Helper that determines whether the device supports a feature */
- private boolean hasFeature(ITestDevice device, String feature)
- throws DeviceNotAvailableException {
- String pmFeatures = device.executeShellCommand("pm list features");
- return pmFeatures.contains(feature);
- }
-
- /*
- * Returns a string representation of the dimension
- * For dimension of width = 480 and height = 360, the resolution string is "480x360"
- */
- protected static String resolutionString(Dimension resolution) {
- return String.format("%dx%d", resolution.width, resolution.height);
- }
-
- /*
- * Returns the device's absolute path to the directory containing 'short' media files, given
- * a resolution. The instance of ITestDevice is used to identify the mount point for
- * external storage.
- */
- protected String getDeviceShortDir(ITestDevice device, Dimension resolution) {
- String mountPoint = device.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- return String.format("%s/test/bbb_short/%s", mountPoint, resolutionString(resolution));
- }
-
- /*
- * Returns the device's absolute path to the directory containing 'full' media files, given
- * a resolution. The instance of ITestDevice is used to identify the mount point for
- * external storage.
- */
- protected String getDeviceFullDir(ITestDevice device, Dimension resolution) {
- String mountPoint = device.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- return String.format("%s/test/bbb_full/%s", mountPoint, resolutionString(resolution));
- }
-
- /*
- * Loops through the predefined maximum video playback resolutions from largest to smallest,
- * And returns the greatest resolution that is strictly smaller than the width and height
- * provided in the arguments.
- */
- private Dimension getMaxVideoPlaybackResolution(int width, int height) {
- for (int resIndex = resolutions.length - 1; resIndex >= RES_DEFAULT; resIndex--) {
- Dimension resolution = resolutions[resIndex];
- if (width >= resolution.width && height >= resolution.height) {
- return resolution;
- }
- }
- return resolutions[RES_DEFAULT];
- }
-
- /**
- * Returns the maximum video playback resolution of the device, in the form of a Dimension
- * object. This method parses dumpsys output to find resolutions listed under the
- * 'mBaseDisplayInfo' field. The value of the 'smallest app' field is used as an estimate for
- * maximum video playback resolution, and is rounded down to the nearest dimension in the
- * resolutions array.
- */
- protected Dimension getMaxVideoPlaybackResolution(ITestDevice device)
- throws DeviceNotAvailableException{
- String dumpsysOutput =
- device.executeShellCommand("dumpsys display | grep mBaseDisplayInfo");
- Pattern pattern = Pattern.compile("smallest app (\\d+) x (\\d+)");
- Matcher matcher = pattern.matcher(dumpsysOutput);
- if(!matcher.find()) {
- // could not find resolution in dumpsysOutput, return largest max playback resolution
- // so that preparer copies all media files
- printInfo(MAX_PLAYBACK_RES_FAILURE_MSG);
- return resolutions[RES_1920_1080];
- }
-
- int first;
- int second;
- try {
- first = Integer.parseInt(matcher.group(1));
- second = Integer.parseInt(matcher.group(2));
- } catch (NumberFormatException e) {
- // match was found, but not an identifiable resolution
- printInfo(MAX_PLAYBACK_RES_FAILURE_MSG);
- return resolutions[RES_1920_1080];
- }
- // ensure that the larger of the two values found is assigned to 'width'
- int height = Math.min(first, second);
- int width = Math.max(first, second);
- return getMaxVideoPlaybackResolution(width, height);
- }
-
- /*
- * After downloading and unzipping the media files, mLocalMediaPath must be the path to the
- * directory containing 'bbb_short' and 'bbb_full' directories, as it is defined in its
- * description as an option.
- * After extraction, this directory exists one level below the the directory 'mediaFolder'.
- * If the 'mediaFolder' contains anything other than exactly one subdirectory, a
- * TargetSetupError is thrown. Otherwise, the mLocalMediaPath variable is set to the path of
- * this subdirectory.
- */
- private void updateLocalMediaPath(File mediaFolder) throws TargetSetupError {
- String[] subDirs = mediaFolder.list();
- if (subDirs.length != 1) {
- throw new TargetSetupError(String.format(
- "Unexpected contents in directory %s", mLocalMediaPath));
- }
- File newMediaFolder = new File(mediaFolder, subDirs[0]);
- mLocalMediaPath = newMediaFolder.toString();
- }
-
- /*
- * Copies the media files to the host from predefined url MEDIA_URL_STRING.
- * The compressed file is downloaded and unzipped into mLocalMediaPath.
- */
- private void downloadMediaToHost() throws TargetSetupError {
-
- URL url;
- try {
- url = new URL(MEDIA_URL_STRING);
- } catch (MalformedURLException e) {
- throw new TargetSetupError(
- String.format("Trouble finding android media files at %s", MEDIA_URL_STRING));
- }
-
- File mediaFolder = new File(mLocalMediaPath);
- File mediaFolderZip = new File(mediaFolder.getAbsolutePath() + ".zip");
- try {
-
- mediaFolder.mkdirs();
- mediaFolderZip.createNewFile();
-
- URLConnection conn = url.openConnection();
- InputStream in = conn.getInputStream();
- BufferedOutputStream out =
- new BufferedOutputStream(new FileOutputStream(mediaFolderZip));
- byte[] buffer = new byte[1024];
- int count;
- printInfo("Downloading media files to host");
- while ((count = in.read(buffer)) >= 0) {
- out.write(buffer, 0, count);
- }
- out.flush();
- out.close();
- in.close();
-
- printInfo("Unzipping media files");
- ZipUtil.extractZip(new ZipFile(mediaFolderZip), mediaFolder);
-
- } catch (IOException e) {
- FileUtil.recursiveDelete(mediaFolder);
- FileUtil.recursiveDelete(mediaFolderZip);
- throw new TargetSetupError("Failed to open media files on host");
- }
- }
-
- /**
- * Pushes directories containing media files to the device for all directories that:
- * - are not already present on the device
- * - contain video files of a resolution less than or equal to the device's
- * max video playback resolution
- */
- protected void copyMediaFiles(ITestDevice device, Dimension mvpr)
- throws DeviceNotAvailableException {
-
- int resIndex = RES_176_144;
- while (resIndex <= RES_1920_1080) {
- Dimension copiedResolution = resolutions[resIndex];
- String resString = resolutionString(copiedResolution);
- if (copiedResolution.width > mvpr.width || copiedResolution.height > mvpr.height) {
- printInfo(String.format(
- "Device cannot support resolutions %s and larger, media copying complete",
- resString));
- return;
- }
- String deviceShortFilePath = getDeviceShortDir(device, copiedResolution);
- String deviceFullFilePath = getDeviceFullDir(device, copiedResolution);
- if (!device.doesFileExist(deviceShortFilePath) ||
- !device.doesFileExist(deviceFullFilePath)) {
- printInfo(String.format("Copying files of resolution %s to device", resString));
- String localShortDirName = "bbb_short/" + resString;
- String localFullDirName = "bbb_full/" + resString;
- File localShortDir = new File(mLocalMediaPath, localShortDirName);
- File localFullDir = new File(mLocalMediaPath, localFullDirName);
- // push short directory of given resolution, if not present on device
- if(!device.doesFileExist(deviceShortFilePath)) {
- device.pushDir(localShortDir, deviceShortFilePath);
- }
- // push full directory of given resolution, if not present on device
- if(!device.doesFileExist(deviceFullFilePath)) {
- device.pushDir(localFullDir, deviceFullFilePath);
- }
- }
- resIndex++;
- }
- }
-
- /*
- * Returns true if all media files of a resolution less than or equal to 'mvpr' exist on the
- * device, and otherwise returns false.
- */
- private boolean mediaFilesExistOnDevice(ITestDevice device, Dimension mvpr)
- throws DeviceNotAvailableException{
- int resIndex = RES_176_144;
- while (resIndex <= RES_1920_1080) {
- Dimension copiedResolution = resolutions[resIndex];
- if (copiedResolution.width > mvpr.width || copiedResolution.height > mvpr.height) {
- break; // we don't need to check for resolutions greater than or equal to this
- }
- String deviceShortFilePath = getDeviceShortDir(device, copiedResolution);
- String deviceFullFilePath = getDeviceFullDir(device, copiedResolution);
- if (!device.doesFileExist(deviceShortFilePath) ||
- !device.doesFileExist(deviceFullFilePath)) {
- // media files of valid resolution not found on the device, and must be pushed
- return false;
- }
- resIndex++;
- }
- return true;
- }
-
- /* Static method that returns a directory called 'dirName' in the system's temp directory */
- private static File createSimpleTempDir(String dirName) throws IOException {
- // find system's temp directory
- File throwaway = File.createTempFile(dirName, null);
- String systemTempDir = throwaway.getParent();
- // create directory with simple name within temp directory
- File simpleTempDir = new File(systemTempDir, dirName);
- // delete file used to find temp directory
- throwaway.delete();
- return simpleTempDir;
- }
-
- /* Method that creates a local media path, and ensures that the necessary media files live
- * within that path */
- private void createLocalMediaPath() throws TargetSetupError {
- File mediaFolder;
- try {
- mediaFolder = createSimpleTempDir(MEDIA_FOLDER_NAME);
- } catch (IOException e) {
- throw new TargetSetupError("Unable to create host temp directory for media files");
- }
- mLocalMediaPath = mediaFolder.getAbsolutePath();
- if (!mediaFolder.exists()) {
- // directory has not been created or filled by previous runs of MediaPreparer
- downloadMediaToHost(); //download media into mLocalMediaPath
- }
- updateLocalMediaPath(mediaFolder);
- }
-
- /*********************************************************************************************
- * PRECONDITION METHODS
- *********************************************************************************************/
-
- /**
- * Prevents the screen from sleeping while charging via USB
- */
- protected void enableStayAwakeSetting(ITestDevice device) throws DeviceNotAvailableException {
- String shellCmd = String.format("settings put global %s %d",
- STAY_ON_WHILE_PLUGGED_IN, BATTERY_PLUGGED_ANY);
- device.executeShellCommand(shellCmd);
- }
-
- /**
- * Prevents package verification on apps installed through ADB/ADT/USB
- */
- protected void disableAdbAppVerification(ITestDevice device)
- throws DeviceNotAvailableException {
- String shellCmd = String.format("settings put global %s 0", PACKAGE_VERIFIER_INCLUDE_ADB);
- device.executeShellCommand(shellCmd);
- }
-
- /**
- * Prevents the keyguard from re-emerging during the CTS test, which can cause some failures
- * Note: the shell command run here is not supported on L
- */
- protected void disableKeyguard(ITestDevice device) throws DeviceNotAvailableException {
- device.executeShellCommand("wm disable-keyguard");
- }
-
- /**
- * Prints a warning if the device's locale is something other than US English, as some tests
- * may pass or fail depending on the 'en-US' locale.
- */
- protected void verifyLocale(ITestDevice device) throws DeviceNotAvailableException {
- String locale = device.getProperty(LOCALE_PROPERTY_STRING);
- if (locale == null) {
- printWarning(String.format("Property %s not found on device", LOCALE_PROPERTY_STRING));
- return;
- }
- if (!locale.equalsIgnoreCase(US_EN_LOCALE_STRING)) {
- printWarning(String.format("Expected locale en-US, detected locale \"%s\"", locale));
- }
- }
-
- /**
- * Prints a warning if the device is not running a user build. This is not allowed for
- * testing production devices, but should not block testers from running CTS on a userdebug
- * build.
- */
- protected void verifyUserBuild(ITestDevice device) throws DeviceNotAvailableException {
- String buildType = device.getProperty(BUILD_TYPE_PROPERTY_STRING);
- if (buildType == null) {
- printWarning(
- String.format("Property %s not found on device", BUILD_TYPE_PROPERTY_STRING));
- return;
- }
- if (!buildType.equalsIgnoreCase(USER_BUILD_STRING)) {
- printWarning(String.format("Expected user build, detected type \"%s\"", buildType));
- }
- }
-
- /**
- * Throws a TargetSetupError if location services are not enabled by gps or a network
- */
- protected void checkLocationServices(ITestDevice device)
- throws DeviceNotAvailableException, TargetSetupError {
-
- String shellCmd = String.format("settings get secure %s", LOCATION_PROVIDERS_ALLOWED);
- String locationServices = device.executeShellCommand(shellCmd);
- if (!locationServices.contains("gps") && !locationServices.contains("network")) {
- // location services are not enabled by gps nor by the network
- throw new TargetSetupError(
- "Location services must be enabled for several CTS test packages");
- }
- }
-
- /**
- * Throws a TargetSetupError if the device is not connected to a WiFi network. Testers can
- * optionally supply a 'wifi-ssid' and 'wifi-psk' (in the options above) to attempt connection
- * to a specific network.
- */
- protected void runWifiPrecondition(ITestDevice device)
- throws TargetSetupError, DeviceNotAvailableException {
- if (mSkipWifiCheck) {
- return; // skip this precondition
- }
- if (mWifiSsid == null) {
- // no connection to create, check for existing connectivity
- if (!device.checkConnectivity()) {
- printWarning("Device has no network connection, option --wifi-ssid was not " +
- "provided. Some CTS tests require an active network connection to pass");
- }
- } else {
- // network provided in options, attempt to create new connection if needed
- if (!device.connectToWifiNetworkIfNeeded(mWifiSsid, mWifiPsk)) {
- printWarning("Unable to establish network connection, some CTS tests require " +
- "an active network connection to pass");
- }
- }
- }
-
- /**
- * Checks that media files for the mediastress tests are present on the device, and if not,
- * pushes them onto the device.
- */
- protected void runMediaPrecondition(ITestDevice device)
- throws TargetSetupError, DeviceNotAvailableException {
- if (mSkipMediaDownload) {
- return; // skip this precondition
- }
- Dimension mvpr = getMaxVideoPlaybackResolution(device);
- if (mediaFilesExistOnDevice(device, mvpr)) {
- return; // media files already found on the device
- }
- if (mLocalMediaPath == null) {
- createLocalMediaPath(); // make new path on host containing media files
- }
- printInfo(String.format("Media files located on host at: %s", mLocalMediaPath));
- copyMediaFiles(device, mvpr);
- }
-
- public void setUp(ITestDevice device, IBuildInfo buildInfo)
- throws TargetSetupError, BuildError, DeviceNotAvailableException {
- if (mSkipPreconditions) {
- return; // skipping host-side preconditions
- }
-
- /* run each host-side precondition */
- enableStayAwakeSetting(device);
- disableAdbAppVerification(device);
- disableKeyguard(device);
- verifyLocale(device);
- verifyUserBuild(device);
-
- if (hasFeature(device, LOCATION_NETWORK_FEATURE) ||
- hasFeature(device, LOCATION_GPS_FEATURE)) {
- checkLocationServices(device); // only check location services if supported
- }
-
- if (hasFeature(device, WIFI_FEATURE)) {
- runWifiPrecondition(device); // check wifi precondition only if device supports wifi
- }
-
- runMediaPrecondition(device);
- }
-
-}
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java
index 6fa648e..29c1324 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java
@@ -22,7 +22,6 @@
import com.android.cts.tradefed.result.TestSummaryXmlTest;
import com.android.cts.tradefed.result.TestTest;
import com.android.cts.tradefed.result.TestLogTest;
-import com.android.cts.tradefed.targetprep.HostPreconditionPreparerTest;
import com.android.cts.tradefed.testtype.Abi;
import com.android.cts.tradefed.testtype.CtsTestTest;
import com.android.cts.tradefed.testtype.DeqpTestRunnerTest;
@@ -60,9 +59,6 @@
addTestSuite(TestTest.class);
addTestSuite(TestLogTest.class);
- // targetprep package
- addTestSuite(HostPreconditionPreparerTest.class);
-
// testtype package
addTestSuite(CtsTestTest.class);
addTestSuite(DeqpTestRunnerTest.class);
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/targetprep/HostPreconditionPreparerTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/targetprep/HostPreconditionPreparerTest.java
deleted file mode 100644
index 44c6a4d..0000000
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/targetprep/HostPreconditionPreparerTest.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.tradefed.targetprep;
-
-import com.android.ddmlib.IDevice;
-import com.android.tradefed.config.OptionSetter;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.targetprep.TargetSetupError;
-
-import java.awt.Dimension;
-
-import junit.framework.TestCase;
-
-import org.easymock.EasyMock;
-
-/**
- * Unit tests for {@link HostPreconditionPreparer}.
- */
-public class HostPreconditionPreparerTest extends TestCase {
-
- private HostPreconditionPreparer mHostPreconditionPreparer;
- private ITestDevice mMockDevice;
- private OptionSetter mOptionSetter;
-
- private final Dimension DEFAULT_DIMENSION =
- HostPreconditionPreparer.resolutions[HostPreconditionPreparer.RES_DEFAULT];
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mHostPreconditionPreparer = new HostPreconditionPreparer();
- mMockDevice = EasyMock.createMock(ITestDevice.class);
- mOptionSetter = new OptionSetter(mHostPreconditionPreparer);
-
- EasyMock.expect(mMockDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE)).andReturn(
- "/sdcard").anyTimes();
- }
-
- public void testLocationServicesOnGpsNetwork() throws Exception {
- String shellCmd = String.format(
- "settings get secure %s", HostPreconditionPreparer.LOCATION_PROVIDERS_ALLOWED);
-
- // expect location to be enabled by both gps and network
- EasyMock.expect(
- mMockDevice.executeShellCommand(shellCmd)).andReturn("\ngps,network\n").once();
- EasyMock.replay(mMockDevice);
- mHostPreconditionPreparer.checkLocationServices(mMockDevice);
- }
-
- public void testLocationServicesOnGps() throws Exception {
- String shellCmd = String.format(
- "settings get secure %s", HostPreconditionPreparer.LOCATION_PROVIDERS_ALLOWED);
-
- // expect location to be enabled by gps only
- EasyMock.expect(
- mMockDevice.executeShellCommand(shellCmd)).andReturn("\ngps\n").once();
- EasyMock.replay(mMockDevice);
- mHostPreconditionPreparer.checkLocationServices(mMockDevice);
- }
-
- public void testLocationServicesOnNetwork() throws Exception {
- String shellCmd = String.format(
- "settings get secure %s", HostPreconditionPreparer.LOCATION_PROVIDERS_ALLOWED);
-
- // expect location to be enabled by network only
- EasyMock.expect(
- mMockDevice.executeShellCommand(shellCmd)).andReturn("\nnetwork\n").once();
- EasyMock.replay(mMockDevice);
- mHostPreconditionPreparer.checkLocationServices(mMockDevice);
- }
-
- public void testLocationServicesOff() throws Exception {
- String shellCmd = String.format(
- "settings get secure %s", HostPreconditionPreparer.LOCATION_PROVIDERS_ALLOWED);
-
- // expect location to be disabled
- EasyMock.expect(
- mMockDevice.executeShellCommand(shellCmd)).andReturn("\n\n").once();
- EasyMock.replay(mMockDevice);
- try {
- mHostPreconditionPreparer.checkLocationServices(mMockDevice);
- fail("TargetSetupError expected");
- } catch (TargetSetupError e) {
- // Expected
- }
- }
-
- public void testWifiConnected() throws Exception {
- EasyMock.expect(mMockDevice.checkConnectivity()).andReturn(true).once();
- EasyMock.replay(mMockDevice);
- mHostPreconditionPreparer.runWifiPrecondition(mMockDevice);
- }
-
- public void testWifiDisconnected() throws Exception {
- EasyMock.expect(mMockDevice.checkConnectivity()).andReturn(false).once();
- EasyMock.replay(mMockDevice);
- try {
- mHostPreconditionPreparer.runWifiPrecondition(mMockDevice);
- fail("TargetSetupError expected");
- } catch (TargetSetupError e) {
- // Expected
- }
- }
-
- public void testWifiConnectionSuccessful() throws Exception {
- EasyMock.expect(
- mMockDevice.connectToWifiNetworkIfNeeded("wifi-ssid", "wifi-psk")).andReturn(true).once();
- mOptionSetter.setOptionValue("wifi-ssid", "wifi-ssid");
- mOptionSetter.setOptionValue("wifi-psk", "wifi-psk");
- EasyMock.replay(mMockDevice);
- mHostPreconditionPreparer.runWifiPrecondition(mMockDevice);
- }
-
- public void testWifiConnectionUnuccessful() throws Exception {
- EasyMock.expect(
- mMockDevice.connectToWifiNetworkIfNeeded("wifi-ssid", "wifi-psk")).andReturn(false).once();
- mOptionSetter.setOptionValue("wifi-ssid", "wifi-ssid");
- mOptionSetter.setOptionValue("wifi-psk", "wifi-psk");
- EasyMock.replay(mMockDevice);
- try {
- mHostPreconditionPreparer.runWifiPrecondition(mMockDevice);
- fail("TargetSetupError expected");
- } catch (TargetSetupError e) {
- // Expected
- }
- }
-
- public void testResolutionString() throws Exception {
- assertEquals("480x360", mHostPreconditionPreparer.resolutionString(DEFAULT_DIMENSION));
- }
-
- public void testGetDeviceDirs() throws Exception {
- EasyMock.replay(mMockDevice);
- String shortDir =
- mHostPreconditionPreparer.getDeviceShortDir(mMockDevice, DEFAULT_DIMENSION);
- String fullDir =
- mHostPreconditionPreparer.getDeviceFullDir(mMockDevice, DEFAULT_DIMENSION);
- assertEquals(shortDir, "/sdcard/test/bbb_short/480x360");
- assertEquals(fullDir, "/sdcard/test/bbb_full/480x360");
- }
-
- public void testGetMaxVideoPlaybackResolutionFound() throws Exception {
- // set "smallest app" field to DEFAULT_DIMENSION
- String mockDumpsysOutput = "mBaseDisplayInfo=DisplayInfo{\"Built-in Screen\", uniqueId " +
- "\"local:0\", app 1440 x 2560, real 1440 x 2560, largest app 1440 x 2560, " +
- "smallest app 360 x 480, mode 1, defaultMode 1, modes [{id=1, width=1440, " +
- "height=2560, fps=60.0}], rotation 0, density 560 (494.27 x 492.606) dpi, " +
- "layerStack 0, appVsyncOff 2500000, presDeadline 17666667, type BUILT_IN, state " +
- "ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}\n";
- EasyMock.expect(mMockDevice.executeShellCommand(
- "dumpsys display | grep mBaseDisplayInfo")).andReturn(mockDumpsysOutput).once();
- EasyMock.replay(mMockDevice);
- Dimension result = mHostPreconditionPreparer.getMaxVideoPlaybackResolution(mMockDevice);
- assertEquals(result, DEFAULT_DIMENSION);
- }
-
- public void testGetMaxVideoPlaybackResolutionNotFound() throws Exception {
- String mockDumpsysOutput = "incorrect output";
- EasyMock.expect(mMockDevice.executeShellCommand(
- "dumpsys display | grep mBaseDisplayInfo")).andReturn(mockDumpsysOutput).once();
- EasyMock.replay(mMockDevice);
- Dimension result = mHostPreconditionPreparer.getMaxVideoPlaybackResolution(mMockDevice);
- Dimension maxRes =
- HostPreconditionPreparer.resolutions[HostPreconditionPreparer.RES_1920_1080];
- assertEquals(result,maxRes);
- }
-
- public void testSkipMediaDownload() throws Exception {
- mOptionSetter.setOptionValue("skip-media-download", "true");
- EasyMock.replay();
- mHostPreconditionPreparer.runMediaPrecondition(mMockDevice);
- }
-
-}
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index a6c76b1..9f462ca 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -310,6 +310,12 @@
plan.Exclude('.*')
self.__WritePlan(plan, 'CTS-webview')
+ # CTS - sub plan for Security
+ plan = tools.TestPlan(packages)
+ plan.Exclude('.*')
+ plan.Include(r'android\.security$')
+ plan.Include('android\.host\.jdwpsecurity$')
+ self.__WritePlan(plan, 'Security')
def BuildAospMediumSizeTestList():
""" Construct a defaultdic that lists package names of medium tests