1/* 2 * Copyright (C) 2016 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 17package android.widget; 18 19import android.app.Activity; 20import android.os.Looper; 21import android.perftests.utils.BenchmarkState; 22import android.perftests.utils.PerfStatusReporter; 23import android.perftests.utils.StubActivity; 24import android.support.test.annotation.UiThreadTest; 25import android.support.test.filters.LargeTest; 26import android.support.test.rule.ActivityTestRule; 27import android.view.View; 28import android.view.ViewGroup; 29 30import com.android.perftests.core.R; 31 32import org.junit.Rule; 33import org.junit.Test; 34import org.junit.runner.RunWith; 35import org.junit.runners.Parameterized; 36 37import java.util.Arrays; 38import java.util.Collection; 39import java.util.List; 40 41import static android.perftests.utils.LayoutUtils.gatherViewTree; 42import static android.perftests.utils.LayoutUtils.requestLayoutForAllNodes; 43import static android.view.View.MeasureSpec.AT_MOST; 44import static android.view.View.MeasureSpec.EXACTLY; 45import static android.view.View.MeasureSpec.UNSPECIFIED; 46import static org.junit.Assert.assertTrue; 47 48@LargeTest 49@RunWith(Parameterized.class) 50public class LayoutPerfTest { 51 @Parameterized.Parameters(name = "{0}") 52 public static Collection measureSpecs() { 53 return Arrays.asList(new Object[][] { 54 { "relative", R.layout.test_relative_layout, R.id.relative_layout_root }, 55 { "linear", R.layout.test_linear_layout, R.id.linear_layout_root }, 56 { "linear_weighted", R.layout.test_linear_layout_weighted, 57 R.id.linear_layout_weighted_root }, 58 }); 59 } 60 61 private int[] mMeasureSpecs = {EXACTLY, AT_MOST, UNSPECIFIED}; 62 63 private int mLayoutId; 64 private int mViewId; 65 66 public LayoutPerfTest(String key, int layoutId, int viewId) { 67 // key is used in the final report automatically. 68 mLayoutId = layoutId; 69 mViewId = viewId; 70 } 71 72 @Rule 73 public ActivityTestRule<StubActivity> mActivityRule = 74 new ActivityTestRule(StubActivity.class); 75 76 @Rule 77 public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); 78 79 @Test 80 @UiThreadTest 81 public void testLayoutPerf() throws Throwable { 82 mActivityRule.runOnUiThread(() -> { 83 assertTrue("We should be running on the main thread", 84 Looper.getMainLooper().getThread() == Thread.currentThread()); 85 assertTrue("We should be running on the main thread", 86 Looper.myLooper() == Looper.getMainLooper()); 87 88 Activity activity = mActivityRule.getActivity(); 89 activity.setContentView(mLayoutId); 90 91 ViewGroup viewGroup = (ViewGroup) activity.findViewById(mViewId); 92 93 List<View> allNodes = gatherViewTree(viewGroup); 94 BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 95 96 int length = mMeasureSpecs.length; 97 while (state.keepRunning()) { 98 for (int i = 0; i < length; i++) { 99 // The overhead of this call is ignorable, like within 1% difference. 100 requestLayoutForAllNodes(allNodes); 101 102 viewGroup.measure(mMeasureSpecs[i % length], mMeasureSpecs[i % length]); 103 viewGroup.layout(0, 0, viewGroup.getMeasuredWidth(), viewGroup.getMeasuredHeight()); 104 } 105 } 106 }); 107 } 108} 109