1 /*
2  * Copyright (C) 2019 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 package com.android.test.hwui;
18 
19 import android.app.Activity;
20 import android.graphics.Bitmap;
21 import android.graphics.Canvas;
22 import android.graphics.Color;
23 import android.graphics.Paint;
24 import android.graphics.Picture;
25 import android.os.Bundle;
26 import android.view.SurfaceHolder;
27 import android.view.SurfaceView;
28 import android.view.View;
29 import android.view.ViewDebug;
30 import android.webkit.WebChromeClient;
31 import android.webkit.WebView;
32 import android.webkit.WebViewClient;
33 import android.widget.ImageView;
34 import android.widget.LinearLayout;
35 import android.widget.LinearLayout.LayoutParams;
36 import android.widget.ProgressBar;
37 
38 import java.io.PipedInputStream;
39 import java.io.PipedOutputStream;
40 import java.util.Random;
41 import java.util.concurrent.ExecutorService;
42 import java.util.concurrent.Executors;
43 import java.util.concurrent.Future;
44 
45 public class PictureCaptureDemo extends Activity {
46     @Override
onCreate(Bundle savedInstanceState)47     protected void onCreate(Bundle savedInstanceState) {
48         super.onCreate(savedInstanceState);
49 
50         final LinearLayout layout = new LinearLayout(this);
51         layout.setOrientation(LinearLayout.VERTICAL);
52 
53         final LinearLayout inner = new LinearLayout(this);
54         inner.setOrientation(LinearLayout.HORIZONTAL);
55         ProgressBar spinner = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge);
56         inner.addView(spinner,
57                 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
58 
59         inner.addView(new View(this), new LayoutParams(50, 1));
60 
61         Picture picture = new Picture();
62         Canvas canvas = picture.beginRecording(100, 100);
63         canvas.drawColor(Color.RED);
64         Paint paint = new Paint();
65         paint.setTextSize(32);
66         paint.setColor(Color.BLACK);
67         canvas.drawText("Hello", 0, 50, paint);
68         picture.endRecording();
69 
70         ImageView iv1 = new ImageView(this);
71         iv1.setImageBitmap(Bitmap.createBitmap(picture, 100, 100, Bitmap.Config.ARGB_8888));
72         inner.addView(iv1, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
73 
74         inner.addView(new View(this), new LayoutParams(50, 1));
75 
76         ImageView iv2 = new ImageView(this);
77         iv2.setImageBitmap(Bitmap.createBitmap(picture, 100, 100, Bitmap.Config.HARDWARE));
78         inner.addView(iv2, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
79 
80         layout.addView(inner,
81                 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
82         // For testing with a functor in the tree
83         WebView wv = new WebView(this);
84         wv.setWebViewClient(new WebViewClient());
85         wv.setWebChromeClient(new WebChromeClient());
86         wv.loadUrl("https://google.com");
87         layout.addView(wv, new LayoutParams(LayoutParams.MATCH_PARENT, 400));
88 
89         SurfaceView mySurfaceView = new SurfaceView(this);
90         layout.addView(mySurfaceView,
91                 new LayoutParams(LayoutParams.MATCH_PARENT, 600));
92 
93         setContentView(layout);
94 
95         mySurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
96             private AutoCloseable mStopCapture;
97 
98             @Override
99             public void surfaceCreated(SurfaceHolder holder) {
100                 final Random rand = new Random();
101                 mStopCapture = ViewDebug.startRenderingCommandsCapture(mySurfaceView,
102                         mCaptureThread, (picture) -> {
103                             if (rand.nextInt(20) == 0) {
104                                 try {
105                                     Thread.sleep(100);
106                                 } catch (InterruptedException e) {
107                                 }
108                             }
109                             Canvas canvas = holder.lockCanvas();
110                             if (canvas == null) {
111                                 return false;
112                             }
113                             canvas.drawPicture(picture);
114                             holder.unlockCanvasAndPost(canvas);
115                             picture.close();
116                             return true;
117                         });
118             }
119 
120             @Override
121             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
122 
123             }
124 
125             @Override
126             public void surfaceDestroyed(SurfaceHolder holder) {
127                 if (mStopCapture != null) {
128                     try {
129                         mStopCapture.close();
130                     } catch (Exception e) {
131                     }
132                     mStopCapture = null;
133                 }
134             }
135         });
136     }
137 
138     ExecutorService mCaptureThread = Executors.newSingleThreadExecutor();
139     ExecutorService mExecutor = Executors.newSingleThreadExecutor();
140 
deepCopy(Picture src)141     Picture deepCopy(Picture src) {
142         try {
143             PipedInputStream inputStream = new PipedInputStream();
144             PipedOutputStream outputStream = new PipedOutputStream(inputStream);
145             Future<Picture> future = mExecutor.submit(() -> Picture.createFromStream(inputStream));
146             src.writeToStream(outputStream);
147             outputStream.close();
148             return future.get();
149         } catch (Exception ex) {
150             throw new RuntimeException(ex);
151         }
152     }
153 }
154