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