StagefrightTest: add cts test for bug 37079296 am: ea0d82d8cb am: c751b3c2d9 am: f29c6c5d49 am: 70b016f674 am: 8816ad2c62 am: 2679e04844 am: 7c8a4abf6a am: 562ab87436 am: 4a51f97fc3 am: 6275c643a5 am: 8782bfb30c am: 716eac7815 am: 0f7ee0050f am: 805869e2f7 am: 0ab0908830 am: c7d5d8f358 am: 33d56cb11d
am: 95b25e1105
Change-Id: Ic357e0d47dea16723ca78d941bc7fdc295858ceb
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index e67b07a..be7fe57 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1685,7 +1685,7 @@
2. If \'Cts Verifier\' is not allowed to install apps, a warning dialog will appear
blocking the install. In this case go to step 3, else skip to step 4.\n
3. Allow \'Cts Verifier\' to install apps. Return to package installer.\n
- 4. Accept the package and verify that it installs.
+ 4. Accept the installation and verify that it succeeds (no error message is displayed).
</string>
<string name="provisioning_byod_nonmarket_deny">Disable non-market apps</string>
@@ -2850,7 +2850,7 @@
<string name="disallow_outgoing_beam">Disallow outgoing beam</string>
<string name="disallow_outgoing_beam_action">Switching on android beam</string>
<string name="disallow_remove_user">Disallow remove user</string>
- <string name="disallow_remove_user_action">Removing other users</string>
+ <string name="disallow_remove_user_action">Removing other users (please create a user and attempt to remove it to verify)</string>
<string name="disallow_remove_managed_profile">Disallow remove managed profile</string>
<string name="disallow_remove_managed_profile_action">Removing the work profile. It shouldn\'t be possible neither from the Accounts screen nor the Device Administrators screen (after selecting the Device Administrator that corresponds to the badged version of \"CTS Verifier\")</string>
<string name="disallow_share_location">Disallow share location</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
index 24d88b7..f3bf7e5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
@@ -88,9 +88,7 @@
logFail("no settings activity");
status = FAIL;
} else {
- String cpPackages = Secure.getString(getContentResolver(),
- Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
- if (cpPackages != null && cpPackages.contains(CP_PACKAGE)) {
+ if (mNm.isNotificationPolicyAccessGranted()) {
status = PASS;
} else {
status = WAIT_FOR_USER;
@@ -505,9 +503,7 @@
@Override
void test() {
- String cpPackages = Secure.getString(getContentResolver(),
- Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
- if (cpPackages == null || !cpPackages.contains(CP_PACKAGE)) {
+ if (!mNm.isNotificationPolicyAccessGranted()) {
status = PASS;
} else {
status = WAIT_FOR_USER;
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/Auth/Android.mk b/hostsidetests/devicepolicy/app/AccountCheck/Auth/Android.mk
index 87700c5..be51112 100644
--- a/hostsidetests/devicepolicy/app/AccountCheck/Auth/Android.mk
+++ b/hostsidetests/devicepolicy/app/AccountCheck/Auth/Android.mk
@@ -31,7 +31,8 @@
android-support-v4 \
ctstestrunner \
ub-uiautomator \
- android-support-test
+ android-support-test \
+ legacy-android-test
LOCAL_JAVA_LIBRARIES := legacy-android-test
diff --git a/hostsidetests/devicepolicy/app/DeviceAdmin/api23/Android.mk b/hostsidetests/devicepolicy/app/DeviceAdmin/api23/Android.mk
index f60ea94..cee19e8 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdmin/api23/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAdmin/api23/Android.mk
@@ -28,7 +28,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
ctstestrunner \
- compatibility-device-util
+ compatibility-device-util \
+ legacy-android-test
LOCAL_JAVA_LIBRARIES := legacy-android-test
diff --git a/hostsidetests/devicepolicy/app/DeviceAdmin/api24/Android.mk b/hostsidetests/devicepolicy/app/DeviceAdmin/api24/Android.mk
index 71496fb..7b21c3c 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdmin/api24/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAdmin/api24/Android.mk
@@ -28,7 +28,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
ctstestrunner \
- compatibility-device-util
+ compatibility-device-util \
+ legacy-android-test
LOCAL_JAVA_LIBRARIES := legacy-android-test
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java
index 8babe14..5728cf6 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java
@@ -17,6 +17,7 @@
package com.android.cts.deviceandprofileowner;
import static android.provider.Settings.Secure.AUTOFILL_SERVICE;
+import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import android.content.Intent;
import static android.os.UserManager.DISALLOW_AUTOFILL;
@@ -28,9 +29,6 @@
private static final String AUTOFILL_PACKAGE_NAME = "com.android.cts.devicepolicy.autofillapp";
private static final String AUTOFILL_ACTIVITY_NAME = AUTOFILL_PACKAGE_NAME + ".SimpleActivity";
- // TODO: should static import Settings.Secure instead, but that's not a @TestApi
- private static String USER_SETUP_COMPLETE = "user_setup_complete";
-
// Currently, autofill_service is a cloned service, so it's only set in the default user.
// That might change, so we're using a guard to decide how to set it
private final boolean USES_CLONED_SETTINGS = true;
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
index 4604b2c..bad1d41 100644
--- a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
+++ b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
@@ -29,7 +29,8 @@
LOCAL_STATIC_JAVA_LIBRARIES = \
android-support-v4 \
ctstestrunner \
- android-support-test
+ android-support-test \
+ legacy-android-test
LOCAL_SDK_VERSION := current
diff --git a/hostsidetests/jvmti/run-tests/test-912/AndroidTest.xml b/hostsidetests/jvmti/run-tests/test-912/AndroidTest.xml
index 697beb2..7137f5f 100644
--- a/hostsidetests/jvmti/run-tests/test-912/AndroidTest.xml
+++ b/hostsidetests/jvmti/run-tests/test-912/AndroidTest.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<configuration description="Config for CTS JVMTI test cases">
+ <option name="config-descriptor:metadata" key="component" value="art" />
<target_preparer class="android.jvmti.cts.JvmtiPreparer">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsJvmtiRunTest912DeviceApp.apk" />
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index cf383a1..eb71ccc 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -18,6 +18,7 @@
import static android.autofillservice.cts.Helper.runShellCommand;
import static android.provider.Settings.Secure.AUTOFILL_SERVICE;
+import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -51,9 +52,6 @@
private static final String TAG = "AutoFillCtsHelper";
- // TODO: should static import Settings.Secure instead, but that's not a @TestApi
- private static String USER_SETUP_COMPLETE = "user_setup_complete";
-
static final boolean VERBOSE = false;
static final String ID_USERNAME_LABEL = "username_label";
diff --git a/tests/tests/accounts/Android.mk b/tests/tests/accounts/Android.mk
index f07fe9b..501feae 100644
--- a/tests/tests/accounts/Android.mk
+++ b/tests/tests/accounts/Android.mk
@@ -22,7 +22,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_STATIC_JAVA_LIBRARIES := \
- CtsAccountTestsCommon ctstestrunner
+ CtsAccountTestsCommon ctstestrunner legacy-android-test
LOCAL_JAVA_LIBRARIES := legacy-android-test
diff --git a/tests/tests/calendarcommon/Android.mk b/tests/tests/calendarcommon/Android.mk
index 9d7091a..bca60b7 100644
--- a/tests/tests/calendarcommon/Android.mk
+++ b/tests/tests/calendarcommon/Android.mk
@@ -25,7 +25,7 @@
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner legacy-android-test
LOCAL_JAVA_LIBRARIES := legacy-android-test
diff --git a/tests/tests/graphics/jni/Android.mk b/tests/tests/graphics/jni/Android.mk
index 629ae64..ff7d081 100644
--- a/tests/tests/graphics/jni/Android.mk
+++ b/tests/tests/graphics/jni/Android.mk
@@ -24,12 +24,13 @@
CtsGraphicsJniOnLoad.cpp \
android_graphics_cts_ANativeWindowTest.cpp \
android_graphics_cts_BitmapTest.cpp \
+ android_graphics_cts_SyncTest.cpp \
android_graphics_cts_VulkanFeaturesTest.cpp
-LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CFLAGS += -std=c++14 -Wall -Werror
LOCAL_STATIC_LIBRARIES := libvkjson_ndk
-LOCAL_SHARED_LIBRARIES := libandroid libvulkan libnativewindow liblog libdl libjnigraphics
+LOCAL_SHARED_LIBRARIES := libandroid libvulkan libnativewindow libsync liblog libdl libjnigraphics
LOCAL_NDK_STL_VARIANT := c++_static
LOCAL_SDK_VERSION := current
diff --git a/tests/tests/graphics/jni/android_graphics_cts_SyncTest.cpp b/tests/tests/graphics/jni/android_graphics_cts_SyncTest.cpp
new file mode 100644
index 0000000..aeea02c
--- /dev/null
+++ b/tests/tests/graphics/jni/android_graphics_cts_SyncTest.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#define LOG_TAG "SyncTest"
+
+#include <poll.h>
+#include <unistd.h>
+
+#include <array>
+#include <memory>
+
+#include <jni.h>
+
+#include <android/sync.h>
+
+namespace {
+
+enum {
+ STATUS_ERROR = -1,
+ STATUS_UNSIGNALED = 0,
+ STATUS_SIGNALED = 1,
+};
+
+jboolean syncPoll(JNIEnv* env, jclass /*clazz*/, jintArray fds_array, jintArray status_array) {
+ jsize n = env->GetArrayLength(fds_array);
+ if (env->GetArrayLength(status_array) != n)
+ return JNI_FALSE;
+ std::unique_ptr<pollfd[]> pollfds = std::make_unique<pollfd[]>(n);
+
+ jint* fds = static_cast<jint*>(env->GetPrimitiveArrayCritical(fds_array, nullptr));
+ for (jsize i = 0; i < n; i++) {
+ pollfds[i].fd = fds[i];
+ pollfds[i].events = POLLIN;
+ }
+ env->ReleasePrimitiveArrayCritical(fds_array, fds, 0);
+
+ int ret;
+ do {
+ ret = poll(pollfds.get(), n, -1 /* infinite timeout */);
+ } while (ret == -1 && errno == EINTR);
+ if (ret == -1)
+ return JNI_FALSE;
+
+ jint* status = static_cast<jint*>(env->GetPrimitiveArrayCritical(status_array, nullptr));
+ for (jsize i = 0; i < n; i++) {
+ if (pollfds[i].fd < 0)
+ continue;
+ if ((pollfds[i].revents & (POLLERR | POLLNVAL)) != 0)
+ status[i] = STATUS_ERROR;
+ else if ((pollfds[i].revents & POLLIN) != 0)
+ status[i] = STATUS_SIGNALED;
+ else
+ status[i] = STATUS_UNSIGNALED;
+ }
+ env->ReleasePrimitiveArrayCritical(status_array, status, 0);
+
+ return JNI_TRUE;
+}
+
+jint syncMerge(JNIEnv* env, jclass /*clazz*/, jstring nameStr, jint fd1, jint fd2) {
+ const char* name = env->GetStringUTFChars(nameStr, nullptr);
+ int32_t result_fd = sync_merge(name, fd1, fd2);
+ env->ReleaseStringUTFChars(nameStr, name);
+ return result_fd;
+}
+
+jobject syncFileInfo(JNIEnv* /*env*/, jclass /*clazz*/, jint fd) {
+ auto info = sync_file_info(fd);
+ if (!info) return nullptr;
+ // TODO: convert to SyncFileInfo
+ sync_file_info_free(info);
+ return nullptr;
+}
+
+void syncClose(int fd) {
+ close(fd);
+}
+
+const std::array<JNINativeMethod, 4> JNI_METHODS = {{
+ { "nSyncPoll", "([I[I)Z", (void*)syncPoll },
+ { "nSyncMerge", "(Ljava/lang/String;II)I", (void*)syncMerge },
+ { "nSyncFileInfo", "(I)Landroid/graphics/cts/SyncTest/SyncFileInfo;", (void*)syncFileInfo },
+ { "nSyncClose", "(I)V", (void*)syncClose },
+}};
+
+}
+
+int register_android_graphics_cts_SyncTest(JNIEnv* env) {
+ jclass clazz = env->FindClass("android/graphics/cts/SyncTest");
+ return env->RegisterNatives(clazz, JNI_METHODS.data(), JNI_METHODS.size());
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
index 9dafaca..4067585 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
@@ -615,19 +615,13 @@
verifyScaled(BitmapFactory.decodeStream(obtainInputStream(), null, scaledOpt));
}
- // Test that writing an index8 bitmap to a Parcel succeeds.
@Test
public void testParcel() {
- // Turn off scaling, which would convert to an 8888 bitmap, which does not expose
- // the bug.
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inScaled = false;
Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.gif_test, opts);
assertNotNull(b);
- // index8 has no Java equivalent, so the Config will be null.
- assertNull(b.getConfig());
-
Parcel p = Parcel.obtain();
b.writeToParcel(p, 0);
@@ -635,9 +629,6 @@
Bitmap b2 = Bitmap.CREATOR.createFromParcel(p);
compareBitmaps(b, b2, 0, true, true);
- // When this failed previously, the bitmap was missing a colortable, resulting in a crash
- // attempting to compress by dereferencing a null pointer. Compress to verify that we do
- // not crash, but succeed instead.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
assertTrue(b2.compress(Bitmap.CompressFormat.JPEG, 50, baos));
}
@@ -665,17 +656,16 @@
// most natural match for the encoded data.
// Options.inPreferredConfig = null
// We will decode to whichever Config is the most natural match with the
- // encoded data. This could be 8-bit indices into a color table (call this
- // INDEX_8), ALPHA_8 (gray), or ARGB_8888.
+ // encoded data. This could be ALPHA_8 (gray) or ARGB_8888.
//
// This test ensures that images are decoded to the intended Config and that the
// decodes match regardless of the Config.
- decodeConfigs(R.drawable.alpha, 31, 31, true, false, false);
- decodeConfigs(R.drawable.baseline_jpeg, 1280, 960, false, false, false);
- decodeConfigs(R.drawable.bmp_test, 320, 240, false, false, false);
- decodeConfigs(R.drawable.scaled2, 6, 8, false, false, true);
- decodeConfigs(R.drawable.grayscale_jpg, 128, 128, false, true, false);
- decodeConfigs(R.drawable.grayscale_png, 128, 128, false, true, false);
+ decodeConfigs(R.drawable.alpha, 31, 31, true, false);
+ decodeConfigs(R.drawable.baseline_jpeg, 1280, 960, false, false);
+ decodeConfigs(R.drawable.bmp_test, 320, 240, false, false);
+ decodeConfigs(R.drawable.scaled2, 6, 8, false, false);
+ decodeConfigs(R.drawable.grayscale_jpg, 128, 128, false, true);
+ decodeConfigs(R.drawable.grayscale_png, 128, 128, false, true);
}
@Test(expected=IllegalArgumentException.class)
@@ -812,8 +802,7 @@
}
}
- private void decodeConfigs(int id, int width, int height, boolean hasAlpha, boolean isGray,
- boolean hasColorTable) {
+ private void decodeConfigs(int id, int width, int height, boolean hasAlpha, boolean isGray) {
Options opts = new BitmapFactory.Options();
opts.inScaled = false;
assertEquals(Config.ARGB_8888, opts.inPreferredConfig);
@@ -859,21 +848,15 @@
compareBitmaps(reference, grayToARGB(alpha8), 0, true, true);
}
- // Setting inPreferredConfig to null selects the most natural color type for
- // the encoded data. If the image has a color table, this should be INDEX_8.
- // If we decode to INDEX_8, the output bitmap will report that the Config is
- // null.
+ // Setting inPreferredConfig to nullptr will cause the default Config to be
+ // selected, which in this case is ARGB_8888.
opts.inPreferredConfig = null;
- Bitmap index8 = BitmapFactory.decodeResource(mRes, id, opts);
- assertNotNull(index8);
- assertEquals(width, index8.getWidth());
- assertEquals(height, index8.getHeight());
- if (hasColorTable) {
- assertEquals(null, index8.getConfig());
- // Convert the INDEX_8 bitmap to ARGB_8888 and test that it is identical to
- // the reference.
- compareBitmaps(reference, index8.copy(Config.ARGB_8888, false), 0, true, true);
- }
+ Bitmap defaultBitmap = BitmapFactory.decodeResource(mRes, id, opts);
+ assertNotNull(defaultBitmap);
+ assertEquals(width, defaultBitmap.getWidth());
+ assertEquals(height, defaultBitmap.getHeight());
+ assertEquals(Config.ARGB_8888, defaultBitmap.getConfig());
+ compareBitmaps(reference, defaultBitmap, 0, true, true);
}
private static Bitmap grayToARGB(Bitmap gray) {
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapFactory_OptionsTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapFactory_OptionsTest.java
index 42b493d..ad759bb 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapFactory_OptionsTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapFactory_OptionsTest.java
@@ -92,7 +92,6 @@
b = BitmapFactory.decodeResource(resources, R.drawable.bitmap_indexed, options);
assertNull(b);
assertEquals("image/gif", options.outMimeType);
- assertEquals(null, options.outConfig);
// Scaled, indexed bitmap
options.inScaled = true;
diff --git a/tests/tests/graphics/src/android/graphics/cts/SyncTest.java b/tests/tests/graphics/src/android/graphics/cts/SyncTest.java
new file mode 100644
index 0000000..a82adfc
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/SyncTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.cts;
+
+import static org.junit.Assert.assertEquals;
+import static android.opengl.EGL14.*;
+
+import android.opengl.EGL14;
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.opengl.GLES20;
+import android.support.test.filters.SmallTest;
+
+import java.util.concurrent.CyclicBarrier;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+
+// This class contains tests for the Linux kernel sync file system, and the NDK interfaces for it
+// (android/sync.h). Unfortunately, the interfaces exposed by the kernel make it difficult to test
+// for a couple reasons:
+//
+// (a) There isn't a standard kernel interface for creating a fence/sync_file. Drivers can create
+// them via driver-specific interfaces. Currently this means we have to use APIs like OpenGL ES
+// or interact with the system compositor in order to generate fences. That makes tests larger
+// and more complicated than they otherwise need to be.
+//
+// This is further complicated by the fact that most of the time GPU work executes in the order
+// it was submitted to the kernel; there isn't much out-of-order execution in practice. So
+// detecting some kinds of bugs is difficult using only the GPU as an event source.
+//
+// (b) A core principal of sync files is that they cannot be created until the work that will
+// signal them has been submitted to the kernel, and will complete without further action from
+// userland. This means that it is impossible to reliably do something before a sync file has
+// signaled.
+
+@SmallTest
+@RunWith(BlockJUnit4ClassRunner.class)
+public class SyncTest {
+
+ static {
+ System.loadLibrary("ctsgraphics_jni");
+ }
+
+ private static final String TAG = SyncTest.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ private EGLDisplay mEglDisplay = EGL_NO_DISPLAY;
+ private EGLConfig mEglConfig = null;
+
+ @Before
+ public void setup() throws Throwable {
+ mEglDisplay = EGL14.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (mEglDisplay == EGL_NO_DISPLAY) {
+ throw new RuntimeException("no EGL display");
+ }
+ int[] major = new int[1];
+ int[] minor = new int[1];
+ if (!EGL14.eglInitialize(mEglDisplay, major, 0, minor, 0)) {
+ throw new RuntimeException("error in eglInitialize");
+ }
+
+ int[] numConfigs = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ if (!EGL14.eglChooseConfig(mEglDisplay,
+ new int[] {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_BUFFER_SIZE, 32,
+ EGL_NONE},
+ 0, configs, 0, 1, numConfigs, 0)) {
+ throw new RuntimeException("eglChooseConfig failed");
+ }
+ mEglConfig = configs[0];
+ }
+
+ @After
+ public void teardown() throws Throwable {
+ EGL14.eglTerminate(mEglDisplay);
+ }
+
+ @Test
+ public void testMergedSyncSignalOrder() {
+ // TODO
+ }
+
+ private static final int STATUS_UNSIGNALED = 0;
+ private static final int STATUS_SIGNALED = 1;
+ private static final int STATUS_ERROR = -1;
+ private static class SyncFileInfo {
+ String name; // char name[32]
+ int status; // __s32 status
+ long flags; // __u32 flags
+ SyncFenceInfo[] fences; // __u32 num_fences; __u64 sync_fence_info
+ }
+ private static class SyncFenceInfo {
+ String name; // char obj_name[32]
+ String driver_name; // char driver_name[32]
+ int status; // __s32 status
+ long flags; // __u32 flags
+ long timestamp_ns; // __u64 timestamp_ns
+ }
+
+ private static native boolean nSyncPoll(int[] fds, int[] status);
+ private static native int nSyncMerge(String name, int fd1, int fd2);
+ private static native SyncFileInfo nSyncFileInfo(int fd);
+ private static native void nSyncClose(int fd);
+}
diff --git a/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java b/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
index 9b5f001..f0b303b 100644
--- a/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
+++ b/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
@@ -21,6 +21,7 @@
import android.graphics.BitmapFactory;
import android.media.ExifInterface;
import android.os.Environment;
+import android.os.FileUtils;
import android.test.AndroidTestCase;
import android.util.Log;
import android.system.ErrnoException;
@@ -70,7 +71,7 @@
ExifInterface.TAG_MAKE,
ExifInterface.TAG_MODEL,
ExifInterface.TAG_F_NUMBER,
- ExifInterface.TAG_DATETIME,
+ ExifInterface.TAG_DATETIME_ORIGINAL,
ExifInterface.TAG_EXPOSURE_TIME,
ExifInterface.TAG_FLASH,
ExifInterface.TAG_FOCAL_LENGTH,
@@ -107,7 +108,7 @@
public final String make;
public final String model;
public final float aperture;
- public final String datetime;
+ public final String dateTimeOriginal;
public final float exposureTime;
public final float flash;
public final String focalLength;
@@ -153,7 +154,7 @@
make = getString(typedArray, index++);
model = getString(typedArray, index++);
aperture = typedArray.getFloat(index++, 0f);
- datetime = getString(typedArray, index++);
+ dateTimeOriginal = getString(typedArray, index++);
exposureTime = typedArray.getFloat(index++, 0f);
flash = typedArray.getFloat(index++, 0f);
focalLength = getString(typedArray, index++);
@@ -273,7 +274,8 @@
assertStringTag(exifInterface, ExifInterface.TAG_MAKE, expectedValue.make);
assertStringTag(exifInterface, ExifInterface.TAG_MODEL, expectedValue.model);
assertFloatTag(exifInterface, ExifInterface.TAG_F_NUMBER, expectedValue.aperture);
- assertStringTag(exifInterface, ExifInterface.TAG_DATETIME, expectedValue.datetime);
+ assertStringTag(exifInterface, ExifInterface.TAG_DATETIME_ORIGINAL,
+ expectedValue.dateTimeOriginal);
assertFloatTag(exifInterface, ExifInterface.TAG_EXPOSURE_TIME, expectedValue.exposureTime);
assertFloatTag(exifInterface, ExifInterface.TAG_FLASH, expectedValue.flash);
assertStringTag(exifInterface, ExifInterface.TAG_FOCAL_LENGTH, expectedValue.focalLength);
@@ -478,4 +480,34 @@
public void testReadExifDataFromSamsungNX3000Srw() throws Throwable {
testExifInterfaceForRaw(SAMSUNG_NX3000_SRW, R.array.samsung_nx3000_srw);
}
+
+ public void testSetDateTime() throws IOException {
+ final String dateTimeValue = "2017:02:02 22:22:22";
+ final String dateTimeOriginalValue = "2017:01:01 11:11:11";
+
+ File srcFile = new File(Environment.getExternalStorageDirectory(),
+ EXTERNAL_BASE_DIRECTORY + EXIF_BYTE_ORDER_II_JPEG);
+ File imageFile = new File(Environment.getExternalStorageDirectory(),
+ EXTERNAL_BASE_DIRECTORY + EXIF_BYTE_ORDER_II_JPEG + "_copied");
+
+ FileUtils.copyFileOrThrow(srcFile, imageFile);
+ ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
+ exif.setAttribute(ExifInterface.TAG_DATETIME, dateTimeValue);
+ exif.setAttribute(ExifInterface.TAG_DATETIME_ORIGINAL, dateTimeOriginalValue);
+ exif.saveAttributes();
+
+ // Check that the DATETIME value is not overwritten by DATETIME_ORIGINAL's value.
+ exif = new ExifInterface(imageFile.getAbsolutePath());
+ assertEquals(dateTimeValue, exif.getAttribute(ExifInterface.TAG_DATETIME));
+ assertEquals(dateTimeOriginalValue, exif.getAttribute(ExifInterface.TAG_DATETIME_ORIGINAL));
+
+ // Now remove the DATETIME value.
+ exif.setAttribute(ExifInterface.TAG_DATETIME, null);
+ exif.saveAttributes();
+
+ // When the DATETIME has no value, then it should be set to DATETIME_ORIGINAL's value.
+ exif = new ExifInterface(imageFile.getAbsolutePath());
+ assertEquals(dateTimeOriginalValue, exif.getAttribute(ExifInterface.TAG_DATETIME));
+ imageFile.delete();
+ }
}
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTest.java b/tests/tests/media/src/android/media/cts/ResourceManagerTest.java
index 5f16bc5..b541a97 100644
--- a/tests/tests/media/src/android/media/cts/ResourceManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/ResourceManagerTest.java
@@ -17,8 +17,12 @@
package android.media.cts;
import android.os.Bundle;
+import android.platform.test.annotations.RequiresDevice;
+import android.support.test.filters.SmallTest;
import android.test.ActivityInstrumentationTestCase2;
+@SmallTest
+@RequiresDevice
public class ResourceManagerTest
extends ActivityInstrumentationTestCase2<ResourceManagerStubActivity> {
diff --git a/tests/tests/media/src/android/media/cts/Utils.java b/tests/tests/media/src/android/media/cts/Utils.java
index 33cc1b7..211aa4e 100644
--- a/tests/tests/media/src/android/media/cts/Utils.java
+++ b/tests/tests/media/src/android/media/cts/Utils.java
@@ -17,6 +17,7 @@
package android.media.cts;
import android.app.Instrumentation;
+import android.app.NotificationManager;
import android.app.UiAutomation;
import android.content.ContentResolver;
import android.content.Context;
@@ -88,57 +89,10 @@
protected static void toggleNotificationPolicyAccess(String packageName,
Instrumentation instrumentation, boolean on) throws IOException {
- // Read the setting listing the package allowed to manage notification policy configuration
- String alreadyEnabledServices = querryNotificationPolicyAccessPakages(instrumentation);
-
- // The property is a list of : separated package
- List<String> enabledServices = Lists.newArrayList(alreadyEnabledServices.split(":"));
-
- // Actually add or remove the package from the list
- if (on) {
- // Only add the package if it is not already in the list
- if (!enabledServices.contains(packageName)) {
- enabledServices.add(packageName);
- setNotificationPolicyAccessPackages(enabledServices, instrumentation);
- }
- } else {
- // Remove all instance of the package in the list
- if (enabledServices.removeIf(packageName::equals)) {
- // Only update the settings if there was a change
- setNotificationPolicyAccessPackages(enabledServices, instrumentation);
- }
- }
- }
-
- /** Read the setting listing the package allowed to manage notification policy configuration */
- private static String querryNotificationPolicyAccessPakages(Instrumentation instrumentation) {
- ContentResolver cr = instrumentation.getContext().getContentResolver();
- String enabledService = Settings.Secure.getString(
- cr,Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
-
- // A non existing property is equivalent to no package listed
- if (enabledService == null) {
- enabledService = "";
- }
- return enabledService;
- }
-
- private static void setNotificationPolicyAccessPackages(final List<String> enabledServicesList,
- final Instrumentation instrumentation) throws IOException {
- // Format the list back to a string
- String enabledServices = String.join(":", enabledServicesList);
-
- // If the list is empty, remove the property by setting it to null
- String enabledServicesStrOrNull = enabledServices.isEmpty() ? "null" : enabledServices;
-
- // Write back the property to the settings database
- String command = "settings --user cur put secure "
- + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + " "
- + enabledServicesStrOrNull;
+ String command = " cmd notification " + (on ? "allow_dnd " : "disallow_dnd ") + packageName;
// Get permission to enable accessibility
UiAutomation uiAutomation = instrumentation.getUiAutomation();
-
// Execute command
try (ParcelFileDescriptor fd = uiAutomation.executeShellCommand(command)) {
Assert.assertNotNull("Failed to execute shell command: " + command, fd);
@@ -153,11 +107,10 @@
uiAutomation.destroy();
}
- // Read the settings again to make sure it is updated
- String nowEnabledServices = querryNotificationPolicyAccessPakages(instrumentation);
- Assert.assertEquals("Wrote setting should be the same as the read one",
- enabledServices, nowEnabledServices);
-
+ NotificationManager nm = (NotificationManager) instrumentation.getContext()
+ .getSystemService(Context.NOTIFICATION_SERVICE);
+ Assert.assertEquals("Wrote setting should be the same as the read one", on,
+ nm.isNotificationPolicyAccessGranted());
}
/**
diff --git a/tests/tests/packageinstaller/externalsources/Android.mk b/tests/tests/packageinstaller/externalsources/Android.mk
index ca2fbda..7d2b1e9 100755
--- a/tests/tests/packageinstaller/externalsources/Android.mk
+++ b/tests/tests/packageinstaller/externalsources/Android.mk
@@ -22,8 +22,6 @@
LOCAL_PACKAGE_NAME := CtsExternalSourcesTestCases
-LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res
-
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator android-support-test android-support-v4
diff --git a/tests/tests/packageinstaller/externalsources/AndroidManifest.xml b/tests/tests/packageinstaller/externalsources/AndroidManifest.xml
index 33d1d6e..8bcdd04 100755
--- a/tests/tests/packageinstaller/externalsources/AndroidManifest.xml
+++ b/tests/tests/packageinstaller/externalsources/AndroidManifest.xml
@@ -21,13 +21,6 @@
<application android:label="Cts External Sources Test">
<uses-library android:name="android.test.runner"/>
- <provider android:authorities="android.packageinstaller.externalsources.cts.fileprovider"
- android:name="android.support.v4.content.FileProvider"
- android:grantUriPermissions="true">
- <meta-data
- android:name="android.support.FILE_PROVIDER_PATHS"
- android:resource="@xml/file_paths" />
- </provider>
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/packageinstaller/externalsources/AndroidTest.xml b/tests/tests/packageinstaller/externalsources/AndroidTest.xml
index 39d2d67..2d782d8 100644
--- a/tests/tests/packageinstaller/externalsources/AndroidTest.xml
+++ b/tests/tests/packageinstaller/externalsources/AndroidTest.xml
@@ -17,16 +17,6 @@
<configuration description="Config for CTS External Sources test cases">
<option name="config-descriptor:metadata" key="component" value="framework" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/cts/externalsources" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/cts"/>
- </target_preparer>
-
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="cleanup" value="true" />
- <option name="push" value="CtsEmptyTestApp.apk->/data/local/tmp/cts/externalsources/CtsEmptyTestApp.apk" />
- </target_preparer>
-
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsExternalSourcesTestCases.apk" />
@@ -34,7 +24,7 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.packageinstaller.externalsources.cts" />
- <option name="runtime-hint" value="1m" />
+ <option name="runtime-hint" value="10s" />
</test>
</configuration>
diff --git a/tests/tests/packageinstaller/externalsources/res/xml/file_paths.xml b/tests/tests/packageinstaller/externalsources/res/xml/file_paths.xml
deleted file mode 100644
index 173435b..0000000
--- a/tests/tests/packageinstaller/externalsources/res/xml/file_paths.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<paths xmlns:android="http://schemas.android.com/apk/res/android">
- <files-path name="apk" path="/" />
-</paths>
\ No newline at end of file
diff --git a/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesTest.java b/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesTest.java
index e10e278..921f5f1 100644
--- a/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesTest.java
+++ b/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesTest.java
@@ -15,122 +15,41 @@
*/
package android.packageinstaller.externalsources.cts;
-import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
-import android.support.v4.content.FileProvider;
-import android.util.Log;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
@RunWith(AndroidJUnit4.class)
-@MediumTest
+@SmallTest
public class ExternalSourcesTest {
- private static final String TAG = ExternalSourcesTest.class.getSimpleName();
- private static final String TEST_APK_NAME = "CtsEmptyTestApp.apk";
- private static final String TEST_APK_EXTERNAL_LOCATION = "/data/local/tmp/cts/externalsources";
- private static final String CONTENT_AUTHORITY =
- "android.packageinstaller.externalsources.cts.fileprovider";
- private static final String PACKAGE_INSTALLER_PACKAGE_NAME = "com.android.packageinstaller";
- private static final String INSTALL_CONFIRM_TEXT_ID = "install_confirm_question";
- private static final String WM_DISMISS_KEYGUARD_COMMAND = "wm dismiss-keyguard";
- private static final String ALERT_DIALOG_TITLE_ID = "android:id/alertTitle";
-
- private static final long WAIT_FOR_UI_TIMEOUT = 5000;
-
private Context mContext;
private PackageManager mPm;
- private Instrumentation mInstrumentation;
private String mPackageName;
- private File mApkFile;
private UiDevice mUiDevice;
-
- @BeforeClass
- public static void setUpOnce() throws IOException {
- File srcApkFile = new File(TEST_APK_EXTERNAL_LOCATION, TEST_APK_NAME);
- File destApkFile = new File(InstrumentationRegistry.getTargetContext().getFilesDir(),
- TEST_APK_NAME);
- copyFile(srcApkFile, destApkFile);
- }
+ private boolean mHasFeature;
@Before
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mPm = mContext.getPackageManager();
mPackageName = mContext.getPackageName();
- mApkFile = new File(mContext.getFilesDir(), TEST_APK_NAME);
- mUiDevice = UiDevice.getInstance(mInstrumentation);
- if (!mUiDevice.isScreenOn()) {
- mUiDevice.wakeUp();
- }
- mUiDevice.executeShellCommand(WM_DISMISS_KEYGUARD_COMMAND);
- }
-
- private static void copyFile(File srcFile, File destFile) throws IOException {
- if (destFile.exists()) {
- destFile.delete();
- }
- FileInputStream inputStream = new FileInputStream(srcFile);
- FileOutputStream out = new FileOutputStream(destFile);
- try {
- byte[] buffer = new byte[4096];
- int bytesRead;
- while ((bytesRead = inputStream.read(buffer)) >= 0) {
- out.write(buffer, 0, bytesRead);
- }
- Log.d(TAG, "copied file " + srcFile + " to " + destFile);
- } finally {
- out.flush();
- try {
- out.getFD().sync();
- } catch (IOException e) {
- }
- out.close();
- inputStream.close();
- }
- }
-
- private void launchPackageInstaller() {
- Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
- intent.setData(FileProvider.getUriForFile(mContext, CONTENT_AUTHORITY, mApkFile));
- intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- Log.d(TAG, "Starting intent with uri " + intent.getDataString());
- mContext.startActivity(intent);
- }
-
- private void assertInstallAllowed(String errorMessage) {
- BySelector selector = By.res(PACKAGE_INSTALLER_PACKAGE_NAME, INSTALL_CONFIRM_TEXT_ID);
- UiObject2 uiObject = mUiDevice.wait(Until.findObject(selector), WAIT_FOR_UI_TIMEOUT);
- Assert.assertNotNull(errorMessage, uiObject);
- mUiDevice.pressBack();
- }
-
- private void assertInstallBlocked(String errorMessage) {
- BySelector selector = By.res(ALERT_DIALOG_TITLE_ID);
- UiObject2 settingsButton = mUiDevice.wait(Until.findObject(selector), WAIT_FOR_UI_TIMEOUT);
- Assert.assertNotNull(errorMessage, settingsButton);
- mUiDevice.pressBack();
+ mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mHasFeature = !mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
}
private void setAppOpsMode(String mode) throws IOException {
@@ -144,35 +63,39 @@
@Test
public void blockedSourceTest() throws Exception {
setAppOpsMode("deny");
- boolean isTrusted = mPm.canRequestPackageInstalls();
+ final boolean isTrusted = mPm.canRequestPackageInstalls();
Assert.assertFalse("Package " + mPackageName
+ " allowed to install packages after setting app op to errored", isTrusted);
- launchPackageInstaller();
- assertInstallBlocked("Install blocking dialog not shown when app op set to errored");
}
@Test
public void allowedSourceTest() throws Exception {
setAppOpsMode("allow");
- boolean isTrusted = mPm.canRequestPackageInstalls();
+ final boolean isTrusted = mPm.canRequestPackageInstalls();
Assert.assertTrue("Package " + mPackageName
+ " blocked from installing packages after setting app op to allowed", isTrusted);
- launchPackageInstaller();
- assertInstallAllowed("Install confirmation not shown when app op set to allowed");
}
@Test
public void defaultSourceTest() throws Exception {
- boolean isTrusted = mPm.canRequestPackageInstalls();
+ setAppOpsMode("default");
+ final boolean isTrusted = mPm.canRequestPackageInstalls();
Assert.assertFalse("Package " + mPackageName
+ " with default app ops state allowed to install packages", isTrusted);
- launchPackageInstaller();
- assertInstallBlocked("Install blocking dialog not shown when app op set to default");
+ }
+
+ @Test
+ public void testManageUnknownSourcesExists() {
+ if (!mHasFeature) {
+ return;
+ }
+ Intent manageUnknownSources = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
+ ResolveInfo info = mPm.resolveActivity(manageUnknownSources, 0);
+ Assert.assertNotNull("No activity found for " + manageUnknownSources.getAction(), info);
}
@After
public void tearDown() throws Exception {
- mUiDevice.pressHome();
setAppOpsMode("default");
}
}
diff --git a/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java b/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
index fad1019..b11fad2 100644
--- a/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
+++ b/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
@@ -51,6 +51,8 @@
private static final String mmsBody = "MMS body CTS";
private static final String[] ID_PROJECTION = new String[] { BaseColumns._ID };
+ private static final String[] ID_TEXT_ONLY_PROJECTION = new String[] { BaseColumns._ID,
+ Telephony.Mms.TEXT_ONLY };
private static final String SMS_SELECTION = Telephony.Sms.ADDRESS + " = ? and "
+ Telephony.Sms.BODY + " = ?";
@@ -130,7 +132,7 @@
/**
* Test adds 2 SMS messages, 1 text-only MMS messages and 1 non-text-only, runs backup,
* deletes the messages from the provider, runs restore, check if the messages are in the
- * provider (w/o non-text-only one).
+ * provider (with non-text-only one).
* @throws Exception
*/
public void testSmsBackupRestore() throws Exception {
@@ -163,39 +165,42 @@
assertEquals(1,
mContentResolver.delete(Telephony.Sms.CONTENT_URI, SMS_SELECTION, smsAddressBody2));
- try (Cursor mmsCursor = mContentResolver.query(Telephony.Mms.CONTENT_URI, ID_PROJECTION,
- MMS_SELECTION, new String[] {mmsSubject}, null)) {
+ try (Cursor mmsCursor = mContentResolver.query(Telephony.Mms.CONTENT_URI,
+ ID_TEXT_ONLY_PROJECTION, MMS_SELECTION, new String[] {mmsSubject}, null)) {
assertNotNull(mmsCursor);
- assertEquals(1, mmsCursor.getCount());
- mmsCursor.moveToFirst();
- final long mmsId = mmsCursor.getLong(0);
- final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon()
- .appendPath(String.valueOf(mmsId)).appendPath("part").build();
- // Check the body.
- try (Cursor partCursor = mContentResolver.query(partUri, MMS_PART_TEXT_PROJECTION,
+ assertEquals(2, mmsCursor.getCount());
+ for (mmsCursor.moveToFirst(); !mmsCursor.isAfterLast(); mmsCursor.moveToNext()) {
+ final long mmsId = mmsCursor.getLong(0);
+ final long mmsTextOnly = mmsCursor.getLong(1);
+ assertEquals(mmsTextOnly, 1);
+ final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon()
+ .appendPath(String.valueOf(mmsId)).appendPath("part").build();
+ // Check the body.
+ try (Cursor partCursor = mContentResolver.query(partUri, MMS_PART_TEXT_PROJECTION,
MMS_PART_TEXT_SELECTION, new String[]{ ContentType.TEXT_PLAIN }, null)) {
assertNotNull(partCursor);
assertEquals(1, partCursor.getCount());
assertTrue(partCursor.moveToFirst());
- assertEquals(mmsBody, partCursor.getString(0));
- }
+ assertTrue(partCursor.getString(0).startsWith(mmsBody));
+ }
- // Check if there are 2 parts (smil and body).
- assertEquals(2, mContentResolver.delete(partUri, MMS_PART_SELECTION,
+ // Check if there are 2 parts (smil and body).
+ assertEquals(2, mContentResolver.delete(partUri, MMS_PART_SELECTION,
new String[]{String.valueOf(mmsId)}));
- // Check addresses.
- final Uri addrUri = getMmsAddrUri(mmsId);
- try (Cursor addrCursor = mContentResolver.query(addrUri, MMS_ADDR_PROJECTION,
+ // Check addresses.
+ final Uri addrUri = getMmsAddrUri(mmsId);
+ try (Cursor addrCursor = mContentResolver.query(addrUri, MMS_ADDR_PROJECTION,
MMS_ADDR_SELECTION, new String[]{String.valueOf(mmsId)}, null)) {
assertNotNull(addrCursor);
for (String addr : mmsAddresses) {
- addrCursor.moveToNext();
- assertEquals(addr, addrCursor.getString(0));
+ addrCursor.moveToNext();
+ assertEquals(addr, addrCursor.getString(0));
}
- }
- assertEquals(mmsAddresses.length, mContentResolver.delete(addrUri, MMS_ADDR_SELECTION,
+ }
+ assertEquals(mmsAddresses.length, mContentResolver.delete(addrUri, MMS_ADDR_SELECTION,
new String[]{String.valueOf(mmsId)}));
+ }
}
}
@@ -257,4 +262,4 @@
ProviderTestUtils.wipeBackup(LOCAL_BACKUP_COMPONENT, TELEPHONY_PROVIDER_PACKAGE,
mUiAutomation);
}
-}
\ No newline at end of file
+}
diff --git a/tests/tests/text/src/android/text/cts/InputFilter_AllCapsTest.java b/tests/tests/text/src/android/text/cts/InputFilter_AllCapsTest.java
index 9e5d293..4d14454 100644
--- a/tests/tests/text/src/android/text/cts/InputFilter_AllCapsTest.java
+++ b/tests/tests/text/src/android/text/cts/InputFilter_AllCapsTest.java
@@ -17,16 +17,24 @@
package android.text.cts;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.text.InputFilter;
import android.text.InputFilter.AllCaps;
+import android.text.SpannableString;
import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.SpannedString;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Locale;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class InputFilter_AllCapsTest {
@@ -41,7 +49,7 @@
String expectedString1 = "AllCAPSTest";
dest.insert(3, source);
- assertEquals(expectedString1 , dest.toString());
+ assertEquals(expectedString1, dest.toString());
String expectedString2 = "AllCAPSCAPS";
dest.replace(7, 11, source);
@@ -58,4 +66,71 @@
allCaps.filter(beforeFilterSource, 2, 7, dest, 0, beforeFilterSource.length());
assertEquals(expectedAfterFilter, actualAfterFilter);
}
+
+ @Test
+ public void testFilter_nonBMP() {
+ // The source string, lowerBee, is two code units that contains a single lowercase letter.
+ // DESERET SMALL LETTER BEE
+ final String lowerBee = new String(Character.toChars(0x1043A));
+ // DESERET CAPITAL LETTER BEE
+ final String upperBee = new String(Character.toChars(0x10412));
+
+ final AllCaps allCaps = new AllCaps();
+ final SpannedString dest = new SpannedString("");
+
+ // If given the whole string, the filter should transform it to uppercase.
+ assertEquals(upperBee, allCaps.filter(lowerBee, 0, lowerBee.length(), dest, 0, 0));
+
+ // If given just part of the character, it should be treated as an isolated surrogate
+ // and not get transformed, so null should be returned.
+ assertNull(allCaps.filter(lowerBee, 0, 1, dest, 0, 0));
+ }
+
+ @Test
+ public void testFilter_turkish() {
+ final String source = "i";
+ final AllCaps usAllCaps = new AllCaps(Locale.US);
+ final AllCaps turkishAllCaps = new AllCaps(new Locale("tr", "TR"));
+ final SpannedString dest = new SpannedString("");
+
+ assertEquals("I", usAllCaps.filter(source, 0, source.length(), dest, 0, 0));
+ assertEquals("İ", turkishAllCaps.filter(source, 0, source.length(), dest, 0, 0));
+ }
+
+ @Test
+ public void testFilter_titlecase() {
+ final String source = "Lj"; // U+01C8 LATIN CAPITAL LETTER L WITH SMALL LETTER J
+ final AllCaps allCaps = new AllCaps();
+ final SpannedString dest = new SpannedString("");
+
+ assertEquals("LJ", // LATIN CAPITAL LETTER LJ
+ allCaps.filter(source, 0, source.length(), dest, 0, 0));
+ }
+
+ @Test
+ public void testFilter_greekWithSpans() {
+ final Locale greek = new Locale("el", "GR");
+ final String lowerString = "ι\u0301ριδα"; // ίριδα with first letter decomposed
+ final String upperString = "ΙΡΙΔΑ"; // uppercased
+
+ final SpannableString source = new SpannableString(lowerString);
+ final Object span = new Object();
+ source.setSpan(span, 0, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE); // around "ί"
+
+ final AllCaps greekAllCaps = new AllCaps(greek);
+ final SpannedString dest = new SpannedString("");
+ final CharSequence result = greekAllCaps.filter(source, 0, source.length(), dest, 0, 0);
+
+ assertEquals(upperString, result.toString());
+ assertTrue(result instanceof Spanned);
+ final Spanned spannedResult = (Spanned) result;
+ final Object[] resultSpans = spannedResult.getSpans(
+ 0, spannedResult.length(), Object.class);
+ assertEquals(1, resultSpans.length);
+ assertSame(span, resultSpans[0]);
+ assertEquals(0, spannedResult.getSpanStart(span));
+ // The two characters in source have been transformed to one character in the result.
+ assertEquals(1, spannedResult.getSpanEnd(span));
+ assertEquals(Spanned.SPAN_INCLUSIVE_INCLUSIVE, spannedResult.getSpanFlags(span));
+ }
}
diff --git a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index 59c6ef4..ec88500 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -25,6 +25,7 @@
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
+import android.telephony.TelephonyManager;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.URLSpan;
@@ -353,10 +354,15 @@
+ " " + numbersUSLocal
+ " " + numbersIntl);
- // phonenumber linkify is locale-dependent
- if (Locale.US.equals(Locale.getDefault())) {
- assertTrue(Linkify.addLinks(spannable, Linkify.PHONE_NUMBERS));
- URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
+ // phonenumber linkify depends on the device's SIM card country.
+ final TelephonyManager tm =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ final String region = tm.getSimCountryIso().toUpperCase(Locale.US);
+
+ assertTrue(Linkify.addLinks(spannable, Linkify.PHONE_NUMBERS));
+ final URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
+ if ("US".equals(region)) {
+ // For the US, these specific phone numbers should be detected.
assertEquals(9, spans.length);
assertEquals("tel:8121234562", spans[0].getURL());
assertEquals("tel:8121234563", spans[1].getURL());
@@ -367,6 +373,16 @@
assertEquals("tel:+4408121234565", spans[6].getURL());
assertEquals("tel:+18005551213", spans[7].getURL());
assertEquals("tel:+18005551214", spans[8].getURL());
+ } else {
+ // For other countries, the phone numbers that would be detected are based on the
+ // country, so the exact list is unknown, but the various international phone numbers,
+ // starting with '+', must always be detected, and must appear next to each other and
+ // at the end of the list.
+ assertTrue(spans.length >= 4);
+ assertEquals("tel:+4408121234564", spans[spans.length - 4].getURL());
+ assertEquals("tel:+4408121234565", spans[spans.length - 3].getURL());
+ assertEquals("tel:+18005551213", spans[spans.length - 2].getURL());
+ assertEquals("tel:+18005551214", spans[spans.length - 1].getURL());
}
assertFalse(Linkify.addLinks((Spannable) null, 0));
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
index 0a7f86d..27c388a 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
@@ -1431,29 +1431,41 @@
final Uri CHANNEL_URI_FOR_PASSTHROUGH_INPUT =
TvContract.buildChannelUriForPassthroughInput("inputId");
final Uri PROGRAM_URI = TvContract.buildProgramUri(0);
+ final Uri RECORDED_PROGRAM_URI = TvContract.buildRecordedProgramUri(0);
// Test isChannelUri
assertTrue(TvContract.isChannelUri(CHANNEL_URI_FOR_TUNER));
assertTrue(TvContract.isChannelUri(CHANNEL_URI_FOR_PASSTHROUGH_INPUT));
assertFalse(TvContract.isChannelUri(PROGRAM_URI));
+ assertFalse(TvContract.isChannelUri(RECORDED_PROGRAM_URI));
assertFalse(TvContract.isChannelUri(null));
// Test isChannelUriForPassthroughInput
assertFalse(TvContract.isChannelUriForPassthroughInput(CHANNEL_URI_FOR_TUNER));
assertTrue(TvContract.isChannelUriForPassthroughInput(CHANNEL_URI_FOR_PASSTHROUGH_INPUT));
assertFalse(TvContract.isChannelUriForPassthroughInput(PROGRAM_URI));
+ assertFalse(TvContract.isChannelUriForPassthroughInput(RECORDED_PROGRAM_URI));
assertFalse(TvContract.isChannelUriForPassthroughInput(null));
// Test isChannelUriForTunerInput
assertTrue(TvContract.isChannelUriForTunerInput(CHANNEL_URI_FOR_TUNER));
assertFalse(TvContract.isChannelUriForTunerInput(CHANNEL_URI_FOR_PASSTHROUGH_INPUT));
assertFalse(TvContract.isChannelUriForTunerInput(PROGRAM_URI));
+ assertFalse(TvContract.isChannelUriForTunerInput(RECORDED_PROGRAM_URI));
assertFalse(TvContract.isChannelUriForTunerInput(null));
// Test isProgramUri
assertFalse(TvContract.isProgramUri(CHANNEL_URI_FOR_TUNER));
assertFalse(TvContract.isProgramUri(CHANNEL_URI_FOR_PASSTHROUGH_INPUT));
assertTrue(TvContract.isProgramUri(PROGRAM_URI));
+ assertFalse(TvContract.isProgramUri(RECORDED_PROGRAM_URI));
assertFalse(TvContract.isProgramUri(null));
+
+ // Test isRecordedProgramUri
+ assertFalse(TvContract.isRecordedProgramUri(CHANNEL_URI_FOR_TUNER));
+ assertFalse(TvContract.isRecordedProgramUri(CHANNEL_URI_FOR_PASSTHROUGH_INPUT));
+ assertFalse(TvContract.isRecordedProgramUri(PROGRAM_URI));
+ assertTrue(TvContract.isRecordedProgramUri(RECORDED_PROGRAM_URI));
+ assertFalse(TvContract.isRecordedProgramUri(null));
}
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
index 1ff74bf..0763e4b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
@@ -109,11 +109,6 @@
}
@Test
- public void testBitmapConfigFromIndex8() {
- testBitmapCopy(R.drawable.index_8, null, Bitmap.Config.HARDWARE);
- }
-
- @Test
public void testBitmapConfigFromHardwareToHardware() {
testBitmapCopy(R.drawable.robot, Bitmap.Config.HARDWARE, Bitmap.Config.HARDWARE);
}
@@ -247,4 +242,4 @@
canvas.drawBitmap(copy, 0, 0, null);
}, true).runWithComparer(new MSSIMComparer(0.99));
}
-}
\ No newline at end of file
+}
diff --git a/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
index 6c95e1f..145436b 100644
--- a/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
+++ b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
@@ -19,6 +19,8 @@
import static org.junit.Assert.fail;
import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -26,7 +28,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-@SmallTest
+@FlakyTest
@RunWith(AndroidJUnit4.class)
public class ChoreographerNativeTest {
private long mChoreographerPtr;
@@ -49,11 +51,13 @@
}
}
+ @MediumTest
@Test
public void testPostCallbackWithoutDelayEventuallyRunsCallbacks() {
nativeTestPostCallbackWithoutDelayEventuallyRunsCallbacks(mChoreographerPtr);
}
+ @SmallTest
@Test
public void testPostCallbackWithDelayEventuallyRunsCallbacks() {
nativeTestPostCallbackWithDelayEventuallyRunsCallbacks(mChoreographerPtr);
diff --git a/tests/tests/webkit/src/android/webkit/cts/ServiceWorkerClientTest.java b/tests/tests/webkit/src/android/webkit/cts/ServiceWorkerClientTest.java
index 1e9f5e8..ac736cf 100644
--- a/tests/tests/webkit/src/android/webkit/cts/ServiceWorkerClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/ServiceWorkerClientTest.java
@@ -57,13 +57,22 @@
+ " <script>\n"
+ " navigator.serviceWorker.register('sw.js').then(function(reg) {\n"
+ " " + JS_INTERFACE_NAME + ".registrationSuccess();\n"
- + " }).catch(function(err) { \n"
+ + " }).catch(function(err) {\n"
+ " console.error(err);\n"
+ " });\n"
+ " </script>\n"
+ " </body>\n"
+ "</html>\n";
private static final String SW_RAW_HTML = "fetch('fetch.html');";
+ private static final String SW_UNREGISTER_RAW_JS =
+ "navigator.serviceWorker.getRegistration().then(function(r) {"
+ + " r.unregister().then(function(success) {"
+ + " if (success) " + JS_INTERFACE_NAME + ".unregisterSuccess();"
+ + " else console.error('unregister() was not successful');"
+ + " });"
+ + "}).catch(function(err) {"
+ + " console.error(err);"
+ + "});";
private JavascriptStatusReceiver mJavascriptStatusReceiver;
private WebViewOnUiThread mOnUiThread;
@@ -171,17 +180,34 @@
assertEquals(2, requests.size());
assertEquals(SW_URL, requests.get(0).getUrl().toString());
assertEquals(FETCH_URL, requests.get(1).getUrl().toString());
+
+ // Clean-up, make sure to unregister the Service Worker.
+ mOnUiThread.evaluateJavascript(SW_UNREGISTER_RAW_JS, null);
+ Callable<Boolean> unregisterSuccess = new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return mJavascriptStatusReceiver.mUnregisterSuccess;
+ }
+ };
+ PollingCheck.check("JS could not unregister Service Worker", POLLING_TIMEOUT,
+ unregisterSuccess);
}
// Object added to the page via AddJavascriptInterface() that is used by the test Javascript to
// notify back to Java if the Service Worker registration was successful.
public final static class JavascriptStatusReceiver {
public volatile boolean mRegistrationSuccess = false;
+ public volatile boolean mUnregisterSuccess = false;
@JavascriptInterface
public void registrationSuccess() {
mRegistrationSuccess = true;
}
+
+ @JavascriptInterface
+ public void unregisterSuccess() {
+ mUnregisterSuccess = true;
+ }
}
}