Skip to content

Commit 6b4e4e4

Browse files
Steven MorelandGenkzsz11
authored andcommitted
Binder interface tokens: remove extra mallocs
- writeInterfaceToken/enforceInterfaceToken try to get the interface token with GetStringRegion, so for classes with short enough interface descriptors, the string is allocated on the stack. A size of 64 was chosen since the longest interface descriptor in a frameworks/base AIDL file is ~40 characters. - remove extra creation of String16 for writeInterfaceToken Bug: 169674485 Test: atest aidl_integration_test Change-Id: I78092abaa4df758ab699fcb103aa619b0b426e6c Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
1 parent 9157214 commit 6b4e4e4

1 file changed

Lines changed: 60 additions & 33 deletions

File tree

core/jni/android_os_Parcel.cpp

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -638,50 +638,77 @@ static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
638638
return ret;
639639
}
640640

641+
// String tries to allocate itself on the stack, within a known size, but will
642+
// make a heap allocation if not.
643+
template <size_t StackReserve>
644+
class StackString {
645+
public:
646+
StackString(JNIEnv* env, jstring str) : mEnv(env), mJStr(str) {
647+
LOG_ALWAYS_FATAL_IF(str == nullptr);
648+
mSize = env->GetStringLength(str);
649+
if (mSize > StackReserve) {
650+
mStr = new jchar[mSize];
651+
} else {
652+
mStr = &mBuffer[0];
653+
}
654+
mEnv->GetStringRegion(str, 0, mSize, mStr);
655+
}
656+
~StackString() {
657+
if (mStr != &mBuffer[0]) {
658+
delete[] mStr;
659+
}
660+
}
661+
const jchar* str() { return mStr; }
662+
jsize size() { return mSize; }
663+
664+
private:
665+
JNIEnv* mEnv;
666+
jstring mJStr;
667+
668+
jchar mBuffer[StackReserve];
669+
// pointer to &mBuffer[0] if string fits in mBuffer, otherwise owned
670+
jchar* mStr;
671+
jsize mSize;
672+
};
673+
674+
// This size is chosen to be longer than most interface descriptors.
675+
// Ones longer than this will be allocated on the heap.
676+
typedef StackString<64> InterfaceDescriptorString;
677+
641678
static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
642679
jstring name)
643680
{
644681
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
645-
if (parcel != NULL) {
646-
// In the current implementation, the token is just the serialized interface name that
647-
// the caller expects to be invoking
648-
const jchar* str = env->GetStringCritical(name, 0);
649-
if (str != NULL) {
650-
parcel->writeInterfaceToken(String16(
651-
reinterpret_cast<const char16_t*>(str),
652-
env->GetStringLength(name)));
653-
env->ReleaseStringCritical(name, str);
654-
}
682+
if (parcel != nullptr) {
683+
InterfaceDescriptorString descriptor(env, name);
684+
parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()),
685+
descriptor.size());
655686
}
656687
}
657688

658689
static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
659690
{
660691
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
661-
if (parcel != NULL) {
662-
const jchar* str = env->GetStringCritical(name, 0);
663-
if (str) {
664-
IPCThreadState* threadState = IPCThreadState::self();
665-
const int32_t oldPolicy = threadState->getStrictModePolicy();
666-
const bool isValid = parcel->enforceInterface(
667-
reinterpret_cast<const char16_t*>(str),
668-
env->GetStringLength(name),
669-
threadState);
670-
env->ReleaseStringCritical(name, str);
671-
if (isValid) {
672-
const int32_t newPolicy = threadState->getStrictModePolicy();
673-
if (oldPolicy != newPolicy) {
674-
// Need to keep the Java-level thread-local strict
675-
// mode policy in sync for the libcore
676-
// enforcements, which involves an upcall back
677-
// into Java. (We can't modify the
678-
// Parcel.enforceInterface signature, as it's
679-
// pseudo-public, and used via AIDL
680-
// auto-generation...)
681-
set_dalvik_blockguard_policy(env, newPolicy);
682-
}
683-
return; // everything was correct -> return silently
692+
if (parcel != nullptr) {
693+
InterfaceDescriptorString descriptor(env, name);
694+
IPCThreadState* threadState = IPCThreadState::self();
695+
const int32_t oldPolicy = threadState->getStrictModePolicy();
696+
const bool isValid =
697+
parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()),
698+
descriptor.size(), threadState);
699+
if (isValid) {
700+
const int32_t newPolicy = threadState->getStrictModePolicy();
701+
if (oldPolicy != newPolicy) {
702+
// Need to keep the Java-level thread-local strict
703+
// mode policy in sync for the libcore
704+
// enforcements, which involves an upcall back
705+
// into Java. (We can't modify the
706+
// Parcel.enforceInterface signature, as it's
707+
// pseudo-public, and used via AIDL
708+
// auto-generation...)
709+
set_dalvik_blockguard_policy(env, newPolicy);
684710
}
711+
return; // everything was correct -> return silently
685712
}
686713
}
687714

0 commit comments

Comments
 (0)