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
23 #include <surfaceflinger/SurfaceComposerClient.h>
24 #include <surfaceflinger/Surface.h>
25 #include <ui/Region.h>
26 #include <ui/Rect.h>
27
28 #include <EGL/egl.h>
29
30 #include <SkCanvas.h>
31 #include <SkBitmap.h>
32 #include <SkRegion.h>
33
34 #include "jni.h"
35 #include <android_runtime/AndroidRuntime.h>
36 #include <android_runtime/android_view_Surface.h>
37 #include <utils/misc.h>
38
39
40 // ----------------------------------------------------------------------------
41
42 namespace android {
43
44 enum {
45 // should match Parcelable.java
46 PARCELABLE_WRITE_RETURN_VALUE = 0x0001
47 };
48
49 // ----------------------------------------------------------------------------
50
51 static const char* const OutOfResourcesException =
52 "android/view/Surface$OutOfResourcesException";
53
54 struct sso_t {
55 jfieldID client;
56 };
57 static sso_t sso;
58
59 struct so_t {
60 jfieldID surfaceControl;
61 jfieldID surface;
62 jfieldID saveCount;
63 jfieldID canvas;
64 };
65 static so_t so;
66
67 struct ro_t {
68 jfieldID l;
69 jfieldID t;
70 jfieldID r;
71 jfieldID b;
72 };
73 static ro_t ro;
74
75 struct po_t {
76 jfieldID x;
77 jfieldID y;
78 };
79 static po_t po;
80
81 struct co_t {
82 jfieldID surfaceFormat;
83 };
84 static co_t co;
85
86 struct no_t {
87 jfieldID native_canvas;
88 jfieldID native_region;
89 jfieldID native_parcel;
90 };
91 static no_t no;
92
93
94 static __attribute__((noinline))
doThrow(JNIEnv * env,const char * exc,const char * msg=NULL)95 void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
96 {
97 if (!env->ExceptionOccurred()) {
98 jclass npeClazz = env->FindClass(exc);
99 env->ThrowNew(npeClazz, msg);
100 }
101 }
102
103 // ----------------------------------------------------------------------------
104 // ----------------------------------------------------------------------------
105 // ----------------------------------------------------------------------------
106
SurfaceSession_init(JNIEnv * env,jobject clazz)107 static void SurfaceSession_init(JNIEnv* env, jobject clazz)
108 {
109 sp<SurfaceComposerClient> client = new SurfaceComposerClient;
110 client->incStrong(clazz);
111 env->SetIntField(clazz, sso.client, (int)client.get());
112 }
113
SurfaceSession_destroy(JNIEnv * env,jobject clazz)114 static void SurfaceSession_destroy(JNIEnv* env, jobject clazz)
115 {
116 SurfaceComposerClient* client =
117 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
118 if (client != 0) {
119 client->decStrong(clazz);
120 env->SetIntField(clazz, sso.client, 0);
121 }
122 }
123
SurfaceSession_kill(JNIEnv * env,jobject clazz)124 static void SurfaceSession_kill(JNIEnv* env, jobject clazz)
125 {
126 SurfaceComposerClient* client =
127 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
128 if (client != 0) {
129 client->dispose();
130 client->decStrong(clazz);
131 env->SetIntField(clazz, sso.client, 0);
132 }
133 }
134
135 // ----------------------------------------------------------------------------
136
getSurfaceControl(JNIEnv * env,jobject clazz)137 static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz)
138 {
139 SurfaceControl* const p =
140 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
141 return sp<SurfaceControl>(p);
142 }
143
setSurfaceControl(JNIEnv * env,jobject clazz,const sp<SurfaceControl> & surface)144 static void setSurfaceControl(JNIEnv* env, jobject clazz,
145 const sp<SurfaceControl>& surface)
146 {
147 SurfaceControl* const p =
148 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
149 if (surface.get()) {
150 surface->incStrong(clazz);
151 }
152 if (p) {
153 p->decStrong(clazz);
154 }
155 env->SetIntField(clazz, so.surfaceControl, (int)surface.get());
156 }
157
getSurface(JNIEnv * env,jobject clazz)158 static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
159 {
160 sp<Surface> result((Surface*)env->GetIntField(clazz, so.surface));
161 if (result == 0) {
162 /*
163 * if this method is called from the WindowManager's process, it means
164 * the client is is not remote, and therefore is allowed to have
165 * a Surface (data), so we create it here.
166 * If we don't have a SurfaceControl, it means we're in a different
167 * process.
168 */
169
170 SurfaceControl* const control =
171 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
172 if (control) {
173 result = control->getSurface();
174 if (result != 0) {
175 result->incStrong(clazz);
176 env->SetIntField(clazz, so.surface, (int)result.get());
177 }
178 }
179 }
180 return result;
181 }
182
android_Surface_getNativeWindow(JNIEnv * env,jobject clazz)183 sp<ANativeWindow> android_Surface_getNativeWindow(
184 JNIEnv* env, jobject clazz) {
185 return getSurface(env, clazz).get();
186 }
187
setSurface(JNIEnv * env,jobject clazz,const sp<Surface> & surface)188 static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
189 {
190 Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
191 if (surface.get()) {
192 surface->incStrong(clazz);
193 }
194 if (p) {
195 p->decStrong(clazz);
196 }
197 env->SetIntField(clazz, so.surface, (int)surface.get());
198 }
199
200 // ----------------------------------------------------------------------------
201
Surface_init(JNIEnv * env,jobject clazz,jobject session,jint pid,jstring jname,jint dpy,jint w,jint h,jint format,jint flags)202 static void Surface_init(
203 JNIEnv* env, jobject clazz,
204 jobject session,
205 jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
206 {
207 if (session == NULL) {
208 doThrow(env, "java/lang/NullPointerException");
209 return;
210 }
211
212 SurfaceComposerClient* client =
213 (SurfaceComposerClient*)env->GetIntField(session, sso.client);
214
215 sp<SurfaceControl> surface;
216 if (jname == NULL) {
217 surface = client->createSurface(pid, dpy, w, h, format, flags);
218 } else {
219 const jchar* str = env->GetStringCritical(jname, 0);
220 const String8 name(str, env->GetStringLength(jname));
221 env->ReleaseStringCritical(jname, str);
222 surface = client->createSurface(pid, name, dpy, w, h, format, flags);
223 }
224
225 if (surface == 0) {
226 doThrow(env, OutOfResourcesException);
227 return;
228 }
229 setSurfaceControl(env, clazz, surface);
230 }
231
Surface_initParcel(JNIEnv * env,jobject clazz,jobject argParcel)232 static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
233 {
234 Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
235 if (parcel == NULL) {
236 doThrow(env, "java/lang/NullPointerException", NULL);
237 return;
238 }
239
240 sp<Surface> sur(Surface::readFromParcel(*parcel));
241 setSurface(env, clazz, sur);
242 }
243
Surface_getIdentity(JNIEnv * env,jobject clazz)244 static jint Surface_getIdentity(JNIEnv* env, jobject clazz)
245 {
246 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
247 if (control != 0) return (jint) control->getIdentity();
248 const sp<Surface>& surface(getSurface(env, clazz));
249 if (surface != 0) return (jint) surface->getIdentity();
250 return -1;
251 }
252
Surface_destroy(JNIEnv * env,jobject clazz,uintptr_t * ostack)253 static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack)
254 {
255 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
256 if (SurfaceControl::isValid(surface)) {
257 surface->clear();
258 }
259 setSurfaceControl(env, clazz, 0);
260 setSurface(env, clazz, 0);
261 }
262
Surface_release(JNIEnv * env,jobject clazz,uintptr_t * ostack)263 static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack)
264 {
265 setSurfaceControl(env, clazz, 0);
266 setSurface(env, clazz, 0);
267 }
268
Surface_isValid(JNIEnv * env,jobject clazz)269 static jboolean Surface_isValid(JNIEnv* env, jobject clazz)
270 {
271 const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz));
272 if (surfaceControl != 0) {
273 return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
274 }
275 const sp<Surface>& surface(getSurface(env, clazz));
276 return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
277 }
278
convertPixelFormat(PixelFormat format)279 static inline SkBitmap::Config convertPixelFormat(PixelFormat format)
280 {
281 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
282 we can map to SkBitmap::kARGB_8888_Config, and optionally call
283 bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
284 */
285 switch (format) {
286 case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config;
287 case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config;
288 case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config;
289 case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config;
290 case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config;
291 default: return SkBitmap::kNo_Config;
292 }
293 }
294
Surface_lockCanvas(JNIEnv * env,jobject clazz,jobject dirtyRect)295 static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
296 {
297 const sp<Surface>& surface(getSurface(env, clazz));
298 if (!Surface::isValid(surface))
299 return 0;
300
301 // get dirty region
302 Region dirtyRegion;
303 if (dirtyRect) {
304 Rect dirty;
305 dirty.left = env->GetIntField(dirtyRect, ro.l);
306 dirty.top = env->GetIntField(dirtyRect, ro.t);
307 dirty.right = env->GetIntField(dirtyRect, ro.r);
308 dirty.bottom= env->GetIntField(dirtyRect, ro.b);
309 if (!dirty.isEmpty()) {
310 dirtyRegion.set(dirty);
311 }
312 } else {
313 dirtyRegion.set(Rect(0x3FFF,0x3FFF));
314 }
315
316 Surface::SurfaceInfo info;
317 status_t err = surface->lock(&info, &dirtyRegion);
318 if (err < 0) {
319 const char* const exception = (err == NO_MEMORY) ?
320 OutOfResourcesException :
321 "java/lang/IllegalArgumentException";
322 doThrow(env, exception, NULL);
323 return 0;
324 }
325
326 // Associate a SkCanvas object to this surface
327 jobject canvas = env->GetObjectField(clazz, so.canvas);
328 env->SetIntField(canvas, co.surfaceFormat, info.format);
329
330 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
331 SkBitmap bitmap;
332 ssize_t bpr = info.s * bytesPerPixel(info.format);
333 bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
334 if (info.format == PIXEL_FORMAT_RGBX_8888) {
335 bitmap.setIsOpaque(true);
336 }
337 if (info.w > 0 && info.h > 0) {
338 bitmap.setPixels(info.bits);
339 } else {
340 // be safe with an empty bitmap.
341 bitmap.setPixels(NULL);
342 }
343 nativeCanvas->setBitmapDevice(bitmap);
344
345 SkRegion clipReg;
346 if (dirtyRegion.isRect()) { // very common case
347 const Rect b(dirtyRegion.getBounds());
348 clipReg.setRect(b.left, b.top, b.right, b.bottom);
349 } else {
350 size_t count;
351 Rect const* r = dirtyRegion.getArray(&count);
352 while (count) {
353 clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
354 r++, count--;
355 }
356 }
357
358 nativeCanvas->clipRegion(clipReg);
359
360 int saveCount = nativeCanvas->save();
361 env->SetIntField(clazz, so.saveCount, saveCount);
362
363 if (dirtyRect) {
364 const Rect& bounds(dirtyRegion.getBounds());
365 env->SetIntField(dirtyRect, ro.l, bounds.left);
366 env->SetIntField(dirtyRect, ro.t, bounds.top);
367 env->SetIntField(dirtyRect, ro.r, bounds.right);
368 env->SetIntField(dirtyRect, ro.b, bounds.bottom);
369 }
370
371 return canvas;
372 }
373
Surface_unlockCanvasAndPost(JNIEnv * env,jobject clazz,jobject argCanvas)374 static void Surface_unlockCanvasAndPost(
375 JNIEnv* env, jobject clazz, jobject argCanvas)
376 {
377 jobject canvas = env->GetObjectField(clazz, so.canvas);
378 if (canvas != argCanvas) {
379 doThrow(env, "java/lang/IllegalArgumentException", NULL);
380 return;
381 }
382
383 const sp<Surface>& surface(getSurface(env, clazz));
384 if (!Surface::isValid(surface))
385 return;
386
387 // detach the canvas from the surface
388 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
389 int saveCount = env->GetIntField(clazz, so.saveCount);
390 nativeCanvas->restoreToCount(saveCount);
391 nativeCanvas->setBitmapDevice(SkBitmap());
392 env->SetIntField(clazz, so.saveCount, 0);
393
394 // unlock surface
395 status_t err = surface->unlockAndPost();
396 if (err < 0) {
397 doThrow(env, "java/lang/IllegalArgumentException", NULL);
398 }
399 }
400
Surface_unlockCanvas(JNIEnv * env,jobject clazz,jobject argCanvas)401 static void Surface_unlockCanvas(
402 JNIEnv* env, jobject clazz, jobject argCanvas)
403 {
404 // XXX: this API has been removed
405 doThrow(env, "java/lang/IllegalArgumentException", NULL);
406 }
407
Surface_openTransaction(JNIEnv * env,jobject clazz)408 static void Surface_openTransaction(
409 JNIEnv* env, jobject clazz)
410 {
411 SurfaceComposerClient::openGlobalTransaction();
412 }
413
Surface_closeTransaction(JNIEnv * env,jobject clazz)414 static void Surface_closeTransaction(
415 JNIEnv* env, jobject clazz)
416 {
417 SurfaceComposerClient::closeGlobalTransaction();
418 }
419
Surface_setOrientation(JNIEnv * env,jobject clazz,jint display,jint orientation,jint flags)420 static void Surface_setOrientation(
421 JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags)
422 {
423 int err = SurfaceComposerClient::setOrientation(display, orientation, flags);
424 if (err < 0) {
425 doThrow(env, "java/lang/IllegalArgumentException", NULL);
426 }
427 }
428
Surface_freezeDisplay(JNIEnv * env,jobject clazz,jint display)429 static void Surface_freezeDisplay(
430 JNIEnv* env, jobject clazz, jint display)
431 {
432 int err = SurfaceComposerClient::freezeDisplay(display, 0);
433 if (err < 0) {
434 doThrow(env, "java/lang/IllegalArgumentException", NULL);
435 }
436 }
437
Surface_unfreezeDisplay(JNIEnv * env,jobject clazz,jint display)438 static void Surface_unfreezeDisplay(
439 JNIEnv* env, jobject clazz, jint display)
440 {
441 int err = SurfaceComposerClient::unfreezeDisplay(display, 0);
442 if (err < 0) {
443 doThrow(env, "java/lang/IllegalArgumentException", NULL);
444 }
445 }
446
Surface_setLayer(JNIEnv * env,jobject clazz,jint zorder)447 static void Surface_setLayer(
448 JNIEnv* env, jobject clazz, jint zorder)
449 {
450 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
451 if (surface == 0) return;
452 status_t err = surface->setLayer(zorder);
453 if (err<0 && err!=NO_INIT)
454 doThrow(env, "java/lang/IllegalArgumentException", NULL);
455 }
456
Surface_setPosition(JNIEnv * env,jobject clazz,jint x,jint y)457 static void Surface_setPosition(
458 JNIEnv* env, jobject clazz, jint x, jint y)
459 {
460 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
461 if (surface == 0) return;
462 status_t err = surface->setPosition(x, y);
463 if (err<0 && err!=NO_INIT)
464 doThrow(env, "java/lang/IllegalArgumentException", NULL);
465 }
466
Surface_setSize(JNIEnv * env,jobject clazz,jint w,jint h)467 static void Surface_setSize(
468 JNIEnv* env, jobject clazz, jint w, jint h)
469 {
470 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
471 if (surface == 0) return;
472 status_t err = surface->setSize(w, h);
473 if (err<0 && err!=NO_INIT)
474 doThrow(env, "java/lang/IllegalArgumentException", NULL);
475 }
476
Surface_hide(JNIEnv * env,jobject clazz)477 static void Surface_hide(
478 JNIEnv* env, jobject clazz)
479 {
480 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
481 if (surface == 0) return;
482 status_t err = surface->hide();
483 if (err<0 && err!=NO_INIT)
484 doThrow(env, "java/lang/IllegalArgumentException", NULL);
485 }
486
Surface_show(JNIEnv * env,jobject clazz)487 static void Surface_show(
488 JNIEnv* env, jobject clazz)
489 {
490 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
491 if (surface == 0) return;
492 status_t err = surface->show();
493 if (err<0 && err!=NO_INIT)
494 doThrow(env, "java/lang/IllegalArgumentException", NULL);
495 }
496
Surface_freeze(JNIEnv * env,jobject clazz)497 static void Surface_freeze(
498 JNIEnv* env, jobject clazz)
499 {
500 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
501 if (surface == 0) return;
502 status_t err = surface->freeze();
503 if (err<0 && err!=NO_INIT)
504 doThrow(env, "java/lang/IllegalArgumentException", NULL);
505 }
506
Surface_unfreeze(JNIEnv * env,jobject clazz)507 static void Surface_unfreeze(
508 JNIEnv* env, jobject clazz)
509 {
510 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
511 if (surface == 0) return;
512 status_t err = surface->unfreeze();
513 if (err<0 && err!=NO_INIT)
514 doThrow(env, "java/lang/IllegalArgumentException", NULL);
515 }
516
Surface_setFlags(JNIEnv * env,jobject clazz,jint flags,jint mask)517 static void Surface_setFlags(
518 JNIEnv* env, jobject clazz, jint flags, jint mask)
519 {
520 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
521 if (surface == 0) return;
522 status_t err = surface->setFlags(flags, mask);
523 if (err<0 && err!=NO_INIT)
524 doThrow(env, "java/lang/IllegalArgumentException", NULL);
525 }
526
Surface_setTransparentRegion(JNIEnv * env,jobject clazz,jobject argRegion)527 static void Surface_setTransparentRegion(
528 JNIEnv* env, jobject clazz, jobject argRegion)
529 {
530 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
531 if (surface == 0) return;
532 SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
533
534 const SkIRect& b(nativeRegion->getBounds());
535 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
536 if (nativeRegion->isComplex()) {
537 SkRegion::Iterator it(*nativeRegion);
538 while (!it.done()) {
539 const SkIRect& r(it.rect());
540 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
541 it.next();
542 }
543 }
544
545 status_t err = surface->setTransparentRegionHint(reg);
546 if (err<0 && err!=NO_INIT)
547 doThrow(env, "java/lang/IllegalArgumentException", NULL);
548 }
549
Surface_setAlpha(JNIEnv * env,jobject clazz,jfloat alpha)550 static void Surface_setAlpha(
551 JNIEnv* env, jobject clazz, jfloat alpha)
552 {
553 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
554 if (surface == 0) return;
555 status_t err = surface->setAlpha(alpha);
556 if (err<0 && err!=NO_INIT)
557 doThrow(env, "java/lang/IllegalArgumentException", NULL);
558 }
559
Surface_setMatrix(JNIEnv * env,jobject clazz,jfloat dsdx,jfloat dtdx,jfloat dsdy,jfloat dtdy)560 static void Surface_setMatrix(
561 JNIEnv* env, jobject clazz,
562 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy)
563 {
564 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
565 if (surface == 0) return;
566 status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
567 if (err<0 && err!=NO_INIT)
568 doThrow(env, "java/lang/IllegalArgumentException", NULL);
569 }
570
Surface_setFreezeTint(JNIEnv * env,jobject clazz,jint tint)571 static void Surface_setFreezeTint(
572 JNIEnv* env, jobject clazz,
573 jint tint)
574 {
575 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
576 if (surface == 0) return;
577 status_t err = surface->setFreezeTint(tint);
578 if (err<0 && err!=NO_INIT)
579 doThrow(env, "java/lang/IllegalArgumentException", NULL);
580 }
581
582 // ----------------------------------------------------------------------------
583
Surface_copyFrom(JNIEnv * env,jobject clazz,jobject other)584 static void Surface_copyFrom(
585 JNIEnv* env, jobject clazz, jobject other)
586 {
587 if (clazz == other)
588 return;
589
590 if (other == NULL) {
591 doThrow(env, "java/lang/NullPointerException", NULL);
592 return;
593 }
594
595 /*
596 * This is used by the WindowManagerService just after constructing
597 * a Surface and is necessary for returning the Surface reference to
598 * the caller. At this point, we should only have a SurfaceControl.
599 */
600
601 const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
602 const sp<SurfaceControl>& rhs = getSurfaceControl(env, other);
603 if (!SurfaceControl::isSameSurface(surface, rhs)) {
604 // we reassign the surface only if it's a different one
605 // otherwise we would loose our client-side state.
606 setSurfaceControl(env, clazz, rhs);
607 }
608 }
609
Surface_readFromParcel(JNIEnv * env,jobject clazz,jobject argParcel)610 static void Surface_readFromParcel(
611 JNIEnv* env, jobject clazz, jobject argParcel)
612 {
613 Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel);
614 if (parcel == NULL) {
615 doThrow(env, "java/lang/NullPointerException", NULL);
616 return;
617 }
618
619 sp<Surface> sur(Surface::readFromParcel(*parcel));
620 setSurface(env, clazz, sur);
621 }
622
Surface_writeToParcel(JNIEnv * env,jobject clazz,jobject argParcel,jint flags)623 static void Surface_writeToParcel(
624 JNIEnv* env, jobject clazz, jobject argParcel, jint flags)
625 {
626 Parcel* parcel = (Parcel*)env->GetIntField(
627 argParcel, no.native_parcel);
628
629 if (parcel == NULL) {
630 doThrow(env, "java/lang/NullPointerException", NULL);
631 return;
632 }
633
634 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
635 SurfaceControl::writeSurfaceToParcel(control, parcel);
636 if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
637 setSurfaceControl(env, clazz, 0);
638 }
639 }
640
641 // ----------------------------------------------------------------------------
642 // ----------------------------------------------------------------------------
643 // ----------------------------------------------------------------------------
644
645 const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession";
646 const char* const kSurfaceClassPathName = "android/view/Surface";
647 static void nativeClassInit(JNIEnv* env, jclass clazz);
648
649 static JNINativeMethod gSurfaceSessionMethods[] = {
650 {"init", "()V", (void*)SurfaceSession_init },
651 {"destroy", "()V", (void*)SurfaceSession_destroy },
652 {"kill", "()V", (void*)SurfaceSession_kill },
653 };
654
655 static JNINativeMethod gSurfaceMethods[] = {
656 {"nativeClassInit", "()V", (void*)nativeClassInit },
657 {"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init },
658 {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel },
659 {"getIdentity", "()I", (void*)Surface_getIdentity },
660 {"destroy", "()V", (void*)Surface_destroy },
661 {"release", "()V", (void*)Surface_release },
662 {"copyFrom", "(Landroid/view/Surface;)V", (void*)Surface_copyFrom },
663 {"isValid", "()Z", (void*)Surface_isValid },
664 {"lockCanvasNative", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", (void*)Surface_lockCanvas },
665 {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
666 {"unlockCanvas", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
667 {"openTransaction", "()V", (void*)Surface_openTransaction },
668 {"closeTransaction", "()V", (void*)Surface_closeTransaction },
669 {"setOrientation", "(III)V", (void*)Surface_setOrientation },
670 {"freezeDisplay", "(I)V", (void*)Surface_freezeDisplay },
671 {"unfreezeDisplay", "(I)V", (void*)Surface_unfreezeDisplay },
672 {"setLayer", "(I)V", (void*)Surface_setLayer },
673 {"setPosition", "(II)V",(void*)Surface_setPosition },
674 {"setSize", "(II)V",(void*)Surface_setSize },
675 {"hide", "()V", (void*)Surface_hide },
676 {"show", "()V", (void*)Surface_show },
677 {"freeze", "()V", (void*)Surface_freeze },
678 {"unfreeze", "()V", (void*)Surface_unfreeze },
679 {"setFlags", "(II)V",(void*)Surface_setFlags },
680 {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
681 {"setAlpha", "(F)V", (void*)Surface_setAlpha },
682 {"setMatrix", "(FFFF)V", (void*)Surface_setMatrix },
683 {"setFreezeTint", "(I)V", (void*)Surface_setFreezeTint },
684 {"readFromParcel", "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
685 {"writeToParcel", "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
686 };
687
nativeClassInit(JNIEnv * env,jclass clazz)688 void nativeClassInit(JNIEnv* env, jclass clazz)
689 {
690 so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
691 so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
692 so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
693 so.canvas = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
694
695 jclass surfaceSession = env->FindClass("android/view/SurfaceSession");
696 sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
697
698 jclass canvas = env->FindClass("android/graphics/Canvas");
699 no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I");
700 co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I");
701
702 jclass region = env->FindClass("android/graphics/Region");
703 no.native_region = env->GetFieldID(region, "mNativeRegion", "I");
704
705 jclass parcel = env->FindClass("android/os/Parcel");
706 no.native_parcel = env->GetFieldID(parcel, "mObject", "I");
707
708 jclass rect = env->FindClass("android/graphics/Rect");
709 ro.l = env->GetFieldID(rect, "left", "I");
710 ro.t = env->GetFieldID(rect, "top", "I");
711 ro.r = env->GetFieldID(rect, "right", "I");
712 ro.b = env->GetFieldID(rect, "bottom", "I");
713
714 jclass point = env->FindClass("android/graphics/Point");
715 po.x = env->GetFieldID(point, "x", "I");
716 po.y = env->GetFieldID(point, "y", "I");
717 }
718
register_android_view_Surface(JNIEnv * env)719 int register_android_view_Surface(JNIEnv* env)
720 {
721 int err;
722 err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName,
723 gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods));
724
725 err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName,
726 gSurfaceMethods, NELEM(gSurfaceMethods));
727 return err;
728 }
729
730 };
731