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