1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "Surface"
18
19 #include <stdio.h>
20
21 #include "android_util_Binder.h"
22 #include "android/graphics/GraphicsJNI.h"
23
24 #include <binder/IMemory.h>
25 #include <gui/SurfaceTexture.h>
26 #include <surfaceflinger/SurfaceComposerClient.h>
27 #include <surfaceflinger/Surface.h>
28 #include <ui/Region.h>
29 #include <ui/Rect.h>
30
31 #include <EGL/egl.h>
32
33 #include <SkCanvas.h>
34 #include <SkBitmap.h>
35 #include <SkRegion.h>
36 #include <SkPixelRef.h>
37
38 #include "jni.h"
39 #include "JNIHelp.h"
40 #include <android_runtime/AndroidRuntime.h>
41 #include <android_runtime/android_view_Surface.h>
42 #include <android_runtime/android_graphics_SurfaceTexture.h>
43 #include <utils/misc.h>
44
45
46 // ----------------------------------------------------------------------------
47
48 namespace android {
49
50 enum {
51 // should match Parcelable.java
52 PARCELABLE_WRITE_RETURN_VALUE = 0x0001
53 };
54
55 // ----------------------------------------------------------------------------
56
57 static const char* const OutOfResourcesException =
58 "android/view/Surface$OutOfResourcesException";
59
60 const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession";
61 const char* const kSurfaceClassPathName = "android/view/Surface";
62
63 struct sso_t {
64 jfieldID client;
65 };
66 static sso_t sso;
67
68 struct so_t {
69 jfieldID surfaceControl;
70 jfieldID surfaceGenerationId;
71 jfieldID surface;
72 jfieldID saveCount;
73 jfieldID canvas;
74 };
75 static so_t so;
76
77 struct ro_t {
78 jfieldID l;
79 jfieldID t;
80 jfieldID r;
81 jfieldID b;
82 };
83 static ro_t ro;
84
85 struct po_t {
86 jfieldID x;
87 jfieldID y;
88 };
89 static po_t po;
90
91 struct co_t {
92 jfieldID surfaceFormat;
93 };
94 static co_t co;
95
96 struct no_t {
97 jfieldID native_canvas;
98 jfieldID native_region;
99 jfieldID native_parcel;
100 };
101 static no_t no;
102
103
104 // ----------------------------------------------------------------------------
105 // ----------------------------------------------------------------------------
106 // ----------------------------------------------------------------------------
107
SurfaceSession_init(JNIEnv * env,jobject clazz)108 static void SurfaceSession_init(JNIEnv* env, jobject clazz)
109 {
110 sp<SurfaceComposerClient> client = new SurfaceComposerClient;
111 client->incStrong(clazz);
112 env->SetIntField(clazz, sso.client, (int)client.get());
113 }
114
SurfaceSession_destroy(JNIEnv * env,jobject clazz)115 static void SurfaceSession_destroy(JNIEnv* env, jobject clazz)
116 {
117 SurfaceComposerClient* client =
118 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
119 if (client != 0) {
120 client->decStrong(clazz);
121 env->SetIntField(clazz, sso.client, 0);
122 }
123 }
124
SurfaceSession_kill(JNIEnv * env,jobject clazz)125 static void SurfaceSession_kill(JNIEnv* env, jobject clazz)
126 {
127 SurfaceComposerClient* client =
128 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
129 if (client != 0) {
130 client->dispose();
131 client->decStrong(clazz);
132 env->SetIntField(clazz, sso.client, 0);
133 }
134 }
135
136 // ----------------------------------------------------------------------------
137
getSurfaceControl(JNIEnv * env,jobject clazz)138 static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz)
139 {
140 SurfaceControl* const p =
141 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
142 return sp<SurfaceControl>(p);
143 }
144
setSurfaceControl(JNIEnv * env,jobject clazz,const sp<SurfaceControl> & surface)145 static void setSurfaceControl(JNIEnv* env, jobject clazz,
146 const sp<SurfaceControl>& surface)
147 {
148 SurfaceControl* const p =
149 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
150 if (surface.get()) {
151 surface->incStrong(clazz);
152 }
153 if (p) {
154 p->decStrong(clazz);
155 }
156 env->SetIntField(clazz, so.surfaceControl, (int)surface.get());
157 }
158
getSurface(JNIEnv * env,jobject clazz)159 static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
160 {
161 sp<Surface> result(Surface_getSurface(env, clazz));
162 if (result == 0) {
163 /*
164 * if this method is called from the WindowManager's process, it means
165 * the client is is not remote, and therefore is allowed to have
166 * a Surface (data), so we create it here.
167 * If we don't have a SurfaceControl, it means we're in a different
168 * process.
169 */
170
171 SurfaceControl* const control =
172 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
173 if (control) {
174 result = control->getSurface();
175 if (result != 0) {
176 result->incStrong(clazz);
177 env->SetIntField(clazz, so.surface, (int)result.get());
178 }
179 }
180 }
181 return result;
182 }
183
android_Surface_getNativeWindow(JNIEnv * env,jobject clazz)184 sp<ANativeWindow> android_Surface_getNativeWindow(
185 JNIEnv* env, jobject clazz) {
186 return getSurface(env, clazz);
187 }
188
android_Surface_isInstanceOf(JNIEnv * env,jobject obj)189 bool android_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
190 jclass surfaceClass = env->FindClass(kSurfaceClassPathName);
191 return env->IsInstanceOf(obj, surfaceClass);
192 }
193
Surface_getSurface(JNIEnv * env,jobject clazz)194 sp<Surface> Surface_getSurface(JNIEnv* env, jobject clazz) {
195 sp<Surface> surface((Surface*)env->GetIntField(clazz, so.surface));
196 return surface;
197 }
198
setSurface(JNIEnv * env,jobject clazz,const sp<Surface> & surface)199 static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
200 {
201 Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
202 if (surface.get()) {
203 surface->incStrong(clazz);
204 }
205 if (p) {
206 p->decStrong(clazz);
207 }
208 env->SetIntField(clazz, so.surface, (int)surface.get());
209 // This test is conservative and it would be better to compare the ISurfaces
210 if (p && p != surface.get()) {
211 jint generationId = env->GetIntField(clazz, so.surfaceGenerationId);
212 generationId++;
213 env->SetIntField(clazz, so.surfaceGenerationId, generationId);
214 }
215 }
216
217 // ----------------------------------------------------------------------------
218
Surface_init(JNIEnv * env,jobject clazz,jobject session,jint,jstring jname,jint dpy,jint w,jint h,jint format,jint flags)219 static void Surface_init(
220 JNIEnv* env, jobject clazz,
221 jobject session,
222 jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
223 {
224 if (session == NULL) {
225 doThrowNPE(env);
226 return;
227 }
228
229 SurfaceComposerClient* client =
230 (SurfaceComposerClient*)env->GetIntField(session, sso.client);
231
232 sp<SurfaceControl> surface;
233 if (jname == NULL) {
234 surface = client->createSurface(dpy, w, h, format, flags);
235 } else {
236 const jchar* str = env->GetStringCritical(jname, 0);
237 const String8 name(str, env->GetStringLength(jname));
238 env->ReleaseStringCritical(jname, str);
239 surface = client->createSurface(name, dpy, w, h, format, flags);
240 }
241
242 if (surface == 0) {
243 jniThrowException(env, OutOfResourcesException, NULL);
244 return;
245 }
246 setSurfaceControl(env, clazz, surface);
247 }
248
Surface_initFromSurfaceTexture(JNIEnv * env,jobject clazz,jobject jst)249 static void Surface_initFromSurfaceTexture(
250 JNIEnv* env, jobject clazz, jobject jst)
251 {
252 sp<ISurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst));
253 sp<Surface> surface(new Surface(st));
254 if (surface == NULL) {
255 jniThrowException(env, OutOfResourcesException, NULL);
256 return;
257 }
258 setSurfaceControl(env, clazz, NULL);
259 setSurface(env, clazz, surface);
260 }
261
Surface_initParcel(JNIEnv * env,jobject clazz,jobject argParcel)262 static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
263 {
264 Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
265 if (parcel == NULL) {
266 doThrowNPE(env);
267 return;
268 }
269
270 sp<Surface> sur(Surface::readFromParcel(*parcel));
271 setSurface(env, clazz, sur);
272 }
273
Surface_getIdentity(JNIEnv * env,jobject clazz)274 static jint Surface_getIdentity(JNIEnv* env, jobject clazz)
275 {
276 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
277 if (control != 0) return (jint) control->getIdentity();
278 const sp<Surface>& surface(getSurface(env, clazz));
279 if (surface != 0) return (jint) surface->getIdentity();
280 return -1;
281 }
282
Surface_destroy(JNIEnv * env,jobject clazz,uintptr_t * ostack)283 static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack)
284 {
285 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
286 if (SurfaceControl::isValid(surface)) {
287 surface->clear();
288 }
289 setSurfaceControl(env, clazz, 0);
290 setSurface(env, clazz, 0);
291 }
292
Surface_release(JNIEnv * env,jobject clazz,uintptr_t * ostack)293 static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack)
294 {
295 setSurfaceControl(env, clazz, 0);
296 setSurface(env, clazz, 0);
297 }
298
Surface_isValid(JNIEnv * env,jobject clazz)299 static jboolean Surface_isValid(JNIEnv* env, jobject clazz)
300 {
301 const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz));
302 if (surfaceControl != 0) {
303 return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
304 }
305 const sp<Surface>& surface(getSurface(env, clazz));
306 return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
307 }
308
convertPixelFormat(PixelFormat format)309 static inline SkBitmap::Config convertPixelFormat(PixelFormat format)
310 {
311 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
312 we can map to SkBitmap::kARGB_8888_Config, and optionally call
313 bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
314 */
315 switch (format) {
316 case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config;
317 case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config;
318 case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config;
319 case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config;
320 case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config;
321 default: return SkBitmap::kNo_Config;
322 }
323 }
324
Surface_lockCanvas(JNIEnv * env,jobject clazz,jobject dirtyRect)325 static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
326 {
327 const sp<Surface>& surface(getSurface(env, clazz));
328 if (!Surface::isValid(surface)) {
329 doThrowIAE(env);
330 return 0;
331 }
332
333 // get dirty region
334 Region dirtyRegion;
335 if (dirtyRect) {
336 Rect dirty;
337 dirty.left = env->GetIntField(dirtyRect, ro.l);
338 dirty.top = env->GetIntField(dirtyRect, ro.t);
339 dirty.right = env->GetIntField(dirtyRect, ro.r);
340 dirty.bottom= env->GetIntField(dirtyRect, ro.b);
341 if (!dirty.isEmpty()) {
342 dirtyRegion.set(dirty);
343 }
344 } else {
345 dirtyRegion.set(Rect(0x3FFF,0x3FFF));
346 }
347
348 Surface::SurfaceInfo info;
349 status_t err = surface->lock(&info, &dirtyRegion);
350 if (err < 0) {
351 const char* const exception = (err == NO_MEMORY) ?
352 OutOfResourcesException :
353 "java/lang/IllegalArgumentException";
354 jniThrowException(env, exception, NULL);
355 return 0;
356 }
357
358 // Associate a SkCanvas object to this surface
359 jobject canvas = env->GetObjectField(clazz, so.canvas);
360 env->SetIntField(canvas, co.surfaceFormat, info.format);
361
362 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
363 SkBitmap bitmap;
364 ssize_t bpr = info.s * bytesPerPixel(info.format);
365 bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
366 if (info.format == PIXEL_FORMAT_RGBX_8888) {
367 bitmap.setIsOpaque(true);
368 }
369 if (info.w > 0 && info.h > 0) {
370 bitmap.setPixels(info.bits);
371 } else {
372 // be safe with an empty bitmap.
373 bitmap.setPixels(NULL);
374 }
375 nativeCanvas->setBitmapDevice(bitmap);
376
377 SkRegion clipReg;
378 if (dirtyRegion.isRect()) { // very common case
379 const Rect b(dirtyRegion.getBounds());
380 clipReg.setRect(b.left, b.top, b.right, b.bottom);
381 } else {
382 size_t count;
383 Rect const* r = dirtyRegion.getArray(&count);
384 while (count) {
385 clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
386 r++, count--;
387 }
388 }
389
390 nativeCanvas->clipRegion(clipReg);
391
392 int saveCount = nativeCanvas->save();
393 env->SetIntField(clazz, so.saveCount, saveCount);
394
395 if (dirtyRect) {
396 const Rect& bounds(dirtyRegion.getBounds());
397 env->SetIntField(dirtyRect, ro.l, bounds.left);
398 env->SetIntField(dirtyRect, ro.t, bounds.top);
399 env->SetIntField(dirtyRect, ro.r, bounds.right);
400 env->SetIntField(dirtyRect, ro.b, bounds.bottom);
401 }
402
403 return canvas;
404 }
405
Surface_unlockCanvasAndPost(JNIEnv * env,jobject clazz,jobject argCanvas)406 static void Surface_unlockCanvasAndPost(
407 JNIEnv* env, jobject clazz, jobject argCanvas)
408 {
409 jobject canvas = env->GetObjectField(clazz, so.canvas);
410 if (env->IsSameObject(canvas, argCanvas) == JNI_FALSE) {
411 doThrowIAE(env);
412 return;
413 }
414
415 const sp<Surface>& surface(getSurface(env, clazz));
416 if (!Surface::isValid(surface))
417 return;
418
419 // detach the canvas from the surface
420 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
421 int saveCount = env->GetIntField(clazz, so.saveCount);
422 nativeCanvas->restoreToCount(saveCount);
423 nativeCanvas->setBitmapDevice(SkBitmap());
424 env->SetIntField(clazz, so.saveCount, 0);
425
426 // unlock surface
427 status_t err = surface->unlockAndPost();
428 if (err < 0) {
429 doThrowIAE(env);
430 }
431 }
432
Surface_unlockCanvas(JNIEnv * env,jobject clazz,jobject argCanvas)433 static void Surface_unlockCanvas(
434 JNIEnv* env, jobject clazz, jobject argCanvas)
435 {
436 // XXX: this API has been removed
437 doThrowIAE(env);
438 }
439
Surface_openTransaction(JNIEnv * env,jobject clazz)440 static void Surface_openTransaction(
441 JNIEnv* env, jobject clazz)
442 {
443 SurfaceComposerClient::openGlobalTransaction();
444 }
445
Surface_closeTransaction(JNIEnv * env,jobject clazz)446 static void Surface_closeTransaction(
447 JNIEnv* env, jobject clazz)
448 {
449 SurfaceComposerClient::closeGlobalTransaction();
450 }
451
Surface_setOrientation(JNIEnv * env,jobject clazz,jint display,jint orientation,jint flags)452 static void Surface_setOrientation(
453 JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags)
454 {
455 int err = SurfaceComposerClient::setOrientation(display, orientation, flags);
456 if (err < 0) {
457 doThrowIAE(env);
458 }
459 }
460
Surface_freezeDisplay(JNIEnv * env,jobject clazz,jint display)461 static void Surface_freezeDisplay(
462 JNIEnv* env, jobject clazz, jint display)
463 {
464 int err = SurfaceComposerClient::freezeDisplay(display, 0);
465 if (err < 0) {
466 doThrowIAE(env);
467 }
468 }
469
Surface_unfreezeDisplay(JNIEnv * env,jobject clazz,jint display)470 static void Surface_unfreezeDisplay(
471 JNIEnv* env, jobject clazz, jint display)
472 {
473 int err = SurfaceComposerClient::unfreezeDisplay(display, 0);
474 if (err < 0) {
475 doThrowIAE(env);
476 }
477 }
478
479 class ScreenshotPixelRef : public SkPixelRef {
480 public:
ScreenshotPixelRef(SkColorTable * ctable)481 ScreenshotPixelRef(SkColorTable* ctable) {
482 fCTable = ctable;
483 SkSafeRef(ctable);
484 setImmutable();
485 }
~ScreenshotPixelRef()486 virtual ~ScreenshotPixelRef() {
487 SkSafeUnref(fCTable);
488 }
489
update(int width,int height,int minLayer,int maxLayer,bool allLayers)490 status_t update(int width, int height, int minLayer, int maxLayer, bool allLayers) {
491 status_t res = (width > 0 && height > 0)
492 ? (allLayers
493 ? mScreenshot.update(width, height)
494 : mScreenshot.update(width, height, minLayer, maxLayer))
495 : mScreenshot.update();
496 if (res != NO_ERROR) {
497 return res;
498 }
499
500 return NO_ERROR;
501 }
502
getWidth() const503 uint32_t getWidth() const {
504 return mScreenshot.getWidth();
505 }
506
getHeight() const507 uint32_t getHeight() const {
508 return mScreenshot.getHeight();
509 }
510
getStride() const511 uint32_t getStride() const {
512 return mScreenshot.getStride();
513 }
514
getFormat() const515 uint32_t getFormat() const {
516 return mScreenshot.getFormat();
517 }
518
519 protected:
520 // overrides from SkPixelRef
onLockPixels(SkColorTable ** ct)521 virtual void* onLockPixels(SkColorTable** ct) {
522 *ct = fCTable;
523 return (void*)mScreenshot.getPixels();
524 }
525
onUnlockPixels()526 virtual void onUnlockPixels() {
527 }
528
529 private:
530 ScreenshotClient mScreenshot;
531 SkColorTable* fCTable;
532
533 typedef SkPixelRef INHERITED;
534 };
535
doScreenshot(JNIEnv * env,jobject clazz,jint width,jint height,jint minLayer,jint maxLayer,bool allLayers)536 static jobject doScreenshot(JNIEnv* env, jobject clazz, jint width, jint height,
537 jint minLayer, jint maxLayer, bool allLayers)
538 {
539 ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
540 if (pixels->update(width, height, minLayer, maxLayer, allLayers) != NO_ERROR) {
541 delete pixels;
542 return 0;
543 }
544
545 uint32_t w = pixels->getWidth();
546 uint32_t h = pixels->getHeight();
547 uint32_t s = pixels->getStride();
548 uint32_t f = pixels->getFormat();
549 ssize_t bpr = s * android::bytesPerPixel(f);
550
551 SkBitmap* bitmap = new SkBitmap();
552 bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
553 if (f == PIXEL_FORMAT_RGBX_8888) {
554 bitmap->setIsOpaque(true);
555 }
556
557 if (w > 0 && h > 0) {
558 bitmap->setPixelRef(pixels)->unref();
559 bitmap->lockPixels();
560 } else {
561 // be safe with an empty bitmap.
562 delete pixels;
563 bitmap->setPixels(NULL);
564 }
565
566 return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
567 }
568
Surface_screenshotAll(JNIEnv * env,jobject clazz,jint width,jint height)569 static jobject Surface_screenshotAll(JNIEnv* env, jobject clazz, jint width, jint height)
570 {
571 return doScreenshot(env, clazz, width, height, 0, 0, true);
572 }
573
Surface_screenshot(JNIEnv * env,jobject clazz,jint width,jint height,jint minLayer,jint maxLayer,bool allLayers)574 static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height,
575 jint minLayer, jint maxLayer, bool allLayers)
576 {
577 return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false);
578 }
579
Surface_setLayer(JNIEnv * env,jobject clazz,jint zorder)580 static void Surface_setLayer(
581 JNIEnv* env, jobject clazz, jint zorder)
582 {
583 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
584 if (surface == 0) return;
585 status_t err = surface->setLayer(zorder);
586 if (err<0 && err!=NO_INIT) {
587 doThrowIAE(env);
588 }
589 }
590
Surface_setPosition(JNIEnv * env,jobject clazz,jfloat x,jfloat y)591 static void Surface_setPosition(
592 JNIEnv* env, jobject clazz, jfloat x, jfloat y)
593 {
594 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
595 if (surface == 0) return;
596 status_t err = surface->setPosition(x, y);
597 if (err<0 && err!=NO_INIT) {
598 doThrowIAE(env);
599 }
600 }
601
Surface_setSize(JNIEnv * env,jobject clazz,jint w,jint h)602 static void Surface_setSize(
603 JNIEnv* env, jobject clazz, jint w, jint h)
604 {
605 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
606 if (surface == 0) return;
607 status_t err = surface->setSize(w, h);
608 if (err<0 && err!=NO_INIT) {
609 doThrowIAE(env);
610 }
611 }
612
Surface_hide(JNIEnv * env,jobject clazz)613 static void Surface_hide(
614 JNIEnv* env, jobject clazz)
615 {
616 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
617 if (surface == 0) return;
618 status_t err = surface->hide();
619 if (err<0 && err!=NO_INIT) {
620 doThrowIAE(env);
621 }
622 }
623
Surface_show(JNIEnv * env,jobject clazz)624 static void Surface_show(
625 JNIEnv* env, jobject clazz)
626 {
627 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
628 if (surface == 0) return;
629 status_t err = surface->show();
630 if (err<0 && err!=NO_INIT) {
631 doThrowIAE(env);
632 }
633 }
634
Surface_freeze(JNIEnv * env,jobject clazz)635 static void Surface_freeze(
636 JNIEnv* env, jobject clazz)
637 {
638 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
639 if (surface == 0) return;
640 status_t err = surface->freeze();
641 if (err<0 && err!=NO_INIT) {
642 doThrowIAE(env);
643 }
644 }
645
Surface_unfreeze(JNIEnv * env,jobject clazz)646 static void Surface_unfreeze(
647 JNIEnv* env, jobject clazz)
648 {
649 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
650 if (surface == 0) return;
651 status_t err = surface->unfreeze();
652 if (err<0 && err!=NO_INIT) {
653 doThrowIAE(env);
654 }
655 }
656
Surface_setFlags(JNIEnv * env,jobject clazz,jint flags,jint mask)657 static void Surface_setFlags(
658 JNIEnv* env, jobject clazz, jint flags, jint mask)
659 {
660 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
661 if (surface == 0) return;
662 status_t err = surface->setFlags(flags, mask);
663 if (err<0 && err!=NO_INIT) {
664 doThrowIAE(env);
665 }
666 }
667
Surface_setTransparentRegion(JNIEnv * env,jobject clazz,jobject argRegion)668 static void Surface_setTransparentRegion(
669 JNIEnv* env, jobject clazz, jobject argRegion)
670 {
671 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
672 if (surface == 0) return;
673 SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
674
675 const SkIRect& b(nativeRegion->getBounds());
676 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
677 if (nativeRegion->isComplex()) {
678 SkRegion::Iterator it(*nativeRegion);
679 while (!it.done()) {
680 const SkIRect& r(it.rect());
681 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
682 it.next();
683 }
684 }
685
686 status_t err = surface->setTransparentRegionHint(reg);
687 if (err<0 && err!=NO_INIT) {
688 doThrowIAE(env);
689 }
690 }
691
Surface_setAlpha(JNIEnv * env,jobject clazz,jfloat alpha)692 static void Surface_setAlpha(
693 JNIEnv* env, jobject clazz, jfloat alpha)
694 {
695 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
696 if (surface == 0) return;
697 status_t err = surface->setAlpha(alpha);
698 if (err<0 && err!=NO_INIT) {
699 doThrowIAE(env);
700 }
701 }
702
Surface_setMatrix(JNIEnv * env,jobject clazz,jfloat dsdx,jfloat dtdx,jfloat dsdy,jfloat dtdy)703 static void Surface_setMatrix(
704 JNIEnv* env, jobject clazz,
705 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy)
706 {
707 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
708 if (surface == 0) return;
709 status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
710 if (err<0 && err!=NO_INIT) {
711 doThrowIAE(env);
712 }
713 }
714
Surface_setFreezeTint(JNIEnv * env,jobject clazz,jint tint)715 static void Surface_setFreezeTint(
716 JNIEnv* env, jobject clazz,
717 jint tint)
718 {
719 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
720 if (surface == 0) return;
721 status_t err = surface->setFreezeTint(tint);
722 if (err<0 && err!=NO_INIT) {
723 doThrowIAE(env);
724 }
725 }
726
727 // ----------------------------------------------------------------------------
728
Surface_copyFrom(JNIEnv * env,jobject clazz,jobject other)729 static void Surface_copyFrom(
730 JNIEnv* env, jobject clazz, jobject other)
731 {
732 if (clazz == other)
733 return;
734
735 if (other == NULL) {
736 doThrowNPE(env);
737 return;
738 }
739
740 /*
741 * This is used by the WindowManagerService just after constructing
742 * a Surface and is necessary for returning the Surface reference to
743 * the caller. At this point, we should only have a SurfaceControl.
744 */
745
746 const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
747 const sp<SurfaceControl>& rhs = getSurfaceControl(env, other);
748 if (!SurfaceControl::isSameSurface(surface, rhs)) {
749 // we reassign the surface only if it's a different one
750 // otherwise we would loose our client-side state.
751 setSurfaceControl(env, clazz, rhs);
752 }
753 }
754
Surface_readFromParcel(JNIEnv * env,jobject clazz,jobject argParcel)755 static void Surface_readFromParcel(
756 JNIEnv* env, jobject clazz, jobject argParcel)
757 {
758 Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel);
759 if (parcel == NULL) {
760 doThrowNPE(env);
761 return;
762 }
763
764 sp<Surface> sur(Surface::readFromParcel(*parcel));
765 setSurface(env, clazz, sur);
766 }
767
Surface_writeToParcel(JNIEnv * env,jobject clazz,jobject argParcel,jint flags)768 static void Surface_writeToParcel(
769 JNIEnv* env, jobject clazz, jobject argParcel, jint flags)
770 {
771 Parcel* parcel = (Parcel*)env->GetIntField(
772 argParcel, no.native_parcel);
773
774 if (parcel == NULL) {
775 doThrowNPE(env);
776 return;
777 }
778
779 // The Java instance may have a SurfaceControl (in the case of the
780 // WindowManager or a system app). In that case, we defer to the
781 // SurfaceControl to send its ISurface. Otherwise, if the Surface is
782 // available we let it parcel itself. Finally, if the Surface is also
783 // NULL we fall back to using the SurfaceControl path which sends an
784 // empty surface; this matches legacy behavior.
785 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
786 if (control != NULL) {
787 SurfaceControl::writeSurfaceToParcel(control, parcel);
788 } else {
789 sp<Surface> surface(Surface_getSurface(env, clazz));
790 if (surface != NULL) {
791 Surface::writeToParcel(surface, parcel);
792 } else {
793 SurfaceControl::writeSurfaceToParcel(NULL, parcel);
794 }
795 }
796 if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
797 setSurfaceControl(env, clazz, NULL);
798 setSurface(env, clazz, NULL);
799 }
800 }
801
802 // ----------------------------------------------------------------------------
803 // ----------------------------------------------------------------------------
804 // ----------------------------------------------------------------------------
805
806 static void nativeClassInit(JNIEnv* env, jclass clazz);
807
808 static JNINativeMethod gSurfaceSessionMethods[] = {
809 {"init", "()V", (void*)SurfaceSession_init },
810 {"destroy", "()V", (void*)SurfaceSession_destroy },
811 {"kill", "()V", (void*)SurfaceSession_kill },
812 };
813
814 static JNINativeMethod gSurfaceMethods[] = {
815 {"nativeClassInit", "()V", (void*)nativeClassInit },
816 {"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init },
817 {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel },
818 {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture },
819 {"getIdentity", "()I", (void*)Surface_getIdentity },
820 {"destroy", "()V", (void*)Surface_destroy },
821 {"release", "()V", (void*)Surface_release },
822 {"copyFrom", "(Landroid/view/Surface;)V", (void*)Surface_copyFrom },
823 {"isValid", "()Z", (void*)Surface_isValid },
824 {"lockCanvasNative", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", (void*)Surface_lockCanvas },
825 {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
826 {"unlockCanvas", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
827 {"openTransaction", "()V", (void*)Surface_openTransaction },
828 {"closeTransaction", "()V", (void*)Surface_closeTransaction },
829 {"setOrientation", "(III)V", (void*)Surface_setOrientation },
830 {"freezeDisplay", "(I)V", (void*)Surface_freezeDisplay },
831 {"unfreezeDisplay", "(I)V", (void*)Surface_unfreezeDisplay },
832 {"screenshot", "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
833 {"screenshot", "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
834 {"setLayer", "(I)V", (void*)Surface_setLayer },
835 {"setPosition", "(FF)V",(void*)Surface_setPosition },
836 {"setSize", "(II)V",(void*)Surface_setSize },
837 {"hide", "()V", (void*)Surface_hide },
838 {"show", "()V", (void*)Surface_show },
839 {"freeze", "()V", (void*)Surface_freeze },
840 {"unfreeze", "()V", (void*)Surface_unfreeze },
841 {"setFlags", "(II)V",(void*)Surface_setFlags },
842 {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
843 {"setAlpha", "(F)V", (void*)Surface_setAlpha },
844 {"setMatrix", "(FFFF)V", (void*)Surface_setMatrix },
845 {"setFreezeTint", "(I)V", (void*)Surface_setFreezeTint },
846 {"readFromParcel", "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
847 {"writeToParcel", "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
848 };
849
nativeClassInit(JNIEnv * env,jclass clazz)850 void nativeClassInit(JNIEnv* env, jclass clazz)
851 {
852 so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
853 so.surfaceGenerationId = env->GetFieldID(clazz, "mSurfaceGenerationId", "I");
854 so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
855 so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
856 so.canvas = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
857
858 jclass surfaceSession = env->FindClass("android/view/SurfaceSession");
859 sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
860
861 jclass canvas = env->FindClass("android/graphics/Canvas");
862 no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I");
863 co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I");
864
865 jclass region = env->FindClass("android/graphics/Region");
866 no.native_region = env->GetFieldID(region, "mNativeRegion", "I");
867
868 jclass parcel = env->FindClass("android/os/Parcel");
869 no.native_parcel = env->GetFieldID(parcel, "mObject", "I");
870
871 jclass rect = env->FindClass("android/graphics/Rect");
872 ro.l = env->GetFieldID(rect, "left", "I");
873 ro.t = env->GetFieldID(rect, "top", "I");
874 ro.r = env->GetFieldID(rect, "right", "I");
875 ro.b = env->GetFieldID(rect, "bottom", "I");
876
877 jclass point = env->FindClass("android/graphics/Point");
878 po.x = env->GetFieldID(point, "x", "I");
879 po.y = env->GetFieldID(point, "y", "I");
880 }
881
register_android_view_Surface(JNIEnv * env)882 int register_android_view_Surface(JNIEnv* env)
883 {
884 int err;
885 err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName,
886 gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods));
887
888 err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName,
889 gSurfaceMethods, NELEM(gSurfaceMethods));
890 return err;
891 }
892
893 };
894