summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/PackageParserCacheHelper.java22
-rw-r--r--core/java/android/os/Parcel.java75
-rw-r--r--core/jni/android_os_Parcel.cpp47
-rw-r--r--core/tests/benchmarks/src/android/os/ParcelStringBenchmark.java72
-rw-r--r--core/tests/coretests/src/android/os/ParcelTest.java23
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());
+ }
+ }
}