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