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