1 /* 2 * Copyright (C) 2014 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 package android.uirendering.cts.testinfrastructure; 17 18 import android.annotation.Nullable; 19 import android.app.Activity; 20 import android.content.res.Configuration; 21 import android.graphics.Point; 22 import android.os.Bundle; 23 import android.os.Handler; 24 import android.os.Message; 25 import android.view.View; 26 import android.view.ViewStub; 27 import android.view.ViewTreeObserver; 28 import android.webkit.WebView; 29 30 import android.uirendering.cts.R; 31 32 /** 33 * A generic activity that uses a view specified by the user. 34 */ 35 public class DrawActivity extends Activity { 36 private final static long TIME_OUT_MS = 10000; 37 private final Point mLock = new Point(); 38 public static final int MIN_NUMBER_OF_DRAWS = 20; 39 40 private Handler mHandler; 41 private View mView; 42 private View mViewWrapper; 43 private boolean mOnTv; 44 onCreate(Bundle bundle)45 public void onCreate(Bundle bundle){ 46 super.onCreate(bundle); 47 getWindow().getDecorView().setSystemUiVisibility( 48 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN); 49 mHandler = new RenderSpecHandler(); 50 int uiMode = getResources().getConfiguration().uiMode; 51 mOnTv = (uiMode & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION; 52 } 53 getOnTv()54 public boolean getOnTv() { 55 return mOnTv; 56 } 57 enqueueRenderSpecAndWait(int layoutId, CanvasClient canvasClient, String webViewUrl, @Nullable ViewInitializer viewInitializer, boolean useHardware)58 public Point enqueueRenderSpecAndWait(int layoutId, CanvasClient canvasClient, String webViewUrl, 59 @Nullable ViewInitializer viewInitializer, boolean useHardware) { 60 ((RenderSpecHandler) mHandler).setViewInitializer(viewInitializer); 61 int arg2 = (useHardware ? View.LAYER_TYPE_NONE : View.LAYER_TYPE_SOFTWARE); 62 if (canvasClient != null) { 63 mHandler.obtainMessage(RenderSpecHandler.CANVAS_MSG, 0, arg2, canvasClient).sendToTarget(); 64 } else if (webViewUrl != null) { 65 mHandler.obtainMessage(RenderSpecHandler.WEB_VIEW_MSG, 0, arg2, webViewUrl).sendToTarget(); 66 } else { 67 mHandler.obtainMessage(RenderSpecHandler.LAYOUT_MSG, layoutId, arg2).sendToTarget(); 68 } 69 70 Point point = new Point(); 71 synchronized (mLock) { 72 try { 73 mLock.wait(TIME_OUT_MS); 74 point.set(mLock.x, mLock.y); 75 } catch (InterruptedException e) { 76 e.printStackTrace(); 77 } 78 } 79 return point; 80 } 81 82 private ViewInitializer mViewInitializer; 83 84 private class RenderSpecHandler extends Handler { 85 public static final int LAYOUT_MSG = 1; 86 public static final int CANVAS_MSG = 2; 87 public static final int WEB_VIEW_MSG = 3; 88 89 setViewInitializer(ViewInitializer viewInitializer)90 public void setViewInitializer(ViewInitializer viewInitializer) { 91 mViewInitializer = viewInitializer; 92 } 93 handleMessage(Message message)94 public void handleMessage(Message message) { 95 int drawCountDelay = 0; 96 setContentView(R.layout.test_container); 97 ViewStub stub = (ViewStub) findViewById(R.id.test_content_stub); 98 mViewWrapper = findViewById(R.id.test_content_wrapper); 99 switch (message.what) { 100 case LAYOUT_MSG: { 101 stub.setLayoutResource(message.arg1); 102 mView = stub.inflate(); 103 } break; 104 105 case CANVAS_MSG: { 106 stub.setLayoutResource(R.layout.test_content_canvasclientview); 107 mView = stub.inflate(); 108 ((CanvasClientView) mView).setCanvasClient((CanvasClient) (message.obj)); 109 } break; 110 111 case WEB_VIEW_MSG: { 112 stub.setLayoutResource(R.layout.test_content_webview); 113 mView = stub.inflate(); 114 ((WebView) mView).loadUrl((String) message.obj); 115 ((WebView) mView).setInitialScale(100); 116 drawCountDelay = 10; 117 } break; 118 } 119 120 if (mView == null) { 121 throw new IllegalStateException("failed to inflate test content"); 122 } 123 124 if (mViewInitializer != null) { 125 mViewInitializer.initializeView(mView); 126 } 127 128 // set layer on wrapper parent of view, so view initializer 129 // can control layer type of View under test. 130 mViewWrapper.setLayerType(message.arg2, null); 131 132 DrawCounterListener onDrawListener = new DrawCounterListener(drawCountDelay); 133 134 mView.getViewTreeObserver().addOnPreDrawListener(onDrawListener); 135 136 mView.postInvalidate(); 137 } 138 } 139 140 @Override onPause()141 protected void onPause() { 142 super.onPause(); 143 if (mViewInitializer != null) { 144 mViewInitializer.teardownView(); 145 } 146 } 147 148 private class DrawCounterListener implements ViewTreeObserver.OnPreDrawListener { 149 private int mCurrentDraws = 0; 150 private int mExtraDraws; 151 DrawCounterListener(int extraDraws)152 public DrawCounterListener(int extraDraws) { 153 mExtraDraws = extraDraws; 154 } 155 156 @Override onPreDraw()157 public boolean onPreDraw() { 158 mCurrentDraws++; 159 if (mCurrentDraws < MIN_NUMBER_OF_DRAWS + mExtraDraws) { 160 mView.postInvalidate(); 161 } else { 162 synchronized (mLock) { 163 mLock.set(mViewWrapper.getLeft(), mViewWrapper.getTop()); 164 mLock.notify(); 165 } 166 mView.getViewTreeObserver().removeOnPreDrawListener(this); 167 } 168 return true; 169 } 170 } 171 } 172