Merge "Binder interface tokens: remove extra mallocs" am: 57fd6a5f10

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1444677

Change-Id: I4414f9216588d7e1fb0a6e3c059bcca3a76fc552
This commit is contained in:
Steven Moreland
2020-10-05 19:49:05 +00:00
committed by Automerger Merge Worker

View File

@@ -638,50 +638,77 @@ static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
return ret; return ret;
} }
// String tries to allocate itself on the stack, within a known size, but will
// make a heap allocation if not.
template <size_t StackReserve>
class StackString {
public:
StackString(JNIEnv* env, jstring str) : mEnv(env), mJStr(str) {
LOG_ALWAYS_FATAL_IF(str == nullptr);
mSize = env->GetStringLength(str);
if (mSize > StackReserve) {
mStr = new jchar[mSize];
} else {
mStr = &mBuffer[0];
}
mEnv->GetStringRegion(str, 0, mSize, mStr);
}
~StackString() {
if (mStr != &mBuffer[0]) {
delete[] mStr;
}
}
const jchar* str() { return mStr; }
jsize size() { return mSize; }
private:
JNIEnv* mEnv;
jstring mJStr;
jchar mBuffer[StackReserve];
// pointer to &mBuffer[0] if string fits in mBuffer, otherwise owned
jchar* mStr;
jsize mSize;
};
// This size is chosen to be longer than most interface descriptors.
// Ones longer than this will be allocated on the heap.
typedef StackString<64> InterfaceDescriptorString;
static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr, static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
jstring name) jstring name)
{ {
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) { if (parcel != nullptr) {
// In the current implementation, the token is just the serialized interface name that InterfaceDescriptorString descriptor(env, name);
// the caller expects to be invoking parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()),
const jchar* str = env->GetStringCritical(name, 0); descriptor.size());
if (str != NULL) {
parcel->writeInterfaceToken(String16(
reinterpret_cast<const char16_t*>(str),
env->GetStringLength(name)));
env->ReleaseStringCritical(name, str);
}
} }
} }
static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name) static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
{ {
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) { if (parcel != nullptr) {
const jchar* str = env->GetStringCritical(name, 0); InterfaceDescriptorString descriptor(env, name);
if (str) { IPCThreadState* threadState = IPCThreadState::self();
IPCThreadState* threadState = IPCThreadState::self(); const int32_t oldPolicy = threadState->getStrictModePolicy();
const int32_t oldPolicy = threadState->getStrictModePolicy(); const bool isValid =
const bool isValid = parcel->enforceInterface( parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()),
reinterpret_cast<const char16_t*>(str), descriptor.size(), threadState);
env->GetStringLength(name), if (isValid) {
threadState); const int32_t newPolicy = threadState->getStrictModePolicy();
env->ReleaseStringCritical(name, str); if (oldPolicy != newPolicy) {
if (isValid) { // Need to keep the Java-level thread-local strict
const int32_t newPolicy = threadState->getStrictModePolicy(); // mode policy in sync for the libcore
if (oldPolicy != newPolicy) { // enforcements, which involves an upcall back
// Need to keep the Java-level thread-local strict // into Java. (We can't modify the
// mode policy in sync for the libcore // Parcel.enforceInterface signature, as it's
// enforcements, which involves an upcall back // pseudo-public, and used via AIDL
// into Java. (We can't modify the // auto-generation...)
// Parcel.enforceInterface signature, as it's set_dalvik_blockguard_policy(env, newPolicy);
// pseudo-public, and used via AIDL
// auto-generation...)
set_dalvik_blockguard_policy(env, newPolicy);
}
return; // everything was correct -> return silently
} }
return; // everything was correct -> return silently
} }
} }