1 /*
2 * Copyright (C) 2019 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_TAG "AdbDebuggingManager-JNI"
18
19 #define LOG_NDEBUG 0
20
21 #include <condition_variable>
22 #include <mutex>
23 #include <optional>
24
25 #include <adb/pairing/pairing_server.h>
26 #include <android-base/properties.h>
27 #include <jni.h>
28 #include <nativehelper/JNIHelp.h>
29 #include <nativehelper/utils.h>
30 #include <utils/Log.h>
31
32 namespace android {
33
34 // ----------------------------------------------------------------------------
35 namespace {
36
37 struct ServerDeleter {
operator ()android::__anon110e76ed0111::ServerDeleter38 void operator()(PairingServerCtx* p) { pairing_server_destroy(p); }
39 };
40 using PairingServerPtr = std::unique_ptr<PairingServerCtx, ServerDeleter>;
41 struct PairingResultWaiter {
42 std::mutex mutex_;
43 std::condition_variable cv_;
44 std::optional<bool> is_valid_;
45 PeerInfo peer_info_;
46
ResultCallbackandroid::__anon110e76ed0111::PairingResultWaiter47 static void ResultCallback(const PeerInfo* peer_info, void* opaque) {
48 auto* p = reinterpret_cast<PairingResultWaiter*>(opaque);
49 {
50 std::unique_lock<std::mutex> lock(p->mutex_);
51 if (peer_info) {
52 memcpy(&(p->peer_info_), peer_info, sizeof(PeerInfo));
53 }
54 p->is_valid_ = (peer_info != nullptr);
55 }
56 p->cv_.notify_one();
57 }
58 };
59
60 PairingServerPtr sServer;
61 std::unique_ptr<PairingResultWaiter> sWaiter;
62 } // namespace
63
native_pairing_start(JNIEnv * env,jobject thiz,jstring javaGuid,jstring javaPassword)64 static jint native_pairing_start(JNIEnv* env, jobject thiz, jstring javaGuid, jstring javaPassword) {
65 // Server-side only sends its GUID on success.
66 PeerInfo system_info = { .type = ADB_DEVICE_GUID };
67
68 ScopedUtfChars guid = GET_UTF_OR_RETURN(env, javaGuid);
69 memcpy(system_info.data, guid.c_str(), guid.size());
70
71 ScopedUtfChars password = GET_UTF_OR_RETURN(env, javaPassword);
72
73 // Create the pairing server
74 sServer = PairingServerPtr(
75 pairing_server_new_no_cert(reinterpret_cast<const uint8_t*>(password.c_str()),
76 password.size(), &system_info, 0));
77
78 sWaiter.reset(new PairingResultWaiter);
79 uint16_t port = pairing_server_start(sServer.get(), sWaiter->ResultCallback, sWaiter.get());
80 if (port == 0) {
81 ALOGE("Failed to start pairing server");
82 return -1;
83 }
84
85 return port;
86 }
87
native_pairing_cancel(JNIEnv *,jclass)88 static void native_pairing_cancel(JNIEnv* /* env */, jclass /* clazz */) {
89 if (sServer != nullptr) {
90 sServer.reset();
91 }
92 }
93
native_pairing_wait(JNIEnv * env,jobject thiz)94 static jboolean native_pairing_wait(JNIEnv* env, jobject thiz) {
95 ALOGI("Waiting for pairing server to complete");
96 std::unique_lock<std::mutex> lock(sWaiter->mutex_);
97 if (!sWaiter->is_valid_.has_value()) {
98 sWaiter->cv_.wait(lock, [&]() { return sWaiter->is_valid_.has_value(); });
99 }
100 if (!*(sWaiter->is_valid_)) {
101 return JNI_FALSE;
102 }
103
104 // Create a Java string for the public key.
105 char* peer_public_key = reinterpret_cast<char*>(sWaiter->peer_info_.data);
106 jstring jpublickey = env->NewStringUTF(peer_public_key);
107 if (jpublickey == nullptr) {
108 return JNI_FALSE;
109 }
110
111 // Write to PairingThread.mPublicKey.
112 jclass clazz = env->GetObjectClass(thiz);
113 jfieldID mPublicKey = env->GetFieldID(clazz, "mPublicKey", "Ljava/lang/String;");
114 env->SetObjectField(thiz, mPublicKey, jpublickey);
115 return JNI_TRUE;
116 }
117
118 // ----------------------------------------------------------------------------
119
120 static const JNINativeMethod gPairingThreadMethods[] = {
121 /* name, signature, funcPtr */
122 {"native_pairing_start", "(Ljava/lang/String;Ljava/lang/String;)I",
123 (void*)native_pairing_start},
124 {"native_pairing_cancel", "()V", (void*)native_pairing_cancel},
125 {"native_pairing_wait", "()Z", (void*)native_pairing_wait},
126 };
127
register_android_server_AdbDebuggingManager(JNIEnv * env)128 int register_android_server_AdbDebuggingManager(JNIEnv* env) {
129 return jniRegisterNativeMethods(env,
130 "com/android/server/adb/AdbDebuggingManager$PairingThread",
131 gPairingThreadMethods, NELEM(gPairingThreadMethods));
132 }
133
134 } /* namespace android */
135