From f0429097a74dc0341bb7e6e4825152fc36b657f0 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Fri, 13 Jan 2012 08:43:27 -0500 Subject: Extend forkAndSpecialize to take further input arguments. Extend forkAndSpecialize to take two further input arguments, a seInfo string and the niceName for the process. These can be used as further selectors in determining the SELinux security context for the process. Change-Id: If3a654070025e699b2266425f6eb8ab7e6b8c562 --- dalvik/src/main/java/dalvik/system/Zygote.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dalvik/src/main/java/dalvik/system/Zygote.java b/dalvik/src/main/java/dalvik/system/Zygote.java index 28c9912..ec114ed 100644 --- a/dalvik/src/main/java/dalvik/system/Zygote.java +++ b/dalvik/src/main/java/dalvik/system/Zygote.java @@ -107,20 +107,23 @@ public class Zygote { * dimension having a length of 3 and representing * (resource, rlim_cur, rlim_max). These are set via the posix * setrlimit(2) call. + * @param seInfo null-ok a string specifying SEAndroid information for + * the new process. + * @param niceName null-ok a string specifying the process name. * * @return 0 if this is the child, pid of the child * if this is the parent, or -1 on error. */ public static int forkAndSpecialize(int uid, int gid, int[] gids, - int debugFlags, int[][] rlimits) { + int debugFlags, int[][] rlimits, String seInfo, String niceName) { preFork(); - int pid = nativeForkAndSpecialize(uid, gid, gids, debugFlags, rlimits); + int pid = nativeForkAndSpecialize(uid, gid, gids, debugFlags, rlimits, seInfo, niceName); postFork(); return pid; } native public static int nativeForkAndSpecialize(int uid, int gid, - int[] gids, int debugFlags, int[][] rlimits); + int[] gids, int debugFlags, int[][] rlimits, String seInfo, String niceName); /** * Forks a new VM instance. @@ -130,7 +133,7 @@ public class Zygote { public static int forkAndSpecialize(int uid, int gid, int[] gids, boolean enableDebugger, int[][] rlimits) { int debugFlags = enableDebugger ? DEBUG_ENABLE_DEBUGGER : 0; - return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits); + return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits, null, null); } /** @@ -175,7 +178,7 @@ public class Zygote { public static int forkSystemServer(int uid, int gid, int[] gids, boolean enableDebugger, int[][] rlimits) { int debugFlags = enableDebugger ? DEBUG_ENABLE_DEBUGGER : 0; - return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits); + return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits, null, null); } native public static int nativeForkSystemServer(int uid, int gid, -- cgit v1.1 From c6d24c6b88ce50c1fa2b9e89253d5839eff1618a Mon Sep 17 00:00:00 2001 From: Lukasz Rymanowski Date: Wed, 7 Dec 2011 12:59:32 +0100 Subject: BT: Adding support for wrf files to BT OPP This patch adds support for wrf files to BT OPP. Proper mime type /application/octet-stream with extension wrf was added to webkit framework. Change-Id: I2cdd961a78281129b96fba51d5df37c534c5c893 Signed-off-by: Christian Bejram --- luni/src/main/java/libcore/net/MimeUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/luni/src/main/java/libcore/net/MimeUtils.java b/luni/src/main/java/libcore/net/MimeUtils.java index 8371c68..4681bbc 100644 --- a/luni/src/main/java/libcore/net/MimeUtils.java +++ b/luni/src/main/java/libcore/net/MimeUtils.java @@ -349,6 +349,7 @@ public final class MimeUtils { add("video/x-ms-wvx", "wvx"); add("video/x-msvideo", "avi"); add("video/x-sgi-movie", "movie"); + add("video/x-webex", "wrf"); add("x-conference/x-cooltalk", "ice"); add("x-epoc/x-sisx-app", "sisx"); applyOverrides(); -- cgit v1.1 From 3ec5e434af58fedddcb34e08dbd021bfb78bc69c Mon Sep 17 00:00:00 2001 From: Masanori Ogino Date: Tue, 17 Apr 2012 17:20:55 +0900 Subject: Avoid a wavy result for InterruptReadable/WritableChannel test Currently Thread#interrupt() API cannot interrupt (just close fd) even if a thread is blocking in I/O operation for an InterruptibleChannel. In other words, if a thread is blocked by read()/write() operation, then the Thread#interrupt() from another thread will close fd, but it cannot interrupt the blocking operation of Channel. In this test case, if the calling sequence is interrupt() -->read()/ write() (actually it occurs on many dual core ICS devices), then the test passes. Because the fd has already been closed. However, if the order of the calling sequence would change to read()/write() --> interrupt(), the test fails (i.e, I/O operation will not return). It occurs on a device which has a single core processor. Indeed, if I change the test case by adding sleep() before interrupt() then it fails on Galaxy Nexus. The blocking call stack is below; at libcore.io.Posix.readBytes(Native Method) <-- BLOCKED! at libcore.io.Posix.read(Posix.java:113) at libcore.io.BlockGuardOs.read(BlockGuardOs.java:144) at java.nio.FileChannelImpl.readImpl(FileChannelImpl.java:294) at java.nio.FileChannelImpl.read(FileChannelImpl.java:278) at java.nio.PipeImpl$PipeSourceChannel.read(PipeImpl.java:89) at libcore.java.io.InterruptedStreamTest. testInterruptReadableChannel(InterruptedStreamTest.java:133) ... So the test should be wait before interrupting the current thread in order to avoid a wavy result for these test cases. They will pass after the interruption of blocked operation in Channel is implemented correctly. And also I correct a wrong method call from testInterruptWritableSocketChannel(). Change-Id: Iaae3128d264070e818dc82d831ea8048bb43ad4a --- luni/src/test/java/libcore/java/io/InterruptedStreamTest.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) mode change 100644 => 100755 luni/src/test/java/libcore/java/io/InterruptedStreamTest.java diff --git a/luni/src/test/java/libcore/java/io/InterruptedStreamTest.java b/luni/src/test/java/libcore/java/io/InterruptedStreamTest.java old mode 100644 new mode 100755 index e973b8f..e1f51bd --- a/luni/src/test/java/libcore/java/io/InterruptedStreamTest.java +++ b/luni/src/test/java/libcore/java/io/InterruptedStreamTest.java @@ -28,6 +28,7 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.ClosedByInterruptException; +import java.nio.channels.ClosedChannelException; import java.nio.channels.Pipe; import java.nio.channels.ReadableByteChannel; import java.nio.channels.ServerSocketChannel; @@ -93,7 +94,7 @@ public final class InterruptedStreamTest extends TestCase { public void testInterruptWritableSocketChannel() throws Exception { sockets = newSocketChannelPair(); - testInterruptReadableChannel(sockets[0].getChannel()); + testInterruptWritableChannel(sockets[0].getChannel()); } /** @@ -166,6 +167,7 @@ public final class InterruptedStreamTest extends TestCase { channel.write(ByteBuffer.allocate(BUFFER_SIZE)); } } catch (ClosedByInterruptException expected) { + } catch (ClosedChannelException expected) { } } @@ -173,6 +175,10 @@ public final class InterruptedStreamTest extends TestCase { final Thread toInterrupt = Thread.currentThread(); new Thread(new Runnable () { @Override public void run() { + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + } toInterrupt.interrupt(); } }).start(); -- cgit v1.1 From b7e0772d25499ddf5435e53a90cf1a6d753786d7 Mon Sep 17 00:00:00 2001 From: Chris Dearman Date: Tue, 1 May 2012 16:11:58 -0700 Subject: [MIPS] Add MIPS Architecture support Change-Id: Idce58bad54a3f25dbe984c580cb6a48cc906ba76 Signed-off-by: Chris Dearman --- luni/src/main/native/libcore_io_Memory.cpp | 131 ++++++++++++++++-------- luni/src/main/native/libcore_io_OsConstants.cpp | 2 + luni/src/test/java/libcore/io/MemoryTest.java | 120 ++++++++++++++++------ 3 files changed, 177 insertions(+), 76 deletions(-) diff --git a/luni/src/main/native/libcore_io_Memory.cpp b/luni/src/main/native/libcore_io_Memory.cpp index 2200453..a511978 100644 --- a/luni/src/main/native/libcore_io_Memory.cpp +++ b/luni/src/main/native/libcore_io_Memory.cpp @@ -31,49 +31,114 @@ #if defined(__arm__) // 32-bit ARM has load/store alignment restrictions for longs. #define LONG_ALIGNMENT_MASK 0x3 +#define INT_ALIGNMENT_MASK 0x0 +#define SHORT_ALIGNMENT_MASK 0x0 +#elif defined(__mips__) +// MIPS has load/store alignment restrictions for longs, ints and shorts. +#define LONG_ALIGNMENT_MASK 0x7 +#define INT_ALIGNMENT_MASK 0x3 +#define SHORT_ALIGNMENT_MASK 0x1 #elif defined(__i386__) // x86 can load anything at any alignment. #define LONG_ALIGNMENT_MASK 0x0 +#define INT_ALIGNMENT_MASK 0x0 +#define SHORT_ALIGNMENT_MASK 0x0 #else #error unknown load/store alignment restrictions for this architecture #endif +// Use packed structures for access to unaligned data on targets with alignment restrictions. +// The compiler will generate appropriate code to access these structures without +// generating alignment exceptions. +template static inline T get_unaligned(const T* address) { + struct unaligned { T v; } __attribute__ ((packed)); + const unaligned* p = reinterpret_cast(address); + return p->v; +} + +template static inline void put_unaligned(T* address, T v) { + struct unaligned { T v; } __attribute__ ((packed)); + unaligned* p = reinterpret_cast(address); + p->v = v; +} + template static T cast(jint address) { return reinterpret_cast(static_cast(address)); } +// Byte-swap 2 jshort values packed in a jint. +static inline jint bswap_2x16(jint v) { + // v is initially ABCD + v = bswap_32(v); // v=DCBA +#if defined(__mips__) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2) + __asm__ volatile ("wsbh %0, %0" : "+r" (v)); // v=BADC +#else + v = (v << 16) | ((v >> 16) & 0xffff); // v=BADC +#endif + return v; +} + static inline void swapShorts(jshort* dstShorts, const jshort* srcShorts, size_t count) { // Do 32-bit swaps as long as possible... jint* dst = reinterpret_cast(dstShorts); const jint* src = reinterpret_cast(srcShorts); - for (size_t i = 0; i < count / 2; ++i) { - jint v = *src++; // v=ABCD - v = bswap_32(v); // v=DCBA - jint v2 = (v << 16) | ((v >> 16) & 0xffff); // v=BADC - *dst++ = v2; - } - // ...with one last 16-bit swap if necessary. - if ((count % 2) != 0) { - jshort v = *reinterpret_cast(src); - *reinterpret_cast(dst) = bswap_16(v); + + if ((reinterpret_cast(dst) & INT_ALIGNMENT_MASK) == 0 && + (reinterpret_cast(src) & INT_ALIGNMENT_MASK) == 0) { + for (size_t i = 0; i < count / 2; ++i) { + jint v = *src++; + *dst++ = bswap_2x16(v); + } + // ...with one last 16-bit swap if necessary. + if ((count % 2) != 0) { + jshort v = *reinterpret_cast(src); + *reinterpret_cast(dst) = bswap_16(v); + } + } else { + for (size_t i = 0; i < count / 2; ++i) { + jint v = get_unaligned(src++); + put_unaligned(dst++, bswap_2x16(v)); + } + if ((count % 2) != 0) { + jshort v = get_unaligned(reinterpret_cast(src)); + put_unaligned(reinterpret_cast(dst), bswap_16(v)); + } } } static inline void swapInts(jint* dstInts, const jint* srcInts, size_t count) { - for (size_t i = 0; i < count; ++i) { - jint v = *srcInts++; - *dstInts++ = bswap_32(v); + if ((reinterpret_cast(dstInts) & INT_ALIGNMENT_MASK) == 0 && + (reinterpret_cast(srcInts) & INT_ALIGNMENT_MASK) == 0) { + for (size_t i = 0; i < count; ++i) { + jint v = *srcInts++; + *dstInts++ = bswap_32(v); + } + } else { + for (size_t i = 0; i < count; ++i) { + jint v = get_unaligned(srcInts++); + put_unaligned(dstInts++, bswap_32(v)); + } } } static inline void swapLongs(jlong* dstLongs, const jlong* srcLongs, size_t count) { jint* dst = reinterpret_cast(dstLongs); const jint* src = reinterpret_cast(srcLongs); - for (size_t i = 0; i < count; ++i) { - jint v1 = *src++; - jint v2 = *src++; - *dst++ = bswap_32(v2); - *dst++ = bswap_32(v1); + if ((reinterpret_cast(dstLongs) & INT_ALIGNMENT_MASK) == 0 && + (reinterpret_cast(srcLongs) & INT_ALIGNMENT_MASK) == 0) { + for (size_t i = 0; i < count; ++i) { + jint v1 = *src++; + jint v2 = *src++; + *dst++ = bswap_32(v2); + *dst++ = bswap_32(v1); + } + } else { + for (size_t i = 0; i < count; ++i) { + jint v1 = get_unaligned(src++); + jint v2 = get_unaligned(src++); + put_unaligned(dst++, bswap_32(v2)); + put_unaligned(dst++, bswap_32(v1)); + } } } @@ -226,20 +291,11 @@ static void Memory_pokeInt(JNIEnv*, jclass, jint dstAddress, jint value, jboolea static jlong Memory_peekLong(JNIEnv*, jclass, jint srcAddress, jboolean swap) { jlong result; + const jlong* src = cast(srcAddress); if ((srcAddress & LONG_ALIGNMENT_MASK) == 0) { - result = *cast(srcAddress); + result = *src; } else { - // Handle unaligned memory access one byte at a time - const jbyte* src = cast(srcAddress); - jbyte* dst = reinterpret_cast(&result); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - dst[3] = src[3]; - dst[4] = src[4]; - dst[5] = src[5]; - dst[6] = src[6]; - dst[7] = src[7]; + result = get_unaligned(src); } if (swap) { result = bswap_64(result); @@ -248,23 +304,14 @@ static jlong Memory_peekLong(JNIEnv*, jclass, jint srcAddress, jboolean swap) { } static void Memory_pokeLong(JNIEnv*, jclass, jint dstAddress, jlong value, jboolean swap) { + jlong* dst = cast(dstAddress); if (swap) { value = bswap_64(value); } if ((dstAddress & LONG_ALIGNMENT_MASK) == 0) { - *cast(dstAddress) = value; + *dst = value; } else { - // Handle unaligned memory access one byte at a time - const jbyte* src = reinterpret_cast(&value); - jbyte* dst = cast(dstAddress); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - dst[3] = src[3]; - dst[4] = src[4]; - dst[5] = src[5]; - dst[6] = src[6]; - dst[7] = src[7]; + put_unaligned(dst, value); } } diff --git a/luni/src/main/native/libcore_io_OsConstants.cpp b/luni/src/main/native/libcore_io_OsConstants.cpp index 942cfce..c432973 100644 --- a/luni/src/main/native/libcore_io_OsConstants.cpp +++ b/luni/src/main/native/libcore_io_OsConstants.cpp @@ -275,7 +275,9 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) { initConstant(env, c, "SIGRTMAX", SIGRTMAX); initConstant(env, c, "SIGRTMIN", SIGRTMIN); initConstant(env, c, "SIGSEGV", SIGSEGV); +#if defined(SIGSTKFLT) initConstant(env, c, "SIGSTKFLT", SIGSTKFLT); +#endif initConstant(env, c, "SIGSTOP", SIGSTOP); initConstant(env, c, "SIGSYS", SIGSYS); initConstant(env, c, "SIGTERM", SIGTERM); diff --git a/luni/src/test/java/libcore/io/MemoryTest.java b/luni/src/test/java/libcore/io/MemoryTest.java index a533f15..9a596fb 100644 --- a/luni/src/test/java/libcore/io/MemoryTest.java +++ b/luni/src/test/java/libcore/io/MemoryTest.java @@ -18,6 +18,7 @@ package libcore.io; import dalvik.system.VMRuntime; +import java.util.Arrays; import junit.framework.TestCase; public class MemoryTest extends TestCase { @@ -28,65 +29,116 @@ public class MemoryTest extends TestCase { swappedValues[i] = Integer.reverseBytes(values[i]); } - int scale = 4; + int scale = SizeOf.INT; VMRuntime runtime = VMRuntime.getRuntime(); - byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length); - int ptr = (int) runtime.addressOf(array); + byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length + 1); + int base_ptr = (int) runtime.addressOf(array); - // Regular copy. - Memory.pokeIntArray(ptr, values, 0, values.length, false); - assertIntsEqual(values, ptr, false); - assertIntsEqual(swappedValues, ptr, true); + for (int ptr_offset = 0; ptr_offset < 2; ++ptr_offset) { + int ptr = base_ptr + ptr_offset; // To test aligned and unaligned accesses. + Arrays.fill(array, (byte) 0); - // Swapped copy. - Memory.pokeIntArray(ptr, values, 0, values.length, true); - assertIntsEqual(values, ptr, true); - assertIntsEqual(swappedValues, ptr, false); + // Regular copy. + Memory.pokeIntArray(ptr, values, 0, values.length, false); + assertIntsEqual(values, ptr, false); + assertIntsEqual(swappedValues, ptr, true); - // Swapped copies of slices (to ensure we test non-zero offsets). - for (int i = 0; i < values.length; ++i) { - Memory.pokeIntArray(ptr + i * scale, values, i, 1, true); + // Swapped copy. + Memory.pokeIntArray(ptr, values, 0, values.length, true); + assertIntsEqual(values, ptr, true); + assertIntsEqual(swappedValues, ptr, false); + + // Swapped copies of slices (to ensure we test non-zero offsets). + for (int i = 0; i < values.length; ++i) { + Memory.pokeIntArray(ptr + i * scale, values, i, 1, true); + } + assertIntsEqual(values, ptr, true); + assertIntsEqual(swappedValues, ptr, false); } - assertIntsEqual(values, ptr, true); - assertIntsEqual(swappedValues, ptr, false); } private void assertIntsEqual(int[] expectedValues, int ptr, boolean swap) { for (int i = 0; i < expectedValues.length; ++i) { - assertEquals(expectedValues[i], Memory.peekInt(ptr + 4 * i, swap)); + assertEquals(expectedValues[i], Memory.peekInt(ptr + SizeOf.INT * i, swap)); } } + public void testSetLongArray() { + long[] values = { 0x1020304050607080L, 0xffeeddccbbaa9988L }; + long[] swappedValues = new long[values.length]; + for (int i = 0; i < values.length; ++i) { + swappedValues[i] = Long.reverseBytes(values[i]); + } + + int scale = SizeOf.LONG; + VMRuntime runtime = VMRuntime.getRuntime(); + byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length + 1); + int base_ptr = (int) runtime.addressOf(array); + + for (int ptr_offset = 0; ptr_offset < 2; ++ptr_offset) { + int ptr = base_ptr + ptr_offset; // To test aligned and unaligned accesses. + Arrays.fill(array, (byte) 0); + + // Regular copy. + Memory.pokeLongArray(ptr, values, 0, values.length, false); + assertLongsEqual(values, ptr, false); + assertLongsEqual(swappedValues, ptr, true); + + // Swapped copy. + Memory.pokeLongArray(ptr, values, 0, values.length, true); + assertLongsEqual(values, ptr, true); + assertLongsEqual(swappedValues, ptr, false); + + // Swapped copies of slices (to ensure we test non-zero offsets). + for (int i = 0; i < values.length; ++i) { + Memory.pokeLongArray(ptr + i * scale, values, i, 1, true); + } + assertLongsEqual(values, ptr, true); + assertLongsEqual(swappedValues, ptr, false); + } + } + + private void assertLongsEqual(long[] expectedValues, int ptr, boolean swap) { + for (int i = 0; i < expectedValues.length; ++i) { + assertEquals(expectedValues[i], Memory.peekLong(ptr + SizeOf.LONG * i, swap)); + } + } + public void testSetShortArray() { short[] values = { 0x0001, 0x0020, 0x0300, 0x4000 }; short[] swappedValues = { 0x0100, 0x2000, 0x0003, 0x0040 }; - int scale = 2; + int scale = SizeOf.SHORT; VMRuntime runtime = VMRuntime.getRuntime(); - byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length); - int ptr = (int) runtime.addressOf(array); + byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length + 1); + int base_ptr = (int) runtime.addressOf(array); - // Regular copy. Memset first so we start from a known state. - Memory.pokeShortArray(ptr, values, 0, values.length, false); - assertShortsEqual(values, ptr, false); - assertShortsEqual(swappedValues, ptr, true); + for (int ptr_offset = 0; ptr_offset < 2; ++ptr_offset) { + int ptr = base_ptr + ptr_offset; // To test aligned and unaligned accesses. + Arrays.fill(array, (byte) 0); - // Swapped copy. - Memory.pokeShortArray(ptr, values, 0, values.length, true); - assertShortsEqual(values, ptr, true); - assertShortsEqual(swappedValues, ptr, false); + // Regular copy. + Memory.pokeShortArray(ptr, values, 0, values.length, false); + assertShortsEqual(values, ptr, false); + assertShortsEqual(swappedValues, ptr, true); - // Swapped copies of slices (to ensure we test non-zero offsets). - for (int i = 0; i < values.length; ++i) { - Memory.pokeShortArray(ptr + i * scale, values, i, 1, true); + // Swapped copy. + Memory.pokeShortArray(ptr, values, 0, values.length, true); + assertShortsEqual(values, ptr, true); + assertShortsEqual(swappedValues, ptr, false); + + // Swapped copies of slices (to ensure we test non-zero offsets). + for (int i = 0; i < values.length; ++i) { + Memory.pokeShortArray(ptr + i * scale, values, i, 1, true); + } + assertShortsEqual(values, ptr, true); + assertShortsEqual(swappedValues, ptr, false); } - assertShortsEqual(values, ptr, true); - assertShortsEqual(swappedValues, ptr, false); } private void assertShortsEqual(short[] expectedValues, int ptr, boolean swap) { for (int i = 0; i < expectedValues.length; ++i) { - assertEquals(expectedValues[i], Memory.peekShort(ptr + 2 * i, swap)); + assertEquals(expectedValues[i], Memory.peekShort(ptr + SizeOf.SHORT * i, swap)); } } } -- cgit v1.1 From eb36a982128aa7e27adcc0d54af8790c44f5c039 Mon Sep 17 00:00:00 2001 From: Pavel Chupin Date: Tue, 24 Apr 2012 12:05:50 +0400 Subject: 4.6: Disable unused-but-set-variable warning build Author: Pavel Chupin Reviewed-by: Lu, Hongjiu Reviewed-by: Beare, Bruce J --- NativeCode.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NativeCode.mk b/NativeCode.mk index 62ef803..85b38e1 100644 --- a/NativeCode.mk +++ b/NativeCode.mk @@ -75,7 +75,7 @@ core_cflags += '-DGCC_HIDDEN=__attribute__((visibility("hidden")))' include $(CLEAR_VARS) -LOCAL_CFLAGS += -Wall -Wextra -Werror +LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-but-set-variable LOCAL_CFLAGS += $(core_cflags) ifeq ($(TARGET_ARCH),arm) # Ignore "note: the mangling of 'va_list' has changed in GCC 4.4" -- cgit v1.1 From 17e2f4bad4068a1a6c7fbe338fa1fa1b6131bb9e Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 11 May 2012 17:20:49 -0700 Subject: Explain a #include of private zlib API. Change-Id: Ifa6130bdbd91c02eb663cbad25db344eab873943 --- luni/src/main/native/zip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luni/src/main/native/zip.h b/luni/src/main/native/zip.h index 0f3c0c1..303c940 100644 --- a/luni/src/main/native/zip.h +++ b/luni/src/main/native/zip.h @@ -23,7 +23,7 @@ #include "UniquePtr.h" #include "jni.h" #include "zlib.h" -#include "zutil.h" +#include "zutil.h" // For DEF_WBITS and DEF_MEM_LEVEL. static void throwExceptionForZlibError(JNIEnv* env, const char* exceptionClassName, int error) { if (error == Z_MEM_ERROR) { -- cgit v1.1 From 811320db23eb8fa68b0ee8659b4448157a0680a5 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 11 May 2012 17:21:28 -0700 Subject: Add more tests for Object.wait. Change-Id: Ifd8d80650a2714ead99c6d3426c902728d43b457 --- luni/src/main/java/java/lang/Object.java | 2 +- .../test/java/libcore/java/lang/OldObjectTest.java | 31 ++++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/luni/src/main/java/java/lang/Object.java b/luni/src/main/java/java/lang/Object.java index 7f4b490..4bca034 100644 --- a/luni/src/main/java/java/lang/Object.java +++ b/luni/src/main/java/java/lang/Object.java @@ -361,7 +361,7 @@ public class Object { * @see java.lang.Thread */ public final void wait() throws InterruptedException { - wait(0 ,0); + wait(0, 0); } /** diff --git a/luni/src/test/java/libcore/java/lang/OldObjectTest.java b/luni/src/test/java/libcore/java/lang/OldObjectTest.java index 08471b2..3ab0327 100644 --- a/luni/src/test/java/libcore/java/lang/OldObjectTest.java +++ b/luni/src/test/java/libcore/java/lang/OldObjectTest.java @@ -16,8 +16,6 @@ */ package libcore.java.lang; -import dalvik.annotation.SideEffect; -import java.util.Vector; import junit.framework.TestCase; public class OldObjectTest extends TestCase { @@ -187,7 +185,36 @@ public class OldObjectTest extends TestCase { fail("InterruptedException was thrown."); } assertEquals(3, status); + } + + public void test_waitJI_invalid() throws Exception { + Object o = new Object(); + synchronized (o) { + try { + o.wait(-1, 0); + fail(); + } catch (IllegalArgumentException expected) { + } + + try { + o.wait(0, -1); + fail(); + } catch (IllegalArgumentException expected) { + } + try { + o.wait(-1, -1); + fail(); + } catch (IllegalArgumentException expected) { + } + + // The ms timeout must fit in 32 bits. + try { + o.wait(Integer.MAX_VALUE + 1, 0); + fail(); + } catch (IllegalArgumentException expected) { + } + } } public void test_waitJ() { -- cgit v1.1 From f3d07392d4fbeb7b6762b08a523431c34fef750a Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 15 May 2012 13:10:04 -0700 Subject: AssertionError(Object) should only initCause if the object is a Throwable. Bug: http://code.google.com/p/android/issues/detail?id=29378 Change-Id: I608901eed848ab496b8f54b784216b1362b561d2 --- luni/src/main/java/java/lang/AssertionError.java | 6 +++-- .../java/libcore/java/lang/AssertionErrorTest.java | 27 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 luni/src/test/java/libcore/java/lang/AssertionErrorTest.java diff --git a/luni/src/main/java/java/lang/AssertionError.java b/luni/src/main/java/java/lang/AssertionError.java index 3d0d2a4..077e57c 100644 --- a/luni/src/main/java/java/lang/AssertionError.java +++ b/luni/src/main/java/java/lang/AssertionError.java @@ -52,8 +52,10 @@ public class AssertionError extends Error { * optionally the cause. */ public AssertionError(Object detailMessage) { - super(String.valueOf(detailMessage), - (detailMessage instanceof Throwable ? (Throwable) detailMessage : null)); + super(String.valueOf(detailMessage)); + if (detailMessage instanceof Throwable) { + initCause((Throwable) detailMessage); + } } /** diff --git a/luni/src/test/java/libcore/java/lang/AssertionErrorTest.java b/luni/src/test/java/libcore/java/lang/AssertionErrorTest.java new file mode 100644 index 0000000..638b15b --- /dev/null +++ b/luni/src/test/java/libcore/java/lang/AssertionErrorTest.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +package libcore.java.lang; + +import junit.framework.TestCase; + +public final class AssertionErrorTest extends TestCase { + // http://code.google.com/p/android/issues/detail?id=29378 + public void test_29378() throws Exception { + AssertionError ae = new AssertionError("hello"); + ae.initCause(new Throwable()); + } +} -- cgit v1.1 From 431d246358fa832bc2e759fcaec9c4ad9f0b09a7 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 15 May 2012 16:08:18 -0700 Subject: Fix BitSet.nextClearBit. Bug: http://code.google.com/p/android/issues/detail?id=31036 Change-Id: I45762449b56773cb5eb323bda7728e8c63a50487 --- luni/src/main/java/java/util/BitSet.java | 2 +- .../test/java/tests/api/java/util/BitSetTest.java | 27 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/luni/src/main/java/java/util/BitSet.java b/luni/src/main/java/java/util/BitSet.java index a841315..a4ee4c1 100644 --- a/luni/src/main/java/java/util/BitSet.java +++ b/luni/src/main/java/java/util/BitSet.java @@ -602,7 +602,7 @@ public class BitSet implements Serializable, Cloneable { while (++arrayIndex < longCount && bits[arrayIndex] == ALL_ONES) { } if (arrayIndex == longCount) { - return size(); + return 64 * longCount; } return 64 * arrayIndex + Long.numberOfTrailingZeros(~bits[arrayIndex]); } diff --git a/luni/src/test/java/tests/api/java/util/BitSetTest.java b/luni/src/test/java/tests/api/java/util/BitSetTest.java index 172c6d1..e1abc48 100644 --- a/luni/src/test/java/tests/api/java/util/BitSetTest.java +++ b/luni/src/test/java/tests/api/java/util/BitSetTest.java @@ -1178,6 +1178,33 @@ public class BitSetTest extends junit.framework.TestCase { // if the index is larger than bs.size(), nextClearBit should return index assertEquals(513, bs.nextClearBit(513)); assertEquals(800, bs.nextClearBit(800)); + + bs.clear(); + assertEquals(0, bs.nextClearBit(0)); + assertEquals(3, bs.nextClearBit(3)); + assertEquals(64, bs.nextClearBit(64)); + assertEquals(128, bs.nextClearBit(128)); + } + + // http://code.google.com/p/android/issues/detail?id=31036 + public void test_31036_clear() { + BitSet bs = new BitSet(500); + for (int i = 0; i < 500; ++i) { + int nextClear = bs.nextClearBit(0); + assertEquals(i, nextClear); + bs.set(i); + } + } + + // http://code.google.com/p/android/issues/detail?id=31036 + public void test_31036_set() { + BitSet bs = new BitSet(500); + bs.set(0, 511); + for (int i = 0; i < 500; ++i) { + int nextSet = bs.nextSetBit(0); + assertEquals(i, nextSet); + bs.clear(i); + } } public void test_isEmpty() { -- cgit v1.1 From da2fb9754a9ccfa954c1b554982f06e7cf7d680a Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 18 May 2012 09:37:47 -0700 Subject: Stop using -fvisibility=hidden. It breaks backtraces, and backtraces are useful. (The debugger uses the ELF debug info, so it doesn't care, but backtracing just uses the symbols.) Bug: 6447213 Change-Id: I2893191d7cec57a04bf7b3f4eea54e699df10507 --- NativeCode.mk | 3 --- luni/src/main/native/libcore_io_Posix.cpp | 2 +- luni/src/main/native/libcore_net_RawSocket.cpp | 6 ++++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/NativeCode.mk b/NativeCode.mk index 2a222b1..fae0fce 100644 --- a/NativeCode.mk +++ b/NativeCode.mk @@ -65,9 +65,6 @@ $(foreach dir, \ core_c_includes := $(sort libcore/include $(LOCAL_C_INCLUDES) $(JNI_H_INCLUDE)) core_shared_libraries := $(sort $(LOCAL_SHARED_LIBRARIES)) core_static_libraries := $(sort $(LOCAL_STATIC_LIBRARIES)) -core_cflags := -fvisibility=hidden -core_cflags += '-DGCC_HIDDEN=__attribute__((visibility("hidden")))' -core_cppflags := -fvisibility-inlines-hidden # diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp index 30ca145..5a3382a 100644 --- a/luni/src/main/native/libcore_io_Posix.cpp +++ b/luni/src/main/native/libcore_io_Posix.cpp @@ -1102,7 +1102,7 @@ static void Posix_setsockoptGroupReq(JNIEnv* env, jobject, jobject javaFd, jint if (rc == -1 && errno == EINVAL) { // Maybe we're a 32-bit binary talking to a 64-bit kernel? // glibc doesn't automatically handle this. - struct GCC_HIDDEN group_req64 { + struct group_req64 { uint32_t gr_interface; uint32_t my_padding; sockaddr_storage gr_group; diff --git a/luni/src/main/native/libcore_net_RawSocket.cpp b/luni/src/main/native/libcore_net_RawSocket.cpp index 4e5059f..2e493ac 100644 --- a/luni/src/main/native/libcore_net_RawSocket.cpp +++ b/luni/src/main/native/libcore_net_RawSocket.cpp @@ -38,10 +38,10 @@ #include #include -union GCC_HIDDEN sockunion { +union sockunion { sockaddr sa; sockaddr_ll sll; -} su; +}; /* * Creates a socket suitable for raw socket operations. The socket is @@ -61,6 +61,7 @@ static void RawSocket_create(JNIEnv* env, jclass, jobject fileDescriptor, return; } + sockunion su; memset(&su, 0, sizeof(su)); su.sll.sll_family = PF_PACKET; su.sll.sll_protocol = htons(protocolType); @@ -119,6 +120,7 @@ static int RawSocket_sendPacket(JNIEnv* env, jclass, jobject fileDescriptor, return 0; } + sockunion su; memset(&su, 0, sizeof(su)); su.sll.sll_hatype = htons(1); // ARPHRD_ETHER su.sll.sll_halen = mac.size(); -- cgit v1.1 From 8ecba5fd3f3ab30aa57caf917963bed50087ea9c Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 7 Feb 2012 18:18:45 -0800 Subject: Fix an ICS DatagramPacket bug. (cherry-picked from e50d82455c813210a2d452070f45fd38d9903159.) Bug: http://code.google.com/p/android/issues/detail?id=24748 Change-Id: Id7772c3f27961c99d3e5e3856e79edb84483dd46 --- luni/src/main/java/java/net/DatagramPacket.java | 62 ++++++++++------------ luni/src/main/java/java/net/DatagramSocket.java | 5 +- luni/src/main/java/libcore/io/IoBridge.java | 2 +- .../libcore/java/net/OldDatagramSocketTest.java | 31 ++++++++--- 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/luni/src/main/java/java/net/DatagramPacket.java b/luni/src/main/java/java/net/DatagramPacket.java index 663585c..3b1bc36 100644 --- a/luni/src/main/java/java/net/DatagramPacket.java +++ b/luni/src/main/java/java/net/DatagramPacket.java @@ -26,26 +26,26 @@ package java.net; */ public final class DatagramPacket { - byte[] data; + private byte[] data; /** * Length of the data to be sent or size of data that was received via * DatagramSocket#receive() method call. */ - int length; + private int length; /** - * Size of internal buffer that is used to store received data. Should be - * greater or equal to "length" field. + * The last user-supplied length (as opposed to a length set by simply receiving a packet). + * This length (unlike 'length') is sticky, and survives until the user sets another length. + * It's used to limit the amount of data that will be taken from future packets. */ - int capacity; + private int userSuppliedLength; - InetAddress address; + private InetAddress address; - int port = -1; // The default port number is -1 - - int offset = 0; + private int port = -1; // The default port number is -1 + private int offset = 0; /** * Constructs a new {@code DatagramPacket} object to receive data up to @@ -92,8 +92,7 @@ public final class DatagramPacket { * @param aPort * the port of the target host. */ - public DatagramPacket(byte[] data, int offset, int length, - InetAddress host, int aPort) { + public DatagramPacket(byte[] data, int offset, int length, InetAddress host, int aPort) { this(data, offset, length); setPort(aPort); address = host; @@ -185,7 +184,7 @@ public final class DatagramPacket { this.data = data; this.offset = offset; this.length = byteCount; - this.capacity = byteCount; + this.userSuppliedLength = byteCount; } /** @@ -197,21 +196,12 @@ public final class DatagramPacket { */ public synchronized void setData(byte[] buf) { length = buf.length; // This will check for null - capacity = buf.length; + userSuppliedLength = length; data = buf; offset = 0; } /** - * Gets the current capacity value. - * - * @return the current capacity value - */ - synchronized int getCapacity() { - return capacity; - } - - /** * Sets the length of the datagram packet. This length plus the offset must * be lesser than or equal to the buffer size. * @@ -219,21 +209,27 @@ public final class DatagramPacket { * the length of this datagram packet. */ public synchronized void setLength(int length) { - setLengthOnly(length); - this.capacity = length; + if (length < 0 || offset + length > data.length) { + throw new IndexOutOfBoundsException("length=" + length + ", offset=" + offset + + ", buffer size=" + data.length); + } + this.length = length; + this.userSuppliedLength = length; } /** - * An alternative to {@link #setLength(int)}, that doesn't reset the {@link #capacity} - * field. - * - * @param len the length of this datagram packet + * Resets 'length' to the last user-supplied length, ready to receive another packet. + * @hide for PlainDatagramSocketImpl */ - synchronized void setLengthOnly(int length) { - if (length < 0 || offset + length > data.length) { - throw new IndexOutOfBoundsException("length=" + length + ", offset=" + offset + - ", buffer size=" + data.length); - } + public void resetLengthForReceive() { + this.length = userSuppliedLength; + } + + /** + * Sets 'length' without changing 'userSuppliedLength', after receiving a packet. + * @hide for IoBridge + */ + public void setReceivedLength(int length) { this.length = length; } diff --git a/luni/src/main/java/java/net/DatagramSocket.java b/luni/src/main/java/java/net/DatagramSocket.java index 487a18a..2b468fa 100644 --- a/luni/src/main/java/java/net/DatagramSocket.java +++ b/luni/src/main/java/java/net/DatagramSocket.java @@ -249,11 +249,8 @@ public class DatagramSocket { if (pendingConnectException != null) { throw new SocketException("Pending connect failure", pendingConnectException); } - - pack.setLength(pack.getCapacity()); + pack.resetLengthForReceive(); impl.receive(pack); - // pack's length field is now updated by native code call; - // pack's capacity field is unchanged } /** diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java index db8d8ad..f95e8ec 100644 --- a/luni/src/main/java/libcore/io/IoBridge.java +++ b/luni/src/main/java/libcore/io/IoBridge.java @@ -525,7 +525,7 @@ public final class IoBridge { return -1; } if (packet != null) { - packet.setLength(byteCount); + packet.setReceivedLength(byteCount); if (!isConnected) { packet.setAddress(srcAddress.getAddress()); packet.setPort(srcAddress.getPort()); diff --git a/luni/src/test/java/libcore/java/net/OldDatagramSocketTest.java b/luni/src/test/java/libcore/java/net/OldDatagramSocketTest.java index 666a503..d51d461 100644 --- a/luni/src/test/java/libcore/java/net/OldDatagramSocketTest.java +++ b/luni/src/test/java/libcore/java/net/OldDatagramSocketTest.java @@ -804,9 +804,11 @@ public class OldDatagramSocketTest extends junit.framework./*Socket*/TestCase { InetAddress localHost = InetAddress.getLocalHost(); Thread.sleep(1000); DatagramSocket sds = new DatagramSocket(ports[1]); - DatagramPacket rdp = new DatagramPacket("Test String" - .getBytes(), 11, localHost, portNumber); - sds.send(rdp); + sds.send(new DatagramPacket("Test".getBytes("UTF-8"), "Test".length(), localHost, portNumber)); + sds.send(new DatagramPacket("Longer test".getBytes("UTF-8"), "Longer test".length(), localHost, portNumber)); + sds.send(new DatagramPacket("3 Test".getBytes("UTF-8"), "3 Test".length(), localHost, portNumber)); + sds.send(new DatagramPacket("4 Test".getBytes("UTF-8"), "4 Test".length(), localHost, portNumber)); + sds.send(new DatagramPacket("5".getBytes("UTF-8"), "5".length(), localHost, portNumber)); sds.close(); } catch (Exception e) { throw new RuntimeException(e); @@ -815,15 +817,30 @@ public class OldDatagramSocketTest extends junit.framework./*Socket*/TestCase { } try { - new Thread(new TestDGRcv(), "DGSender").start(); + new Thread(new TestDGRcv(), "datagram receiver").start(); ds = new java.net.DatagramSocket(portNumber); ds.setSoTimeout(6000); - byte rbuf[] = new byte[1000]; + byte[] rbuf = new byte[1000]; DatagramPacket rdp = new DatagramPacket(rbuf, rbuf.length); + + // Receive the first packet. + ds.receive(rdp); + assertEquals("Test", new String(rbuf, 0, rdp.getLength())); + // Check that we can still receive a longer packet (http://code.google.com/p/android/issues/detail?id=24748). ds.receive(rdp); + assertEquals("Longer test", new String(rbuf, 0, rdp.getLength())); + // See what happens if we manually call DatagramPacket.setLength. + rdp.setLength(4); + ds.receive(rdp); + assertEquals("3 Te", new String(rbuf, 0, rdp.getLength())); + // And then another. + ds.receive(rdp); + assertEquals("4 Te", new String(rbuf, 0, rdp.getLength())); + // And then a packet shorter than the user-supplied length. + ds.receive(rdp); + assertEquals("5", new String(rbuf, 0, rdp.getLength())); + ds.close(); - assertEquals("Send/Receive failed to return correct data: " - + new String(rbuf, 0, 11), "Test String", new String(rbuf, 0, 11)); } finally { ds.close(); } -- cgit v1.1 From f0e583ce305f656c05aa2f7dc2878c2e314d418c Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 7 Jun 2012 12:32:53 -0700 Subject: Buffer System.in. Android apps won't notice this, but command-line tools will. Console was already doing this. Bug: 6603218 Change-Id: I0f65f3154f5e3ec5c49a6a2c4c87f30a846bb008 --- luni/src/main/java/java/lang/System.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luni/src/main/java/java/lang/System.java b/luni/src/main/java/java/lang/System.java index c65ebbb..f452186 100644 --- a/luni/src/main/java/java/lang/System.java +++ b/luni/src/main/java/java/lang/System.java @@ -34,6 +34,7 @@ package java.lang; import dalvik.system.VMRuntime; import dalvik.system.VMStack; +import java.io.BufferedInputStream; import java.io.Console; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -83,10 +84,9 @@ public final class System { private static Properties systemProperties; static { - // TODO: all three streams are buffered in Harmony. err = new PrintStream(new FileOutputStream(FileDescriptor.err)); out = new PrintStream(new FileOutputStream(FileDescriptor.out)); - in = new FileInputStream(FileDescriptor.in); + in = new BufferedInputStream(new FileInputStream(FileDescriptor.in)); lineSeparator = System.getProperty("line.separator"); } -- cgit v1.1 From 4718b07e482ccb083ce3dfff228d0615b96a8dd2 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Mon, 11 Jun 2012 16:54:08 -0700 Subject: Add OpenSSL provider for SHA1PRNG Change-Id: I45a3c1c0089aa439629e4645f15b16bd35aa6f55 --- .../harmony/xnet/provider/jsse/NativeCrypto.java | 2 + .../xnet/provider/jsse/OpenSSLProvider.java | 9 ++ .../harmony/xnet/provider/jsse/OpenSSLRandom.java | 41 ++++++++ ...che_harmony_xnet_provider_jsse_NativeCrypto.cpp | 19 ++++ .../libcore/java/security/SecureRandomTest.java | 114 +++++++++++++++++++++ .../tests/java/security/SecureRandom2Test.java | 35 ++----- .../xnet/provider/jsse/NativeCryptoTest.java | 21 ++++ 7 files changed, 212 insertions(+), 29 deletions(-) create mode 100644 luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java create mode 100644 luni/src/test/java/libcore/java/security/SecureRandomTest.java diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java index 759fc85..f3cc1ac 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java @@ -172,6 +172,8 @@ public final class NativeCrypto { public static native int RAND_load_file(String filename, long max_bytes); + public static native void RAND_bytes(byte[] output); + // --- X509_NAME ----------------------------------------------------------- public static int X509_NAME_hash(X500Principal principal) { diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java index 97753cf..4c88fc3 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java @@ -108,5 +108,14 @@ public final class OpenSSLProvider extends Provider { put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.3", "SHA1withDSA"); put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA"); put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA"); + + // SecureRandom + /* + * We have to specify SHA1PRNG because various documentation mentions + * that algorithm by name instead of just recommending calling + * "new SecureRandom()" + */ + put("SecureRandom.SHA1PRNG", OpenSSLRandom.class.getName()); + put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); } } diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java new file mode 100644 index 0000000..fd011f0 --- /dev/null +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package org.apache.harmony.xnet.provider.jsse; + +import java.io.Serializable; +import java.security.SecureRandomSpi; + +public class OpenSSLRandom extends SecureRandomSpi implements Serializable { + private static final long serialVersionUID = 8506210602917522860L; + + @Override + protected void engineSetSeed(byte[] seed) { + NativeCrypto.RAND_seed(seed); + } + + @Override + protected void engineNextBytes(byte[] bytes) { + NativeCrypto.RAND_bytes(bytes); + } + + @Override + protected byte[] engineGenerateSeed(int numBytes) { + byte[] output = new byte[numBytes]; + NativeCrypto.RAND_bytes(output); + return output; + } +} diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp index 687c57e..0b07531 100644 --- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp +++ b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp @@ -1828,6 +1828,24 @@ static jint NativeCrypto_RAND_load_file(JNIEnv* env, jclass, jstring filename, j return result; } +static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) { + JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output); + + ScopedByteArrayRW outputBytes(env, output); + if (outputBytes.get() == NULL) { + return; + } + + unsigned char* tmp = reinterpret_cast(outputBytes.get()); + if (!RAND_bytes(tmp, outputBytes.size())) { + throwExceptionIfNecessary(env, "NativeCrypto_RAND_bytes"); + JNI_TRACE("ctx=%p NativeCrypto_RAND_bytes => threw error", ctx); + return; + } + + JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output); +} + #ifdef WITH_JNI_TRACE /** * Based on example logging call back from SSL_CTX_set_info_callback man page @@ -4269,6 +4287,7 @@ static JNINativeMethod sNativeCryptoMethods[] = { NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_cleanup, "(I)V"), NATIVE_METHOD(NativeCrypto, RAND_seed, "([B)V"), NATIVE_METHOD(NativeCrypto, RAND_load_file, "(Ljava/lang/String;J)I"), + NATIVE_METHOD(NativeCrypto, RAND_bytes, "([B)V"), NATIVE_METHOD(NativeCrypto, SSL_CTX_new, "()I"), NATIVE_METHOD(NativeCrypto, SSL_CTX_free, "(I)V"), NATIVE_METHOD(NativeCrypto, SSL_CTX_set_session_id_context, "(I[B)V"), diff --git a/luni/src/test/java/libcore/java/security/SecureRandomTest.java b/luni/src/test/java/libcore/java/security/SecureRandomTest.java new file mode 100644 index 0000000..43d1e55 --- /dev/null +++ b/luni/src/test/java/libcore/java/security/SecureRandomTest.java @@ -0,0 +1,114 @@ +/* + * 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. + */ + +package libcore.java.security; + +import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider; + +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; +import java.util.Arrays; +import java.util.Set; + +import junit.framework.TestCase; + +public class SecureRandomTest extends TestCase { + private static final Class EXPECTED_PROVIDER = OpenSSLProvider.class; + + private static final byte[] STATIC_SEED_BYTES = new byte[] { + 0x0A, (byte) 0xA0, 0x01, 0x10, (byte) 0xFF, (byte) 0xF0, 0x0F + }; + + private static final long STATIC_SEED_LONG = 8506210602917522860L; + + public void test_getInstance() throws Exception { + Provider[] providers = Security.getProviders(); + for (Provider provider : providers) { + Set services = provider.getServices(); + for (Provider.Service service : services) { + String type = service.getType(); + if (!type.equals("SecureRandom")) { + continue; + } + + String algorithm = service.getAlgorithm(); + try { + SecureRandom sr1 = SecureRandom.getInstance(algorithm); + assertEquals(algorithm, sr1.getAlgorithm()); + test_SecureRandom(sr1); + + // SecureRandom.getInstance(String, Provider) + SecureRandom sr2 = SecureRandom.getInstance(algorithm, provider); + assertEquals(algorithm, sr2.getAlgorithm()); + assertEquals(provider, sr2.getProvider()); + test_SecureRandom(sr2); + + // SecureRandom.getInstance(String, String) + SecureRandom sr3 = SecureRandom.getInstance(algorithm, provider.getName()); + assertEquals(algorithm, sr3.getAlgorithm()); + assertEquals(provider, sr3.getProvider()); + test_SecureRandom(sr3); + + System.out.println("SecureRandomTest " + algorithm + " and provider " + + provider.getName()); + } catch (Exception e) { + throw new Exception("Problem testing SecureRandom." + algorithm + + ", provider: " + provider.getName(), e); + } + } + } + } + + private void test_SecureRandom(SecureRandom sr) throws Exception { + byte[] out1 = new byte[20]; + byte[] out2 = new byte[20]; + + sr.nextBytes(out1); + sr.nextBytes(out2); + assertFalse(Arrays.equals(out1, out2)); + + byte[] seed1 = sr.generateSeed(20); + byte[] seed2 = sr.generateSeed(20); + assertFalse(Arrays.equals(seed1, seed2)); + + sr.setSeed(STATIC_SEED_BYTES); + sr.nextBytes(out1); + sr.nextBytes(out2); + assertFalse(Arrays.equals(out1, out2)); + + sr.setSeed(STATIC_SEED_LONG); + sr.nextBytes(out1); + sr.nextBytes(out2); + assertFalse(Arrays.equals(out1, out2)); + } + + public void testGetCommonInstances_Success() throws Exception { + SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); + assertNotNull(sr); + assertEquals(EXPECTED_PROVIDER, sr.getProvider().getClass()) + } + + public void testNewConstructors_Success() throws Exception { + SecureRandom sr1 = new SecureRandom(); + assertEquals(EXPECTED_PROVIDER, sr1.getProvider().getClass()); + test_SecureRandom(sr1); + + SecureRandom sr2 = new SecureRandom(STATIC_SEED_BYTES); + assertEquals(EXPECTED_PROVIDER, sr2.getProvider().getClass()); + test_SecureRandom(sr2); + } +} diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java index cf030c7..aa0ec67 100644 --- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java +++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java @@ -301,40 +301,15 @@ public class SecureRandom2Test extends TestCase { * as it tends to be error prone and open up security holes. * See {@link SecureRandom} for more details about insecure seeding. * - * @see #testSameSeedGeneratesSameResultsWhenConstructorIsUsed() + * Note that this only works with the Harmony "Crypto" provider. */ public void testSameSeedGeneratesSameResults() throws Exception { byte[] seed1 = { 'a', 'b', 'c' }; - SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG"); + SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr1.setSeed(seed1); byte[] seed2 = { 'a', 'b', 'c' }; - SecureRandom sr2 = SecureRandom.getInstance("SHA1PRNG"); - sr2.setSeed(seed2); - - assertTrue(sr1.nextLong() == sr2.nextLong()); - } - - /** - * Same tests as {@link #testSameSeedGeneratesSameResults()}, except - * here we use the constructor, not {@link SecureRandom#getInstance(String)}. - * - * Note that Android behaves differently than the reference implementation. - * This test fails on the reference implementation. - * - * In the future, it may make sense to change our implementation to - * match the reference implementation. It may also make sense to - * disallow seeding {@code SecureRandom} completely, as it tends to - * be error prone and open up security holes. See {@link SecureRandom} - * for more details about insecure seeding. - */ - public void testSameSeedGeneratesSameResultsWhenConstructorIsUsed() { - byte[] seed1 = { 'a', 'b', 'c' }; - SecureRandom sr1 = new SecureRandom(); - sr1.setSeed(seed1); - - byte[] seed2 = { 'a', 'b', 'c' }; - SecureRandom sr2 = new SecureRandom(); + SecureRandom sr2 = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr2.setSeed(seed2); assertTrue(sr1.nextLong() == sr2.nextLong()); @@ -348,10 +323,12 @@ public class SecureRandom2Test extends TestCase { * SHA1PRNG, so users of {@code SecureRandom} should not assume * the same seed will always produce the same value. This test * is not a guarantee of future compatibility. + * + * In fact, this test only works with the Harmony "Crypto" provider. */ public void testAlwaysSameValueWithSameSeed() throws Exception { byte[] seed1 = { 'a', 'b', 'c' }; - SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG"); + SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr1.setSeed(seed1); // This long value has no special meaning and may change in the future. diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java index c8df4ab..51c00fe 100644 --- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java +++ b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java @@ -1771,4 +1771,25 @@ public class NativeCryptoTest extends TestCase { // Success } } + + public void test_RAND_bytes_Success() throws Exception { + byte[] output = new byte[32]; + NativeCrypto.RAND_bytes(output); + + boolean isZero = true; + for (int i = 0; i < output.length; i++) { + isZero &= (output[i] == 0); + } + + assertFalse("Random output was zero. This is a very low probability event " + + "and probably indicates an error.", isZero); + } + + public void test_RAND_bytes_Null_Failure() throws Exception { + byte[] output = null; + try { + NativeCrypto.RAND_bytes(output); + fail("Should be an error on null buffer input"); + } catch (RuntimeException success) { } + } } -- cgit v1.1 From 177714f960fc0c586930e23b4c98341b9b4eef56 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 12 Jun 2012 12:46:47 -0700 Subject: Take the Buffer's position into account when accessing the array External bug: http://code.google.com/p/android/issues/detail?id=32588 Prior to this patch, our APIs would take into account a Buffer's position if it was backed by native memory. The position would not be taken into account for buffers backed by a Dalvik array. Change-Id: Ibf0bfc14055742ec6ca9f40ab7082f8ae9bca7b6 --- luni/src/main/java/java/nio/NIOAccess.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/luni/src/main/java/java/nio/NIOAccess.java b/luni/src/main/java/java/nio/NIOAccess.java index 361a37f..36c41cf 100644 --- a/luni/src/main/java/java/nio/NIOAccess.java +++ b/luni/src/main/java/java/nio/NIOAccess.java @@ -28,7 +28,7 @@ final class NIOAccess { * different than what the Harmony implementation calls a "base * address." * - * @param Buffer b the Buffer to be queried + * @param b the Buffer to be queried * @return the native pointer to the Buffer's data at its current * position, or 0 if there is none */ @@ -44,7 +44,7 @@ final class NIOAccess { * Returns the underlying Java array containing the data of the * given Buffer, or null if the Buffer is not backed by a Java array. * - * @param Buffer b the Buffer to be queried + * @param b the Buffer to be queried * @return the Java array containing the Buffer's data, or null if * there is none */ @@ -55,13 +55,14 @@ final class NIOAccess { /** * Returns the offset in bytes from the start of the underlying * Java array object containing the data of the given Buffer to - * the actual start of the data. This method is only meaningful if - * getBaseArray() returns non-null. + * the actual start of the data. The start of the data takes into + * account the Buffer's current position. This method is only + * meaningful if getBaseArray() returns non-null. * - * @param Buffer b the Buffer to be queried + * @param b the Buffer to be queried * @return the data offset in bytes to the start of this Buffer's data */ static int getBaseArrayOffset(Buffer b) { - return b.hasArray() ? (b.arrayOffset() << b._elementSizeShift) : 0; + return b.hasArray() ? ((b.arrayOffset() + b.position) << b._elementSizeShift) : 0; } } -- cgit v1.1 From 84fb77d814b0ad04d70addb04847797925acf805 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Tue, 12 Jun 2012 17:10:19 -0700 Subject: Fix build Missed commit amend Change-Id: I0b6baffc5c4145a8a54487d9932f4b37127ceebc --- luni/src/test/java/libcore/java/security/SecureRandomTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luni/src/test/java/libcore/java/security/SecureRandomTest.java b/luni/src/test/java/libcore/java/security/SecureRandomTest.java index 43d1e55..8199120 100644 --- a/luni/src/test/java/libcore/java/security/SecureRandomTest.java +++ b/luni/src/test/java/libcore/java/security/SecureRandomTest.java @@ -99,7 +99,7 @@ public class SecureRandomTest extends TestCase { public void testGetCommonInstances_Success() throws Exception { SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); assertNotNull(sr); - assertEquals(EXPECTED_PROVIDER, sr.getProvider().getClass()) + assertEquals(EXPECTED_PROVIDER, sr.getProvider().getClass()); } public void testNewConstructors_Success() throws Exception { -- cgit v1.1 From 32c5676df786e29990b7fff9886b48b11555e004 Mon Sep 17 00:00:00 2001 From: Brian Carlstrom Date: Wed, 13 Jun 2012 09:19:08 -0700 Subject: CA certificate update: T-TeleSec GlobalRoot Class 3 Added SHA1 : 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1 Subject : C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, CN=T-TeleSec GlobalRoot Class 3 Bug: http://code.google.com/p/android/issues/detail?id=33063 Change-Id: I6ab504f4b1a7ef318d02e7c6b8f6ffd77bf69716 --- luni/src/main/files/cacerts/1e1eab7c.0 | 80 ++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 luni/src/main/files/cacerts/1e1eab7c.0 diff --git a/luni/src/main/files/cacerts/1e1eab7c.0 b/luni/src/main/files/cacerts/1e1eab7c.0 new file mode 100644 index 0000000..a7cf5f9 --- /dev/null +++ b/luni/src/main/files/cacerts/1e1eab7c.0 @@ -0,0 +1,80 @@ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, CN=T-TeleSec GlobalRoot Class 3 + Validity + Not Before: Oct 1 10:29:56 2008 GMT + Not After : Oct 1 23:59:59 2033 GMT + Subject: C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, CN=T-TeleSec GlobalRoot Class 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:bd:75:93:f0:62:22:6f:24:ae:e0:7a:76:ac:7d: + bd:d9:24:d5:b8:b7:fc:cd:f0:42:e0:eb:78:88:56: + 5e:9b:9a:54:1d:4d:0c:8a:f6:d3:cf:70:f4:52:b5: + d8:93:04:e3:46:86:71:41:4a:2b:f0:2a:2c:55:03: + d6:48:c3:e0:39:38:ed:f2:5c:3c:3f:44:bc:93:3d: + 61:ab:4e:cd:0d:be:f0:20:27:58:0e:44:7f:04:1a: + 87:a5:d7:96:14:36:90:d0:49:7b:a1:75:fb:1a:6b: + 73:b1:f8:ce:a9:09:2c:f2:53:d5:c3:14:44:b8:86: + a5:f6:8b:2b:39:da:a3:33:54:d9:fa:72:1a:f7:22: + 15:1c:88:91:6b:7f:66:e5:c3:6a:80:b0:24:f3:df: + 86:45:88:fd:19:7f:75:87:1f:1f:b1:1b:0a:73:24: + 5b:b9:65:e0:2c:54:c8:60:d3:66:17:3f:e1:cc:54: + 33:73:91:02:3a:a6:7f:7b:76:39:a2:1f:96:b6:38: + ae:b5:c8:93:74:1d:9e:b9:b4:e5:60:9d:2f:56:d1: + e0:eb:5e:5b:4c:12:70:0c:6c:44:20:ab:11:d8:f4: + 19:f6:d2:9c:52:37:e7:fa:b6:c2:31:3b:4a:d4:14: + 99:ad:c7:1a:f5:5d:5f:fa:07:b8:7c:0d:1f:d6:83: + 1e:b3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + B5:03:F7:76:3B:61:82:6A:12:AA:18:53:EB:03:21:94:BF:FE:CE:CA + Signature Algorithm: sha256WithRSAEncryption + 56:3d:ef:94:d5:bd:da:73:b2:58:be:ae:90:ad:98:27:97:fe: + 01:b1:b0:52:00:b8:4d:e4:1b:21:74:1b:7e:c0:ee:5e:69:2a: + 25:af:5c:d6:1d:da:d2:79:c9:f3:97:29:e0:86:87:de:04:59: + 0f:f1:59:d4:64:85:4b:99:af:25:04:1e:c9:46:a9:97:de:82: + b2:1b:70:9f:9c:f6:af:71:31:dd:7b:05:a5:2c:d3:b9:ca:47: + f6:ca:f2:f6:e7:ad:b9:48:3f:bc:16:b7:c1:6d:f4:ea:09:af: + ec:f3:b5:e7:05:9e:a6:1e:8a:53:51:d6:93:81:cc:74:93:f6: + b9:da:a6:25:05:74:79:5a:7e:40:3e:82:4b:26:11:30:6e:e1: + 3f:41:c7:47:00:35:d5:f5:d3:f7:54:3e:81:3d:da:49:6a:9a: + b3:ef:10:3d:e6:eb:6f:d1:c8:22:47:cb:cc:cf:01:31:92:d9: + 18:e3:22:be:09:1e:1a:3e:5a:b2:e4:6b:0c:54:7a:7d:43:4e: + b8:89:a5:7b:d7:a2:3d:96:86:cc:f2:26:34:2d:6a:92:9d:9a: + 1a:d0:30:e2:5d:4e:04:b0:5f:8b:20:7e:77:c1:3d:95:82:d1: + 46:9a:3b:3c:78:b8:6f:a1:d0:0d:64:a2:78:1e:29:4e:93:c3: + a4:54:14:5b +SHA1 Fingerprint=55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1 -- cgit v1.1 From 68618152969be1144d460add7349f0b89ae8f499 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 22 Jun 2012 18:41:27 -0700 Subject: Bring Random.nextGaussian in line with the specification. Bug: 6126164 Change-Id: I36d5ccc776b15f7f4085da23c189f91507d57224 --- luni/src/main/java/java/util/Random.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/luni/src/main/java/java/util/Random.java b/luni/src/main/java/java/util/Random.java index 7ce74cc..cc9de58 100644 --- a/luni/src/main/java/java/util/Random.java +++ b/luni/src/main/java/java/util/Random.java @@ -140,25 +140,21 @@ public class Random implements Serializable { * section 3.4.1, subsection C, algorithm P. */ public synchronized double nextGaussian() { - if (haveNextNextGaussian) { // if X1 has been returned, return the - // second Gaussian + if (haveNextNextGaussian) { haveNextNextGaussian = false; return nextNextGaussian; } double v1, v2, s; do { - v1 = 2 * nextDouble() - 1; // Generates two independent random - // variables U1, U2 + v1 = 2 * nextDouble() - 1; v2 = 2 * nextDouble() - 1; s = v1 * v1 + v2 * v2; - } while (s >= 1); - double norm = Math.sqrt(-2 * Math.log(s) / s); - nextNextGaussian = v2 * norm; // should that not be norm instead - // of multiplier ? + } while (s >= 1 || s == 0); + double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s); + nextNextGaussian = v2 * multiplier; haveNextNextGaussian = true; - return v1 * norm; // should that not be norm instead of multiplier - // ? + return v1 * multiplier; } /** -- cgit v1.1 From 91348f798cddae22b59ee1a17bd24315c0897f6f Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 22 Jun 2012 17:47:28 -0700 Subject: Be more careful when parsing custom zone ids. The old code was allowing invalid ids. Bug: 6556561 Change-Id: I691d33fa133527a76bbffa4e3b56a023c389ca8f --- luni/src/main/java/java/util/TimeZone.java | 99 +++++++--------------- .../test/java/libcore/java/util/TimeZoneTest.java | 33 +++++++- 2 files changed, 63 insertions(+), 69 deletions(-) diff --git a/luni/src/main/java/java/util/TimeZone.java b/luni/src/main/java/java/util/TimeZone.java index 0abb609..e7253f7 100644 --- a/luni/src/main/java/java/util/TimeZone.java +++ b/luni/src/main/java/java/util/TimeZone.java @@ -18,6 +18,8 @@ package java.util; import java.io.Serializable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import libcore.icu.TimeZones; import libcore.util.ZoneInfoDB; @@ -28,7 +30,7 @@ import libcore.util.ZoneInfoDB; *

Most applications will use {@link #getDefault} which returns a {@code TimeZone} based on * the time zone where the program is running. * - *

You can also get a specific {@code TimeZone} {@link #getTimeZone by id}. + *

You can also get a specific {@code TimeZone} {@link #getTimeZone by Olson ID}. * *

It is highly unlikely you'll ever want to use anything but the factory methods yourself. * Let classes like {@link Calendar} and {@link java.text.SimpleDateFormat} do the date @@ -64,6 +66,8 @@ import libcore.util.ZoneInfoDB; public abstract class TimeZone implements Serializable, Cloneable { private static final long serialVersionUID = 3581463369166924961L; + private static final Pattern CUSTOM_ZONE_ID_PATTERN = Pattern.compile("^GMT[-+](\\d{1,2})(:?(\\d\\d))?$"); + /** * The short display name style, such as {@code PDT}. Requests for this * style may yield GMT offsets like {@code GMT-08:00}. @@ -265,17 +269,18 @@ public abstract class TimeZone implements Serializable, Cloneable { public abstract int getRawOffset(); /** - * Returns a {@code TimeZone} suitable for {@code id}, or {@code GMT} on failure. + * Returns a {@code TimeZone} corresponding to the given {@code id}, or {@code GMT} on failure. * - *

An id can be an Olson name of the form Area/Location, such + *

An ID can be an Olson name of the form Area/Location, such * as {@code America/Los_Angeles}. The {@link #getAvailableIDs} method returns * the supported names. * - *

This method can also create a custom {@code TimeZone} using the following - * syntax: {@code GMT[+|-]hh[[:]mm]}. For example, {@code TimeZone.getTimeZone("GMT+14:00")} - * would return an object with a raw offset of +14 hours from UTC, and which does not - * use daylight savings. These are rarely useful, because they don't correspond to time - * zones actually in use. + *

This method can also create a custom {@code TimeZone} given an ID with the following + * syntax: {@code GMT[+|-]hh[[:]mm]}. For example, {@code "GMT+05:00"}, {@code "GMT+0500"}, + * {@code "GMT+5:00"}, {@code "GMT+500"}, {@code "GMT+05"}, and {@code "GMT+5"} all return + * an object with a raw offset of +5 hours from UTC, and which does not use daylight + * savings. These are rarely useful, because they don't correspond to time zones actually + * in use by humans. * *

Other than the special cases "UTC" and "GMT" (which are synonymous in this context, * both corresponding to UTC), Android does not support the deprecated three-letter time @@ -296,66 +301,37 @@ public abstract class TimeZone implements Serializable, Cloneable { } /** - * Returns a new SimpleTimeZone for an id of the form "GMT[+|-]hh[[:]mm]", or null. + * Returns a new SimpleTimeZone for an ID of the form "GMT[+|-]hh[[:]mm]", or null. */ private static TimeZone getCustomTimeZone(String id) { - char sign = id.charAt(3); - if (sign != '+' && sign != '-') { - return null; - } - int[] position = new int[1]; - String formattedName = formatTimeZoneName(id, 4); - int hour = parseNumber(formattedName, 4, position); - if (hour < 0 || hour > 23) { - return null; - } - int index = position[0]; - if (index == -1) { + Matcher m = CUSTOM_ZONE_ID_PATTERN.matcher(id); + if (!m.matches()) { return null; } - int raw = hour * 3600000; - if (index < formattedName.length() && formattedName.charAt(index) == ':') { - int minute = parseNumber(formattedName, index + 1, position); - if (position[0] == -1 || minute < 0 || minute > 59) { - return null; - } - raw += minute * 60000; - } else if (hour >= 30 || index > 6) { - raw = (hour / 100 * 3600000) + (hour % 100 * 60000); - } - if (sign == '-') { - raw = -raw; - } - return new SimpleTimeZone(raw, formattedName); - } - private static String formatTimeZoneName(String name, int offset) { - StringBuilder buf = new StringBuilder(); - int index = offset, length = name.length(); - buf.append(name.substring(0, offset)); - - while (index < length) { - if (Character.digit(name.charAt(index), 10) != -1) { - buf.append(name.charAt(index)); - if ((length - (index + 1)) == 2) { - buf.append(':'); - } - } else if (name.charAt(index) == ':') { - buf.append(':'); + int hour; + int minute = 0; + try { + hour = Integer.parseInt(m.group(1)); + if (m.group(3) != null) { + minute = Integer.parseInt(m.group(3)); } - index++; + } catch (NumberFormatException impossible) { + throw new AssertionError(impossible); } - if (buf.toString().indexOf(":") == -1) { - buf.append(':'); - buf.append("00"); + if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { + return null; } - if (buf.toString().indexOf(":") == 5) { - buf.insert(4, '0'); + char sign = id.charAt(3); + int raw = (hour * 3600000) + (minute * 60000); + if (sign == '-') { + raw = -raw; } - return buf.toString(); + String cleanId = String.format("GMT%c%02d:%02d", sign, hour, minute); + return new SimpleTimeZone(raw, cleanId); } /** @@ -377,17 +353,6 @@ public abstract class TimeZone implements Serializable, Cloneable { */ public abstract boolean inDaylightTime(Date time); - private static int parseNumber(String string, int offset, int[] position) { - int index = offset, length = string.length(), digit, result = 0; - while (index < length - && (digit = Character.digit(string.charAt(index), 10)) != -1) { - index++; - result = result * 10 + digit; - } - position[0] = index == offset ? -1 : index; - return result; - } - /** * Overrides the default time zone for the current process only. * diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java index 39ac19d..9708c2a 100644 --- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java +++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java @@ -144,8 +144,37 @@ public class TimeZoneTest extends junit.framework.TestCase { // http://code.google.com/p/android/issues/detail?id=11918 public void testHasSameRules() throws Exception { - TimeZone denver = TimeZone.getTimeZone ("America/Denver") ; - TimeZone phoenix = TimeZone.getTimeZone ("America/Phoenix") ; + TimeZone denver = TimeZone.getTimeZone("America/Denver"); + TimeZone phoenix = TimeZone.getTimeZone("America/Phoenix"); assertFalse(denver.hasSameRules(phoenix)); } + + // http://b.corp.google.com/issue?id=6556561 + public void testCustomZoneIds() throws Exception { + // These are all okay (and equivalent). + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+05:00").getID()); + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+5:00").getID()); + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+0500").getID()); + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+500").getID()); + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+5").getID()); + // These aren't. + assertEquals("GMT", TimeZone.getTimeZone("GMT+5.5").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:5").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:0").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:005").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:000").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+005:00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+05:99").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+28:00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+05:00.00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+05:00:00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:00junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("junkGMT+5:00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("gmt+5:00").getID()); + } } -- cgit v1.1 From 953dfe37db00b2610807c3f895c72183c7ce5b14 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 29 Jun 2012 15:31:18 -0700 Subject: Clarify the documentation of the Pattern character classes. Android (via icu4c) supports the full Unicode TR-18 definitions rather than the traditional ASCII-only ones. Document this fact. Bug: http://code.google.com/p/android/issues/detail?id=21176 Change-Id: If9b94d4e7769ec1ef7c443a7db47bc7586f49b44 --- luni/src/main/java/java/util/regex/Pattern.java | 21 ++++++++++++++------- .../libcore/java/util/regex/OldMatcherTest.java | 10 ++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/luni/src/main/java/java/util/regex/Pattern.java b/luni/src/main/java/java/util/regex/Pattern.java index 46984b9..cbd5965 100644 --- a/luni/src/main/java/java/util/regex/Pattern.java +++ b/luni/src/main/java/java/util/regex/Pattern.java @@ -82,16 +82,23 @@ import java.io.Serializable; * *

Most of the time, the built-in character classes are more useful: * - * - * - * - * - * - * + * + * + * + * + * + * * * *
\d Any digit character.
\D Any non-digit character.
\s Any whitespace character.
\S Any non-whitespace character.
\w Any word character.
\W Any non-word character.
\d Any digit character (see note below).
\D Any non-digit character (see note below).
\s Any whitespace character (see note below).
\S Any non-whitespace character (see note below).
\w Any word character (see note below).
\W Any non-word character (see note below).
\p{NAME} Any character in the class with the given NAME.
\P{NAME} Any character not in the named class.
- *

There are a variety of named classes: + *

Note that these built-in classes don't just cover the traditional ASCII range. For example, + * \w is equivalent to the character class [\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}]. + * For more details see Unicode TR-18, + * and bear in mind that the set of characters in each class can vary between Unicode releases. + * If you actually want to match only ASCII characters, specify the explicit characters you want; + * if you mean 0-9 use [0-9] rather than \d, which would also include + * Gurmukhi digits and so forth. + *

There are also a variety of named classes: *