Merge "Fixed "Camera FOV Calibration" crash issue for non back-facing camera." into jb-mr1.1-dev
diff --git a/tests/Android.mk b/tests/Android.mk
index 15705dd..4a87b07 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -20,7 +20,8 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)\
$(call all-renderscript-files-under, src)\
src/android/app/cts/ISecondary.aidl\
- src/android/os/cts/IEmptyService.aidl
+ src/android/os/cts/IEmptyService.aidl\
+ src/android/security/cts/activity/ISecureRandomService.aidl
LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 590ee36..f487ab0 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -106,7 +106,10 @@
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
-
+
+ <!-- Used for ClonedSecureRandomTest -->
+ <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
+
<!-- Used for PackageManager test, don't delete this permission-tree -->
<permission-tree android:name="com.android.cts.stub.permission.TEST_DYNAMIC"
android:label="Test Tree"/>
@@ -973,6 +976,9 @@
<activity android:name="android.renderscript.cts.RenderscriptGLStubActivity"
android:label="RenderscriptGLStub"/>
+
+ <service android:name="android.security.cts.activity.SecureRandomService"
+ android:process=":secureRandom"/>
</application>
diff --git a/tests/deviceadmin/AndroidManifest.xml b/tests/deviceadmin/AndroidManifest.xml
index 69bc74d..2395d99 100644
--- a/tests/deviceadmin/AndroidManifest.xml
+++ b/tests/deviceadmin/AndroidManifest.xml
@@ -40,6 +40,17 @@
</intent-filter>
</receiver>
+ <!-- Device Admin that needs to be in the deactivated state in order
+ for tests to pass. -->
+ <receiver android:name="android.deviceadmin.cts.CtsDeviceAdminDeactivatedReceiver"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
<!-- Helper Activity used by Device Admin activation tests -->
<activity android:name="android.deviceadmin.cts.CtsDeviceAdminActivationTestActivity"
android:label="Device Admin activation test" />
diff --git a/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminDeactivatedReceiver.java b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminDeactivatedReceiver.java
new file mode 100644
index 0000000..ec59f63
--- /dev/null
+++ b/tests/deviceadmin/src/android/deviceadmin/cts/CtsDeviceAdminDeactivatedReceiver.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.deviceadmin.cts;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class CtsDeviceAdminDeactivatedReceiver extends DeviceAdminReceiver {
+}
diff --git a/tests/src/android/security/cts/activity/ISecureRandomService.aidl b/tests/src/android/security/cts/activity/ISecureRandomService.aidl
new file mode 100644
index 0000000..af264c9
--- /dev/null
+++ b/tests/src/android/security/cts/activity/ISecureRandomService.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 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.activity;
+
+interface ISecureRandomService {
+ int getRandomBytesAndPid(inout byte[] randomBytes);
+}
diff --git a/tests/src/android/security/cts/activity/SecureRandomService.java b/tests/src/android/security/cts/activity/SecureRandomService.java
new file mode 100644
index 0000000..2d425b3
--- /dev/null
+++ b/tests/src/android/security/cts/activity/SecureRandomService.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 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.activity;
+
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.security.cts.activity.ISecureRandomService;
+
+import android.app.Service;
+import android.content.Intent;
+
+import java.security.SecureRandom;
+
+public class SecureRandomService extends Service {
+ /**
+ * This helps the process shut down a little faster and get us a new
+ * PID earlier than calling stopService.
+ */
+ private Handler mShutdownHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ stopSelf();
+ }
+ };
+
+ private final ISecureRandomService.Stub mBinder = new ISecureRandomService.Stub() {
+
+ /**
+ * Returns output from SecureRandom and the current process PID. Note
+ * that this should only be called once. To ensure that it's only called
+ * once, this will throw an error if it's called twice in a row.
+ */
+ public int getRandomBytesAndPid(byte[] randomBytes) {
+ mShutdownHandler.sendEmptyMessage(-1);
+
+ SecureRandom sr = new SecureRandom();
+ sr.nextBytes(randomBytes);
+ return android.os.Process.myPid();
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+}
diff --git a/tests/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java b/tests/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java
index 7e09989..cb0425a 100644
--- a/tests/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java
+++ b/tests/tests/admin/src/android/admin/cts/DeviceAdminActivationTest.java
@@ -19,13 +19,14 @@
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver;
import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver2;
import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver3;
import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver4;
import android.deviceadmin.cts.CtsDeviceAdminBrokenReceiver5;
-import android.deviceadmin.cts.CtsDeviceAdminReceiver;
+import android.deviceadmin.cts.CtsDeviceAdminDeactivatedReceiver;
import android.deviceadmin.cts.CtsDeviceAdminActivationTestActivity;
import android.deviceadmin.cts.CtsDeviceAdminActivationTestActivity.OnActivityResultListener;
import android.os.SystemClock;
@@ -98,37 +99,49 @@
}
public void testActivateGoodReceiverDisplaysActivationUi() throws Exception {
- startAddDeviceAdminActivityForResult(CtsDeviceAdminReceiver.class);
+ assertDeviceAdminDeactivated(CtsDeviceAdminDeactivatedReceiver.class);
+ startAddDeviceAdminActivityForResult(CtsDeviceAdminDeactivatedReceiver.class);
assertWithTimeoutOnActivityResultNotInvoked();
// The UI is up and running. Assert that dismissing the UI returns the corresponding result
// to the test activity.
finishActivateDeviceAdminActivity();
assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminDeactivatedReceiver.class);
}
public void testActivateBrokenReceiverFails() throws Exception {
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver.class);
startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver.class);
assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver.class);
}
public void testActivateBrokenReceiver2Fails() throws Exception {
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver2.class);
startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver2.class);
assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver2.class);
}
public void testActivateBrokenReceiver3Fails() throws Exception {
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver3.class);
startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver3.class);
assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver3.class);
}
public void testActivateBrokenReceiver4Fails() throws Exception {
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver4.class);
startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver4.class);
assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver4.class);
}
public void testActivateBrokenReceiver5Fails() throws Exception {
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver5.class);
startAddDeviceAdminActivityForResult(CtsDeviceAdminBrokenReceiver5.class);
assertWithTimeoutOnActivityResultInvokedWithResultCode(Activity.RESULT_CANCELED);
+ assertDeviceAdminDeactivated(CtsDeviceAdminBrokenReceiver5.class);
}
private void startAddDeviceAdminActivityForResult(Class<?> receiverClass) {
@@ -179,4 +192,12 @@
private void finishActivateDeviceAdminActivity() {
getActivity().finishActivity(REQUEST_CODE_ACTIVATE_ADMIN);
}
+
+ private void assertDeviceAdminDeactivated(Class<?> receiverClass) {
+ DevicePolicyManager devicePolicyManager =
+ (DevicePolicyManager) getActivity().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ assertFalse(devicePolicyManager.isAdminActive(
+ new ComponentName(getInstrumentation().getTargetContext(), receiverClass)));
+ }
}
diff --git a/tests/tests/app/src/android/app/cts/FragmentTest.java b/tests/tests/app/src/android/app/cts/FragmentTest.java
new file mode 100644
index 0000000..c5c0d6c
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/FragmentTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.cts;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.test.AndroidTestCase;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+@TestTargetClass(Fragment.class)
+public class FragmentTest extends AndroidTestCase {
+
+ public static class TestFragment extends Fragment {
+ public TestFragment() {}
+ }
+
+ public static class TestNotFragment {
+ public TestNotFragment() {
+ throw new IllegalStateException("Shouldn't call constructor");
+ }
+ }
+
+ public void testInstantiateFragment() {
+ assertNotNull(Fragment.instantiate(getContext(), TestFragment.class.getName()));
+ }
+
+ public void testInstantiateNonFragment() {
+ try {
+ Fragment.instantiate(getContext(), TestNotFragment.class.getName());
+ fail();
+ } catch (Exception e) {
+ assertTrue(e instanceof IllegalStateException);
+ }
+ }
+}
+
diff --git a/tests/tests/drm/Android.mk b/tests/tests/drm/Android.mk
index 3264c32..8b76cd8 100644
--- a/tests/tests/drm/Android.mk
+++ b/tests/tests/drm/Android.mk
@@ -16,8 +16,8 @@
include $(CLEAR_VARS)
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
+
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
@@ -31,7 +31,13 @@
LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
+LOCAL_JNI_SHARED_LIBRARIES := \
+ libctsdrm_jni \
+ libdrmtestplugin
+
# uncomment when dalvik.annotation.Test* are removed or part of SDK
#LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/drm/jni/Android.mk b/tests/tests/drm/jni/Android.mk
new file mode 100644
index 0000000..06b2df9
--- /dev/null
+++ b/tests/tests/drm/jni/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libctsdrm_jni
+
+# Don't include this package in any configuration by default.
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+ CtsDrmJniOnLoad.cpp \
+ android_drm_cts_NativeCodeTest.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := liblog libdl
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/drm/jni/CtsDrmJniOnLoad.cpp b/tests/tests/drm/jni/CtsDrmJniOnLoad.cpp
new file mode 100644
index 0000000..a9ec3da
--- /dev/null
+++ b/tests/tests/drm/jni/CtsDrmJniOnLoad.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+#include <stdio.h>
+
+extern int register_android_drm_cts_NativeCodeTest(JNIEnv*);
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+ JNIEnv *env = NULL;
+
+ if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
+ return JNI_ERR;
+ }
+
+ if (register_android_drm_cts_NativeCodeTest(env)) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_4;
+}
diff --git a/tests/tests/drm/jni/android_drm_cts_NativeCodeTest.cpp b/tests/tests/drm/jni/android_drm_cts_NativeCodeTest.cpp
new file mode 100644
index 0000000..398a44e
--- /dev/null
+++ b/tests/tests/drm/jni/android_drm_cts_NativeCodeTest.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <utils/Log.h>
+
+/*
+ * Returns true iff this device may be vulnerable to installation of rogue drm
+ * plugins, as determined by the existance of the _installDrmEngine symbol in the
+ * libdrmframework_jni.so library.
+ */
+static jboolean android_drm_cts_InstallDrmEngineTest(JNIEnv* env, jobject thiz)
+{
+ jboolean result = false;
+
+ // install /system/lib/libdrmtestplugin.so
+ FILE *f = popen("service call drm.drmManager 6 i32 0 i32 31 i32 1937339183 i32 795698548 "
+ "i32 794978668 i32 1684171116 i32 1702129010 i32 1819309171 i32 1852401525 "
+ "i32 7303982 i32 1598902849", "r");
+ if (f) {
+ char buffer[128];
+ if (fgets(buffer, sizeof(buffer), f) != NULL) {
+ const char *match = "Result: Parcel(00000000 '....')";
+ if (!strncmp(buffer, match, strlen(match))) {
+ result = true;
+ }
+ }
+ pclose(f);
+ }
+ return result;
+}
+
+static JNINativeMethod gMethods[] = {
+ { "doInstallDrmEngineTest", "()Z",
+ (void *) android_drm_cts_InstallDrmEngineTest },
+};
+
+int register_android_drm_cts_NativeCodeTest(JNIEnv* env)
+{
+ jclass clazz = env->FindClass("android/drm/cts/NativeCodeTest");
+ return env->RegisterNatives(clazz, gMethods,
+ sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/drm/lib/Android.mk b/tests/tests/drm/lib/Android.mk
new file mode 100644
index 0000000..3ebc4a0
--- /dev/null
+++ b/tests/tests/drm/lib/Android.mk
@@ -0,0 +1,37 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libdrmtestplugin
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ TestPlugin.cpp
+
+LOCAL_C_INCLUDES := \
+ $(JNI_H_INCLUDE) \
+ $(TOP)/frameworks/av/drm/libdrmframework/plugins/common/include
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libutils
+
+LOCAL_STATIC_LIBRARIES := \
+ libdrmframeworkcommon
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/drm/lib/TestPlugin.cpp b/tests/tests/drm/lib/TestPlugin.cpp
new file mode 100644
index 0000000..5708909
--- /dev/null
+++ b/tests/tests/drm/lib/TestPlugin.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2010 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 "TestPlugin"
+#include <utils/Log.h>
+
+#include <drm/DrmRights.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
+#include <drm/DrmInfo.h>
+#include <drm/DrmInfoEvent.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmConvertedStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+#include <TestPlugin.h>
+
+using namespace android;
+
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" IDrmEngine* create() {
+ return new TestPlugIn();
+}
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" void destroy(IDrmEngine* pPlugIn) {
+ delete pPlugIn;
+ pPlugIn = NULL;
+}
+
+TestPlugIn::TestPlugIn()
+ : DrmEngineBase() {
+
+}
+
+TestPlugIn::~TestPlugIn() {
+
+}
+
+DrmMetadata* TestPlugIn::onGetMetadata(int uniqueId, const String8* path) {
+ return NULL;
+}
+
+DrmConstraints* TestPlugIn::onGetConstraints(
+ int uniqueId, const String8* path, int action) {
+ return NULL;
+}
+
+DrmInfoStatus* TestPlugIn::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ return NULL;
+}
+
+status_t TestPlugIn::onSetOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+ return DRM_NO_ERROR;
+}
+
+status_t TestPlugIn::onInitialize(int uniqueId) {
+ return DRM_NO_ERROR;
+}
+
+status_t TestPlugIn::onTerminate(int uniqueId) {
+ return DRM_NO_ERROR;
+}
+
+DrmSupportInfo* TestPlugIn::onGetSupportInfo(int uniqueId) {
+ DrmSupportInfo* drmSupportInfo = new DrmSupportInfo();
+ return drmSupportInfo;
+}
+
+status_t TestPlugIn::onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ return DRM_NO_ERROR;
+}
+
+DrmInfo* TestPlugIn::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ return NULL;
+}
+
+bool TestPlugIn::onCanHandle(int uniqueId, const String8& path) {
+ return false;
+}
+
+String8 TestPlugIn::onGetOriginalMimeType(int uniqueId, const String8& path, int fd) {
+ return String8("video/none");
+}
+
+int TestPlugIn::onGetDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ return DrmObjectType::UNKNOWN;
+}
+
+int TestPlugIn::onCheckRightsStatus(int uniqueId, const String8& path, int action) {
+ int rightsStatus = RightsStatus::RIGHTS_VALID;
+ return rightsStatus;
+}
+
+status_t TestPlugIn::onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
+ int action, bool reserve) {
+ return DRM_NO_ERROR;
+}
+
+status_t TestPlugIn::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+ int playbackStatus, int64_t position) {
+ return DRM_NO_ERROR;
+}
+
+bool TestPlugIn::onValidateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ return true;
+}
+
+status_t TestPlugIn::onRemoveRights(int uniqueId, const String8& path) {
+ return DRM_NO_ERROR;
+}
+
+status_t TestPlugIn::onRemoveAllRights(int uniqueId) {
+ return DRM_NO_ERROR;
+}
+
+status_t TestPlugIn::onOpenConvertSession(int uniqueId, int convertId) {
+ return DRM_NO_ERROR;
+}
+
+DrmConvertedStatus* TestPlugIn::onConvertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0);
+}
+
+DrmConvertedStatus* TestPlugIn::onCloseConvertSession(int uniqueId, int convertId) {
+ return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0);
+}
+
+status_t TestPlugIn::onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length) {
+ return DRM_ERROR_CANNOT_HANDLE;
+}
+
+status_t TestPlugIn::onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri) {
+ return DRM_ERROR_CANNOT_HANDLE;
+}
+
+status_t TestPlugIn::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ return DRM_NO_ERROR;
+}
+
+status_t TestPlugIn::onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ return DRM_NO_ERROR;
+}
+
+status_t TestPlugIn::onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ return DRM_NO_ERROR;
+}
+
+status_t TestPlugIn::onFinalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ return DRM_NO_ERROR;
+}
+
+ssize_t TestPlugIn::onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset) {
+ return 0;
+}
+
diff --git a/tests/tests/drm/lib/TestPlugin.h b/tests/tests/drm/lib/TestPlugin.h
new file mode 100644
index 0000000..40d4ec7
--- /dev/null
+++ b/tests/tests/drm/lib/TestPlugin.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_TEST_PLUGIN_H__
+#define __DRM_TEST_PLUGIN_H__
+
+#include <DrmEngineBase.h>
+
+namespace android {
+
+class TestPlugIn : public DrmEngineBase {
+
+public:
+ TestPlugIn();
+ virtual ~TestPlugIn();
+
+protected:
+ DrmConstraints* onGetConstraints(int uniqueId, const String8* path, int action);
+
+ DrmMetadata* onGetMetadata(int uniqueId, const String8* path);
+
+ status_t onInitialize(int uniqueId);
+
+ status_t onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
+
+ status_t onTerminate(int uniqueId);
+
+ bool onCanHandle(int uniqueId, const String8& path);
+
+ DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ status_t onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ DrmInfo* onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ String8 onGetOriginalMimeType(int uniqueId, const String8& path, int fd);
+
+ int onGetDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int onCheckRightsStatus(int uniqueId, const String8& path, int action);
+
+ status_t onConsumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ status_t onSetPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+
+ bool onValidateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ status_t onRemoveRights(int uniqueId, const String8& path);
+
+ status_t onRemoveAllRights(int uniqueId);
+
+ status_t onOpenConvertSession(int uniqueId, int convertId);
+
+ DrmConvertedStatus* onConvertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId);
+
+ DrmSupportInfo* onGetSupportInfo(int uniqueId);
+
+ status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length);
+
+ status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri);
+
+ status_t onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ status_t onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ status_t onFinalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
+
+private:
+ DecryptHandle* openDecryptSessionImpl();
+};
+
+};
+
+#endif /* __DRM_TEST_PLUGIN_H__ */
diff --git a/tests/tests/drm/src/android/drm/cts/NativeCodeTest.java b/tests/tests/drm/src/android/drm/cts/NativeCodeTest.java
new file mode 100644
index 0000000..856cb88
--- /dev/null
+++ b/tests/tests/drm/src/android/drm/cts/NativeCodeTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 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.drm.cts;
+
+import junit.framework.TestCase;
+
+public class NativeCodeTest extends TestCase {
+
+ static {
+ System.loadLibrary("ctsdrm_jni");
+ }
+
+ public void testInstallDrmEngine() throws Exception {
+ assertFalse("Device is vulnerable to arbitrary code execution in drmserver process.",
+ doInstallDrmEngineTest());
+ }
+
+ /**
+ * Returns true iff this device is vulnerable to arbitrary code execution in drm server
+ */
+ private static native boolean doInstallDrmEngineTest();
+}
diff --git a/tests/tests/media/res/raw/monotestm4a.m4a b/tests/tests/media/res/raw/monotestm4a.m4a
new file mode 100644
index 0000000..9ef6651
--- /dev/null
+++ b/tests/tests/media/res/raw/monotestm4a.m4a
Binary files differ
diff --git a/tests/tests/media/res/raw/monotestmp3.mp3 b/tests/tests/media/res/raw/monotestmp3.mp3
new file mode 100644
index 0000000..43a8ac3
--- /dev/null
+++ b/tests/tests/media/res/raw/monotestmp3.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/monotestogg.ogg b/tests/tests/media/res/raw/monotestogg.ogg
new file mode 100644
index 0000000..3dc5644
--- /dev/null
+++ b/tests/tests/media/res/raw/monotestogg.ogg
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index ac80538..76103f5 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -31,7 +31,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
-import java.util.Map;
+import java.util.Arrays;
public class DecoderTest extends AndroidTestCase {
private static final String TAG = "DecoderTest";
@@ -203,5 +203,152 @@
assertTrue("decoding error too big: " + rmse, rmse <= maxerror);
}
+ public void testDecodeMonoMp3() throws Exception {
+ monoTest(R.raw.monotestmp3);
+ }
+
+ public void testDecodeMonoM4a() throws Exception {
+ monoTest(R.raw.monotestm4a);
+ }
+
+ public void testDecodeMonoOgg() throws Exception {
+ monoTest(R.raw.monotestogg);
+ }
+
+ private void monoTest(int res) throws Exception {
+ short [] mono = decodeToMemory(res);
+ if (mono.length == 44100) {
+ // expected
+ return;
+ } else if (mono.length == 88200) {
+ // the decoder output 2 channels instead of 1, check that the left and right channel
+ // are identical
+ for (int i = 0; i < mono.length; i += 2) {
+ assertEquals("mismatched samples at " + i, mono[i], mono[i+1]);
+ }
+ } else {
+ fail("wrong number of samples: " + mono.length);
+ }
+ }
+
+ private short[] decodeToMemory(int testinput) throws IOException {
+
+ short [] decoded = new short[0];
+ int decodedIdx = 0;
+
+ AssetFileDescriptor testFd = mResources.openRawResourceFd(testinput);
+
+ MediaExtractor extractor;
+ MediaCodec codec;
+ ByteBuffer[] codecInputBuffers;
+ ByteBuffer[] codecOutputBuffers;
+
+ extractor = new MediaExtractor();
+ extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
+ testFd.getLength());
+ testFd.close();
+
+ assertEquals("wrong number of tracks", 1, extractor.getTrackCount());
+ MediaFormat format = extractor.getTrackFormat(0);
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ assertTrue("not an audio file", mime.startsWith("audio/"));
+ Log.i("@@@@", "extractor format: " + format);
+
+ codec = MediaCodec.createDecoderByType(mime);
+ codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
+ codec.start();
+ codecInputBuffers = codec.getInputBuffers();
+ codecOutputBuffers = codec.getOutputBuffers();
+
+ extractor.selectTrack(0);
+
+ // start decoding
+ final long kTimeOutUs = 5000;
+ MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+ boolean sawInputEOS = false;
+ boolean sawOutputEOS = false;
+ int noOutputCounter = 0;
+ while (!sawOutputEOS && noOutputCounter < 50) {
+ noOutputCounter++;
+ if (!sawInputEOS) {
+ int inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
+
+ if (inputBufIndex >= 0) {
+ ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
+
+ int sampleSize =
+ extractor.readSampleData(dstBuf, 0 /* offset */);
+
+ long presentationTimeUs = 0;
+
+ if (sampleSize < 0) {
+ Log.d(TAG, "saw input EOS.");
+ sawInputEOS = true;
+ sampleSize = 0;
+ } else {
+ presentationTimeUs = extractor.getSampleTime();
+ }
+
+ codec.queueInputBuffer(
+ inputBufIndex,
+ 0 /* offset */,
+ sampleSize,
+ presentationTimeUs,
+ sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
+
+ if (!sawInputEOS) {
+ extractor.advance();
+ }
+ }
+ }
+
+ int res = codec.dequeueOutputBuffer(info, kTimeOutUs);
+
+ if (res >= 0) {
+ //Log.d(TAG, "got frame, size " + info.size + "/" + info.presentationTimeUs);
+
+ if (info.size > 0) {
+ noOutputCounter = 0;
+ }
+
+ int outputBufIndex = res;
+ ByteBuffer buf = codecOutputBuffers[outputBufIndex];
+
+ if (decodedIdx + (info.size / 2) >= decoded.length) {
+ decoded = Arrays.copyOf(decoded, decodedIdx + (info.size / 2));
+ }
+
+ for (int i = 0; i < info.size; i += 2) {
+ decoded[decodedIdx++] = buf.getShort(i);
+ }
+
+ codec.releaseOutputBuffer(outputBufIndex, false /* render */);
+
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ Log.d(TAG, "saw output EOS.");
+ sawOutputEOS = true;
+ }
+ } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+ codecOutputBuffers = codec.getOutputBuffers();
+
+ Log.d(TAG, "output buffers have changed.");
+ } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ MediaFormat oformat = codec.getOutputFormat();
+
+ Log.d(TAG, "output format has changed to " + oformat);
+ } else {
+ Log.d(TAG, "dequeueOutputBuffer returned " + res);
+ }
+ }
+
+ if (noOutputCounter >= 50) {
+ fail("failed to get output for 50 iterations");
+ }
+
+ codec.stop();
+ codec.release();
+ return decoded;
+ }
+
}
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 5b943ca..40000b7 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -48,11 +48,11 @@
public void testRTSP_H264Base_AAC_Video1() throws Exception {
playVideoTest("rtsp://v2.cache7.c.youtube.com/video.3gp?cid=0x271de9756065677e"
- + "&fmt=18&user=android-device-test", 480, 270);
+ + "&fmt=18&user=android-device-test", 640, 360);
}
public void testRTSP_H264Base_AAC_Video2() throws Exception {
playVideoTest("rtsp://v2.cache7.c.youtube.com/video.3gp?cid=0xc80658495af60617"
- + "&fmt=18&user=android-device-test", 480, 270);
+ + "&fmt=18&user=android-device-test", 640, 360);
}
*/
// Streaming HTTP video from YouTube
@@ -96,7 +96,7 @@
+ "&sparams=ip,ipbits,expire,ip,ipbits,expire,id,itag"
+ "&signature=1219C2B07AF0638C27916307A6093C0E43CB894E"
+ ".126B6B916BD57157782738AA7C03E59F21DBC168"
- + "&key=test_key1&user=android-device-test", 480, 270);
+ + "&key=test_key1&user=android-device-test", 640, 360);
}
public void testHTTP_H264Base_AAC_Video2() throws Exception {
playVideoTest("http://v20.lscache8.c.youtube.com/videoplayback?id=c80658495af60617"
@@ -104,7 +104,7 @@
+ "&sparams=ip,ipbits,expire,ip,ipbits,expire,id,itag"
+ "&signature=61674BC069F2C812A18C390DE785CECD296228C7"
+ ".11F5FCE823FB8FA31269A06A483C2F9B2C22F357"
- + "&key=test_key1&user=android-device-test", 480, 270);
+ + "&key=test_key1&user=android-device-test", 640, 360);
}
// Streaming HLS video from YouTube
diff --git a/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java b/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
index 70ab54d..ceb74d1 100644
--- a/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
+++ b/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
@@ -86,9 +86,9 @@
}
// a host and port that are expected to be available but have
- // a cert with a different CN, in this case CN=mtalk.google.com
- private static String TEST_CREATE_SOCKET_HOST = "mobile-gtalk.l.google.com";
- private static int TEST_CREATE_SOCKET_PORT = 5228;
+ // a cert with a different CN, in this case CN=mail.google.com
+ private static String TEST_CREATE_SOCKET_HOST = "googlemail.com";
+ private static int TEST_CREATE_SOCKET_PORT = 443;
/**
* b/2807618 Make sure that hostname verifcation in cases were it
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index f5948ff..ab4a90b 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -356,6 +356,7 @@
"/data/data/recovery/HTCFOTA",
"/data/data/recovery/OMADM",
"/data/data/shared",
+ "/data/diag_logs",
"/data/dontpanic",
"/data/drm",
"/data/drm/fwdlock",
@@ -423,6 +424,7 @@
"/data/property",
"/data/radio",
"/data/secure",
+ "/data/security",
"/data/sensors",
"/data/shared",
"/data/simcom",
@@ -431,6 +433,7 @@
"/data/system",
"/data/tmp",
"/data/tombstones",
+ "/data/tombstones/ramdump",
"/data/tpapi",
"/data/tpapi/etc",
"/data/tpapi/etc/tpa",
@@ -670,6 +673,24 @@
insecure.isEmpty());
}
+ public void testDevRandomWorldReadableAndWritable() throws Exception {
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ assertTrue(FileUtils.getFileStatus("/dev/random", status, false));
+ assertTrue(
+ "/dev/random not world-readable/writable. Actual mode: 0"
+ + Integer.toString(status.mode, 8),
+ (status.mode & 0666) == 0666);
+ }
+
+ public void testDevUrandomWorldReadableAndWritable() throws Exception {
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ assertTrue(FileUtils.getFileStatus("/dev/urandom", status, false));
+ assertTrue(
+ "/dev/urandom not world-readable/writable. Actual mode: 0"
+ + Integer.toString(status.mode, 8),
+ (status.mode & 0666) == 0666);
+ }
+
private static Set<File>
getAllInsecureBlockDevicesInDirAndSubdir(File dir) throws Exception {
assertTrue(dir.isDirectory());
diff --git a/tests/tests/provider/src/android/provider/cts/CalendarTest.java b/tests/tests/provider/src/android/provider/cts/CalendarTest.java
index e460453..cbefa9d 100644
--- a/tests/tests/provider/src/android/provider/cts/CalendarTest.java
+++ b/tests/tests/provider/src/android/provider/cts/CalendarTest.java
@@ -1946,6 +1946,10 @@
assertTrue(eventId >= 0);
return eventValues;
}
+
+ public long getCalendarId() {
+ return mCalendarId;
+ }
}
/**
@@ -1981,7 +1985,8 @@
CalendarContract.Instances.CONTENT_BY_DAY_URI, julianStart + "/" + julianEnd);
// Query the range, sorting by event start time
- Cursor c = mContentResolver.query(uri, null, null, null, Events.DTSTART);
+ Cursor c = mContentResolver.query(uri, null, Instances.CALENDAR_ID + "="
+ + helper.getCalendarId(), null, Events.DTSTART);
// Assert that two events are returned
assertEquals(c.getCount(), 2);
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
index 1e8a4ac..c68f660 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
@@ -21,6 +21,7 @@
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
+import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
@@ -30,6 +31,8 @@
import android.test.AndroidTestCase;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
public class MediaStore_FilesTest extends AndroidTestCase {
@@ -146,6 +149,133 @@
}
}
+ public void testAccess() throws IOException {
+ // clean up from previous run
+ mResolver.delete(MediaStore.Images.Media.INTERNAL_CONTENT_URI,
+ "_data NOT LIKE ?", new String[] { "/system/%" } );
+
+ // insert some dummy starter data into the provider
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.Images.Media.DISPLAY_NAME, "My Bitmap");
+ values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
+ values.put(MediaStore.Images.Media.DATA, "/mnt/sdcard/dummy.jpg");
+ Uri uri = mResolver.insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
+
+ // point _data at directory and try to get an fd for it
+ values = new ContentValues();
+ values.put("_data", "/data/media");
+ mResolver.update(uri, values, null, null);
+ ParcelFileDescriptor pfd = null;
+ try {
+ pfd = mResolver.openFileDescriptor(uri, "r");
+ pfd.close();
+ fail("shouldn't be here");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+
+ // try to create a file in a place we don't have access to
+ values = new ContentValues();
+ values.put("_data", "/data/media/test.dat");
+ mResolver.update(uri, values, null, null);
+ try {
+ pfd = mResolver.openFileDescriptor(uri, "w");
+ pfd.close();
+ fail("shouldn't be here");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+ // read file back
+ try {
+ pfd = mResolver.openFileDescriptor(uri, "r");
+ pfd.close();
+ fail("shouldn't be here");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+
+ // point _data at media database and read it
+ values = new ContentValues();
+ values.put("_data", "/data/data/com.android.providers.media/databases/internal.db");
+ mResolver.update(uri, values, null, null);
+ try {
+ pfd = mResolver.openFileDescriptor(uri, "r");
+ pfd.close();
+ fail("shouldn't be here");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+
+ // Insert a private file into the database. Since it's private, the media provider won't
+ // be able to open it
+ FileOutputStream fos = mContext.openFileOutput("dummy.dat", Context.MODE_PRIVATE);
+ fos.write(0);
+ fos.close();
+ File path = mContext.getFileStreamPath("dummy.dat");
+ values = new ContentValues();
+ values.put("_data", path.getAbsolutePath());
+
+ mResolver.update(uri, values, null, null);
+ try {
+ pfd = mResolver.openFileDescriptor(uri, "r");
+ pfd.close();
+ fail("shouldn't be here");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+ // now make the file world-readable
+ fos = mContext.openFileOutput("dummy.dat", Context.MODE_WORLD_READABLE);
+ fos.write(0);
+ fos.close();
+ try {
+ pfd = mResolver.openFileDescriptor(uri, "r");
+ pfd.close();
+ } catch (FileNotFoundException e) {
+ fail("failed to open file");
+ }
+ path.delete();
+
+ File sdfile = null;
+ if (Environment.isExternalStorageEmulated()) {
+ // create file on sdcard and check access via real path
+ String fileDir = Environment.getExternalStorageDirectory() +
+ "/" + getClass().getCanonicalName() + "/test.mp3";
+ sdfile = new File(fileDir);
+ writeFile(R.raw.testmp3, sdfile.getCanonicalPath());
+ assertTrue(sdfile.exists());
+ values = new ContentValues();
+ values.put("_data", sdfile.getCanonicalPath());
+ mResolver.update(uri, values, null, null);
+ try {
+ pfd = mResolver.openFileDescriptor(uri, "r");
+
+ // get the real path from the file descriptor
+ File real = new File("/proc/self/fd/" + pfd.getFd());
+ values = new ContentValues();
+ values.put("_data", real.getCanonicalPath());
+ mResolver.update(uri, values, null, null);
+ pfd.close();
+
+ // we shouldn't be able to access this
+ try {
+ pfd = mResolver.openFileDescriptor(uri, "r");
+ pfd.close();
+ fail("shouldn't be here");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+ } catch (FileNotFoundException e) {
+ fail("couldn't open file");
+ }
+ }
+
+ // clean up
+ assertEquals(1, mResolver.delete(uri, null, null));
+ if (sdfile != null) {
+ sdfile.delete();
+ }
+ }
+
private void writeFile(int resid, String path) throws IOException {
File out = new File(path);
File dir = out.getParentFile();
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 6c2c87a..771a184 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -19,13 +19,15 @@
package="com.android.cts.security">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
+
<application>
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="android.test.InstrumentationCtsTestRunner"
android:targetPackage="com.android.cts.stub"
- android:label="CTS tests of com.android.cts.security"/>
+ android:label="CTS tests of com.android.cts.stub"/>
</manifest>
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 5821ec0..06172c5 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -24,7 +24,8 @@
LOCAL_SRC_FILES := \
CtsSecurityJniOnLoad.cpp \
android_security_cts_CharDeviceTest.cpp \
- android_security_cts_NativeCodeTest.cpp
+ android_security_cts_LinuxRngTest.cpp \
+ android_security_cts_NativeCodeTest.cpp \
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 7244fc2..7577eef 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -18,6 +18,7 @@
#include <stdio.h>
extern int register_android_security_cts_CharDeviceTest(JNIEnv*);
+extern int register_android_security_cts_LinuxRngTest(JNIEnv*);
extern int register_android_security_cts_NativeCodeTest(JNIEnv*);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
@@ -31,6 +32,10 @@
return JNI_ERR;
}
+ if (register_android_security_cts_LinuxRngTest(env)) {
+ return JNI_ERR;
+ }
+
if (register_android_security_cts_NativeCodeTest(env)) {
return JNI_ERR;
}
diff --git a/tests/tests/security/jni/android_security_cts_LinuxRngTest.cpp b/tests/tests/security/jni/android_security_cts_LinuxRngTest.cpp
new file mode 100644
index 0000000..671226b
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_LinuxRngTest.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <jni.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+/*
+ * Native methods used by
+ * cts/tests/tests/permission/src/android/security/cts/LinuxRngTest.java
+ */
+
+static void throwIOException(JNIEnv* env, const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+
+ char *message;
+ vasprintf(&message, format, ap);
+
+ va_end(ap);
+
+ jclass cls = env->FindClass("java/io/IOException");
+ env->ThrowNew(cls, message);
+
+ free(message);
+}
+
+jint android_security_cts_LinuxRngTest_getCharDeviceMajor(JNIEnv* env,
+ jobject thiz, jstring name)
+{
+ const char* nameStr = env->GetStringUTFChars(name, NULL);
+
+ jint result = -1;
+ struct stat st;
+ if (stat(nameStr, &st) == -1) {
+ throwIOException(env, "Failed to stat %s: %s", nameStr, strerror(errno));
+ goto ret;
+ }
+
+ if (!S_ISCHR(st.st_mode)) {
+ throwIOException(env, "%s is not a character device: mode is 0%o", nameStr, st.st_mode);
+ goto ret;
+ }
+
+ result = major(st.st_rdev);
+
+ret:
+ if (nameStr != NULL) {
+ env->ReleaseStringUTFChars(name, nameStr);
+ }
+ return result;
+}
+
+jint android_security_cts_LinuxRngTest_getCharDeviceMinor(JNIEnv* env,
+ jobject thiz, jstring name)
+{
+ const char* nameStr = env->GetStringUTFChars(name, NULL);
+
+ jint result = -1;
+ struct stat st;
+ if (stat(nameStr, &st) == -1) {
+ throwIOException(env, "Failed to stat %s: %s", nameStr, strerror(errno));
+ goto ret;
+ }
+
+ if (!S_ISCHR(st.st_mode)) {
+ throwIOException(env, "%s is not a character device: mode is 0%o", nameStr, st.st_mode);
+ goto ret;
+ }
+
+ result = minor(st.st_rdev);
+
+ret:
+ if (nameStr != NULL) {
+ env->ReleaseStringUTFChars(name, nameStr);
+ }
+ return result;
+}
+
+static JNINativeMethod gMethods[] = {
+ { "getCharDeviceMajor", "(Ljava/lang/String;)I",
+ (void *) android_security_cts_LinuxRngTest_getCharDeviceMajor },
+ { "getCharDeviceMinor", "(Ljava/lang/String;)I",
+ (void *) android_security_cts_LinuxRngTest_getCharDeviceMinor },
+};
+
+int register_android_security_cts_LinuxRngTest(JNIEnv* env)
+{
+ jclass clazz = env->FindClass("android/security/cts/LinuxRngTest");
+ return env->RegisterNatives(clazz, gMethods,
+ sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/security/src/android/security/cts/BannedFilesTest.java b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
index b4deed5..6913fb2 100644
--- a/tests/tests/security/src/android/security/cts/BannedFilesTest.java
+++ b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
@@ -20,12 +20,34 @@
import junit.framework.TestCase;
+import java.io.File;
+
public class BannedFilesTest extends TestCase {
public void testNoSyncAgent() {
assertNotSetugid("/system/bin/sync_agent");
}
+ public void testNoSu() {
+ assertFalse("/sbin/su", new File("/sbin/su").exists());
+ assertFalse("/system/bin/su", new File("/system/bin/su").exists());
+ assertFalse("/system/sbin/su", new File("/system/sbin/su").exists());
+ assertFalse("/system/xbin/su", new File("/system/xbin/su").exists());
+ assertFalse("/vendor/bin/su", new File("/vendor/bin/su").exists());
+ }
+
+ public void testNoSuInPath() {
+ String path = System.getenv("PATH");
+ if (path == null) {
+ return;
+ }
+ String[] elems = path.split(":");
+ for (String i : elems) {
+ File f = new File(i, "su");
+ assertFalse(f.getAbsolutePath() + " exists", f.exists());
+ }
+ }
+
/**
* setuid or setgid "ip" command can be used to modify the
* routing tables of a device, potentially allowing a malicious
diff --git a/tests/tests/security/src/android/security/cts/ClonedSecureRandomTest.java b/tests/tests/security/src/android/security/cts/ClonedSecureRandomTest.java
new file mode 100644
index 0000000..e51b11c
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/ClonedSecureRandomTest.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2013 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.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.security.cts.activity.ISecureRandomService;
+import android.security.cts.activity.SecureRandomService;
+import android.test.AndroidTestCase;
+
+import java.io.BufferedReader;
+import java.io.EOFException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class ClonedSecureRandomTest extends AndroidTestCase {
+ private static final int ANSWER_TIMEOUT_SECONDS = 60;
+
+ private static final String SEPARATE_PROCESS_NAME = ":secureRandom";
+
+ private static final int MAX_PID = 32768;
+
+ /**
+ * Attempt to burn through PIDs faster after this many iterations to reach a
+ * wrap-around point faster.
+ */
+ private static final int PRIMING_ITERATIONS = 128;
+
+ private static final int RANDOM_BYTES_PER_PID = 8;
+
+ private static final int MAX_PIDS_WASTED = 1024;
+
+ private static final int PID_WASTING_SKIP_LOWER = 64;
+
+ private static final int PID_WASTING_SKIP_UPPER = 2048;
+
+ private volatile CountDownLatch mLatch;
+
+ private Intent mSeparateIntent;
+
+ private ISecureRandomService mSecureRandomService;
+
+ private ServiceConnection mServiceConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mSecureRandomService = ISecureRandomService.Stub.asInterface(service);
+ mLatch.countDown();
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ }
+ };
+
+ private boolean mHasDisconnected;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mSeparateIntent = new Intent(getContext(), SecureRandomService.class);
+ }
+
+ /**
+ * This test spawns a Service in a new process to check the initial state of
+ * SecureRandom. It then attempts to make the PID number wrap around so it
+ * sees a new process with the same PID twice. The test completes when it
+ * sees two newly started processes with the same PID and compares their
+ * output.
+ */
+ 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"));
+
+ final String packageName = getContext().getPackageName();
+ String separateProcessName = packageName + SEPARATE_PROCESS_NAME;
+
+ /*
+ * Using a byte[][] and BitSet gives us a fixed upper bound for the
+ * memory cost of this test. One could possibly use a SparseArray if the
+ * upper bound becomes too large (for instance, if PID_MAX is large),
+ * only keep track of a smaller number of outputs, and just cause a
+ * wrap-around of PIDs to keep the test working.
+ */
+ byte[][] outputs = new byte[MAX_PID][RANDOM_BYTES_PER_PID];
+ BitSet seenPids = new BitSet(MAX_PID);
+
+ ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+
+ int myPid = android.os.Process.myPid();
+
+ /*
+ * We're guaranteed to see at least one duplicate if we iterate MAX_PID
+ * number of times because of the pigeonhole principle. In an attempt to
+ * hit a collision faster, first get a closely-spaced sampling of PIDs
+ * then spin up a bunch of threads locally to get us closer to wrapping
+ * around to the first PID.
+ */
+ int firstPid = -1;
+ int previousPid = -1;
+ for (int i = 0; i < MAX_PID; i++) {
+ byte[] output = new byte[RANDOM_BYTES_PER_PID];
+ int pid;
+
+ mLatch = new CountDownLatch(1);
+ getContext().startService(mSeparateIntent);
+ getContext().bindService(mSeparateIntent, mServiceConnection, 0);
+ if (!mLatch.await(ANSWER_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
+ fail("Timeout waiting for answer from SecureRandomService; cannot complete test");
+ }
+
+ pid = mSecureRandomService.getRandomBytesAndPid(output);
+
+ getContext().unbindService(mServiceConnection);
+ getContext().stopService(mSeparateIntent);
+ am.killBackgroundProcesses(packageName);
+
+ /*
+ * Make sure the AndroidManifest.xml wasn't altered in a way that
+ * breaks the test.
+ */
+ assertFalse("SecureRandomService must run in a different process. Check "
+ + "AndroidManifest.xml to ensure it has a unique android:process=\"...\"",
+ myPid == pid);
+
+ // We didn't get a new process for some reason. Try again.
+ if (previousPid == pid) {
+ i--;
+ continue;
+ } else if (previousPid == -1 && firstPid == -1) {
+ /*
+ * The first time around, we'll discard the output. This is
+ * needed because we don't know if the SecureRandomService instance
+ * has been running before or not. To be consistent, we only
+ * want the first outputs from SecureRandom for this test.
+ */
+ i--;
+ previousPid = pid;
+ continue;
+ } else {
+ previousPid = pid;
+ }
+
+ if (seenPids.get(pid)) {
+ assertFalse("SecureRandom should not output the same value twice (pid=" + pid
+ + ", output=" + Arrays.toString(output) + ", outputs[pid]="
+ + Arrays.toString(outputs[pid]) + ")",
+ Arrays.equals(output, outputs[pid]));
+ return;
+ }
+
+ seenPids.set(pid);
+ System.arraycopy(output, 0, outputs[pid], 0, output.length);
+
+ if (firstPid == -1) {
+ firstPid = pid;
+ }
+
+ if (i > PRIMING_ITERATIONS) {
+ wastePids(firstPid, previousPid);
+ }
+ }
+
+ /*
+ * This should never be reached unless the test was altered to break it.
+ * Since we're looping until we see PID_MAX unique answers, we must have
+ * seen a duplicate by the pigeonhole principle.
+ */
+ fail("Must see a duplicate PID");
+ }
+
+ /**
+ * This is an attempt to get the PIDs to roll over faster. Threads use up
+ * PIDs on Android and spawning a new thread is much faster than having
+ * another service spawned as we are doing in this test.
+ */
+ private static void wastePids(int firstPid, int previousPid) {
+ int distance = (firstPid - previousPid + MAX_PID) % MAX_PID;
+
+ // Don't waste PIDs if we're close to wrap-around to improve odds of
+ // collision.
+ if ((distance < PID_WASTING_SKIP_LOWER) || (MAX_PID - distance < PID_WASTING_SKIP_UPPER)) {
+ return;
+ }
+
+ for (int i = 0; i < distance; i++) {
+ Thread t = new Thread();
+ t.start();
+ }
+ }
+
+ private static String getFirstLineFromFile(String filename) throws IOException {
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new FileReader(filename));
+ final String line = in.readLine();
+ if (line == null) {
+ throw new EOFException("EOF encountered before reading first line of " + filename);
+ }
+ return line.trim();
+ } finally {
+ if (in != null) {
+ in.close();
+ }
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/KernelSettingsTest.java b/tests/tests/security/src/android/security/cts/KernelSettingsTest.java
index cc4b6a6..e660009 100644
--- a/tests/tests/security/src/android/security/cts/KernelSettingsTest.java
+++ b/tests/tests/security/src/android/security/cts/KernelSettingsTest.java
@@ -30,6 +30,17 @@
public class KernelSettingsTest extends TestCase {
/**
+ * Ensure that SELinux is not in enforcing mode.
+ */
+ public void testSELinuxEnforcing() throws IOException {
+ try {
+ assertEquals("0", getFile("/sys/fs/selinux/enforce"));
+ } catch (FileNotFoundException e) {
+ // SELinux is not compiled into the kernel. Ignore exception.
+ }
+ }
+
+ /**
* Protect against kernel based NULL pointer attacks by enforcing a
* minimum (and maximum!) value of mmap_min_addr.
*
diff --git a/tests/tests/security/src/android/security/cts/LinuxRngTest.java b/tests/tests/security/src/android/security/cts/LinuxRngTest.java
new file mode 100644
index 0000000..6bc5fd3
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/LinuxRngTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 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;
+
+import java.io.IOException;
+
+public class LinuxRngTest extends TestCase {
+ static {
+ System.loadLibrary("ctssecurity_jni");
+ }
+
+ public void testDevRandomMajorMinor() throws Exception {
+ // Based on Linux kernel's drivers/char/random.c
+ assertEquals("/dev/random major", 1, getCharDeviceMajor("/dev/random"));
+ assertEquals("/dev/random minor", 8, getCharDeviceMinor("/dev/random"));
+ }
+
+ public void testDevUrandomMajorMinor() throws Exception {
+ // Based on Linux kernel's drivers/char/random.c
+ assertEquals("/dev/urandom major", 1, getCharDeviceMajor("/dev/urandom"));
+ assertEquals("/dev/urandom minor", 9, getCharDeviceMinor("/dev/urandom"));
+ }
+
+ public static native int getCharDeviceMajor(String file) throws IOException;
+ public static native int getCharDeviceMinor(String file) throws IOException;
+}
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
old mode 100755
new mode 100644
index 3055e44..5e7902e
--- a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
@@ -125,6 +125,7 @@
"45008", // KT
"45005", // SKT Mobility
"45002", // SKT Mobility
+ "45006", // LGT
// Verizon
"310004",
"310012",
@@ -159,6 +160,7 @@
"30272", // Rogers
"302370", // Fido
"30237", // Fido
+ "45006", // LGT
"45008" // KT
);