• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #undef ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION // TODO:remove this and fix code
17 
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "android_os_HwBinder"
20 #include <android-base/logging.h>
21 
22 #include "android_os_HwBinder.h"
23 
24 #include "android_util_Binder.h" // for binder_report_exception
25 
26 #include "android_os_HwParcel.h"
27 #include "android_os_HwRemoteBinder.h"
28 
29 #include <cstring>
30 
31 #include <nativehelper/JNIHelp.h>
32 #include <android/hidl/manager/1.0/IServiceManager.h>
33 #include <android/hidl/base/1.0/IBase.h>
34 #include <android/hidl/base/1.0/BpHwBase.h>
35 #include <android_runtime/AndroidRuntime.h>
36 #include <hidl/ServiceManagement.h>
37 #include <hidl/Status.h>
38 #include <hidl/HidlTransportSupport.h>
39 #include <hwbinder/IPCThreadState.h>
40 #include <hwbinder/ProcessState.h>
41 #include <nativehelper/ScopedLocalRef.h>
42 #include <nativehelper/ScopedUtfChars.h>
43 #include <utils/misc.h>
44 
45 #include "core_jni_helpers.h"
46 
47 using android::AndroidRuntime;
48 using android::hardware::hidl_vec;
49 using android::hardware::hidl_string;
50 using android::hardware::IPCThreadState;
51 using android::hardware::ProcessState;
52 template<typename T>
53 using Return = android::hardware::Return<T>;
54 
55 #define PACKAGE_PATH    "android/os"
56 #define CLASS_NAME      "HwBinder"
57 #define CLASS_PATH      PACKAGE_PATH "/" CLASS_NAME
58 
59 namespace android {
60 
61 static jclass gErrorClass;
62 
63 static struct fields_t {
64     jfieldID contextID;
65     jmethodID onTransactID;
66 } gFields;
67 
68 struct JHwBinderHolder : public RefBase {
JHwBinderHolderandroid::JHwBinderHolder69     JHwBinderHolder() {}
70 
getandroid::JHwBinderHolder71     sp<JHwBinder> get(JNIEnv *env, jobject obj) {
72         Mutex::Autolock autoLock(mLock);
73 
74         sp<JHwBinder> binder = mBinder.promote();
75 
76         if (binder == NULL) {
77             binder = new JHwBinder(env, obj);
78             mBinder = binder;
79         }
80 
81         return binder;
82     }
83 
84 private:
85     Mutex mLock;
86     wp<JHwBinder> mBinder;
87 
88     DISALLOW_COPY_AND_ASSIGN(JHwBinderHolder);
89 };
90 
91 // static
InitClass(JNIEnv * env)92 void JHwBinder::InitClass(JNIEnv *env) {
93     ScopedLocalRef<jclass> clazz(
94             env, FindClassOrDie(env, CLASS_PATH));
95 
96     gFields.contextID =
97         GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
98 
99     gFields.onTransactID =
100         GetMethodIDOrDie(
101                 env,
102                 clazz.get(),
103                 "onTransact",
104                 "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V");
105 }
106 
107 // static
SetNativeContext(JNIEnv * env,jobject thiz,const sp<JHwBinderHolder> & context)108 sp<JHwBinderHolder> JHwBinder::SetNativeContext(
109         JNIEnv *env, jobject thiz, const sp<JHwBinderHolder> &context) {
110     sp<JHwBinderHolder> old =
111         (JHwBinderHolder *)env->GetLongField(thiz, gFields.contextID);
112 
113     if (context != NULL) {
114         context->incStrong(NULL /* id */);
115     }
116 
117     if (old != NULL) {
118         old->decStrong(NULL /* id */);
119     }
120 
121     env->SetLongField(thiz, gFields.contextID, (long)context.get());
122 
123     return old;
124 }
125 
126 // static
GetNativeBinder(JNIEnv * env,jobject thiz)127 sp<JHwBinder> JHwBinder::GetNativeBinder(
128         JNIEnv *env, jobject thiz) {
129     JHwBinderHolder *holder =
130         reinterpret_cast<JHwBinderHolder *>(
131                 env->GetLongField(thiz, gFields.contextID));
132 
133     return holder->get(env, thiz);
134 }
135 
JHwBinder(JNIEnv * env,jobject thiz)136 JHwBinder::JHwBinder(JNIEnv *env, jobject thiz) {
137     jclass clazz = env->GetObjectClass(thiz);
138     CHECK(clazz != NULL);
139 
140     mObject = env->NewGlobalRef(thiz);
141 }
142 
~JHwBinder()143 JHwBinder::~JHwBinder() {
144     JNIEnv *env = AndroidRuntime::getJNIEnv();
145 
146     env->DeleteGlobalRef(mObject);
147     mObject = NULL;
148 }
149 
onTransact(uint32_t code,const hardware::Parcel & data,hardware::Parcel * reply,uint32_t flags,TransactCallback callback)150 status_t JHwBinder::onTransact(
151         uint32_t code,
152         const hardware::Parcel &data,
153         hardware::Parcel *reply,
154         uint32_t flags,
155         TransactCallback callback) {
156     JNIEnv *env = AndroidRuntime::getJNIEnv();
157     bool isOneway = (flags & IBinder::FLAG_ONEWAY) != 0;
158     ScopedLocalRef<jobject> replyObj(env, nullptr);
159     sp<JHwParcel> replyContext = nullptr;
160 
161     ScopedLocalRef<jobject> requestObj(env, JHwParcel::NewObject(env));
162     JHwParcel::GetNativeContext(env, requestObj.get())->setParcel(
163             const_cast<hardware::Parcel *>(&data), false /* assumeOwnership */);
164 
165 
166     if (!isOneway) {
167         replyObj.reset(JHwParcel::NewObject(env));
168 
169         replyContext = JHwParcel::GetNativeContext(env, replyObj.get());
170 
171         replyContext->setParcel(reply, false /* assumeOwnership */);
172         replyContext->setTransactCallback(callback);
173     }
174 
175     env->CallVoidMethod(
176             mObject,
177             gFields.onTransactID,
178             code,
179             requestObj.get(),
180             replyObj.get(),
181             flags);
182 
183     if (env->ExceptionCheck()) {
184         jthrowable excep = env->ExceptionOccurred();
185         env->ExceptionDescribe();
186         env->ExceptionClear();
187 
188         binder_report_exception(env, excep, "Uncaught error or exception in hwbinder!");
189 
190         env->DeleteLocalRef(excep);
191     }
192 
193     status_t err = OK;
194 
195     if (!isOneway) {
196         if (!replyContext->wasSent()) {
197             // The implementation never finished the transaction.
198             err = UNKNOWN_ERROR;  // XXX special error code instead?
199 
200             reply->setDataPosition(0 /* pos */);
201         }
202 
203         // Release all temporary storage now that scatter-gather data
204         // has been consolidated, either by calling the TransactCallback,
205         // if wasSent() == true or clearing the reply parcel (setDataOffset above).
206         replyContext->getStorage()->release(env);
207 
208         // We cannot permanently pass ownership of "data" and "reply" over to their
209         // Java object wrappers (we don't own them ourselves).
210         replyContext->setParcel(
211                 NULL /* parcel */, false /* assumeOwnership */);
212 
213     }
214 
215     JHwParcel::GetNativeContext(env, requestObj.get())->setParcel(
216             NULL /* parcel */, false /* assumeOwnership */);
217 
218     return err;
219 }
220 
validateCanUseHwBinder(const sp<hardware::IBinder> & binder)221 bool validateCanUseHwBinder(const sp<hardware::IBinder>& binder) {
222     if (binder != nullptr && binder->localBinder() != nullptr) {
223         // untested/unsupported/inefficient
224         // see b/129150021, doesn't work with scatter-gather
225         //
226         // explicitly disabling until it is supported
227         // (note, even if this is fixed to work with scatter gather, we would also need
228         // to convert this to the Java object rather than re-wrapping with a proxy)
229         LOG(ERROR) << "Local Java Binder not supported.";
230         return false;
231     }
232 
233     return true;
234 }
235 
236 }  // namespace android
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 
240 using namespace android;
241 
releaseNativeContext(void * nativeContext)242 static void releaseNativeContext(void *nativeContext) {
243     sp<JHwBinderHolder> context = static_cast<JHwBinderHolder *>(nativeContext);
244 
245     if (context != NULL) {
246         context->decStrong(NULL /* id */);
247     }
248 }
249 
JHwBinder_native_init(JNIEnv * env)250 static jlong JHwBinder_native_init(JNIEnv *env) {
251     JHwBinder::InitClass(env);
252 
253     return reinterpret_cast<jlong>(&releaseNativeContext);
254 }
255 
JHwBinder_native_setup(JNIEnv * env,jobject thiz)256 static void JHwBinder_native_setup(JNIEnv *env, jobject thiz) {
257     sp<JHwBinderHolder> context = new JHwBinderHolder;
258     JHwBinder::SetNativeContext(env, thiz, context);
259 }
260 
JHwBinder_native_transact(JNIEnv * env,jobject thiz,jint code,jobject requestObj,jobject replyObj,jint flags)261 static void JHwBinder_native_transact(JNIEnv *env, jobject thiz, jint code, jobject requestObj,
262                                       jobject replyObj, jint flags) {
263     if (requestObj == NULL) {
264         jniThrowException(env, "java/lang/NullPointerException", NULL);
265         return;
266     }
267     sp<hardware::IBinder> binder = JHwBinder::GetNativeBinder(env, thiz);
268     sp<android::hidl::base::V1_0::IBase> base = new android::hidl::base::V1_0::BpHwBase(binder);
269     hidl_string desc;
270     auto ret = base->interfaceDescriptor(
271             [&desc](const hidl_string &descriptor) { desc = descriptor; });
272     ret.assertOk();
273     // Only the fake hwservicemanager is allowed to be used locally like this.
274     if (desc != "android.hidl.manager@1.2::IServiceManager" &&
275         desc != "android.hidl.manager@1.1::IServiceManager" &&
276         desc != "android.hidl.manager@1.0::IServiceManager") {
277         LOG(FATAL) << "Local binders are not supported!";
278     }
279     if (replyObj == nullptr) {
280         LOG(FATAL) << "Unexpected null replyObj. code: " << code;
281         return;
282     }
283     const hardware::Parcel *request = JHwParcel::GetNativeContext(env, requestObj)->getParcel();
284     sp<JHwParcel> replyContext = JHwParcel::GetNativeContext(env, replyObj);
285     hardware::Parcel *reply = replyContext->getParcel();
286 
287     request->setDataPosition(0);
288 
289     bool isOneway = (flags & IBinder::FLAG_ONEWAY) != 0;
290     if (!isOneway) {
291         replyContext->setTransactCallback([](auto &replyParcel) {});
292     }
293 
294     env->CallVoidMethod(thiz, gFields.onTransactID, code, requestObj, replyObj, flags);
295 
296     if (env->ExceptionCheck()) {
297         jthrowable excep = env->ExceptionOccurred();
298         env->ExceptionDescribe();
299         env->ExceptionClear();
300 
301         binder_report_exception(env, excep, "Uncaught error or exception in hwbinder!");
302 
303         env->DeleteLocalRef(excep);
304     }
305 
306     if (!isOneway) {
307         if (!replyContext->wasSent()) {
308             // The implementation never finished the transaction.
309             LOG(ERROR) << "The reply failed to send!";
310         }
311     }
312 
313     reply->setDataPosition(0);
314 }
315 
JHwBinder_native_registerService(JNIEnv * env,jobject thiz,jstring serviceNameObj)316 static void JHwBinder_native_registerService(
317         JNIEnv *env,
318         jobject thiz,
319         jstring serviceNameObj) {
320     ScopedUtfChars str(env, serviceNameObj);
321     if (str.c_str() == nullptr) {
322         return;  // NPE will be pending.
323     }
324 
325     sp<hardware::IBinder> binder = JHwBinder::GetNativeBinder(env, thiz);
326     sp<hidl::base::V1_0::IBase> base = new hidl::base::V1_0::BpHwBase(binder);
327 
328     bool ok = hardware::details::registerAsServiceInternal(base, str.c_str()) == OK;
329 
330     if (ok) {
331         LOG(INFO) << "HwBinder: Starting thread pool for " << str.c_str();
332         ::android::hardware::ProcessState::self()->startThreadPool();
333     }
334 
335     // avoiding richer error exceptions to stick with legacy behavior
336     signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR), true /*canThrowRemoteException*/);
337 }
338 
JHwBinder_native_getService(JNIEnv * env,jclass,jstring ifaceNameObj,jstring serviceNameObj,jboolean retry)339 static jobject JHwBinder_native_getService(
340         JNIEnv *env,
341         jclass /* clazzObj */,
342         jstring ifaceNameObj,
343         jstring serviceNameObj,
344         jboolean retry) {
345 
346     using ::android::hidl::base::V1_0::IBase;
347     using ::android::hardware::details::getRawServiceInternal;
348 
349     std::string ifaceName;
350     {
351         ScopedUtfChars str(env, ifaceNameObj);
352         if (str.c_str() == nullptr) {
353             return nullptr;  // NPE will be pending.
354         }
355         ifaceName = str.c_str();
356     }
357 
358     std::string serviceName;
359     {
360         ScopedUtfChars str(env, serviceNameObj);
361         if (str.c_str() == nullptr) {
362             return nullptr;  // NPE will be pending.
363         }
364         serviceName = str.c_str();
365     }
366 
367     sp<IBase> ret = getRawServiceInternal(ifaceName, serviceName, retry /* retry */, false /* getStub */);
368     sp<hardware::IBinder> service = hardware::toBinder<hidl::base::V1_0::IBase>(ret);
369 
370     if (service == nullptr || !validateCanUseHwBinder(service)) {
371         signalExceptionForError(env, NAME_NOT_FOUND);
372         return nullptr;
373     }
374 
375     LOG(INFO) << "HwBinder: Starting thread pool for getting: " << ifaceName << "/" << serviceName;
376     ::android::hardware::ProcessState::self()->startThreadPool();
377 
378     return JHwRemoteBinder::NewObject(env, service);
379 }
380 
JHwBinder_native_setTrebleTestingOverride(JNIEnv *,jclass,jboolean testingOverride)381 void JHwBinder_native_setTrebleTestingOverride(JNIEnv*, jclass, jboolean testingOverride) {
382     hardware::details::setTrebleTestingOverride(testingOverride);
383 }
384 
JHwBinder_native_configureRpcThreadpool(JNIEnv *,jclass,jlong maxThreads,jboolean callerWillJoin)385 void JHwBinder_native_configureRpcThreadpool(JNIEnv *, jclass,
386         jlong maxThreads, jboolean callerWillJoin) {
387     CHECK(maxThreads > 0);
388     ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/);
389 }
390 
JHwBinder_native_joinRpcThreadpool()391 void JHwBinder_native_joinRpcThreadpool() {
392     IPCThreadState::self()->joinThreadPool();
393 }
394 
JHwBinder_report_sysprop_change(JNIEnv *,jclass)395 static void JHwBinder_report_sysprop_change(JNIEnv * /*env*/, jclass /*clazz*/)
396 {
397     report_sysprop_change();
398 }
399 
400 static JNINativeMethod gMethods[] = {
native_init()401     { "native_init", "()J", (void *)JHwBinder_native_init },
native_setup()402     { "native_setup", "()V", (void *)JHwBinder_native_setup },
403 
404     { "transact",
405         "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
406         (void *)JHwBinder_native_transact },
407 
registerService(Ljava/lang/String;)408     { "registerService", "(Ljava/lang/String;)V",
409         (void *)JHwBinder_native_registerService },
410 
getService(Ljava/lang/String;Ljava/lang/String;Z)411     { "getService", "(Ljava/lang/String;Ljava/lang/String;Z)L" PACKAGE_PATH "/IHwBinder;",
412         (void *)JHwBinder_native_getService },
413 
setTrebleTestingOverride(Z)414     { "setTrebleTestingOverride", "(Z)V",
415         (void *)JHwBinder_native_setTrebleTestingOverride },
416 
configureRpcThreadpool(JZ)417     { "configureRpcThreadpool", "(JZ)V",
418         (void *)JHwBinder_native_configureRpcThreadpool },
419 
joinRpcThreadpool()420     { "joinRpcThreadpool", "()V",
421         (void *)JHwBinder_native_joinRpcThreadpool },
422 
native_report_sysprop_change()423     { "native_report_sysprop_change", "()V",
424         (void *)JHwBinder_report_sysprop_change },
425 };
426 
427 namespace android {
428 
register_android_os_HwBinder(JNIEnv * env)429 int register_android_os_HwBinder(JNIEnv *env) {
430     jclass errorClass = FindClassOrDie(env, "java/lang/Error");
431     gErrorClass = MakeGlobalRefOrDie(env, errorClass);
432 
433     return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
434 }
435 
436 }  // namespace android
437