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