| 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 |