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.animation.ObjectAnimator; 20 import android.app.Activity; 21 import android.graphics.Color; 22 import android.graphics.HardwareRenderer; 23 import android.graphics.Paint; 24 import android.graphics.RecordingCanvas; 25 import android.graphics.RenderNode; 26 import android.os.Bundle; 27 import android.os.Handler; 28 import android.view.SurfaceHolder; 29 30 public class CustomRenderer extends Activity { 31 private RenderNode mRootNode = new RenderNode("CustomRenderer"); 32 private RenderNode mChildNode = new RenderNode("RedBox"); 33 private HardwareRenderer mRenderer = new HardwareRenderer(); 34 private ObjectAnimator mAnimator; 35 private Handler mRedrawHandler = new Handler(true); 36 37 @Override onCreate(Bundle savedInstanceState)38 protected void onCreate(Bundle savedInstanceState) { 39 super.onCreate(savedInstanceState); 40 getWindow().takeSurface(mSurfaceCallbacks); 41 } 42 43 @Override onStart()44 protected void onStart() { 45 super.onStart(); 46 mAnimator = ObjectAnimator.ofFloat(mChildNode, "translationY", 0, 300); 47 mAnimator.setRepeatMode(ObjectAnimator.REVERSE); 48 mAnimator.setRepeatCount(ObjectAnimator.INFINITE); 49 final Runnable redraw = this::draw; 50 mAnimator.addUpdateListener(animation -> { 51 mRedrawHandler.post(redraw); 52 }); 53 } 54 55 @Override onStop()56 protected void onStop() { 57 super.onStop(); 58 mAnimator.end(); 59 mAnimator = null; 60 } 61 setupRoot(int width, int height)62 private void setupRoot(int width, int height) { 63 mRootNode.setPosition(0, 0, width, height); 64 65 RecordingCanvas canvas = mRootNode.beginRecording(); 66 canvas.drawColor(Color.WHITE); 67 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 68 paint.setColor(Color.BLACK); 69 paint.setTextAlign(Paint.Align.CENTER); 70 float textSize = Math.min(width, height) * .05f; 71 paint.setTextSize(textSize); 72 canvas.drawText("Hello custom renderer!", width / 2, textSize * 2, paint); 73 74 canvas.translate(0, height / 4); 75 canvas.drawRenderNode(mChildNode); 76 canvas.translate(width / 2, 0); 77 canvas.drawRenderNode(mChildNode); 78 mRootNode.endRecording(); 79 80 setupChild(width / 2, height / 2); 81 } 82 setupChild(int width, int height)83 private void setupChild(int width, int height) { 84 mChildNode.setPosition(0, 0, width, height); 85 mChildNode.setScaleX(.5f); 86 mChildNode.setScaleY(.5f); 87 88 RecordingCanvas canvas = mChildNode.beginRecording(); 89 canvas.drawColor(Color.RED); 90 mChildNode.endRecording(); 91 } 92 draw()93 private void draw() { 94 // Since we are constantly pumping frames between onStart & onStop we don't really 95 // care about any errors that may happen. They will self-correct. 96 mRenderer.createRenderRequest() 97 .setVsyncTime(System.nanoTime()) 98 .syncAndDraw(); 99 } 100 101 private SurfaceHolder.Callback2 mSurfaceCallbacks = new SurfaceHolder.Callback2() { 102 103 @Override 104 public void surfaceRedrawNeeded(SurfaceHolder holder) { 105 } 106 107 @Override 108 public void surfaceCreated(SurfaceHolder holder) { 109 } 110 111 @Override 112 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 113 setupRoot(width, height); 114 115 mRenderer.setContentRoot(mRootNode); 116 mRenderer.setSurface(holder.getSurface()); 117 draw(); 118 if (!mAnimator.isStarted()) { 119 mAnimator.start(); 120 } 121 } 122 123 @Override 124 public void surfaceDestroyed(SurfaceHolder holder) { 125 mRenderer.destroy(); 126 } 127 }; 128 } 129