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_NDEBUG 0 18 #define LOG_TAG "android_os_HwBinder" 19 #include <android-base/logging.h> 20 21 #include "android_os_HwBinder.h" 22 23 #include "android_os_HwParcel.h" 24 #include "android_os_HwRemoteBinder.h" 25 26 #include <cstring> 27 28 #include <nativehelper/JNIHelp.h> 29 #include <android/hidl/manager/1.0/IServiceManager.h> 30 #include <android/hidl/base/1.0/IBase.h> 31 #include <android/hidl/base/1.0/BpHwBase.h> 32 #include <android_runtime/AndroidRuntime.h> 33 #include <hidl/ServiceManagement.h> 34 #include <hidl/Status.h> 35 #include <hidl/HidlTransportSupport.h> 36 #include <hwbinder/ProcessState.h> 37 #include <nativehelper/ScopedLocalRef.h> 38 #include <nativehelper/ScopedUtfChars.h> 39 #include <vintf/parse_string.h> 40 #include <utils/misc.h> 41 42 #include "core_jni_helpers.h" 43 44 using android::AndroidRuntime; 45 using android::hardware::hidl_vec; 46 using android::hardware::hidl_string; 47 using android::hardware::IPCThreadState; 48 using android::hardware::ProcessState; 49 template<typename T> 50 using Return = android::hardware::Return<T>; 51 52 #define PACKAGE_PATH "android/os" 53 #define CLASS_NAME "HwBinder" 54 #define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME 55 56 namespace android { 57 58 static jclass gErrorClass; 59 60 static struct fields_t { 61 jfieldID contextID; 62 jmethodID onTransactID; 63 } gFields; 64 65 struct JHwBinderHolder : public RefBase { 66 JHwBinderHolder() {} 67 68 sp<JHwBinder> get(JNIEnv *env, jobject obj) { 69 Mutex::Autolock autoLock(mLock); 70 71 sp<JHwBinder> binder = mBinder.promote(); 72 73 if (binder == NULL) { 74 binder = new JHwBinder(env, obj); 75 mBinder = binder; 76 } 77 78 return binder; 79 } 80 81 private: 82 Mutex mLock; 83 wp<JHwBinder> mBinder; 84 85 DISALLOW_COPY_AND_ASSIGN(JHwBinderHolder); 86 }; 87 88 // static 89 void JHwBinder::InitClass(JNIEnv *env) { 90 ScopedLocalRef<jclass> clazz( 91 env, FindClassOrDie(env, CLASS_PATH)); 92 93 gFields.contextID = 94 GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J"); 95 96 gFields.onTransactID = 97 GetMethodIDOrDie( 98 env, 99 clazz.get(), 100 "onTransact", 101 "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V"); 102 } 103 104 // static 105 sp<JHwBinderHolder> JHwBinder::SetNativeContext( 106 JNIEnv *env, jobject thiz, const sp<JHwBinderHolder> &context) { 107 sp<JHwBinderHolder> old = 108 (JHwBinderHolder *)env->GetLongField(thiz, gFields.contextID); 109 110 if (context != NULL) { 111 context->incStrong(NULL /* id */); 112 } 113 114 if (old != NULL) { 115 old->decStrong(NULL /* id */); 116 } 117 118 env->SetLongField(thiz, gFields.contextID, (long)context.get()); 119 120 return old; 121 } 122 123 // static 124 sp<JHwBinder> JHwBinder::GetNativeBinder( 125 JNIEnv *env, jobject thiz) { 126 JHwBinderHolder *holder = 127 reinterpret_cast<JHwBinderHolder *>( 128 env->GetLongField(thiz, gFields.contextID)); 129 130 return holder->get(env, thiz); 131 } 132 133 JHwBinder::JHwBinder(JNIEnv *env, jobject thiz) { 134 jclass clazz = env->GetObjectClass(thiz); 135 CHECK(clazz != NULL); 136 137 mObject = env->NewGlobalRef(thiz); 138 } 139 140 JHwBinder::~JHwBinder() { 141 JNIEnv *env = AndroidRuntime::getJNIEnv(); 142 143 env->DeleteGlobalRef(mObject); 144 mObject = NULL; 145 } 146 147 status_t JHwBinder::onTransact( 148 uint32_t code, 149 const hardware::Parcel &data, 150 hardware::Parcel *reply, 151 uint32_t flags, 152 TransactCallback callback) { 153 JNIEnv *env = AndroidRuntime::getJNIEnv(); 154 bool isOneway = (flags & TF_ONE_WAY) != 0; 155 ScopedLocalRef<jobject> replyObj(env, nullptr); 156 sp<JHwParcel> replyContext = nullptr; 157 158 ScopedLocalRef<jobject> requestObj(env, JHwParcel::NewObject(env)); 159 JHwParcel::GetNativeContext(env, requestObj.get())->setParcel( 160 const_cast<hardware::Parcel *>(&data), false /* assumeOwnership */); 161 162 163 if (!isOneway) { 164 replyObj.reset(JHwParcel::NewObject(env)); 165 166 replyContext = JHwParcel::GetNativeContext(env, replyObj.get()); 167 168 replyContext->setParcel(reply, false /* assumeOwnership */); 169 replyContext->setTransactCallback(callback); 170 } 171 172 env->CallVoidMethod( 173 mObject, 174 gFields.onTransactID, 175 code, 176 requestObj.get(), 177 replyObj.get(), 178 flags); 179 180 if (env->ExceptionCheck()) { 181 jthrowable excep = env->ExceptionOccurred(); 182 env->ExceptionDescribe(); 183 env->ExceptionClear(); 184 185 // It is illegal to call IsInstanceOf if there is a pending exception. 186 // Attempting to do so results in a JniAbort which crashes the entire process. 187 if (env->IsInstanceOf(excep, gErrorClass)) { 188 /* It's an error */ 189 LOG(ERROR) << "Forcefully exiting"; 190 exit(1); 191 } else { 192 LOG(ERROR) << "Uncaught exception!"; 193 } 194 195 env->DeleteLocalRef(excep); 196 } 197 198 status_t err = OK; 199 200 if (!isOneway) { 201 if (!replyContext->wasSent()) { 202 // The implementation never finished the transaction. 203 err = UNKNOWN_ERROR; // XXX special error code instead? 204 205 reply->setDataPosition(0 /* pos */); 206 } 207 208 // Release all temporary storage now that scatter-gather data 209 // has been consolidated, either by calling the TransactCallback, 210 // if wasSent() == true or clearing the reply parcel (setDataOffset above). 211 replyContext->getStorage()->release(env); 212 213 // We cannot permanently pass ownership of "data" and "reply" over to their 214 // Java object wrappers (we don't own them ourselves). 215 replyContext->setParcel( 216 NULL /* parcel */, false /* assumeOwnership */); 217 218 } 219 220 JHwParcel::GetNativeContext(env, requestObj.get())->setParcel( 221 NULL /* parcel */, false /* assumeOwnership */); 222 223 return err; 224 } 225 226 } // namespace android 227 228 //////////////////////////////////////////////////////////////////////////////// 229 230 using namespace android; 231 232 static void releaseNativeContext(void *nativeContext) { 233 sp<JHwBinderHolder> context = static_cast<JHwBinderHolder *>(nativeContext); 234 235 if (context != NULL) { 236 context->decStrong(NULL /* id */); 237 } 238 } 239 240 static jlong JHwBinder_native_init(JNIEnv *env) { 241 JHwBinder::InitClass(env); 242 243 return reinterpret_cast<jlong>(&releaseNativeContext); 244 } 245 246 static void JHwBinder_native_setup(JNIEnv *env, jobject thiz) { 247 sp<JHwBinderHolder> context = new JHwBinderHolder; 248 JHwBinder::SetNativeContext(env, thiz, context); 249 } 250 251 static void JHwBinder_native_transact( 252 JNIEnv * /* env */, 253 jobject /* thiz */, 254 jint /* code */, 255 jobject /* requestObj */, 256 jobject /* replyObj */, 257 jint /* flags */) { 258 CHECK(!"Should not be here"); 259 } 260 261 static void JHwBinder_native_registerService( 262 JNIEnv *env, 263 jobject thiz, 264 jstring serviceNameObj) { 265 ScopedUtfChars str(env, serviceNameObj); 266 if (str.c_str() == nullptr) { 267 return; // NPE will be pending. 268 } 269 270 sp<hardware::IBinder> binder = JHwBinder::GetNativeBinder(env, thiz); 271 272 /* TODO(b/33440494) this is not right */ 273 sp<hidl::base::V1_0::IBase> base = new hidl::base::V1_0::BpHwBase(binder); 274 275 auto manager = hardware::defaultServiceManager(); 276 277 if (manager == nullptr) { 278 LOG(ERROR) << "Could not get hwservicemanager."; 279 signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */); 280 return; 281 } 282 283 Return<bool> ret = manager->add(str.c_str(), base); 284 285 bool ok = ret.isOk() && ret; 286 287 if (ok) { 288 LOG(INFO) << "HwBinder: Starting thread pool for " << str.c_str(); 289 ::android::hardware::ProcessState::self()->startThreadPool(); 290 } 291 292 signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR), true /* canThrowRemoteException */); 293 } 294 295 static jobject JHwBinder_native_getService( 296 JNIEnv *env, 297 jclass /* clazzObj */, 298 jstring ifaceNameObj, 299 jstring serviceNameObj, 300 jboolean retry) { 301 302 using ::android::hidl::base::V1_0::IBase; 303 using ::android::hardware::details::getRawServiceInternal; 304 305 std::string ifaceName; 306 { 307 ScopedUtfChars str(env, ifaceNameObj); 308 if (str.c_str() == nullptr) { 309 return nullptr; // NPE will be pending. 310 } 311 ifaceName = str.c_str(); 312 } 313 314 std::string serviceName; 315 { 316 ScopedUtfChars str(env, serviceNameObj); 317 if (str.c_str() == nullptr) { 318 return nullptr; // NPE will be pending. 319 } 320 serviceName = str.c_str(); 321 } 322 323 sp<IBase> ret = getRawServiceInternal(ifaceName, serviceName, retry /* retry */, false /* getStub */); 324 sp<hardware::IBinder> service = hardware::toBinder<hidl::base::V1_0::IBase>(ret); 325 326 if (service == NULL) { 327 signalExceptionForError(env, NAME_NOT_FOUND); 328 return NULL; 329 } 330 331 LOG(INFO) << "HwBinder: Starting thread pool for " << serviceName << "::" << ifaceName; 332 ::android::hardware::ProcessState::self()->startThreadPool(); 333 334 return JHwRemoteBinder::NewObject(env, service); 335 } 336 337 void JHwBinder_native_configureRpcThreadpool(JNIEnv *, jclass, 338 jlong maxThreads, jboolean callerWillJoin) { 339 CHECK(maxThreads > 0); 340 ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/); 341 } 342 343 void JHwBinder_native_joinRpcThreadpool() { 344 IPCThreadState::self()->joinThreadPool(); 345 } 346 347 static void JHwBinder_report_sysprop_change(JNIEnv * /*env*/, jclass /*clazz*/) 348 { 349 report_sysprop_change(); 350 } 351 352 static JNINativeMethod gMethods[] = { 353 { "native_init", "()J", (void *)JHwBinder_native_init }, 354 { "native_setup", "()V", (void *)JHwBinder_native_setup }, 355 356 { "transact", 357 "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V", 358 (void *)JHwBinder_native_transact }, 359 360 { "registerService", "(Ljava/lang/String;)V", 361 (void *)JHwBinder_native_registerService }, 362 363 { "getService", "(Ljava/lang/String;Ljava/lang/String;Z)L" PACKAGE_PATH "/IHwBinder;", 364 (void *)JHwBinder_native_getService }, 365 366 { "configureRpcThreadpool", "(JZ)V", 367 (void *)JHwBinder_native_configureRpcThreadpool }, 368 369 { "joinRpcThreadpool", "()V", 370 (void *)JHwBinder_native_joinRpcThreadpool }, 371 372 { "native_report_sysprop_change", "()V", 373 (void *)JHwBinder_report_sysprop_change }, 374 }; 375 376 namespace android { 377 378 int register_android_os_HwBinder(JNIEnv *env) { 379 jclass errorClass = FindClassOrDie(env, "java/lang/Error"); 380 gErrorClass = MakeGlobalRefOrDie(env, errorClass); 381 382 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods)); 383 } 384 385 } // namespace android 386