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