blob: 8fa90185b7aafe0593f39a084217161999567812 [file] [log] [blame]
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdochbbcdd452013-07-25 10:06:34 +01005#include "remoting/client/jni/chromoting_jni_runtime.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006
7#include "base/android/base_jni_registrar.h"
8#include "base/android/jni_android.h"
9#include "base/memory/singleton.h"
Ben Murdoch9ab55632013-07-18 11:57:30 +010010#include "media/base/yuv_convert.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010011#include "net/android/net_jni_registrar.h"
12#include "remoting/base/url_request_context.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010013
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010014// Class and package name of the Java class supporting the methods we call.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010015const char* const kJavaClass = "org/chromium/chromoting/jni/JniInterface";
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010016
17namespace remoting {
18
19// static
Ben Murdochbbcdd452013-07-25 10:06:34 +010020ChromotingJniRuntime* ChromotingJniRuntime::GetInstance() {
21 return Singleton<ChromotingJniRuntime>::get();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010022}
23
Ben Murdochbbcdd452013-07-25 10:06:34 +010024ChromotingJniRuntime::ChromotingJniRuntime() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010025 // Obtain a reference to the Java environment. (Future calls to this function
26 // made from the same thread return the same stored reference instead of
27 // repeating the work of attaching to the JVM.)
28 JNIEnv* env = base::android::AttachCurrentThread();
29
30 // The base and networks stacks must be registered with JNI in order to work
31 // on Android. An AtExitManager cleans this up at process exit.
32 at_exit_manager_.reset(new base::AtExitManager());
33 base::android::RegisterJni(env);
34 net::android::RegisterJni(env);
35
36 // On Android, the UI thread is managed by Java, so we need to attach and
37 // start a special type of message loop to allow Chromium code to run tasks.
38 LOG(INFO) << "Starting main message loop";
39 ui_loop_.reset(new base::MessageLoopForUI());
40 ui_loop_->Start();
41
42 LOG(INFO) << "Spawning additional threads";
43 // TODO(solb) Stop pretending to control the managed UI thread's lifetime.
44 ui_task_runner_ = new AutoThreadTaskRunner(ui_loop_->message_loop_proxy(),
45 base::MessageLoop::QuitClosure());
46 network_task_runner_ = AutoThread::CreateWithType("native_net",
47 ui_task_runner_,
48 base::MessageLoop::TYPE_IO);
49 display_task_runner_ = AutoThread::Create("native_disp",
50 ui_task_runner_);
51
52 url_requester_ = new URLRequestContextGetter(ui_task_runner_,
53 network_task_runner_);
54
Ben Murdoch9ab55632013-07-18 11:57:30 +010055 // Allows later decoding of video frames.
56 media::InitializeCPUSpecificYUVConversions();
57
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010058 class_ = static_cast<jclass>(env->NewGlobalRef(env->FindClass(kJavaClass)));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010059}
60
Ben Murdochbbcdd452013-07-25 10:06:34 +010061ChromotingJniRuntime::~ChromotingJniRuntime() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010062 // The singleton should only ever be destroyed on the main thread.
63 DCHECK(ui_task_runner_->BelongsToCurrentThread());
64
65 // The session must be shut down first, since it depends on our other
66 // components' still being alive.
67 DisconnectFromHost();
68
69 JNIEnv* env = base::android::AttachCurrentThread();
70 env->DeleteGlobalRef(class_);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010071 // TODO(solb): Detach all threads from JVM here.
72 // crbug.com/259594
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010073}
74
Ben Murdochbbcdd452013-07-25 10:06:34 +010075void ChromotingJniRuntime::ConnectToHost(const char* username,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010076 const char* auth_token,
77 const char* host_jid,
78 const char* host_id,
Ben Murdochbb1529c2013-08-08 10:24:53 +010079 const char* host_pubkey,
80 const char* pairing_id,
81 const char* pairing_secret) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010082 DCHECK(ui_task_runner_->BelongsToCurrentThread());
83 DCHECK(!session_);
Ben Murdochbbcdd452013-07-25 10:06:34 +010084 session_ = new ChromotingJniInstance(this,
85 username,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010086 auth_token,
87 host_jid,
88 host_id,
Ben Murdochbb1529c2013-08-08 10:24:53 +010089 host_pubkey,
90 pairing_id,
91 pairing_secret);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010092}
93
Ben Murdochbbcdd452013-07-25 10:06:34 +010094void ChromotingJniRuntime::DisconnectFromHost() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010095 DCHECK(ui_task_runner_->BelongsToCurrentThread());
96 if (session_) {
97 session_->Cleanup();
98 session_ = NULL;
99 }
100}
101
Ben Murdochbbcdd452013-07-25 10:06:34 +0100102void ChromotingJniRuntime::ReportConnectionStatus(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100103 protocol::ConnectionToHost::State state,
104 protocol::ErrorCode error) {
105 DCHECK(ui_task_runner_->BelongsToCurrentThread());
106
107 JNIEnv* env = base::android::AttachCurrentThread();
108 env->CallStaticVoidMethod(
109 class_,
110 env->GetStaticMethodID(class_, "reportConnectionStatus", "(II)V"),
111 state,
112 error);
113}
114
Ben Murdochbbcdd452013-07-25 10:06:34 +0100115void ChromotingJniRuntime::DisplayAuthenticationPrompt() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100116 DCHECK(ui_task_runner_->BelongsToCurrentThread());
117
118 JNIEnv* env = base::android::AttachCurrentThread();
119 env->CallStaticVoidMethod(
120 class_,
121 env->GetStaticMethodID(class_, "displayAuthenticationPrompt", "()V"));
122}
123
Ben Murdochbb1529c2013-08-08 10:24:53 +0100124void ChromotingJniRuntime::CommitPairingCredentials(const std::string& host,
125 const std::string& id,
126 const std::string& secret) {
127 DCHECK(ui_task_runner_->BelongsToCurrentThread());
128
129 JNIEnv* env = base::android::AttachCurrentThread();
130 jstring host_jstr = env->NewStringUTF(host.c_str());
131 jbyteArray id_arr = env->NewByteArray(id.size());
132 env->SetByteArrayRegion(id_arr, 0, id.size(),
133 reinterpret_cast<const jbyte*>(id.c_str()));
134 jbyteArray secret_arr = env->NewByteArray(secret.size());
135 env->SetByteArrayRegion(secret_arr, 0, secret.size(),
136 reinterpret_cast<const jbyte*>(secret.c_str()));
137
138 env->CallStaticVoidMethod(
139 class_,
140 env->GetStaticMethodID(
141 class_,
142 "commitPairingCredentials",
143 "(Ljava/lang/String;[B[B)V"),
144 host_jstr,
145 id_arr,
146 secret_arr);
147
148 // Because we passed them as arguments, their corresponding Java objects were
149 // GCd as soon as the managed method returned, so we mustn't release it here.
150}
151
Ben Murdochbbcdd452013-07-25 10:06:34 +0100152void ChromotingJniRuntime::UpdateImageBuffer(int width,
153 int height,
154 jobject buffer) {
Ben Murdoch9ab55632013-07-18 11:57:30 +0100155 DCHECK(display_task_runner_->BelongsToCurrentThread());
156
157 JNIEnv* env = base::android::AttachCurrentThread();
158 env->SetStaticIntField(
159 class_,
160 env->GetStaticFieldID(class_, "sWidth", "I"),
161 width);
162 env->SetStaticIntField(
163 class_,
164 env->GetStaticFieldID(class_, "sHeight", "I"),
165 height);
166 env->SetStaticObjectField(
167 class_,
168 env->GetStaticFieldID(class_, "sBuffer", "Ljava/nio/ByteBuffer;"),
169 buffer);
170}
171
Ben Murdochbbcdd452013-07-25 10:06:34 +0100172void ChromotingJniRuntime::RedrawCanvas() {
Ben Murdoch9ab55632013-07-18 11:57:30 +0100173 DCHECK(display_task_runner_->BelongsToCurrentThread());
174
175 JNIEnv* env = base::android::AttachCurrentThread();
176 env->CallStaticVoidMethod(
177 class_,
178 env->GetStaticMethodID(class_, "redrawGraphicsInternal", "()V"));
179}
180
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100181} // namespace remoting