Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Side by Side Diff: remoting/client/jni/chromoting_jni_runtime.cc

Issue 29583003: Use jni_generator in Chromoting Android client (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/client/jni/chromoting_jni_runtime.h" 5 #include "remoting/client/jni/chromoting_jni_runtime.h"
6 6
7 #include "base/android/base_jni_registrar.h" 7 #include "base/android/base_jni_registrar.h"
8 #include "base/android/jni_android.h" 8 #include "base/android/jni_android.h"
9 #include "base/android/jni_registrar.h"
10 #include "base/android/jni_string.h"
9 #include "base/android/scoped_java_ref.h" 11 #include "base/android/scoped_java_ref.h"
12 #include "base/basictypes.h"
13 #include "base/command_line.h"
10 #include "base/memory/singleton.h" 14 #include "base/memory/singleton.h"
11 #include "base/stl_util.h" 15 #include "base/stl_util.h"
12 #include "base/synchronization/waitable_event.h" 16 #include "base/synchronization/waitable_event.h"
17 #include "google_apis/google_api_keys.h"
18 #include "jni/JniInterface_jni.h"
13 #include "media/base/yuv_convert.h" 19 #include "media/base/yuv_convert.h"
14 #include "net/android/net_jni_registrar.h" 20 #include "net/android/net_jni_registrar.h"
15 #include "remoting/base/url_request_context.h" 21 #include "remoting/base/url_request_context.h"
16 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" 22 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
23 #include "ui/gfx/android/gfx_jni_registrar.h"
24
25 using base::android::ConvertJavaStringToUTF8;
17 26
18 namespace { 27 namespace {
19 28
20 // Class and package name of the Java class supporting the methods we call.
21 const char* const kJavaClass = "org/chromium/chromoting/jni/JniInterface";
22
23 const int kBytesPerPixel = 4; 29 const int kBytesPerPixel = 4;
24 30
25 } // namespace 31 } // namespace
26 32
33 extern "C" {
34
35 JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
36 base::android::InitVM(vm);
37
38 JNIEnv* env = base::android::AttachCurrentThread();
39 static base::android::RegistrationMethod kRemotingRegisteredMethods[] = {
40 { "base", base::android::RegisterJni },
41 { "gfx", gfx::android::RegisterJni },
42 { "net", net::android::RegisterJni },
43 { "remoting", remoting::RegisterNativesImpl },
digit1 2013/10/19 09:50:04 nit: I would suggest moving this into its own sour
Lambros 2013/10/23 17:35:23 Done.
44 };
45
46 if (!base::android::RegisterNativeMethods(
47 env, kRemotingRegisteredMethods, arraysize(kRemotingRegisteredMethods))) {
48 return -1;
49 }
50
51 return JNI_VERSION_1_4;
52 }
53
54 } // extern "C"
55
27 namespace remoting { 56 namespace remoting {
28 57
58 // Implementation of stubs defined in JniInterface_jni.h. These are the entry
59 // points for JNI calls from Java into C++.
60
61 static void loadNative(JNIEnv* env, jclass clazz, jobject context) {
digit1 2013/10/19 09:50:04 After renaming the Java method to "nativeLoadNativ
Lambros 2013/10/23 17:35:23 Done.
62 base::android::ScopedJavaLocalRef<jobject> context_activity(env, context);
63 base::android::InitApplicationContext(context_activity);
64
65 // The google_apis functions check the command-line arguments to make sure no
66 // runtime API keys have been specified by the environment. Unfortunately, we
67 // neither launch Chromium nor have a command line, so we need to prevent
68 // them from DCHECKing out when they go looking.
69 CommandLine::Init(0, NULL);
70
71 // Create the singleton now so that the Chromoting threads will be set up.
72 remoting::ChromotingJniRuntime::GetInstance();
73 }
74
75 static jstring getApiKey(JNIEnv* env, jclass clazz) {
76 return env->NewStringUTF(google_apis::GetAPIKey().c_str());
77 }
78
79 static jstring getClientId(JNIEnv* env, jclass clazz) {
80 return env->NewStringUTF(
81 google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING).c_str());
82 }
83
84 static jstring getClientSecret(JNIEnv* env, jclass clazz) {
85 return env->NewStringUTF(
86 google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING).c_str());
87 }
88
89 static void connectNative(JNIEnv* env,
90 jclass clazz,
91 jstring username,
92 jstring authToken,
93 jstring hostJid,
94 jstring hostId,
95 jstring hostPubkey,
96 jstring pairId,
97 jstring pairSecret) {
98 remoting::ChromotingJniRuntime::GetInstance()->ConnectToHost(
99 ConvertJavaStringToUTF8(env, username).c_str(),
100 ConvertJavaStringToUTF8(env, authToken).c_str(),
101 ConvertJavaStringToUTF8(env, hostJid).c_str(),
102 ConvertJavaStringToUTF8(env, hostId).c_str(),
103 ConvertJavaStringToUTF8(env, hostPubkey).c_str(),
104 ConvertJavaStringToUTF8(env, pairId).c_str(),
105 ConvertJavaStringToUTF8(env, pairSecret).c_str());
106 }
107
108 static void disconnectNative(JNIEnv* env, jclass clazz) {
109 remoting::ChromotingJniRuntime::GetInstance()->DisconnectFromHost();
110 }
111
112 static void authenticationResponse(JNIEnv* env,
113 jclass clazz,
114 jstring pin,
115 jboolean createPair) {
116 remoting::ChromotingJniRuntime::GetInstance()->session()->ProvideSecret(
117 ConvertJavaStringToUTF8(env, pin).c_str(), createPair);
118 }
119
120 static void scheduleRedrawNative(JNIEnv* env, jclass clazz) {
121 remoting::ChromotingJniRuntime::GetInstance()->session()->RedrawDesktop();
122 }
123
124 static void mouseActionNative(JNIEnv* env,
125 jclass clazz,
126 jint x,
127 jint y,
128 jint whichButton,
129 jboolean buttonDown) {
130 // Button must be within the bounds of the MouseEvent_MouseButton enum.
131 DCHECK(whichButton >= 0 && whichButton < 5);
132
133 remoting::ChromotingJniRuntime::GetInstance()->session()->PerformMouseAction(
134 x,
135 y,
136 static_cast<remoting::protocol::MouseEvent_MouseButton>(whichButton),
137 buttonDown);
138 }
139
140 static void keyboardActionNative(JNIEnv* env,
141 jclass clazz,
142 jint keyCode,
143 jboolean keyDown) {
144 remoting::ChromotingJniRuntime::GetInstance()
145 ->session()
146 ->PerformKeyboardAction(keyCode, keyDown);
147 }
148
149 // ChromotingJniRuntime implementation.
150
29 // static 151 // static
30 ChromotingJniRuntime* ChromotingJniRuntime::GetInstance() { 152 ChromotingJniRuntime* ChromotingJniRuntime::GetInstance() {
31 return Singleton<ChromotingJniRuntime>::get(); 153 return Singleton<ChromotingJniRuntime>::get();
32 } 154 }
33 155
34 ChromotingJniRuntime::ChromotingJniRuntime() { 156 ChromotingJniRuntime::ChromotingJniRuntime() {
35 // Obtain a reference to the Java environment. (Future calls to this function
36 // made from the same thread return the same stored reference instead of
37 // repeating the work of attaching to the JVM.)
38 JNIEnv* env = base::android::AttachCurrentThread();
39
40 // The base and networks stacks must be registered with JNI in order to work
41 // on Android. An AtExitManager cleans this up at process exit.
42 at_exit_manager_.reset(new base::AtExitManager()); 157 at_exit_manager_.reset(new base::AtExitManager());
43 base::android::RegisterJni(env);
44 net::android::RegisterJni(env);
45 158
46 // On Android, the UI thread is managed by Java, so we need to attach and 159 // On Android, the UI thread is managed by Java, so we need to attach and
47 // start a special type of message loop to allow Chromium code to run tasks. 160 // start a special type of message loop to allow Chromium code to run tasks.
48 LOG(INFO) << "Starting main message loop"; 161 LOG(INFO) << "Starting main message loop";
49 ui_loop_.reset(new base::MessageLoopForUI()); 162 ui_loop_.reset(new base::MessageLoopForUI());
50 ui_loop_->Start(); 163 ui_loop_->Start();
51 164
52 LOG(INFO) << "Spawning additional threads"; 165 LOG(INFO) << "Spawning additional threads";
53 // TODO(solb) Stop pretending to control the managed UI thread's lifetime. 166 // TODO(solb) Stop pretending to control the managed UI thread's lifetime.
54 ui_task_runner_ = new AutoThreadTaskRunner(ui_loop_->message_loop_proxy(), 167 ui_task_runner_ = new AutoThreadTaskRunner(ui_loop_->message_loop_proxy(),
55 base::MessageLoop::QuitClosure()); 168 base::MessageLoop::QuitClosure());
56 network_task_runner_ = AutoThread::CreateWithType("native_net", 169 network_task_runner_ = AutoThread::CreateWithType("native_net",
57 ui_task_runner_, 170 ui_task_runner_,
58 base::MessageLoop::TYPE_IO); 171 base::MessageLoop::TYPE_IO);
59 display_task_runner_ = AutoThread::Create("native_disp", 172 display_task_runner_ = AutoThread::Create("native_disp",
60 ui_task_runner_); 173 ui_task_runner_);
61 174
62 url_requester_ = new URLRequestContextGetter(network_task_runner_); 175 url_requester_ = new URLRequestContextGetter(network_task_runner_);
63 176
64 // Allows later decoding of video frames. 177 // Allows later decoding of video frames.
65 media::InitializeCPUSpecificYUVConversions(); 178 media::InitializeCPUSpecificYUVConversions();
66
67 class_ = static_cast<jclass>(env->NewGlobalRef(env->FindClass(kJavaClass)));
68 } 179 }
69 180
70 ChromotingJniRuntime::~ChromotingJniRuntime() { 181 ChromotingJniRuntime::~ChromotingJniRuntime() {
71 // The singleton should only ever be destroyed on the main thread. 182 // The singleton should only ever be destroyed on the main thread.
72 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 183 DCHECK(ui_task_runner_->BelongsToCurrentThread());
73 184
74 // The session must be shut down first, since it depends on our other 185 // The session must be shut down first, since it depends on our other
75 // components' still being alive. 186 // components' still being alive.
76 DisconnectFromHost(); 187 DisconnectFromHost();
77 188
78 JNIEnv* env = base::android::AttachCurrentThread();
79 env->DeleteGlobalRef(class_);
80
81 base::WaitableEvent done_event(false, false); 189 base::WaitableEvent done_event(false, false);
82 network_task_runner_->PostTask(FROM_HERE, base::Bind( 190 network_task_runner_->PostTask(FROM_HERE, base::Bind(
83 &ChromotingJniRuntime::DetachFromVmAndSignal, 191 &ChromotingJniRuntime::DetachFromVmAndSignal,
84 base::Unretained(this), 192 base::Unretained(this),
85 &done_event)); 193 &done_event));
86 done_event.Wait(); 194 done_event.Wait();
87 display_task_runner_->PostTask(FROM_HERE, base::Bind( 195 display_task_runner_->PostTask(FROM_HERE, base::Bind(
88 &ChromotingJniRuntime::DetachFromVmAndSignal, 196 &ChromotingJniRuntime::DetachFromVmAndSignal,
89 base::Unretained(this), 197 base::Unretained(this),
90 &done_event)); 198 &done_event));
(...skipping 27 matching lines...) Expand all
118 session_ = NULL; 226 session_ = NULL;
119 } 227 }
120 } 228 }
121 229
122 void ChromotingJniRuntime::ReportConnectionStatus( 230 void ChromotingJniRuntime::ReportConnectionStatus(
123 protocol::ConnectionToHost::State state, 231 protocol::ConnectionToHost::State state,
124 protocol::ErrorCode error) { 232 protocol::ErrorCode error) {
125 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 233 DCHECK(ui_task_runner_->BelongsToCurrentThread());
126 234
127 JNIEnv* env = base::android::AttachCurrentThread(); 235 JNIEnv* env = base::android::AttachCurrentThread();
128 env->CallStaticVoidMethod( 236 Java_JniInterface_reportConnectionStatus(env, state, error);
129 class_,
130 env->GetStaticMethodID(class_, "reportConnectionStatus", "(II)V"),
131 state,
132 error);
133 } 237 }
134 238
135 void ChromotingJniRuntime::DisplayAuthenticationPrompt(bool pairing_supported) { 239 void ChromotingJniRuntime::DisplayAuthenticationPrompt(bool pairing_supported) {
136 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 240 DCHECK(ui_task_runner_->BelongsToCurrentThread());
137 241
138 JNIEnv* env = base::android::AttachCurrentThread(); 242 JNIEnv* env = base::android::AttachCurrentThread();
139 env->CallStaticVoidMethod( 243 Java_JniInterface_displayAuthenticationPrompt(env, pairing_supported);
140 class_,
141 env->GetStaticMethodID(class_, "displayAuthenticationPrompt", "(Z)V"),
142 pairing_supported);
143 } 244 }
144 245
145 void ChromotingJniRuntime::CommitPairingCredentials(const std::string& host, 246 void ChromotingJniRuntime::CommitPairingCredentials(const std::string& host,
146 const std::string& id, 247 const std::string& id,
147 const std::string& secret) { 248 const std::string& secret) {
148 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 249 DCHECK(ui_task_runner_->BelongsToCurrentThread());
149 250
150 JNIEnv* env = base::android::AttachCurrentThread(); 251 JNIEnv* env = base::android::AttachCurrentThread();
151 jstring host_jstr = env->NewStringUTF(host.c_str()); 252 jstring host_jstr = env->NewStringUTF(host.c_str());
152 jbyteArray id_arr = env->NewByteArray(id.size()); 253 jbyteArray id_arr = env->NewByteArray(id.size());
153 env->SetByteArrayRegion(id_arr, 0, id.size(), 254 env->SetByteArrayRegion(id_arr, 0, id.size(),
154 reinterpret_cast<const jbyte*>(id.c_str())); 255 reinterpret_cast<const jbyte*>(id.c_str()));
155 jbyteArray secret_arr = env->NewByteArray(secret.size()); 256 jbyteArray secret_arr = env->NewByteArray(secret.size());
156 env->SetByteArrayRegion(secret_arr, 0, secret.size(), 257 env->SetByteArrayRegion(secret_arr, 0, secret.size(),
157 reinterpret_cast<const jbyte*>(secret.c_str())); 258 reinterpret_cast<const jbyte*>(secret.c_str()));
158 259
159 env->CallStaticVoidMethod( 260 Java_JniInterface_commitPairingCredentials(env, host_jstr, id_arr,
160 class_, 261 secret_arr);
161 env->GetStaticMethodID(
162 class_,
163 "commitPairingCredentials",
164 "(Ljava/lang/String;[B[B)V"),
165 host_jstr,
166 id_arr,
167 secret_arr);
168 262
169 // Because we passed them as arguments, their corresponding Java objects were 263 // Because we passed them as arguments, their corresponding Java objects were
170 // GCd as soon as the managed method returned, so we mustn't release it here. 264 // GCd as soon as the managed method returned, so we mustn't release it here.
171 } 265 }
172 266
173 base::android::ScopedJavaLocalRef<jobject> ChromotingJniRuntime::NewBitmap( 267 base::android::ScopedJavaLocalRef<jobject> ChromotingJniRuntime::NewBitmap(
174 webrtc::DesktopSize size) { 268 webrtc::DesktopSize size) {
175 JNIEnv* env = base::android::AttachCurrentThread(); 269 JNIEnv* env = base::android::AttachCurrentThread();
176 270 return Java_JniInterface_newBitmap(env, size.width(), size.height());
177 jobject bitmap = env->CallStaticObjectMethod(
178 class_,
179 env->GetStaticMethodID(
180 class_,
181 "newBitmap",
182 "(II)Landroid/graphics/Bitmap;"),
183 size.width(),
184 size.height());
185 return base::android::ScopedJavaLocalRef<jobject>(env, bitmap);
186 } 271 }
187 272
188 void ChromotingJniRuntime::UpdateFrameBitmap(jobject bitmap) { 273 void ChromotingJniRuntime::UpdateFrameBitmap(jobject bitmap) {
189 DCHECK(display_task_runner_->BelongsToCurrentThread()); 274 DCHECK(display_task_runner_->BelongsToCurrentThread());
190 275
191 JNIEnv* env = base::android::AttachCurrentThread(); 276 JNIEnv* env = base::android::AttachCurrentThread();
192 277 Java_JniInterface_setVideoFrame(env, bitmap);
193 env->CallStaticVoidMethod(
194 class_,
195 env->GetStaticMethodID(
196 class_,
197 "setVideoFrame",
198 "(Landroid/graphics/Bitmap;)V"),
199 bitmap);
200 } 278 }
201 279
202 void ChromotingJniRuntime::UpdateCursorShape( 280 void ChromotingJniRuntime::UpdateCursorShape(
203 const protocol::CursorShapeInfo& cursor_shape) { 281 const protocol::CursorShapeInfo& cursor_shape) {
204 DCHECK(display_task_runner_->BelongsToCurrentThread()); 282 DCHECK(display_task_runner_->BelongsToCurrentThread());
205 283
206 // const_cast<> is safe as long as the Java updateCursorShape() method copies 284 // const_cast<> is safe as long as the Java updateCursorShape() method copies
207 // the data out of the buffer without mutating it, and doesn't keep any 285 // the data out of the buffer without mutating it, and doesn't keep any
208 // reference to the buffer afterwards. Unfortunately, there seems to be no way 286 // reference to the buffer afterwards. Unfortunately, there seems to be no way
209 // to create a read-only ByteBuffer from a pointer-to-const. 287 // to create a read-only ByteBuffer from a pointer-to-const.
210 char* data = string_as_array(const_cast<std::string*>(&cursor_shape.data())); 288 char* data = string_as_array(const_cast<std::string*>(&cursor_shape.data()));
211 int cursor_total_bytes = 289 int cursor_total_bytes =
212 cursor_shape.width() * cursor_shape.height() * kBytesPerPixel; 290 cursor_shape.width() * cursor_shape.height() * kBytesPerPixel;
213 291
214 JNIEnv* env = base::android::AttachCurrentThread(); 292 JNIEnv* env = base::android::AttachCurrentThread();
215 base::android::ScopedJavaLocalRef<jobject> buffer(env, 293 base::android::ScopedJavaLocalRef<jobject> buffer(env,
216 env->NewDirectByteBuffer(data, cursor_total_bytes)); 294 env->NewDirectByteBuffer(data, cursor_total_bytes));
217 env->CallStaticVoidMethod( 295 Java_JniInterface_updateCursorShape(env,
218 class_, 296 cursor_shape.width(),
219 env->GetStaticMethodID( 297 cursor_shape.height(),
220 class_, 298 cursor_shape.hotspot_x(),
221 "updateCursorShape", 299 cursor_shape.hotspot_y(),
222 "(IIIILjava/nio/ByteBuffer;)V"), 300 buffer.obj());
223 cursor_shape.width(),
224 cursor_shape.height(),
225 cursor_shape.hotspot_x(),
226 cursor_shape.hotspot_y(),
227 buffer.obj());
228 } 301 }
229 302
230 void ChromotingJniRuntime::RedrawCanvas() { 303 void ChromotingJniRuntime::RedrawCanvas() {
231 DCHECK(display_task_runner_->BelongsToCurrentThread()); 304 DCHECK(display_task_runner_->BelongsToCurrentThread());
232 305
233 JNIEnv* env = base::android::AttachCurrentThread(); 306 JNIEnv* env = base::android::AttachCurrentThread();
234 env->CallStaticVoidMethod( 307 Java_JniInterface_redrawGraphicsInternal(env);
235 class_,
236 env->GetStaticMethodID(class_, "redrawGraphicsInternal", "()V"));
237 } 308 }
238 309
239 void ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) { 310 void ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) {
240 base::android::DetachFromVM(); 311 base::android::DetachFromVM();
241 waiter->Signal(); 312 waiter->Signal();
242 } 313 }
243 314
244 } // namespace remoting 315 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698