• 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 <vintf/parse_string.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 *,jobject,jint,jobject,jobject,jint)261 static void JHwBinder_native_transact(
262         JNIEnv * /* env */,
263         jobject /* thiz */,
264         jint /* code */,
265         jobject /* requestObj */,
266         jobject /* replyObj */,
267         jint /* flags */) {
268     CHECK(!"Should not be here");
269 }
270 
JHwBinder_native_registerService(JNIEnv * env,jobject thiz,jstring serviceNameObj)271 static void JHwBinder_native_registerService(
272         JNIEnv *env,
273         jobject thiz,
274         jstring serviceNameObj) {
275     ScopedUtfChars str(env, serviceNameObj);
276     if (str.c_str() == nullptr) {
277         return;  // NPE will be pending.
278     }
279 
280     sp<hardware::IBinder> binder = JHwBinder::GetNativeBinder(env, thiz);
281     sp<hidl::base::V1_0::IBase> base = new hidl::base::V1_0::BpHwBase(binder);
282 
283     bool ok = hardware::details::registerAsServiceInternal(base, str.c_str()) == OK;
284 
285     if (ok) {
286         LOG(INFO) << "HwBinder: Starting thread pool for " << str.c_str();
287         ::android::hardware::ProcessState::self()->startThreadPool();
288     }
289 
290     // avoiding richer error exceptions to stick with legacy behavior
291     signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR), true /*canThrowRemoteException*/);
292 }
293 
JHwBinder_native_getService(JNIEnv * env,jclass,jstring ifaceNameObj,jstring serviceNameObj,jboolean retry)294 static jobject JHwBinder_native_getService(
295         JNIEnv *env,
296         jclass /* clazzObj */,
297         jstring ifaceNameObj,
298         jstring serviceNameObj,
299         jboolean retry) {
300 
301     using ::android::hidl::base::V1_0::IBase;
302     using ::android::hardware::details::getRawServiceInternal;
303 
304     std::string ifaceName;
305     {
306         ScopedUtfChars str(env, ifaceNameObj);
307         if (str.c_str() == nullptr) {
308             return nullptr;  // NPE will be pending.
309         }
310         ifaceName = str.c_str();
311     }
312 
313     std::string serviceName;
314     {
315         ScopedUtfChars str(env, serviceNameObj);
316         if (str.c_str() == nullptr) {
317             return nullptr;  // NPE will be pending.
318         }
319         serviceName = str.c_str();
320     }
321 
322     sp<IBase> ret = getRawServiceInternal(ifaceName, serviceName, retry /* retry */, false /* getStub */);
323     sp<hardware::IBinder> service = hardware::toBinder<hidl::base::V1_0::IBase>(ret);
324 
325     if (service == nullptr || !validateCanUseHwBinder(service)) {
326         signalExceptionForError(env, NAME_NOT_FOUND);
327         return nullptr;
328     }
329 
330     LOG(INFO) << "HwBinder: Starting thread pool for getting: " << ifaceName << "/" << serviceName;
331     ::android::hardware::ProcessState::self()->startThreadPool();
332 
333     return JHwRemoteBinder::NewObject(env, service);
334 }
335 
JHwBinder_native_setTrebleTestingOverride(JNIEnv *,jclass,jboolean testingOverride)336 void JHwBinder_native_setTrebleTestingOverride(JNIEnv*, jclass, jboolean testingOverride) {
337     hardware::details::setTrebleTestingOverride(testingOverride);
338 }
339 
JHwBinder_native_configureRpcThreadpool(JNIEnv *,jclass,jlong maxThreads,jboolean callerWillJoin)340 void JHwBinder_native_configureRpcThreadpool(JNIEnv *, jclass,
341         jlong maxThreads, jboolean callerWillJoin) {
342     CHECK(maxThreads > 0);
343     ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/);
344 }
345 
JHwBinder_native_joinRpcThreadpool()346 void JHwBinder_native_joinRpcThreadpool() {
347     IPCThreadState::self()->joinThreadPool();
348 }
349 
JHwBinder_report_sysprop_change(JNIEnv *,jclass)350 static void JHwBinder_report_sysprop_change(JNIEnv * /*env*/, jclass /*clazz*/)
351 {
352     report_sysprop_change();
353 }
354 
355 static JNINativeMethod gMethods[] = {
356     { "native_init", "()J", (void *)JHwBinder_native_init },
357     { "native_setup", "()V", (void *)JHwBinder_native_setup },
358 
359     { "transact",
360         "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
361         (void *)JHwBinder_native_transact },
362 
363     { "registerService", "(Ljava/lang/String;)V",
364         (void *)JHwBinder_native_registerService },
365 
366     { "getService", "(Ljava/lang/String;Ljava/lang/String;Z)L" PACKAGE_PATH "/IHwBinder;",
367         (void *)JHwBinder_native_getService },
368 
369     { "setTrebleTestingOverride", "(Z)V",
370         (void *)JHwBinder_native_setTrebleTestingOverride },
371 
372     { "configureRpcThreadpool", "(JZ)V",
373         (void *)JHwBinder_native_configureRpcThreadpool },
374 
375     { "joinRpcThreadpool", "()V",
376         (void *)JHwBinder_native_joinRpcThreadpool },
377 
378     { "native_report_sysprop_change", "()V",
379         (void *)JHwBinder_report_sysprop_change },
380 };
381 
382 namespace android {
383 
register_android_os_HwBinder(JNIEnv * env)384 int register_android_os_HwBinder(JNIEnv *env) {
385     jclass errorClass = FindClassOrDie(env, "java/lang/Error");
386     gErrorClass = MakeGlobalRefOrDie(env, errorClass);
387 
388     return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
389 }
390 
391 }  // namespace android
392