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