Merge "Fix max directionality in AndroidCharacter.getDirectionalities"
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 8885aac..9bba13a 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -25,9 +25,10 @@
 #include "unicode/uchar.h"
 
 #define PROPERTY_UNDEFINED (-1)
+#define JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY 18
 
 // ICU => JDK mapping
-static int directionality_map[U_CHAR_DIRECTION_COUNT] = {
+static int directionality_map[JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY + 1] = {
     0, // U_LEFT_TO_RIGHT (0) => DIRECTIONALITY_LEFT_TO_RIGHT (0)
     1, // U_RIGHT_TO_LEFT (1) => DIRECTIONALITY_RIGHT_TO_LEFT (1)
     3, // U_EUROPEAN_NUMBER (2) => DIRECTIONALITY_EUROPEAN_NUMBER (3)
@@ -75,7 +76,7 @@
             int c = 0x00010000 + ((src[i] - 0xD800) << 10) +
                                  (src[i + 1] & 0x3FF);
             int dir = u_charDirection(c);
-            if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT)
+            if (dir < 0 || dir > JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY)
                 dir = PROPERTY_UNDEFINED;
             else
                 dir = directionality_map[dir];
@@ -85,7 +86,7 @@
         } else {
             int c = src[i];
             int dir = u_charDirection(c);
-            if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT)
+            if (dir < 0 || dir > JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY)
                 dest[i] = PROPERTY_UNDEFINED;
             else
                 dest[i] = directionality_map[dir];
@@ -96,7 +97,7 @@
 static jint getEastAsianWidth(JNIEnv* env, jobject obj, jchar input)
 {
     int width = u_getIntPropertyValue(input, UCHAR_EAST_ASIAN_WIDTH);
-    if (width < 0 || width >= U_EA_COUNT)
+    if (width < 0 || width > u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH))
         width = PROPERTY_UNDEFINED;
 
     return width;
@@ -121,6 +122,7 @@
         return;
     }
 
+    int maxWidth = u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH);
     for (int i = 0; i < count; i++) {
         const int srci = start + i;
         if (src[srci] >= 0xD800 && src[srci] <= 0xDBFF &&
@@ -129,7 +131,7 @@
             int c = 0x00010000 + ((src[srci] - 0xD800) << 10) +
                                  (src[srci + 1] & 0x3FF);
             int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH);
-            if (width < 0 || width >= U_EA_COUNT)
+            if (width < 0 || width > maxWidth)
                 width = PROPERTY_UNDEFINED;
 
             dest[i++] = width;
@@ -137,7 +139,7 @@
         } else {
             int c = src[srci];
             int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH);
-            if (width < 0 || width >= U_EA_COUNT)
+            if (width < 0 || width > maxWidth)
                 width = PROPERTY_UNDEFINED;
 
             dest[i] = width;
diff --git a/core/tests/coretests/src/android/text/AndroidCharacterTest.java b/core/tests/coretests/src/android/text/AndroidCharacterTest.java
new file mode 100644
index 0000000..d976adb
--- /dev/null
+++ b/core/tests/coretests/src/android/text/AndroidCharacterTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 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,d
+ * 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.text;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@Presubmit
+@SmallTest
+public class AndroidCharacterTest {
+
+    @Test
+    public void testGetDirectionalities_nonSupplementaryCharacters() {
+        int size = Character.MAX_VALUE + 1
+                - (Character.MAX_SURROGATE - Character.MIN_SURROGATE + 1);
+        char[] chars = new char[size];
+        byte[] java_lang_results = new byte[size];
+        int index = 0;
+        for (int cp = 0; cp <= Character.MAX_VALUE; cp++) {
+            // Exempt unassigned code point due to b/120074586
+            if (Character.getType(cp) != Character.UNASSIGNED) {
+                if (cp < Character.MIN_SURROGATE || cp > Character.MAX_SURROGATE) {
+                    chars[index] = (char) cp;
+                    java_lang_results[index] = Character.getDirectionality(cp);
+                    index++;
+                }
+            }
+        }
+
+        byte[] android_text_results = new byte[size];
+        AndroidCharacter.getDirectionalities(chars, android_text_results, index);
+        assertArrayEquals(java_lang_results, android_text_results);
+    }
+
+    @Test
+    public void testGetDirectionalities_supplementaryCharacters() {
+        int maxNumberOfChars = Character.MAX_CODE_POINT - Character.MIN_SUPPLEMENTARY_CODE_POINT
+                + 1;
+        int size = maxNumberOfChars * 2;
+        char[] chars = new char[size];
+        byte[] java_lang_results = new byte[size];
+        int index = 0;
+        for (int cp = Character.MIN_SUPPLEMENTARY_CODE_POINT; cp <= Character.MAX_CODE_POINT;
+                cp++) {
+            // Exempt unassigned code point due to b/120074586
+            if (Character.getType(cp) != Character.UNASSIGNED) {
+                chars[index] = Character.highSurrogate(cp);
+                chars[index + 1] = Character.lowSurrogate(cp);
+                java_lang_results[index] = java_lang_results[index + 1] = Character
+                        .getDirectionality(cp);
+                index += 2;
+            }
+        }
+
+        byte[] android_text_results = new byte[size];
+        AndroidCharacter.getDirectionalities(chars, android_text_results, index);
+        assertArrayEquals(java_lang_results, android_text_results);
+    }
+}