diff options
| -rw-r--r-- | core/java/android/content/pm/PackageParserCacheHelper.java | 22 | ||||
| -rw-r--r-- | core/java/android/os/Parcel.java | 75 | ||||
| -rw-r--r-- | core/jni/android_os_Parcel.cpp | 47 | ||||
| -rw-r--r-- | core/tests/benchmarks/src/android/os/ParcelStringBenchmark.java | 72 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/os/ParcelTest.java | 23 |
5 files changed, 221 insertions, 18 deletions
diff --git a/core/java/android/content/pm/PackageParserCacheHelper.java b/core/java/android/content/pm/PackageParserCacheHelper.java index 44def3321c34..8212224e114c 100644 --- a/core/java/android/content/pm/PackageParserCacheHelper.java +++ b/core/java/android/content/pm/PackageParserCacheHelper.java @@ -78,10 +78,19 @@ public class PackageParserCacheHelper { /** * Read an string index from a parcel, and returns the corresponding string from the pool. */ - @Override public String readString(Parcel p) { return mStrings.get(p.readInt()); } + + @Override + public String readString8(Parcel p) { + return readString(p); + } + + @Override + public String readString16(Parcel p) { + return readString(p); + } } /** @@ -110,7 +119,6 @@ public class PackageParserCacheHelper { * Instead of writing a string directly to a parcel, this method adds it to the pool, * and write the index in the pool to the parcel. */ - @Override public void writeString(Parcel p, String s) { final Integer cur = mIndexes.get(s); if (cur != null) { @@ -133,6 +141,16 @@ public class PackageParserCacheHelper { } } + @Override + public void writeString8(Parcel p, String s) { + writeString(p, s); + } + + @Override + public void writeString16(Parcel p, String s) { + writeString(p, s); + } + /** * Closes a parcel by appending the string pool at the end and updating the pool offset, * which it assumes is at the first byte. It also uninstalls itself as a read-write helper. diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index f0b7b5fa5a1a..93f6607ff9d4 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -307,7 +307,9 @@ public final class Parcel { @FastNative private static native void nativeWriteDouble(long nativePtr, double val); @FastNative - static native void nativeWriteString(long nativePtr, String val); + private static native void nativeWriteString8(long nativePtr, String val); + @FastNative + private static native void nativeWriteString16(long nativePtr, String val); @FastNative private static native void nativeWriteStrongBinder(long nativePtr, IBinder val); @FastNative @@ -325,7 +327,9 @@ public final class Parcel { @CriticalNative private static native double nativeReadDouble(long nativePtr); @FastNative - static native String nativeReadString(long nativePtr); + private static native String nativeReadString8(long nativePtr); + @FastNative + private static native String nativeReadString16(long nativePtr); @FastNative private static native IBinder nativeReadStrongBinder(long nativePtr); @FastNative @@ -386,8 +390,12 @@ public final class Parcel { * must use {@link #writeStringNoHelper(String)} to avoid * infinity recursive calls. */ - public void writeString(Parcel p, String s) { - nativeWriteString(p.mNativePtr, s); + public void writeString8(Parcel p, String s) { + p.writeString8NoHelper(s); + } + + public void writeString16(Parcel p, String s) { + p.writeString16NoHelper(s); } /** @@ -395,8 +403,12 @@ public final class Parcel { * must use {@link #readStringNoHelper()} to avoid * infinity recursive calls. */ - public String readString(Parcel p) { - return nativeReadString(p.mNativePtr); + public String readString8(Parcel p) { + return p.readString8NoHelper(); + } + + public String readString16(Parcel p) { + return p.readString16NoHelper(); } } @@ -759,7 +771,17 @@ public final class Parcel { * growing dataCapacity() if needed. */ public final void writeString(@Nullable String val) { - mReadWriteHelper.writeString(this, val); + writeString16(val); + } + + /** {@hide} */ + public final void writeString8(@Nullable String val) { + mReadWriteHelper.writeString8(this, val); + } + + /** {@hide} */ + public final void writeString16(@Nullable String val) { + mReadWriteHelper.writeString16(this, val); } /** @@ -770,7 +792,17 @@ public final class Parcel { * @hide */ public void writeStringNoHelper(@Nullable String val) { - nativeWriteString(mNativePtr, val); + writeString16NoHelper(val); + } + + /** {@hide} */ + public void writeString8NoHelper(@Nullable String val) { + nativeWriteString8(mNativePtr, val); + } + + /** {@hide} */ + public void writeString16NoHelper(@Nullable String val) { + nativeWriteString16(mNativePtr, val); } /** @@ -2337,7 +2369,17 @@ public final class Parcel { */ @Nullable public final String readString() { - return mReadWriteHelper.readString(this); + return readString16(); + } + + /** {@hide} */ + public final @Nullable String readString8() { + return mReadWriteHelper.readString8(this); + } + + /** {@hide} */ + public final @Nullable String readString16() { + return mReadWriteHelper.readString16(this); } /** @@ -2347,9 +2389,18 @@ public final class Parcel { * * @hide */ - @Nullable - public String readStringNoHelper() { - return nativeReadString(mNativePtr); + public @Nullable String readStringNoHelper() { + return readString16NoHelper(); + } + + /** {@hide} */ + public @Nullable String readString8NoHelper() { + return nativeReadString8(mNativePtr); + } + + /** {@hide} */ + public @Nullable String readString16NoHelper() { + return nativeReadString16(mNativePtr); } /** diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp index 483b455965f7..e7a2fb428b50 100644 --- a/core/jni/android_os_Parcel.cpp +++ b/core/jni/android_os_Parcel.cpp @@ -273,7 +273,28 @@ static void android_os_Parcel_writeDouble(JNIEnv* env, jclass clazz, jlong nativ } } -static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jlong nativePtr, jstring val) +static void android_os_Parcel_writeString8(JNIEnv* env, jclass clazz, jlong nativePtr, jstring val) +{ + Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); + if (parcel != NULL) { + status_t err = NO_MEMORY; + if (val) { + const size_t len = env->GetStringUTFLength(val); + const char* str = env->GetStringUTFChars(val, 0); + if (str) { + err = parcel->writeString8(str, len); + env->ReleaseStringUTFChars(val, str); + } + } else { + err = parcel->writeString8(NULL, 0); + } + if (err != NO_ERROR) { + signalExceptionForError(env, clazz, err); + } + } +} + +static void android_os_Parcel_writeString16(JNIEnv* env, jclass clazz, jlong nativePtr, jstring val) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { @@ -444,7 +465,21 @@ static jdouble android_os_Parcel_readDouble(jlong nativePtr) return 0; } -static jstring android_os_Parcel_readString(JNIEnv* env, jclass clazz, jlong nativePtr) +static jstring android_os_Parcel_readString8(JNIEnv* env, jclass clazz, jlong nativePtr) +{ + Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); + if (parcel != NULL) { + size_t len; + const char* str = parcel->readString8Inplace(&len); + if (str) { + return env->NewStringUTF(str); + } + return NULL; + } + return NULL; +} + +static jstring android_os_Parcel_readString16(JNIEnv* env, jclass clazz, jlong nativePtr) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { @@ -722,7 +757,9 @@ static const JNINativeMethod gParcelMethods[] = { // @FastNative {"nativeWriteDouble", "(JD)V", (void*)android_os_Parcel_writeDouble}, // @FastNative - {"nativeWriteString", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString}, + {"nativeWriteString8", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString8}, + // @FastNative + {"nativeWriteString16", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString16}, // @FastNative {"nativeWriteStrongBinder", "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder}, // @FastNative @@ -740,7 +777,9 @@ static const JNINativeMethod gParcelMethods[] = { // @CriticalNative {"nativeReadDouble", "(J)D", (void*)android_os_Parcel_readDouble}, // @FastNative - {"nativeReadString", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString}, + {"nativeReadString8", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString8}, + // @FastNative + {"nativeReadString16", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString16}, // @FastNative {"nativeReadStrongBinder", "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder}, // @FastNative diff --git a/core/tests/benchmarks/src/android/os/ParcelStringBenchmark.java b/core/tests/benchmarks/src/android/os/ParcelStringBenchmark.java new file mode 100644 index 000000000000..daa90c28e0c4 --- /dev/null +++ b/core/tests/benchmarks/src/android/os/ParcelStringBenchmark.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 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.os; + +import com.google.caliper.AfterExperiment; +import com.google.caliper.BeforeExperiment; +import com.google.caliper.Param; + +public class ParcelStringBenchmark { + + @Param({"com.example.typical_package_name", "從不喜歡孤單一個 - 蘇永康/吳雨霏"}) + String mValue; + + private Parcel mParcel; + + @BeforeExperiment + protected void setUp() { + mParcel = Parcel.obtain(); + } + + @AfterExperiment + protected void tearDown() { + mParcel.recycle(); + mParcel = null; + } + + public void timeWriteString8(int reps) { + for (int i = 0; i < reps; i++) { + mParcel.setDataPosition(0); + mParcel.writeString8(mValue); + } + } + + public void timeReadString8(int reps) { + mParcel.writeString8(mValue); + + for (int i = 0; i < reps; i++) { + mParcel.setDataPosition(0); + mParcel.readString8(); + } + } + + public void timeWriteString16(int reps) { + for (int i = 0; i < reps; i++) { + mParcel.setDataPosition(0); + mParcel.writeString16(mValue); + } + } + + public void timeReadString16(int reps) { + mParcel.writeString16(mValue); + + for (int i = 0; i < reps; i++) { + mParcel.setDataPosition(0); + mParcel.readString16(); + } + } +} diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java index 46873b9eb70b..dcb3e2f23da8 100644 --- a/core/tests/coretests/src/android/os/ParcelTest.java +++ b/core/tests/coretests/src/android/os/ParcelTest.java @@ -87,4 +87,27 @@ public class ParcelTest { p.recycle(); } + + /** + * Verify that writing/reading UTF-8 and UTF-16 strings works well. + */ + @Test + public void testStrings() { + final String[] strings = { + null, "", "abc\0def", "com.example.typical_package_name", + "從不喜歡孤單一個 - 蘇永康/吳雨霏", "example" + }; + + final Parcel p = Parcel.obtain(); + for (String string : strings) { + p.writeString8(string); + p.writeString16(string); + } + + p.setDataPosition(0); + for (String string : strings) { + assertEquals(string, p.readString8()); + assertEquals(string, p.readString16()); + } + } } |