OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 | |
5 package org.chromium.chromoting.jni; | |
6 | |
7 import android.graphics.Bitmap; | |
8 import android.graphics.Point; | |
9 import android.os.Looper; | |
10 | |
11 import org.chromium.base.Log; | |
12 import org.chromium.base.annotations.CalledByNative; | |
13 import org.chromium.base.annotations.JNINamespace; | |
14 import org.chromium.chromoting.AbstractDesktopView; | |
15 import org.chromium.chromoting.Desktop; | |
16 import org.chromium.chromoting.DesktopView; | |
17 import org.chromium.chromoting.DesktopViewFactory; | |
18 | |
19 import java.nio.ByteBuffer; | |
20 import java.nio.ByteOrder; | |
21 | |
22 /** | |
23 * This class is for drawing the desktop on the canvas and controlling the lifet
ime of the | |
24 * corresponding C++ object. It only draws the desktop on the graphics (=display
) thread but also | |
25 * has functions accessible on UI thread. | |
26 */ | |
27 @JNINamespace("remoting") | |
28 public class Display { | |
29 private static final String TAG = "Chromoting"; | |
30 | |
31 // Pointer to the C++ object. Casted to |long|. | |
32 private long mNativeJniDisplayHandler; | |
33 | |
34 /** | |
35 * Callback invoked on the graphics thread to repaint the desktop. Read on t
he UI and | |
36 * graphics threads. Write only on the UI thread. | |
37 */ | |
38 private Runnable mRedrawCallback; | |
39 | |
40 /** | |
41 * Protects access to {@link mRedrawCallback}. | |
42 * Locking is not required when reading on the UI thread. | |
43 */ | |
44 private final Object mRedrawCallbackLock = new Object(); | |
45 | |
46 /** Protects access to {@link mFrameBitmap}. */ | |
47 private final Object mFrameLock = new Object(); | |
48 | |
49 /** Bitmap holding a copy of the latest video frame. Accessed on the UI and
graphics threads. */ | |
50 private Bitmap mFrameBitmap; | |
51 | |
52 /** Position of cursor hot-spot. Accessed on the graphics thread. */ | |
53 private Point mCursorHotspot = new Point(); | |
54 | |
55 /** Bitmap holding the cursor shape. Accessed on the graphics thread. */ | |
56 private Bitmap mCursorBitmap; | |
57 | |
58 private Display(long nativeDisplayHandler) { | |
59 mNativeJniDisplayHandler = nativeDisplayHandler; | |
60 } | |
61 | |
62 /** | |
63 * Sets the redraw callback to the provided functor. Provide a value of null
whenever the | |
64 * window is no longer visible so that we don't continue to draw onto it. Ca
lled on the UI | |
65 * thread. | |
66 */ | |
67 public void provideRedrawCallback(Runnable redrawCallback) { | |
68 synchronized (mRedrawCallbackLock) { | |
69 mRedrawCallback = redrawCallback; | |
70 } | |
71 } | |
72 | |
73 /** | |
74 * Invalidates this object and disconnects from the native display handler.
Called on the | |
75 * display thread by the native code. | |
76 */ | |
77 @CalledByNative | |
78 private void invalidate() { | |
79 // Drop the reference to free the Bitmap for GC. | |
80 synchronized (mFrameLock) { | |
81 mFrameBitmap = null; | |
82 } | |
83 | |
84 provideRedrawCallback(null); | |
85 mNativeJniDisplayHandler = 0; | |
86 } | |
87 | |
88 /** Forces the native graphics thread to redraw to the canvas. Called on the
UI thread. */ | |
89 public boolean redrawGraphics() { | |
90 if (mRedrawCallback == null) return false; | |
91 | |
92 nativeScheduleRedraw(mNativeJniDisplayHandler); | |
93 return true; | |
94 } | |
95 | |
96 /** | |
97 * Called on the graphics thread to perform the redrawing callback requested
by | |
98 * {@link #redrawGraphics}. This is a no-op if the window isn't visible (the
callback is null). | |
99 */ | |
100 @CalledByNative | |
101 void redrawGraphicsInternal() { | |
102 Runnable callback; | |
103 synchronized (mRedrawCallbackLock) { | |
104 callback = mRedrawCallback; | |
105 } | |
106 if (callback != null) { | |
107 callback.run(); | |
108 } | |
109 } | |
110 | |
111 /** | |
112 * Returns a bitmap of the latest video frame. Called on the native graphics
thread when | |
113 * DesktopView is repainted. | |
114 */ | |
115 public Bitmap getVideoFrame() { | |
116 if (Looper.myLooper() == Looper.getMainLooper()) { | |
117 Log.w(TAG, "Canvas being redrawn on UI thread"); | |
118 } | |
119 | |
120 synchronized (mFrameLock) { | |
121 return mFrameBitmap; | |
122 } | |
123 } | |
124 | |
125 /** | |
126 * Set a new video frame. Called on the native graphics thread when a new fr
ame is allocated. | |
127 */ | |
128 @CalledByNative | |
129 void setVideoFrame(Bitmap bitmap) { | |
130 if (Looper.myLooper() == Looper.getMainLooper()) { | |
131 Log.w(TAG, "Video frame updated on UI thread"); | |
132 } | |
133 | |
134 synchronized (mFrameLock) { | |
135 mFrameBitmap = bitmap; | |
136 } | |
137 } | |
138 | |
139 /** | |
140 * Creates a new Bitmap to hold video frame pixels. The returned Bitmap is r
eferenced by native | |
141 * code which writes the decoded frame pixels to it. | |
142 */ | |
143 @CalledByNative | |
144 static Bitmap newBitmap(int width, int height) { | |
145 return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); | |
146 } | |
147 | |
148 /** | |
149 * Updates the cursor shape. This is called on the graphics thread when rece
iving a new cursor | |
150 * shape from the host. | |
151 */ | |
152 @CalledByNative | |
153 void updateCursorShape(int width, int height, int hotspotX, int hotspotY, By
teBuffer buffer) { | |
154 mCursorHotspot = new Point(hotspotX, hotspotY); | |
155 | |
156 int[] data = new int[width * height]; | |
157 buffer.order(ByteOrder.LITTLE_ENDIAN); | |
158 buffer.asIntBuffer().get(data, 0, data.length); | |
159 mCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A
RGB_8888); | |
160 } | |
161 | |
162 /** Position of cursor hotspot within cursor image. Called on the graphics t
hread. */ | |
163 public Point getCursorHotspot() { | |
164 return mCursorHotspot; | |
165 } | |
166 | |
167 /** Returns the current cursor shape. Called on the graphics thread. */ | |
168 public Bitmap getCursorBitmap() { | |
169 return mCursorBitmap; | |
170 } | |
171 | |
172 @CalledByNative | |
173 private void initializeClient(Client client) { | |
174 client.setDesktopViewFactory(new DesktopViewFactory() { | |
175 @Override | |
176 public AbstractDesktopView createDesktopView(Desktop desktop, Client
client) { | |
177 return new DesktopView(Display.this, desktop, client); | |
178 } | |
179 }); | |
180 } | |
181 | |
182 @CalledByNative | |
183 private static Display createJavaDisplayObject(long nativeDisplayHandler) { | |
184 return new Display(nativeDisplayHandler); | |
185 } | |
186 | |
187 /** Schedules a redraw on the native graphics thread. */ | |
188 private native void nativeScheduleRedraw(long nativeJniDisplayHandler); | |
189 } | |
OLD | NEW |