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