resolve merge conflicts of a721fc2f5f to mnc-dev.
Change-Id: I7f993b3e7d2d27b57b6b11de1b05e089da148c93
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 765dda0..320734c 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -105,7 +105,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 72658a2..08e223f 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_r3">
+ 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/tests/tests/graphics/assets/bombfont2.ttf b/tests/tests/graphics/assets/bombfont2.ttf
new file mode 100644
index 0000000..604a698
--- /dev/null
+++ b/tests/tests/graphics/assets/bombfont2.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/bombfont2.ttx b/tests/tests/graphics/assets/bombfont2.ttx
new file mode 100644
index 0000000..ccac1b6
--- /dev/null
+++ b/tests/tests/graphics/assets/bombfont2.ttx
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="a"/>
+ <GlyphID id="2" name="b"/>
+ <GlyphID id="3" name="c"/>
+ <GlyphID id="4" name="d"/>
+ <GlyphID id="5" name="e"/>
+ <GlyphID id="6" name="BombEmoji"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0xaf28220f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Sep 9 08:01:17 2015"/>
+ <modified value="Tue Dec 8 03:58:55 2015"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="0"/>
+ <yMax value="0"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="7"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="1000"/>
+ <descent value="-200"/>
+ <lineGap value="0"/>
+ <advanceWidthMax value="500"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="0"/>
+ <xMaxExtent value="0"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="1"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="7"/>
+ <maxPoints value="0"/>
+ <maxContours value="0"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="2"/>
+ <maxTwilightPoints value="12"/>
+ <maxStorage value="28"/>
+ <maxFunctionDefs value="119"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="61"/>
+ <maxSizeOfInstructions value="2967"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="594"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00001000"/>
+ <ySubscriptXSize value="650"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="650"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="350"/>
+ <yStrikeoutSize value="50"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="5"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="UKWN"/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="97"/>
+ <usLastCharIndex value="65535"/>
+ <sTypoAscender value="800"/>
+ <sTypoDescender value="-200"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="200"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="700"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="93"/>
+ <mtx name="BombEmoji" width="500" lsb="93"/>
+ <mtx name="a" width="500" lsb="93"/>
+ <mtx name="b" width="500" lsb="93"/>
+ <mtx name="c" width="500" lsb="93"/>
+ <mtx name="d" width="500" lsb="93"/>
+ <mtx name="e" width="500" lsb="93"/>
+ </hmtx>
+
+ <cmap ERROR="decompilation error" raw="True">
+ <!-- An error occurred during the decompilation of this table -->
+ <hexdata>
+ 00000002 00030001 00000014 00030001
+ 00000034 00040020 00000004 00040001
+ 00000065 ffff0000 0061ffff ffa00001
+ 00000000 000c0000 00000028 00000000
+ 00000002 00000063 0000005f 00000001
+ 0001f4a3 0001f4a3 00000006
+ </hexdata>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="BombEmoji"/><!-- contains no outline data -->
+
+ <TTGlyph name="a"/><!-- contains no outline data -->
+
+ <TTGlyph name="b"/><!-- contains no outline data -->
+
+ <TTGlyph name="c"/><!-- contains no outline data -->
+
+ <TTGlyph name="d"/><!-- contains no outline data -->
+
+ <TTGlyph name="e"/><!-- contains no outline data -->
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
+ SampleFont Test
+ </namerecord>
+ <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
+ SampleFont Test
+ </namerecord>
+ <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
+ SampleFontTest-Regular
+ </namerecord>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ SampleFont Test
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ SampleFont Test
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SampleFontTest-Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="2.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-166"/>
+ <underlineThickness value="20"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ <psNames>
+ <!-- This file uses unique glyph names based on the information
+ found in the 'post' table. Since these names might not be unique,
+ we have to invent artificial names in case of clashes. In order to
+ be able to retain the original information, we need a name to
+ ps name mapping for those cases where they differ. That's what
+ you see below.
+ -->
+ </psNames>
+ <extraNames>
+ <!-- following are the name that are not taken from the standard Mac glyph order -->
+ <psName name="BombEmoji"/>
+ </extraNames>
+ </post>
+
+</ttFont>
diff --git a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
index 2c1b132..5528372 100644
--- a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
@@ -192,4 +192,15 @@
float widthCustomTypeface = p.measureText(testString);
assertEquals(widthDefaultTypeface, widthCustomTypeface, 1.0f);
}
+
+ public void testInvalidCmapFont2() {
+ Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), "bombfont2.ttf");
+ assertNotNull(typeface);
+ Paint p = new Paint();
+ final String testString = "abcde";
+ float widthDefaultTypeface = p.measureText(testString);
+ p.setTypeface(typeface);
+ float widthCustomTypeface = p.measureText(testString);
+ assertEquals(widthDefaultTypeface, widthCustomTypeface, 1.0f);
+ }
}
diff --git a/tests/tests/media/res/raw/video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz.mp4
deleted file mode 100644
index 6b6040f..0000000
--- a/tests/tests/media/res/raw/video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
index 8797b9b..f5680f6 100644
--- a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
@@ -61,7 +61,6 @@
private MediaFormat mDecOutputFormat;
private double[] mMeasuredFps;
private String[] mResultRawData;
- private boolean mVerifyResults;
private Resources mResources;
private DeviceReportLog mReportLog;
@@ -69,7 +68,6 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mVerifyResults = true;
mResources = mContext.getResources();
mReportLog = new DeviceReportLog();
}
@@ -300,10 +298,6 @@
mResultRawData[round] = result;
}
- if (!mVerifyResults) {
- return true;
- }
-
return MediaUtils.verifyResults(name, mime, w, h, fps);
}
@@ -547,20 +541,6 @@
352, 288, true /* isGoog */);
}
- public void testMPEG40176x0144Other() throws Exception {
- mVerifyResults = false;
- decode(VIDEO_MPEG4,
- R.raw.video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz,
- 176, 144, false /* isGoog */);
- }
-
- public void testMPEG40176x0144Goog() throws Exception {
- mVerifyResults = false;
- decode(VIDEO_MPEG4,
- R.raw.video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz,
- 176, 144, true /* isGoog */);
- }
-
public void testMPEG40480x0360Other() throws Exception {
decode(VIDEO_MPEG4,
R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index d8d8dfa..3039f81 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -23,6 +23,7 @@
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 5e6a870..a04bd34 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -32,28 +32,16 @@
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_AudioEffectBinderTest.cpp \
android_security_cts_AudioFlingerBinderTest.cpp \
- android_security_cts_AudioEffectBinderTest.cpp
+ android_security_cts_StagefrightFoundationTest.cpp \
+ android_security_cts_GraphicBufferInfoLeakTest.cpp
-LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE) \
- system/core/include \
- frameworks/base/media/jni
+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 \
- libmedia_jni
+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 2f749b7..f73b2f4 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);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
@@ -85,5 +87,13 @@
return JNI_ERR;
}
+ if (register_android_security_cts_StagefrightFoundationTest(env)) {
+ return JNI_ERR;
+ }
+
+ if (register_android_security_cts_GraphicBufferInfoLeakTest(env)) {
+ return JNI_ERR;
+ }
+
return JNI_VERSION_1_4;
}
diff --git a/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp b/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp
index fb80d6b..c916122 100644
--- a/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp
@@ -92,9 +92,6 @@
status_t status = AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
"0", "");
- if (status != NO_ERROR) {
- return false;
- }
bool mute;
status = AudioSystem::getMasterMute(&mute);
@@ -136,9 +133,6 @@
status_t status = AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
"0", "");
- if (status != NO_ERROR) {
- return false;
- }
float vol;
status = AudioSystem::getMasterVolume(&vol);
diff --git a/tests/tests/security/jni/android_security_cts_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/res/raw/bug_25812590.mp2 b/tests/tests/security/res/raw/bug_25812590.mp2
new file mode 100644
index 0000000..dbde03e
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_25812590.mp2
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_26070014.mp2 b/tests/tests/security/res/raw/bug_26070014.mp2
new file mode 100644
index 0000000..ccb8e41
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_26070014.mp2
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_26366256.midi b/tests/tests/security/res/raw/bug_26366256.midi
new file mode 100644
index 0000000..5114d92
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_26366256.midi
Binary files differ
diff --git a/tests/tests/security/res/raw/drm_uaf.dm b/tests/tests/security/res/raw/drm_uaf.dm
new file mode 100644
index 0000000..50f42bc
--- /dev/null
+++ b/tests/tests/security/res/raw/drm_uaf.dm
Binary files differ
diff --git a/tests/tests/security/res/raw/midi_crash.midi b/tests/tests/security/res/raw/midi_crash.midi
new file mode 100644
index 0000000..1880229
--- /dev/null
+++ b/tests/tests/security/res/raw/midi_crash.midi
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/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
new file mode 100644
index 0000000..9dff6dd
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.content.res.AssetFileDescriptor;
+import android.drm.DrmConvertedStatus;
+import android.drm.DrmManagerClient;
+import android.media.MediaPlayer;
+import android.os.ConditionVariable;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import com.android.cts.security.R;
+
+public class MediaServerCrashTest extends AndroidTestCase {
+ private static final String TAG = "MediaServerCrashTest";
+
+ private static final String MIMETYPE_DRM_MESSAGE = "application/vnd.oma.drm.message";
+
+ private String mFlFilePath;
+
+ private final MediaPlayer mMediaPlayer = new MediaPlayer();
+ private final ConditionVariable mOnPrepareCalled = new ConditionVariable();
+ private final ConditionVariable mOnCompletionCalled = new ConditionVariable();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mFlFilePath = new File(Environment.getExternalStorageDirectory(),
+ "temp.fl").getAbsolutePath();
+
+ mOnPrepareCalled.close();
+ mOnCompletionCalled.close();
+ mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ assertTrue(mp == mMediaPlayer);
+ assertTrue("mediaserver process died", what != MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+ Log.w(TAG, "onError " + what);
+ return false;
+ }
+ });
+
+ mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ assertTrue(mp == mMediaPlayer);
+ mOnPrepareCalled.open();
+ }
+ });
+
+ mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ assertTrue(mp == mMediaPlayer);
+ mOnCompletionCalled.open();
+ }
+ });
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ File flFile = new File(mFlFilePath);
+ if (flFile.exists()) {
+ flFile.delete();
+ }
+ }
+
+ public void testInvalidMidiNullPointerAccess() throws Exception {
+ testIfMediaServerDied(R.raw.midi_crash);
+ }
+
+ private void testIfMediaServerDied(int res) throws Exception {
+ AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(res);
+ mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+ afd.close();
+ try {
+ mMediaPlayer.prepareAsync();
+ if (!mOnPrepareCalled.block(5000)) {
+ Log.w(TAG, "testIfMediaServerDied: Timed out waiting for prepare");
+ return;
+ }
+ mMediaPlayer.start();
+ if (!mOnCompletionCalled.block(5000)) {
+ Log.w(TAG, "testIfMediaServerDied: Timed out waiting for Error/Completion");
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "playback failed", e);
+ } finally {
+ mMediaPlayer.release();
+ }
+ }
+
+ public void testDrmManagerClientReset() throws Exception {
+ checkIfMediaServerDiedForDrm(R.raw.drm_uaf);
+ }
+
+ private void checkIfMediaServerDiedForDrm(int res) throws Exception {
+ if (!convertDmToFl(res, mFlFilePath)) {
+ fail("Can not convert dm to fl");
+ }
+ Log.d(TAG, "intermediate fl file is " + mFlFilePath);
+
+ ParcelFileDescriptor flFd = null;
+ try {
+ flFd = ParcelFileDescriptor.open(new File(mFlFilePath),
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ fail("Could not find file: " + mFlFilePath + e);
+ }
+
+ mMediaPlayer.setDataSource(flFd.getFileDescriptor(), 0, flFd.getStatSize());
+ flFd.close();
+ try {
+ mMediaPlayer.prepare();
+ } catch (Exception e) {
+ Log.d(TAG, "Prepare failed", e);
+ }
+
+ try {
+ mMediaPlayer.reset();
+ if (!mOnCompletionCalled.block(5000)) {
+ Log.w(TAG, "checkIfMediaServerDiedForDrm: Timed out waiting for Error/Completion");
+ }
+ } catch (Exception e) {
+ fail("reset failed" + e);
+ } finally {
+ mMediaPlayer.release();
+ }
+ }
+
+ private boolean convertDmToFl(int res, String flFilePath) throws Exception {
+ AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(res);
+ FileInputStream inputStream = afd.createInputStream();
+ int inputLength = (int)afd.getLength();
+ byte[] fileData = new byte[inputLength];
+ int readSize = inputStream.read(fileData, 0, inputLength);
+ assertEquals("can not pull in all data", readSize, inputLength);
+ inputStream.close();
+ afd.close();
+
+ FileOutputStream flStream = new FileOutputStream(new File(flFilePath));
+
+ DrmManagerClient drmClient = null;
+ try {
+ drmClient = new DrmManagerClient(mContext);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "DrmManagerClient instance could not be created, context is Illegal.");
+ return false;
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "DrmManagerClient didn't initialize properly.");
+ return false;
+ }
+
+ if (drmClient == null) {
+ Log.w(TAG, "Failed to create DrmManagerClient.");
+ return false;
+ }
+
+ int convertSessionId = -1;
+ try {
+ convertSessionId = drmClient.openConvertSession(MIMETYPE_DRM_MESSAGE);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "Conversion of Mimetype: " + MIMETYPE_DRM_MESSAGE
+ + " is not supported.", e);
+ return false;
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Could not access Open DrmFramework.", e);
+ return false;
+ }
+
+ if (convertSessionId < 0) {
+ Log.w(TAG, "Failed to open session.");
+ return false;
+ }
+
+ DrmConvertedStatus convertedStatus = null;
+ try {
+ convertedStatus = drmClient.convertData(convertSessionId, fileData);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "Buffer with data to convert is illegal. Convertsession: "
+ + convertSessionId, e);
+ return false;
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Could not convert data. Convertsession: " + convertSessionId, e);
+ return false;
+ }
+
+ if (convertedStatus == null ||
+ convertedStatus.statusCode != DrmConvertedStatus.STATUS_OK ||
+ convertedStatus.convertedData == null) {
+ Log.w(TAG, "Error in converting data. Convertsession: " + convertSessionId);
+ try {
+ drmClient.closeConvertSession(convertSessionId);
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Could not close session. Convertsession: " +
+ convertSessionId, e);
+ }
+ return false;
+ }
+
+ flStream.write(convertedStatus.convertedData, 0, convertedStatus.convertedData.length);
+ flStream.close();
+
+ try {
+ convertedStatus = drmClient.closeConvertSession(convertSessionId);
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Could not close convertsession. Convertsession: " +
+ convertSessionId, e);
+ return false;
+ }
+
+ if (convertedStatus == null ||
+ convertedStatus.statusCode != DrmConvertedStatus.STATUS_OK ||
+ convertedStatus.convertedData == null) {
+ Log.w(TAG, "Error in closing session. Convertsession: " + convertSessionId);
+ return false;
+ }
+
+ RandomAccessFile flRandomAccessFile = null;
+ try {
+ flRandomAccessFile = new RandomAccessFile(flFilePath, "rw");
+ flRandomAccessFile.seek(convertedStatus.offset);
+ flRandomAccessFile.write(convertedStatus.convertedData);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "File: " + flFilePath + " could not be found.", e);
+ return false;
+ } catch (IOException e) {
+ Log.w(TAG, "Could not access File: " + flFilePath + " .", e);
+ return false;
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "Could not open file in mode: rw", e);
+ return false;
+ } catch (SecurityException e) {
+ Log.w(TAG, "Access to File: " + flFilePath +
+ " was denied denied by SecurityManager.", e);
+ return false;
+ } finally {
+ if (flRandomAccessFile != null) {
+ try {
+ flRandomAccessFile.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to close File:" + flFilePath + ".", e);
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+}
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 0f79860..b28c06a 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;
@@ -43,6 +55,8 @@
public class StagefrightTest extends InstrumentationTestCase {
static final String TAG = "StagefrightTest";
+ private final long TIMEOUT_NS = 10000000000L; // 10 seconds.
+
public StagefrightTest() {
}
@@ -94,14 +108,65 @@
doStagefrightTest(R.raw.cve_2015_6598);
}
+ public void testStagefright_bug_26366256() throws Exception {
+ doStagefrightTest(R.raw.bug_26366256);
+ }
+
+ public void testStagefright_bug_25765591() throws Exception {
+ doStagefrightTest(R.raw.bug_25765591);
+ }
+
+ public void testStagefright_bug_25812590() throws Exception {
+ doStagefrightTest(R.raw.bug_25812590);
+ }
+
+ public void testStagefright_bug_26070014() throws Exception {
+ doStagefrightTest(R.raw.bug_26070014);
+ }
+
private void doStagefrightTest(final int rid) throws Exception {
+ doStagefrightTestMediaPlayer(rid);
+ doStagefrightTestMediaCodec(rid);
+ }
+
+ private Surface getDummySurface() {
+ int[] textures = new int[1];
+ GLES20.glGenTextures(1, textures, 0);
+ GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
+ GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_MIN_FILTER,
+ GLES20.GL_NEAREST);
+ GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_MAG_FILTER,
+ GLES20.GL_LINEAR);
+ GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_WRAP_S,
+ GLES20.GL_CLAMP_TO_EDGE);
+ GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
+ GLES20.GL_TEXTURE_WRAP_T,
+ GLES20.GL_CLAMP_TO_EDGE);
+ SurfaceTexture surfaceTex = new SurfaceTexture(textures[0]);
+ surfaceTex.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
+ @Override
+ public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+ Log.i(TAG, "new frame available");
+ }
+ });
+ return new Surface(surfaceTex);
+ }
+
+ private void doStagefrightTestMediaPlayer(final int rid) throws Exception {
class MediaPlayerCrashListener
implements MediaPlayer.OnErrorListener,
MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener {
@Override
public boolean onError(MediaPlayer mp, int newWhat, int extra) {
- what = newWhat;
+ Log.i(TAG, "error: " + newWhat);
+ // don't overwrite a more severe error with a less severe one
+ if (what != MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
+ what = newWhat;
+ }
lock.lock();
condition.signal();
lock.unlock();
@@ -116,7 +181,7 @@
@Override
public void onCompletion(MediaPlayer mp) {
- what = 0;
+ // preserve error condition, if any
lock.lock();
condition.signal();
lock.unlock();
@@ -124,8 +189,16 @@
public int waitForError() throws InterruptedException {
lock.lock();
- condition.await();
+ if (condition.awaitNanos(TIMEOUT_NS) <= 0) {
+ Log.d(TAG, "timed out on waiting for error");
+ }
lock.unlock();
+ if (what != 0) {
+ // Sometimes mediaserver signals a decoding error first, and *then* crashes
+ // due to additional in-flight buffers being processed, so wait a little
+ // and see if more errors show up.
+ SystemClock.sleep(1000);
+ }
return what;
}
@@ -134,6 +207,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() {
@@ -145,6 +221,8 @@
mp.setOnErrorListener(mpcl);
mp.setOnPreparedListener(mpcl);
mp.setOnCompletionListener(mpcl);
+ Surface surface = getDummySurface();
+ mp.setSurface(surface);
try {
AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
.openRawResourceFd(rid);
@@ -163,10 +241,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/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 b1d4638..4582935 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 (30) 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/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 64a2b31..0000000
--- a/tools/tradefed-host/preconditions/src/com/android/cts/preconditions/PreconditionsTest.java
+++ /dev/null
@@ -1,48 +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.os.Environment;
-import android.test.AndroidTestCase;
-
-/**
- * An AndroidTestCase class to verify that device-side preconditions are met for CTS
- */
-public class PreconditionsTest extends AndroidTestCase {
-
- /**
- * Test if device has no screen lock
- * @throws Exception
- */
- public void testScreenUnlocked() throws Exception {
- 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 66a4562..3038e80 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
@Option(name="cts-install-path", description="the path to the cts installation to use")
private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
- public static final String CTS_BUILD_VERSION = "6.0_r3";
+ public static final String CTS_BUILD_VERSION = "6.0_r201602s";
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 039470b..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/DevicePreconditionPreparer.java
+++ /dev/null
@@ -1,213 +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.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.CLog;
-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";
-
- /* Map used to track test failures */
- private ConcurrentHashMap<TestIdentifier, String> testFailures = new ConcurrentHashMap<>();
-
- /**
- * {@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)) {
- throw new TargetSetupError("Not all device-side preconditions met");
- }
- } 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);
- CLog.e("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) {
- CLog.e("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 8998f16..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/HostPreconditionPreparer.java
+++ /dev/null
@@ -1,538 +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 = "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_USB = 2;
-
- /* 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_USB);
- 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 (mWifiSsid == null) {
- // no connection to create, check for existing connectivity
- if (!device.checkConnectivity()) {
- throw new TargetSetupError("Device has no network connection, no ssid provided");
- }
- } else {
- // network provided in options, attempt to create new connection if needed
- if (!device.connectToWifiNetworkIfNeeded(mWifiSsid, mWifiPsk)) {
- throw new TargetSetupError("Unable to establish network connection," +
- "some CTS packages require an active network connection");
- }
- }
- }
-
- /**
- * 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