OLD | NEW |
---|---|
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 package org.chromium.chromoting.jni; | 5 package org.chromium.chromoting.jni; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.app.AlertDialog; | 8 import android.app.AlertDialog; |
9 import android.app.ProgressDialog; | |
10 import android.content.Context; | 9 import android.content.Context; |
11 import android.content.DialogInterface; | 10 import android.content.DialogInterface; |
12 import android.content.SharedPreferences; | 11 import android.content.SharedPreferences; |
13 import android.graphics.Bitmap; | 12 import android.graphics.Bitmap; |
14 import android.graphics.Point; | 13 import android.graphics.Point; |
15 import android.os.Looper; | 14 import android.os.Looper; |
16 import android.util.Log; | 15 import android.util.Log; |
17 import android.view.KeyEvent; | 16 import android.view.KeyEvent; |
18 import android.view.View; | 17 import android.view.View; |
19 import android.widget.CheckBox; | 18 import android.widget.CheckBox; |
20 import android.widget.TextView; | 19 import android.widget.TextView; |
21 import android.widget.Toast; | 20 import android.widget.Toast; |
22 | 21 |
23 import org.chromium.base.CalledByNative; | 22 import org.chromium.base.CalledByNative; |
24 import org.chromium.base.JNINamespace; | 23 import org.chromium.base.JNINamespace; |
25 import org.chromium.chromoting.R; | 24 import org.chromium.chromoting.R; |
26 | 25 |
27 import java.nio.ByteBuffer; | 26 import java.nio.ByteBuffer; |
28 import java.nio.ByteOrder; | 27 import java.nio.ByteOrder; |
29 | 28 |
30 /** | 29 /** |
31 * Initializes the Chromium remoting library, and provides JNI calls into it. | 30 * Initializes the Chromium remoting library, and provides JNI calls into it. |
32 * All interaction with the native code is centralized in this class. | 31 * All interaction with the native code is centralized in this class. |
33 */ | 32 */ |
34 @JNINamespace("remoting") | 33 @JNINamespace("remoting") |
35 public class JniInterface { | 34 public class JniInterface { |
36 /** The status code indicating successful connection. */ | |
37 private static final int SUCCESSFUL_CONNECTION = 3; | |
38 | |
39 /* | 35 /* |
40 * Library-loading state machine. | 36 * Library-loading state machine. |
41 */ | 37 */ |
42 /** Whether the library has been loaded. Accessed on the UI thread. */ | 38 /** Whether the library has been loaded. Accessed on the UI thread. */ |
43 private static boolean sLoaded = false; | 39 private static boolean sLoaded = false; |
44 | 40 |
45 /** The application context. Accessed on the UI thread. */ | 41 /** The application context. Accessed on the UI thread. */ |
46 private static Activity sContext = null; | 42 private static Activity sContext = null; |
47 | 43 |
44 /** Interface used for connection state notifications. */ | |
45 public interface ConnectionListener { | |
46 /** | |
47 * These values must match the C++ enumeration remoting::protocol::Conne ctionToHost::State. | |
48 */ | |
49 int STATE_INITIALIZING = 0; | |
Sergey Ulanov
2014/01/08 20:30:45
Can we use Java enums here? In the past it was rec
Lambros
2014/01/08 22:30:01
Done.
| |
50 int STATE_CONNECTING = 1; | |
51 int STATE_AUTHENTICATED = 2; | |
52 int STATE_CONNECTED = 3; | |
53 int STATE_FAILED = 4; | |
54 int STATE_CLOSED = 5; | |
55 | |
56 /** | |
57 * These values must match the C++ enumeration remoting::protocol::Error Code. | |
58 */ | |
59 int ERROR_OK = 0; | |
60 int ERROR_PEER_IS_OFFLINE = 1; | |
61 int ERROR_SESSION_REJECTED = 2; | |
62 int ERROR_INCOMPATIBLE_PROTOCOL = 3; | |
63 int ERROR_AUTHENTICATION_FAILED = 4; | |
64 int ERROR_CHANNEL_CONNECTION_ERROR = 5; | |
65 int ERROR_SIGNALING_ERROR = 6; | |
66 int ERROR_SIGNALING_TIMEOUT = 7; | |
67 int ERROR_HOST_OVERLOAD = 8; | |
68 int ERROR_UNKNOWN_ERROR = 9; | |
69 | |
70 /** | |
71 * Notified on connection state change. | |
72 * @param state The new connection state. | |
73 * @param error The error code, if state is STATE_FAILED. | |
74 */ | |
75 void onConnectionState(int state, int error); | |
76 } | |
77 | |
48 /* | 78 /* |
49 * Connection-initiating state machine. | 79 * Connection-initiating state machine. |
50 */ | 80 */ |
51 /** Whether the native code is attempting a connection. Accessed on the UI t hread. */ | 81 /** Whether the native code is attempting a connection. Accessed on the UI t hread. */ |
52 private static boolean sConnected = false; | 82 private static boolean sConnected = false; |
53 | 83 |
54 /** Callback to signal upon successful connection. Accessed on the UI thread . */ | 84 /** Notified upon successful connection or disconnection. Accessed on the UI thread. */ |
55 private static Runnable sSuccessCallback = null; | 85 private static ConnectionListener sConnectionListener = null; |
56 | |
57 /** Dialog for reporting connection progress. Accessed on the UI thread. */ | |
58 private static ProgressDialog sProgressIndicator = null; | |
59 | |
60 // Protects access to |sProgressIndicator|. Used only to silence FindBugs wa rnings - the | |
61 // variable it protects is only accessed on a single thread. | |
62 // TODO(lambroslambrou): Refactor the ProgressIndicator into a separate clas s. | |
63 private static Object sProgressIndicatorLock = new Object(); | |
64 | 86 |
65 /** | 87 /** |
66 * Callback invoked on the graphics thread to repaint the desktop. Accessed on the UI and | 88 * Callback invoked on the graphics thread to repaint the desktop. Accessed on the UI and |
67 * graphics threads. | 89 * graphics threads. |
68 */ | 90 */ |
69 private static Runnable sRedrawCallback = null; | 91 private static Runnable sRedrawCallback = null; |
70 | 92 |
71 /** Bitmap holding a copy of the latest video frame. Accessed on the UI and graphics threads. */ | 93 /** Bitmap holding a copy of the latest video frame. Accessed on the UI and graphics threads. */ |
72 private static Bitmap sFrameBitmap = null; | 94 private static Bitmap sFrameBitmap = null; |
73 | 95 |
(...skipping 27 matching lines...) Expand all Loading... | |
101 | 123 |
102 /* | 124 /* |
103 * API/OAuth2 keys access. | 125 * API/OAuth2 keys access. |
104 */ | 126 */ |
105 public static native String nativeGetApiKey(); | 127 public static native String nativeGetApiKey(); |
106 public static native String nativeGetClientId(); | 128 public static native String nativeGetClientId(); |
107 public static native String nativeGetClientSecret(); | 129 public static native String nativeGetClientSecret(); |
108 | 130 |
109 /** Attempts to form a connection to the user-selected host. Called on the U I thread. */ | 131 /** Attempts to form a connection to the user-selected host. Called on the U I thread. */ |
110 public static void connectToHost(String username, String authToken, | 132 public static void connectToHost(String username, String authToken, |
111 String hostJid, String hostId, String hostPubkey, Runnable successCa llback) { | 133 String hostJid, String hostId, String hostPubkey, ConnectionListener listener) { |
112 disconnectFromHost(); | 134 disconnectFromHost(); |
113 | 135 |
114 sSuccessCallback = successCallback; | 136 sConnectionListener = listener; |
115 SharedPreferences prefs = sContext.getPreferences(Activity.MODE_PRIVATE) ; | 137 SharedPreferences prefs = sContext.getPreferences(Activity.MODE_PRIVATE) ; |
116 nativeConnect(username, authToken, hostJid, hostId, hostPubkey, | 138 nativeConnect(username, authToken, hostJid, hostId, hostPubkey, |
117 prefs.getString(hostId + "_id", ""), prefs.getString(hostId + "_ secret", "")); | 139 prefs.getString(hostId + "_id", ""), prefs.getString(hostId + "_ secret", "")); |
118 sConnected = true; | 140 sConnected = true; |
119 } | 141 } |
120 | 142 |
121 /** Performs the native portion of the connection. */ | 143 /** Performs the native portion of the connection. */ |
122 private static native void nativeConnect(String username, String authToken, String hostJid, | 144 private static native void nativeConnect(String username, String authToken, String hostJid, |
123 String hostId, String hostPubkey, String pairId, String pairSecret); | 145 String hostId, String hostPubkey, String pairId, String pairSecret); |
124 | 146 |
125 /** Severs the connection and cleans up. Called on the UI thread. */ | 147 /** Severs the connection and cleans up. Called on the UI thread. */ |
126 public static void disconnectFromHost() { | 148 public static void disconnectFromHost() { |
127 if (!sConnected) return; | 149 if (!sConnected) return; |
128 | 150 |
129 synchronized (sProgressIndicatorLock) { | 151 sConnectionListener.onConnectionState(ConnectionListener.STATE_CLOSED, 0 ); |
130 if (sProgressIndicator != null) { | |
131 sProgressIndicator.dismiss(); | |
132 sProgressIndicator = null; | |
133 } | |
134 } | |
135 | 152 |
136 nativeDisconnect(); | 153 nativeDisconnect(); |
137 sSuccessCallback = null; | 154 sConnectionListener = null; |
138 sConnected = false; | 155 sConnected = false; |
139 | 156 |
140 // Drop the reference to free the Bitmap for GC. | 157 // Drop the reference to free the Bitmap for GC. |
141 synchronized (sFrameLock) { | 158 synchronized (sFrameLock) { |
142 sFrameBitmap = null; | 159 sFrameBitmap = null; |
143 } | 160 } |
144 } | 161 } |
145 | 162 |
146 /** Performs the native portion of the cleanup. */ | 163 /** Performs the native portion of the cleanup. */ |
147 private static native void nativeDisconnect(); | 164 private static native void nativeDisconnect(); |
148 | 165 |
149 /** Reports whenever the connection status changes. Called on the UI thread. */ | 166 /** Reports whenever the connection status changes. Called on the UI thread. */ |
150 @CalledByNative | 167 @CalledByNative |
151 private static void reportConnectionStatus(int state, int error) { | 168 private static void reportConnectionStatus(int state, int error) { |
152 if (state < SUCCESSFUL_CONNECTION && error == 0) { | 169 sConnectionListener.onConnectionState(state, error); |
153 // The connection is still being established, so we'll report the cu rrent progress. | |
154 synchronized (sProgressIndicatorLock) { | |
155 if (sProgressIndicator == null) { | |
156 sProgressIndicator = ProgressDialog.show(sContext, sContext. | |
157 getString(R.string.progress_title), sContext.getReso urces(). | |
158 getStringArray(R.array.protoc_states)[state], true, true, | |
159 new DialogInterface.OnCancelListener() { | |
160 @Override | |
161 public void onCancel(DialogInterface dialog) { | |
162 Log.i("jniiface", "User canceled connection initiation"); | |
163 disconnectFromHost(); | |
164 } | |
165 }); | |
166 } else { | |
167 sProgressIndicator.setMessage( | |
168 sContext.getResources().getStringArray(R.array.proto c_states)[state]); | |
169 } | |
170 } | |
171 } else { | |
172 // The connection is complete or has failed, so we can lose the prog ress indicator. | |
173 synchronized (sProgressIndicatorLock) { | |
174 if (sProgressIndicator != null) { | |
175 sProgressIndicator.dismiss(); | |
176 sProgressIndicator = null; | |
177 } | |
178 } | |
179 | |
180 if (state == SUCCESSFUL_CONNECTION) { | |
181 Toast.makeText(sContext, sContext.getResources(). | |
182 getStringArray(R.array.protoc_states)[state], Toast.LENG TH_SHORT).show(); | |
183 | |
184 // Actually display the remote desktop. | |
185 sSuccessCallback.run(); | |
186 } else { | |
187 Toast.makeText(sContext, sContext.getResources().getStringArray( | |
188 R.array.protoc_states)[state] + (error == 0 ? "" : ": " + | |
189 sContext.getResources().getStringArray(R.array.protoc_er rors)[error]), | |
190 Toast.LENGTH_LONG).show(); | |
191 } | |
192 } | |
193 } | 170 } |
194 | 171 |
195 /** Prompts the user to enter a PIN. Called on the UI thread. */ | 172 /** Prompts the user to enter a PIN. Called on the UI thread. */ |
196 @CalledByNative | 173 @CalledByNative |
197 private static void displayAuthenticationPrompt(boolean pairingSupported) { | 174 private static void displayAuthenticationPrompt(boolean pairingSupported) { |
198 AlertDialog.Builder pinPrompt = new AlertDialog.Builder(sContext); | 175 AlertDialog.Builder pinPrompt = new AlertDialog.Builder(sContext); |
199 pinPrompt.setTitle(sContext.getString(R.string.pin_entry_title)); | 176 pinPrompt.setTitle(sContext.getString(R.string.pin_entry_title)); |
200 pinPrompt.setMessage(sContext.getString(R.string.pin_entry_message)); | 177 pinPrompt.setMessage(sContext.getString(R.string.pin_entry_message)); |
201 pinPrompt.setIcon(android.R.drawable.ic_lock_lock); | 178 pinPrompt.setIcon(android.R.drawable.ic_lock_lock); |
202 | 179 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 buffer.asIntBuffer().get(data, 0, data.length); | 369 buffer.asIntBuffer().get(data, 0, data.length); |
393 sCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A RGB_8888); | 370 sCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A RGB_8888); |
394 } | 371 } |
395 | 372 |
396 /** Position of cursor hotspot within cursor image. Called on the graphics t hread. */ | 373 /** Position of cursor hotspot within cursor image. Called on the graphics t hread. */ |
397 public static Point getCursorHotspot() { return sCursorHotspot; } | 374 public static Point getCursorHotspot() { return sCursorHotspot; } |
398 | 375 |
399 /** Returns the current cursor shape. Called on the graphics thread. */ | 376 /** Returns the current cursor shape. Called on the graphics thread. */ |
400 public static Bitmap getCursorBitmap() { return sCursorBitmap; } | 377 public static Bitmap getCursorBitmap() { return sCursorBitmap; } |
401 } | 378 } |
OLD | NEW |