Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9cf73e36 authored by Ling Ma's avatar Ling Ma Committed by Automerger Merge Worker
Browse files

Merge changes from topic "truncate operator name" am: ffa0f982

parents 0aeb6102 ffa0f982
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -350,6 +350,53 @@ public class TextUtils {
        return ret;
    }


    /**
     * Returns the longest prefix of a string for which the UTF-8 encoding fits into the given
     * number of bytes, with the additional guarantee that the string is not truncated in the middle
     * of a valid surrogate pair.
     *
     * <p>Unpaired surrogates are counted as taking 3 bytes of storage. However, a subsequent
     * attempt to actually encode a string containing unpaired surrogates is likely to be rejected
     * by the UTF-8 implementation.
     *
     * (copied from google/thirdparty)
     *
     * @param str a string
     * @param maxbytes the maximum number of UTF-8 encoded bytes
     * @return the beginning of the string, so that it uses at most maxbytes bytes in UTF-8
     * @throws IndexOutOfBoundsException if maxbytes is negative
     *
     * @hide
     */
    public static String truncateStringForUtf8Storage(String str, int maxbytes) {
        if (maxbytes < 0) {
            throw new IndexOutOfBoundsException();
        }

        int bytes = 0;
        for (int i = 0, len = str.length(); i < len; i++) {
            char c = str.charAt(i);
            if (c < 0x80) {
                bytes += 1;
            } else if (c < 0x800) {
                bytes += 2;
            } else if (c < Character.MIN_SURROGATE
                    || c > Character.MAX_SURROGATE
                    || str.codePointAt(i) < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
                bytes += 3;
            } else {
                bytes += 4;
                i += (bytes > maxbytes) ? 0 : 1;
            }
            if (bytes > maxbytes) {
                return str.substring(0, i);
            }
        }
        return str;
    }


    /**
     * Returns a string containing the tokens joined by delimiters.
     *
+76 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.google.android.collect.Lists;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -781,6 +782,81 @@ public class TextUtilsTest {
        TextUtils.trimToSize("abc", 0);
    }

    @Test
    public void truncateStringForUtf8Storage() {
        assertEquals("", TextUtils.truncateStringForUtf8Storage("abc", 0));

        //================ long normal case ================
        StringBuilder builder = new StringBuilder();

        int n = 50;
        for (int i = 0; i < 2 * n; i++) {
            builder.append("哈");
        }
        String initial = builder.toString();
        String result = TextUtils.truncateStringForUtf8Storage(initial, n);

        // Result should be the beginning of initial
        assertTrue(initial.startsWith(result));

        // Result should take less than n bytes in UTF-8
        assertTrue(result.getBytes(StandardCharsets.UTF_8).length <= n);

        // result + the next codePoint should take strictly more than
        // n bytes in UTF-8
        assertTrue(initial.substring(0, initial.offsetByCodePoints(result.length(), 1))
                .getBytes(StandardCharsets.UTF_8).length > n);

        // =================== short normal case =====================
        String s = "sf\u20ACgk\u00E9ls\u00E9fg";
        result = TextUtils.truncateStringForUtf8Storage(s, 100);
        assertEquals(s, result);
    }

    @Test
    public void testTruncateInMiddleOfSurrogate() {
        StringBuilder builder = new StringBuilder();
        String beginning = "a";
        builder.append(beginning);
        builder.append(Character.toChars(0x1D11E));

        String result = TextUtils.truncateStringForUtf8Storage(builder.toString(), 3);

        // \u1D11E is a surrogate and needs 4 bytes in UTF-8. beginning == "a" uses
        // only 1 bytes in UTF8
        // As we allow only 3 bytes for the whole string, so just 2 for this
        // codePoint, there is not enough place and the string will be truncated
        // just before it
        assertEquals(beginning, result);
    }

    @Test
    public void testTruncateInMiddleOfChar() {
        StringBuilder builder = new StringBuilder();
        String beginning = "a";
        builder.append(beginning);
        builder.append(Character.toChars(0x20AC));

        String result = TextUtils.truncateStringForUtf8Storage(builder.toString(), 3);

        // Like above, \u20AC uses 3 bytes in UTF-8, with "beginning", that makes
        // 4 bytes so it is too big and should be truncated
        assertEquals(beginning, result);
    }

    @Test
    public void testTruncateSubString() {
        String test = "sdgkl;hjsl;gjhdgkljdfhglkdj";
        String sub = test.substring(10, 20);
        String res = TextUtils.truncateStringForUtf8Storage(sub, 255);
        assertEquals(sub, res);
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void truncateStringForUtf8StorageThrowsExceptionForNegativeSize() {
        TextUtils.truncateStringForUtf8Storage("abc", -1);
    }

    @Test
    public void length() {
        assertEquals(0, TextUtils.length(null));
+19 −1
Original line number Diff line number Diff line
@@ -11487,7 +11487,25 @@ public class TelephonyManager {
        if (SubscriptionManager.isValidPhoneId(phoneId)) {
            List<String> newList = updateTelephonyProperty(
                    TelephonyProperties.operator_alpha(), phoneId, name);
            try {
                TelephonyProperties.operator_alpha(newList);
            } catch (IllegalArgumentException e) { //property value is longer than the byte limit
                Log.e(TAG, "setNetworkOperatorNameForPhone: ", e);
                int numberOfEntries = newList.size();
                int maxOperatorLength = //save 1 byte for joiner " , "
                        (SystemProperties.PROP_VALUE_MAX - numberOfEntries) / numberOfEntries;
                //examine and truncate every operator and retry
                for (int i = 0; i < newList.size(); i++) {
                    if (newList.get(i) != null) {
                        newList.set(i, TextUtils
                                .truncateStringForUtf8Storage(newList.get(i), maxOperatorLength));
                    }
                }
                TelephonyProperties.operator_alpha(newList);
                Log.e(TAG, "successfully truncated operator_alpha: " + newList);
            }
        }
    }