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