• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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