1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "EphemeralStorage" 18 //#define LOG_NDEBUG 0 19 20 #include <android-base/logging.h> 21 22 #include "EphemeralStorage.h" 23 24 using ::android::hardware::hidl_string; 25 using ::android::hardware::hidl_vec; 26 27 namespace android { 28 29 EphemeralStorage::EphemeralStorage() { 30 } 31 32 EphemeralStorage::~EphemeralStorage() { 33 CHECK(mItems.empty()) 34 << "All item storage should have been released by now."; 35 } 36 37 hidl_string *EphemeralStorage::allocStringArray(size_t size) { 38 Item item; 39 item.mType = TYPE_STRING_ARRAY; 40 item.mObj = NULL; 41 item.mPtr = new hidl_string[size]; 42 mItems.push_back(item); 43 44 return static_cast<hidl_string *>(item.mPtr); 45 } 46 47 void *EphemeralStorage::allocTemporaryStorage(size_t size) { 48 Item item; 49 item.mType = TYPE_STORAGE; 50 item.mObj = NULL; 51 item.mPtr = malloc(size); 52 mItems.push_back(item); 53 54 return item.mPtr; 55 } 56 57 const hidl_string *EphemeralStorage::allocTemporaryString( 58 JNIEnv *env, jstring stringObj) { 59 jstring obj = (jstring)env->NewGlobalRef(stringObj); 60 const char *val = env->GetStringUTFChars(obj, NULL); 61 62 Item item; 63 item.mType = TYPE_STRING; 64 item.mObj = obj; 65 item.mPtr = (void *)val; 66 mItems.push_back(item); 67 68 hidl_string *s = allocStringArray(1 /* size */); 69 s->setToExternal((char *)val, strlen(val)); 70 71 return s; 72 } 73 74 native_handle_t *EphemeralStorage::allocTemporaryNativeHandle( 75 int numFds, int numInts) { 76 Item item; 77 item.mType = TYPE_NATIVE_HANDLE; 78 item.mObj = nullptr; 79 item.mPtr = native_handle_create(numFds, numInts); 80 mItems.push_back(item); 81 82 return static_cast<native_handle_t*>(item.mPtr); 83 } 84 85 #define DEFINE_ALLOC_VECTOR_METHODS(Suffix,Type,NewType) \ 86 const hidl_vec<Type> *EphemeralStorage::allocTemporary ## Suffix ## Vector( \ 87 JNIEnv *env, Type ## Array arrayObj) { \ 88 Type ## Array obj = (Type ## Array)env->NewGlobalRef(arrayObj); \ 89 jsize len = env->GetArrayLength(obj); \ 90 const Type *val = env->Get ## NewType ## ArrayElements(obj, NULL); \ 91 \ 92 Item item; \ 93 item.mType = TYPE_ ## Suffix ## _ARRAY; \ 94 item.mObj = obj; \ 95 item.mPtr = (void *)val; \ 96 mItems.push_back(item); \ 97 \ 98 void *vecPtr = allocTemporaryStorage(sizeof(hidl_vec<Type>)); \ 99 \ 100 hidl_vec<Type> *vec = new (vecPtr) hidl_vec<Type>; \ 101 vec->setToExternal(const_cast<Type *>(val), len); \ 102 \ 103 return vec; \ 104 } 105 106 DEFINE_ALLOC_VECTOR_METHODS(Int8,jbyte,Byte) 107 DEFINE_ALLOC_VECTOR_METHODS(Int16,jshort,Short) 108 DEFINE_ALLOC_VECTOR_METHODS(Int32,jint,Int) 109 DEFINE_ALLOC_VECTOR_METHODS(Int64,jlong,Long) 110 DEFINE_ALLOC_VECTOR_METHODS(Float,jfloat,Float) 111 DEFINE_ALLOC_VECTOR_METHODS(Double,jdouble,Double) 112 113 #define DEFINE_RELEASE_ARRAY_CASE(Suffix,Type,NewType) \ 114 case TYPE_ ## Suffix ## _ARRAY: \ 115 { \ 116 env->Release ## NewType ## ArrayElements( \ 117 (Type ## Array)item.mObj, \ 118 (Type *)item.mPtr, \ 119 0 /* mode */); \ 120 \ 121 env->DeleteGlobalRef(item.mObj); \ 122 break; \ 123 } 124 125 __attribute__((no_sanitize("unsigned-integer-overflow"))) 126 void EphemeralStorage::release(JNIEnv *env) { 127 for (size_t i = mItems.size(); i--;) { 128 const Item &item = mItems[i]; 129 130 switch (item.mType) { 131 case TYPE_STRING_ARRAY: 132 { 133 delete[] static_cast<hidl_string *>(item.mPtr); 134 break; 135 } 136 137 case TYPE_STORAGE: 138 { 139 free(item.mPtr); 140 break; 141 } 142 143 case TYPE_STRING: 144 { 145 env->ReleaseStringUTFChars( 146 (jstring)item.mObj, (const char *)item.mPtr); 147 148 env->DeleteGlobalRef(item.mObj); 149 break; 150 } 151 152 DEFINE_RELEASE_ARRAY_CASE(Int8,jbyte,Byte) 153 DEFINE_RELEASE_ARRAY_CASE(Int16,jshort,Short) 154 DEFINE_RELEASE_ARRAY_CASE(Int32,jint,Int) 155 DEFINE_RELEASE_ARRAY_CASE(Int64,jlong,Long) 156 DEFINE_RELEASE_ARRAY_CASE(Float,jfloat,Float) 157 DEFINE_RELEASE_ARRAY_CASE(Double,jdouble,Double) 158 159 case TYPE_NATIVE_HANDLE: 160 { 161 int err = native_handle_delete(static_cast<native_handle_t *>(item.mPtr)); 162 CHECK(err == 0); 163 break; 164 } 165 166 default: 167 CHECK(!"Should not be here"); 168 } 169 } 170 171 mItems.clear(); 172 } 173 174 } // namespace android 175 176