1 /* 2 * Copyright (C) 2010 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.dumprendertree2; 18 19 import com.android.dumprendertree2.scriptsupport.OnEverythingFinishedCallback; 20 21 import android.app.Activity; 22 import android.app.ProgressDialog; 23 import android.content.Intent; 24 import android.content.res.Configuration; 25 import android.os.Bundle; 26 import android.os.Handler; 27 import android.os.Message; 28 import android.view.Gravity; 29 import android.view.Window; 30 import android.webkit.WebView; 31 import android.widget.Toast; 32 33 import java.io.File; 34 import java.util.ArrayList; 35 36 /** 37 * An Activity that generates a list of tests and sends the intent to 38 * LayoutTestsExecuter to run them. It also restarts the LayoutTestsExecuter 39 * after it crashes. 40 */ 41 public class TestsListActivity extends Activity { 42 43 private static final int MSG_TEST_LIST_PRELOADER_DONE = 0; 44 45 /** Constants for adding extras to an intent */ 46 public static final String EXTRA_TEST_PATH = "TestPath"; 47 48 private static ProgressDialog sProgressDialog; 49 50 private Handler mHandler = new Handler() { 51 @Override 52 public void handleMessage(Message msg) { 53 switch (msg.what) { 54 case MSG_TEST_LIST_PRELOADER_DONE: 55 sProgressDialog.dismiss(); 56 mTestsList = (ArrayList<String>)msg.obj; 57 mTotalTestCount = mTestsList.size(); 58 restartExecutor(0); 59 break; 60 } 61 } 62 }; 63 64 private ArrayList<String> mTestsList; 65 private int mTotalTestCount; 66 67 private OnEverythingFinishedCallback mOnEverythingFinishedCallback; 68 private boolean mEverythingFinished; 69 70 @Override 71 protected void onCreate(Bundle savedInstanceState) { 72 super.onCreate(savedInstanceState); 73 74 /** Prepare the progress dialog */ 75 sProgressDialog = new ProgressDialog(TestsListActivity.this); 76 sProgressDialog.setCancelable(false); 77 sProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 78 sProgressDialog.setTitle(R.string.dialog_progress_title); 79 sProgressDialog.setMessage(getText(R.string.dialog_progress_msg)); 80 81 requestWindowFeature(Window.FEATURE_PROGRESS); 82 83 Intent intent = getIntent(); 84 if (!intent.getAction().equals(Intent.ACTION_RUN)) { 85 return; 86 } 87 String path = intent.getStringExtra(EXTRA_TEST_PATH); 88 89 sProgressDialog.show(); 90 Message doneMsg = Message.obtain(mHandler, MSG_TEST_LIST_PRELOADER_DONE); 91 92 Intent serviceIntent = new Intent(this, ManagerService.class); 93 serviceIntent.putExtra("path", path); 94 startService(serviceIntent); 95 96 new TestsListPreloaderThread(path, doneMsg).start(); 97 } 98 99 @Override 100 protected void onNewIntent(Intent intent) { 101 if (intent.getAction().equals(Intent.ACTION_REBOOT)) { 102 onCrashIntent(intent); 103 } else if (intent.getAction().equals(Intent.ACTION_SHUTDOWN)) { 104 onEverythingFinishedIntent(intent); 105 } 106 } 107 108 /** 109 * This method handles an intent that comes from ManageService when crash is detected. 110 * The intent contains an index in mTestsList of the test that crashed. TestsListActivity 111 * restarts the LayoutTestsExecutor from the following test in mTestsList, by sending 112 * an intent to it. This new intent contains a list of remaining tests to run, 113 * total count of all tests, and the index of the first test to run after restarting. 114 * LayoutTestExecutor runs then as usual, sending reports to ManagerService. If it 115 * detects the crash it sends a new intent and the flow repeats. 116 */ 117 private void onCrashIntent(Intent intent) { 118 int nextTestToRun = intent.getIntExtra("crashedTestIndex", -1) + 1; 119 if (nextTestToRun > 0 && nextTestToRun <= mTotalTestCount) { 120 restartExecutor(nextTestToRun); 121 } 122 } 123 124 public void registerOnEverythingFinishedCallback(OnEverythingFinishedCallback callback) { 125 mOnEverythingFinishedCallback = callback; 126 if (mEverythingFinished) { 127 mOnEverythingFinishedCallback.onFinished(); 128 } 129 } 130 131 private void onEverythingFinishedIntent(Intent intent) { 132 Toast toast = Toast.makeText(this, 133 "All tests finished.\nPress back key to return to the tests' list.", 134 Toast.LENGTH_LONG); 135 toast.setGravity(Gravity.CENTER, -40, 0); 136 toast.show(); 137 138 /** Show the details to the user */ 139 WebView webView = new WebView(this); 140 webView.getSettings().setJavaScriptEnabled(true); 141 webView.getSettings().setBuiltInZoomControls(true); 142 webView.getSettings().setEnableSmoothTransition(true); 143 /** This enables double-tap to zoom */ 144 webView.getSettings().setUseWideViewPort(true); 145 146 setContentView(webView); 147 webView.loadUrl(Summarizer.getDetailsUri().toString()); 148 149 mEverythingFinished = true; 150 if (mOnEverythingFinishedCallback != null) { 151 mOnEverythingFinishedCallback.onFinished(); 152 } 153 } 154 155 /** 156 * This, together with android:configChanges="orientation" in manifest file, prevents 157 * the activity from restarting on orientation change. 158 */ 159 @Override 160 public void onConfigurationChanged(Configuration newConfig) { 161 super.onConfigurationChanged(newConfig); 162 } 163 164 @Override 165 protected void onSaveInstanceState(Bundle outState) { 166 outState.putStringArrayList("testsList", mTestsList); 167 outState.putInt("totalCount", mTotalTestCount); 168 169 super.onSaveInstanceState(outState); 170 } 171 172 @Override 173 protected void onRestoreInstanceState(Bundle savedInstanceState) { 174 super.onRestoreInstanceState(savedInstanceState); 175 176 mTestsList = savedInstanceState.getStringArrayList("testsList"); 177 mTotalTestCount = savedInstanceState.getInt("totalCount"); 178 } 179 180 /** 181 * (Re)starts the executer activity from the given test number (inclusive, 0-based). 182 * This number is an index in mTestsList, not the sublist passed in the intent. 183 * 184 * @param startFrom 185 * test index in mTestsList to start the tests from (inclusive, 0-based) 186 */ 187 private void restartExecutor(int startFrom) { 188 Intent intent = new Intent(); 189 intent.setClass(this, LayoutTestsExecutor.class); 190 intent.setAction(Intent.ACTION_RUN); 191 192 if (startFrom < mTotalTestCount) { 193 File testListFile = new File(getExternalFilesDir(null), "test_list.txt"); 194 FsUtils.saveTestListToStorage(testListFile, startFrom, mTestsList); 195 intent.putExtra(LayoutTestsExecutor.EXTRA_TESTS_FILE, testListFile.getAbsolutePath()); 196 intent.putExtra(LayoutTestsExecutor.EXTRA_TEST_INDEX, startFrom); 197 } else { 198 intent.putExtra(LayoutTestsExecutor.EXTRA_TESTS_FILE, ""); 199 } 200 201 startActivity(intent); 202 } 203 }