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