1bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck/* 2bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * Copyright (C) 2014 The Android Open Source Project 3bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * 4bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 5bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * you may not use this file except in compliance with the License. 6bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * You may obtain a copy of the License at 7bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * 8bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * http://www.apache.org/licenses/LICENSE-2.0 9bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * 10bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * Unless required by applicable law or agreed to in writing, software 11bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * distributed under the License is distributed on an "AS IS" BASIS, 12bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * See the License for the specific language governing permissions and 14bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck * limitations under the License. 15bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck */ 16bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 17bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckpackage com.android.test.hwui; 18bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 19bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.app.Activity; 2010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reckimport android.graphics.Bitmap; 21bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.graphics.Canvas; 22bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.graphics.Paint; 23bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.graphics.PorterDuff; 24bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.os.Bundle; 2510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reckimport android.os.Environment; 26e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reckimport android.view.PixelCopy; 27bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.view.Surface; 28bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.view.SurfaceHolder; 29bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.view.SurfaceHolder.Callback; 30bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.view.SurfaceView; 3110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reckimport android.view.View; 3210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reckimport android.widget.Button; 33bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckimport android.widget.FrameLayout; 3410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reckimport android.widget.LinearLayout; 3510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reckimport android.widget.Toast; 3610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck 3710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reckimport java.io.FileOutputStream; 38bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 39bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reckpublic class HardwareCanvasSurfaceViewActivity extends Activity implements Callback { 40bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck private SurfaceView mSurfaceView; 41bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck private HardwareCanvasSurfaceViewActivity.RenderingThread mThread; 42bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 43bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck @Override 44bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck protected void onCreate(Bundle savedInstanceState) { 45bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck super.onCreate(savedInstanceState); 46bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 47bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck FrameLayout content = new FrameLayout(this); 48bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 49bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck mSurfaceView = new SurfaceView(this); 50bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck mSurfaceView.getHolder().addCallback(this); 51bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 5210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck Button button = new Button(this); 5310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck button.setText("Copy bitmap to /sdcard/surfaceview.png"); 5410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck button.setOnClickListener((View v) -> { 55e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck final Bitmap b = Bitmap.createBitmap( 56e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck mSurfaceView.getWidth(), mSurfaceView.getHeight(), 57e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck Bitmap.Config.ARGB_8888); 5810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck PixelCopy.request(mSurfaceView, b, 59e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck (int result) -> { 60e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck if (result != PixelCopy.SUCCESS) { 61e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck Toast.makeText(HardwareCanvasSurfaceViewActivity.this, 62e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck "Failed to copy", Toast.LENGTH_SHORT).show(); 63e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck return; 64e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck } 65e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck try { 66e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck try (FileOutputStream out = new FileOutputStream( 67e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck Environment.getExternalStorageDirectory() + "/surfaceview.png");) { 68e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck b.compress(Bitmap.CompressFormat.PNG, 100, out); 69e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck } 70e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck } catch (Exception e) { 71e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck // Ignore 72e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck } 73e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck }, mSurfaceView.getHandler()); 7410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck }); 7510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck 7610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck LinearLayout layout = new LinearLayout(this); 7710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck layout.setOrientation(LinearLayout.VERTICAL); 7810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck layout.addView(button, LinearLayout.LayoutParams.MATCH_PARENT, 7910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck LinearLayout.LayoutParams.WRAP_CONTENT); 8010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck layout.addView(mSurfaceView, LinearLayout.LayoutParams.MATCH_PARENT, 8110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck LinearLayout.LayoutParams.MATCH_PARENT); 8210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck 8310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck content.addView(layout, new FrameLayout.LayoutParams( 84bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck FrameLayout.LayoutParams.MATCH_PARENT, 8510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck FrameLayout.LayoutParams.MATCH_PARENT)); 86bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck setContentView(content); 87bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 88bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 89bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck @Override 90bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck public void surfaceCreated(SurfaceHolder holder) { 916bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck mThread = new RenderingThread(holder); 92bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck mThread.start(); 93bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 94bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 95bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck @Override 96bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 97bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck mThread.setSize(width, height); 98bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 99bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 100bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck @Override 101bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck public void surfaceDestroyed(SurfaceHolder holder) { 102bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck if (mThread != null) mThread.stopRendering(); 103bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 104bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 105bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck private static class RenderingThread extends Thread { 1066bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck private final SurfaceHolder mSurface; 107bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck private volatile boolean mRunning = true; 108bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck private int mWidth, mHeight; 109bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 1106bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck public RenderingThread(SurfaceHolder surface) { 111bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck mSurface = surface; 112bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 113bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 114bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck void setSize(int width, int height) { 115bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck mWidth = width; 116bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck mHeight = height; 117bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 118bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 119bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck @Override 120bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck public void run() { 121bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck float x = 0.0f; 122bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck float y = 0.0f; 123bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck float speedX = 5.0f; 124bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck float speedY = 3.0f; 125bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 126bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck Paint paint = new Paint(); 127bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck paint.setColor(0xff00ff00); 128bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 129bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck while (mRunning && !Thread.interrupted()) { 130bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck final Canvas canvas = mSurface.lockHardwareCanvas(); 131bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck try { 132bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR); 133bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck canvas.drawRect(x, y, x + 20.0f, y + 20.0f, paint); 134bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } finally { 135bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck mSurface.unlockCanvasAndPost(canvas); 136bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 137bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 138bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck if (x + 20.0f + speedX >= mWidth || x + speedX <= 0.0f) { 139bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck speedX = -speedX; 140bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 141bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck if (y + 20.0f + speedY >= mHeight || y + speedY <= 0.0f) { 142bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck speedY = -speedY; 143bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 144bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 145bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck x += speedX; 146bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck y += speedY; 147bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 148bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck try { 149bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck Thread.sleep(15); 150bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } catch (InterruptedException e) { 151bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck // Interrupted 152bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 153bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 154bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 155bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck 156bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck void stopRendering() { 157bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck interrupt(); 158bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck mRunning = false; 159bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 160bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck } 161bb2d0cc7e1d487f7021b1f9ec0c6740e41b535f2John Reck} 162