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