1ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne/* 2ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Copyright (C) 2014 The Android Open Source Project 3ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * 4ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Licensed under the Apache License, Version 2.0 (the "License"); 5ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * you may not use this file except in compliance with the License. 6ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * You may obtain a copy of the License at 7ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * 8ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * http://www.apache.org/licenses/LICENSE-2.0 9ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * 10ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Unless required by applicable law or agreed to in writing, software 11ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * distributed under the License is distributed on an "AS IS" BASIS, 12ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * See the License for the specific language governing permissions and 14ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * limitations under the License. 15ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne */ 16ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 17ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhnepackage com.android.test.hwui; 18ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 19ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.app.Activity; 20ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.graphics.Canvas; 21ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.graphics.ColorFilter; 22ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.graphics.Paint; 23ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.graphics.PixelFormat; 24ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.graphics.Rect; 25ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.graphics.drawable.Drawable; 26ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.os.Bundle; 27ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.view.DisplayListCanvas; 2851aaf906f9f5fb2f117f5ccfae8be6974f7cb903John Reckimport android.view.ThreadedRenderer; 29ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.view.RenderNode; 30ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.view.ThreadedRenderer; 31ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.view.View; 32ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.view.View.OnClickListener; 33ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.widget.AbsoluteLayout; 34ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhneimport android.widget.AbsoluteLayout.LayoutParams; 35ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 36ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhnepublic class MultiProducerActivity extends Activity implements OnClickListener { 37ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private static final int DURATION = 800; 38ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private View mBackgroundTarget = null; 39ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private View mFrameTarget = null; 40ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private View mContent = null; 41ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // The width & height of our "output drawing". 42ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private final int WIDTH = 900; 43ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private final int HEIGHT = 600; 44ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // A border width around the drawing. 45ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private static final int BORDER_WIDTH = 20; 46ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // The Gap between the content and the frame which should get filled on the right and bottom 47ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // side by the backdrop. 48ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne final int CONTENT_GAP = 100; 49ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 50ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // For debug purposes - disable drawing of frame / background. 51ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private final boolean USE_FRAME = true; 52ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private final boolean USE_BACK = true; 53ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 54ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 55ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne protected void onCreate(Bundle savedInstanceState) { 56ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne super.onCreate(savedInstanceState); 57ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // To make things simple - we do a quick and dirty absolute layout. 58ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne final AbsoluteLayout layout = new AbsoluteLayout(this); 59ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 60ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Create the outer frame 61ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (USE_FRAME) { 62ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mFrameTarget = new View(this); 63ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne LayoutParams frameLP = new LayoutParams(WIDTH, HEIGHT, 0, 0); 64ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne layout.addView(mFrameTarget, frameLP); 65ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 66ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 67ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Create the background which fills the gap between content and frame. 68ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (USE_BACK) { 69ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mBackgroundTarget = new View(this); 70ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne LayoutParams backgroundLP = new LayoutParams( 71ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne WIDTH - 2 * BORDER_WIDTH, HEIGHT - 2 * BORDER_WIDTH, 72ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne BORDER_WIDTH, BORDER_WIDTH); 73ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne layout.addView(mBackgroundTarget, backgroundLP); 74ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 75ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 76ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Create the content 77ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Note: We reduce the size by CONTENT_GAP pixels on right and bottom, so that they get 78ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // drawn by the backdrop. 79ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mContent = new View(this); 80ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mContent.setBackground(new ColorPulse(0xFFF44336, 0xFF9C27B0, null)); 81ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mContent.setOnClickListener(this); 82ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne LayoutParams contentLP = new LayoutParams(WIDTH - 2 * BORDER_WIDTH - CONTENT_GAP, 83ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne HEIGHT - 2 * BORDER_WIDTH - CONTENT_GAP, BORDER_WIDTH, BORDER_WIDTH); 84ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne layout.addView(mContent, contentLP); 85ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 86ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne setContentView(layout); 87ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 88ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 89ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 90ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne protected void onStart() { 91ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne super.onStart(); 92ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne View view = mBackgroundTarget != null ? mBackgroundTarget : mFrameTarget; 93ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (view != null) { 94ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne view.post(mSetup); 95ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 96ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 97ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 98ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 99ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne protected void onStop() { 100ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne super.onStop(); 101ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne View view = mBackgroundTarget != null ? mBackgroundTarget : mFrameTarget; 102ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (view != null) { 103ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne view.removeCallbacks(mSetup); 104ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 105ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (mBgRenderer != null) { 106ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mBgRenderer.destroy(); 107ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mBgRenderer = null; 108ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 109ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 110ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 111ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 112ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public void onClick(View view) { 113ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne sBlockThread.run(); 114ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 115ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 116ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private Runnable mSetup = new Runnable() { 117ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 118ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public void run() { 119ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne View view = mBackgroundTarget != null ? mBackgroundTarget : mFrameTarget; 120ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (view == null) { 121ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne view.postDelayed(mSetup, 50); 122ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 12351aaf906f9f5fb2f117f5ccfae8be6974f7cb903John Reck ThreadedRenderer renderer = view.getHardwareRenderer(); 124ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (renderer == null || view.getWidth() == 0) { 125ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne view.postDelayed(mSetup, 50); 126ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 127ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne ThreadedRenderer threaded = (ThreadedRenderer) renderer; 128ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 129ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mBgRenderer = new FakeFrame(threaded,mFrameTarget, mBackgroundTarget); 130ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mBgRenderer.start(); 131ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 132ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne }; 133ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 134ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private FakeFrame mBgRenderer; 135ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private class FakeFrame extends Thread { 136ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne ThreadedRenderer mRenderer; 137ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne volatile boolean mRunning = true; 138ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne View mTargetFrame; 139ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne View mTargetBack; 140ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne Drawable mFrameContent; 141ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne Drawable mBackContent; 142ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // The Z value where to place this. 143ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int mZFrame; 144ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int mZBack; 145ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne String mRenderNodeName; 146ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 147ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne FakeFrame(ThreadedRenderer renderer, View targetFrame, View targetBack) { 148ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mRenderer = renderer; 149ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mTargetFrame = targetFrame; 150ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 151ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mTargetBack = targetBack; 152ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mFrameContent = new ColorPulse(0xFF101010, 0xFF707070, new Rect(0, 0, WIDTH, HEIGHT)); 153ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mBackContent = new ColorPulse(0xFF909090, 0xFFe0e0e0, null); 154ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 155ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 156ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 157ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public void run() { 158ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne Rect currentFrameBounds = new Rect(); 159ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne Rect currentBackBounds = new Rect(); 160ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne Rect newBounds = new Rect(); 161ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int[] surfaceOrigin = new int[2]; 162ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne RenderNode nodeFrame = null; 163ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne RenderNode nodeBack = null; 164ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 165ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Since we are overriding the window painting logic we need to at least fill the 166ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // surface with some window content (otherwise the world will go black). 167ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne try { 168ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne Thread.sleep(200); 169ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } catch (InterruptedException e) { 170ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 171ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 172ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (mTargetBack != null) { 173ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne nodeBack = RenderNode.create("FakeBackdrop", null); 174ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne nodeBack.setClipToBounds(true); 175ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mRenderer.addRenderNode(nodeBack, true); 176ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 177ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 178ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (mTargetFrame != null) { 179ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne nodeFrame = RenderNode.create("FakeFrame", null); 180ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne nodeFrame.setClipToBounds(true); 181ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mRenderer.addRenderNode(nodeFrame, false); 182ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 183ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 184ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne while (mRunning) { 185ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Get the surface position to draw to within our surface. 186ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[0] = 0; 187ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[1] = 0; 188ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // This call should be done while the rendernode's displaylist is produced. 189ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // For simplicity of this test we do this before we kick off the draw. 190ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mContent.getLocationInSurface(surfaceOrigin); 191b816087962aba0019b022303330f03b897b580edSkuhne mRenderer.setContentDrawBounds(surfaceOrigin[0], surfaceOrigin[1], 192ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[0] + mContent.getWidth(), 193ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[1] + mContent.getHeight()); 194ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Determine new position for frame. 195ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (nodeFrame != null) { 196ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[0] = 0; 197ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[1] = 0; 198ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mTargetFrame.getLocationInSurface(surfaceOrigin); 199ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne newBounds.set(surfaceOrigin[0], surfaceOrigin[1], 200ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[0] + mTargetFrame.getWidth(), 201ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[1] + mTargetFrame.getHeight()); 202ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (!currentFrameBounds.equals(newBounds)) { 203ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne currentFrameBounds.set(newBounds); 204ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne nodeFrame.setLeftTopRightBottom(currentFrameBounds.left, 205ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne currentFrameBounds.top, 206ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne currentFrameBounds.right, currentFrameBounds.bottom); 207ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 208ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 209ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Draw frame 210ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne DisplayListCanvas canvas = nodeFrame.start(currentFrameBounds.width(), 211ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne currentFrameBounds.height()); 212ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mFrameContent.draw(canvas); 213ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne nodeFrame.end(canvas); 214ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 215ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 216ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Determine new position for backdrop 217ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (nodeBack != null) { 218ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[0] = 0; 219ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[1] = 0; 220ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mTargetBack.getLocationInSurface(surfaceOrigin); 221ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne newBounds.set(surfaceOrigin[0], surfaceOrigin[1], 222ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[0] + mTargetBack.getWidth(), 223ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne surfaceOrigin[1] + mTargetBack.getHeight()); 224ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (!currentBackBounds.equals(newBounds)) { 225ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne currentBackBounds.set(newBounds); 226ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne nodeBack.setLeftTopRightBottom(currentBackBounds.left, 227ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne currentBackBounds.top, 228ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne currentBackBounds.right, currentBackBounds.bottom); 229ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 230ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 231ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // Draw Backdrop 232ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne DisplayListCanvas canvas = nodeBack.start(currentBackBounds.width(), 233ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne currentBackBounds.height()); 234ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mBackContent.draw(canvas); 235ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne nodeBack.end(canvas); 236ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 237ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 238ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne // we need to only render one guy - the rest will happen automatically (I think). 239ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (nodeFrame != null) { 240ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mRenderer.drawRenderNode(nodeFrame); 241ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 242ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (nodeBack != null) { 243ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mRenderer.drawRenderNode(nodeBack); 244ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 245ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne try { 246ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne Thread.sleep(5); 247ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } catch (InterruptedException e) {} 248ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 249ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (nodeFrame != null) { 250ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mRenderer.removeRenderNode(nodeFrame); 251ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 252ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (nodeBack != null) { 253ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mRenderer.removeRenderNode(nodeBack); 254ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 255ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 256ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 257ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public void destroy() { 258ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mRunning = false; 259ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne try { 260ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne join(); 261ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } catch (InterruptedException e) {} 262ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 263ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 264ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 265ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private final static Runnable sBlockThread = new Runnable() { 266ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 267ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public void run() { 268ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne try { 269ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne Thread.sleep(DURATION); 270ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } catch (InterruptedException e) { 271ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 272ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 273ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne }; 274ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 275ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne static class ColorPulse extends Drawable { 276ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 277ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private int mColorStart; 278ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private int mColorEnd; 279ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private int mStep; 280ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private Rect mRect; 281ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne private Paint mPaint = new Paint(); 282ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 283ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public ColorPulse(int color1, int color2, Rect rect) { 284ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mColorStart = color1; 285ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mColorEnd = color2; 286ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (rect != null) { 287ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mRect = new Rect(rect.left + BORDER_WIDTH / 2, rect.top + BORDER_WIDTH / 2, 288ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne rect.right - BORDER_WIDTH / 2, rect.bottom - BORDER_WIDTH / 2); 289ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 290ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 291ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 292ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne static int evaluate(float fraction, int startInt, int endInt) { 293ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int startA = (startInt >> 24) & 0xff; 294ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int startR = (startInt >> 16) & 0xff; 295ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int startG = (startInt >> 8) & 0xff; 296ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int startB = startInt & 0xff; 297ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 298ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int endA = (endInt >> 24) & 0xff; 299ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int endR = (endInt >> 16) & 0xff; 300ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int endG = (endInt >> 8) & 0xff; 301ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int endB = endInt & 0xff; 302ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 303ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne return (int)((startA + (int)(fraction * (endA - startA))) << 24) | 304ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne (int)((startR + (int)(fraction * (endR - startR))) << 16) | 305ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne (int)((startG + (int)(fraction * (endG - startG))) << 8) | 306ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne (int)((startB + (int)(fraction * (endB - startB)))); 307ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 308ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 309ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 310ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public void draw(Canvas canvas) { 311ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne float frac = mStep / 50.0f; 312ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int color = evaluate(frac, mColorStart, mColorEnd); 313ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (mRect != null && !mRect.isEmpty()) { 314ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mPaint.setStyle(Paint.Style.STROKE); 315ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mPaint.setStrokeWidth(BORDER_WIDTH); 316ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mPaint.setColor(color); 317ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne canvas.drawRect(mRect, mPaint); 318ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } else { 319ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne canvas.drawColor(color); 320ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 321ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 322ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mStep++; 323ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne if (mStep >= 50) { 324ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mStep = 0; 325ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne int tmp = mColorStart; 326ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mColorStart = mColorEnd; 327ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne mColorEnd = tmp; 328ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 329ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne invalidateSelf(); 330ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 331ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 332ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 333ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public void setAlpha(int alpha) { 334ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 335ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 336ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 337ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public void setColorFilter(ColorFilter colorFilter) { 338ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 339ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 340ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne @Override 341ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public int getOpacity() { 342ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne return mRect == null || mRect.isEmpty() ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT; 343ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 344ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 345ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 346ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne} 347ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 348