1 /* 2 * Copyright (C) 2012 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.Color; 21 import android.os.Bundle; 22 import android.view.View; 23 import android.view.ViewGroup; 24 import android.widget.LinearLayout; 25 import android.widget.TextView; 26 27 import java.util.ArrayList; 28 29 public class ViewLayerInvalidationActivity extends Activity { 30 31 int currentColor = Color.WHITE; 32 boolean nestedLayersOn = false; 33 ArrayList<LinearLayout> linearLayouts = new ArrayList<LinearLayout>(); 34 ArrayList<LinearLayout> topLayouts = new ArrayList<LinearLayout>(); 35 ArrayList<TextView> textViews = new ArrayList<TextView>(); 36 LinearLayout container = null; 37 boolean randomInvalidates = false; 38 TextView nestedStatusTV, invalidateStatusTV; 39 static final String NO_NESTING = "Nested Layer: NO "; 40 static final String NESTING = "Nested Layers: YES "; 41 static final String NO_INVALIDATING = "Random Invalidating: NO "; 42 static final String INVALIDATING = "Random Invalidating: YES "; 43 static final int TEXT_COLOR_INTERVAL = 400; 44 static final int INVALIDATING_INTERVAL = 1000; 45 static final int NESTING_INTERVAL = 2000; 46 47 @Override onCreate(Bundle savedInstanceState)48 public void onCreate(Bundle savedInstanceState) { 49 super.onCreate(savedInstanceState); 50 setContentView(R.layout.view_layer_invalidation); 51 52 container = findViewById(R.id.container); 53 final LinearLayout container1 = findViewById(R.id.container1); 54 final LinearLayout container2 = findViewById(R.id.container2); 55 final LinearLayout container3 = findViewById(R.id.container3); 56 nestedStatusTV = findViewById(R.id.nestedStatus); 57 invalidateStatusTV = findViewById(R.id.invalidateStatus); 58 final TextView tva = findViewById(R.id.textviewa); 59 60 topLayouts.add(container1); 61 topLayouts.add(container2); 62 topLayouts.add(container3); 63 64 collectLinearLayouts(container); 65 collectTextViews(container); 66 67 nestedStatusTV.setText(NO_NESTING); 68 invalidateStatusTV.setText(NO_INVALIDATING); 69 70 tva.setLayerType(View.LAYER_TYPE_HARDWARE, null); 71 container1.setLayerType(View.LAYER_TYPE_HARDWARE, null); 72 container2.setLayerType(View.LAYER_TYPE_HARDWARE, null); 73 container3.setLayerType(View.LAYER_TYPE_HARDWARE, null); 74 75 container.postDelayed(textColorSetter, TEXT_COLOR_INTERVAL); 76 container.postDelayed(nestedLayerSetter, NESTING_INTERVAL); 77 container.postDelayed(randomInvalidatesSetter, INVALIDATING_INTERVAL); 78 } 79 80 private Runnable textColorSetter = new Runnable() { 81 @Override 82 public void run() { 83 currentColor = (currentColor == Color.WHITE) ? Color.RED : Color.WHITE; 84 for (TextView tv : textViews) { 85 tv.setTextColor(currentColor); 86 } 87 if (randomInvalidates) { 88 randomInvalidator(container); 89 } 90 container.postDelayed(textColorSetter, TEXT_COLOR_INTERVAL); 91 } 92 }; 93 94 private Runnable randomInvalidatesSetter = new Runnable() { 95 @Override 96 public void run() { 97 randomInvalidates = !randomInvalidates; 98 invalidateStatusTV.setText(randomInvalidates ? INVALIDATING : NO_INVALIDATING); 99 container.postDelayed(randomInvalidatesSetter, INVALIDATING_INTERVAL); 100 } 101 }; 102 103 private Runnable nestedLayerSetter = new Runnable() { 104 @Override 105 public void run() { 106 nestedLayersOn = !nestedLayersOn; 107 nestedStatusTV.setText(nestedLayersOn ? NESTING : NO_NESTING); 108 for (LinearLayout layout : linearLayouts) { 109 layout.setLayerType(nestedLayersOn ? 110 View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE, null); 111 } 112 if (!nestedLayersOn) { 113 for (LinearLayout layout : topLayouts) { 114 layout.setLayerType(View.LAYER_TYPE_HARDWARE, null); 115 } 116 } 117 container.postDelayed(nestedLayerSetter, NESTING_INTERVAL); 118 } 119 }; 120 121 /** 122 * Invalidates views based on random chance (50%). This is meant to test 123 * invalidating several items in the hierarchy at the same time, which can cause artifacts 124 * if our invalidation-propagation logic is not sound. 125 */ randomInvalidator(ViewGroup parent)126 private void randomInvalidator(ViewGroup parent) { 127 for (int i = 0; i < parent.getChildCount(); ++i) { 128 View child = parent.getChildAt(i); 129 if (Math.random() < .5) { 130 child.invalidate(); 131 } 132 if (child instanceof ViewGroup) { 133 randomInvalidator((ViewGroup) child); 134 } 135 } 136 } 137 collectLinearLayouts(View view)138 private void collectLinearLayouts(View view) { 139 if (!(view instanceof LinearLayout)) { 140 return; 141 } 142 LinearLayout parent = (LinearLayout) view; 143 linearLayouts.add(parent); 144 for (int i = 0; i < parent.getChildCount(); ++i) { 145 collectLinearLayouts(parent.getChildAt(i)); 146 } 147 } 148 collectTextViews(View view)149 private void collectTextViews(View view) { 150 if (view instanceof TextView) { 151 textViews.add((TextView) view); 152 return; 153 } 154 if (!(view instanceof ViewGroup)) { 155 return; 156 } 157 ViewGroup parent = (ViewGroup) view; 158 for (int i = 0; i < parent.getChildCount(); ++i) { 159 collectTextViews(parent.getChildAt(i)); 160 } 161 } 162 } 163