1 /* 2 * Copyright © 2012 Linaro Limited 3 * 4 * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark. 5 * 6 * glmark2 is free software: you can redistribute it and/or modify it under the 7 * terms of the GNU General Public License as published by the Free Software 8 * Foundation, either version 3 of the License, or (at your option) any later 9 * version. 10 * 11 * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY 12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 * details. 15 * 16 * You should have received a copy of the GNU General Public License along with 17 * glmark2. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * Authors: 20 * Alexandros Frantzis 21 */ 22 package org.linaro.glmark2; 23 24 import java.util.ArrayList; 25 26 import android.os.Bundle; 27 import android.app.Activity; 28 import android.app.AlertDialog; 29 import android.app.Dialog; 30 import android.content.Context; 31 import android.content.DialogInterface; 32 import android.content.DialogInterface.OnDismissListener; 33 import android.content.Intent; 34 import android.content.SharedPreferences; 35 import android.preference.PreferenceManager; 36 import android.widget.BaseAdapter; 37 import android.widget.ArrayAdapter; 38 import android.widget.ListView; 39 import android.widget.TextView; 40 import android.widget.Button; 41 import android.widget.EditText; 42 import android.widget.CheckBox; 43 import android.view.KeyEvent; 44 import android.view.LayoutInflater; 45 import android.view.Menu; 46 import android.view.MenuInflater; 47 import android.view.MenuItem; 48 import android.view.View; 49 import android.view.ViewGroup; 50 import android.view.WindowManager; 51 import android.view.inputmethod.EditorInfo; 52 import android.util.Log; 53 import android.widget.AdapterView.OnItemClickListener; 54 import android.widget.AdapterView.OnItemLongClickListener; 55 import android.widget.AdapterView; 56 import android.widget.TextView.OnEditorActionListener; 57 58 public class MainActivity extends Activity { 59 public static final int DIALOG_ERROR_ID = 0; 60 public static final int DIALOG_BENCHMARK_ACTIONS_ID = 1; 61 public static final int DIALOG_SAVE_LIST_ID = 2; 62 public static final int DIALOG_LOAD_LIST_ID = 3; 63 public static final int DIALOG_DELETE_LIST_ID = 4; 64 65 public static final int ACTIVITY_GLMARK2_REQUEST_CODE = 1; 66 public static final int ACTIVITY_EDITOR_REQUEST_CODE = 2; 67 68 /** 69 * The supported benchmark item actions. 70 */ 71 public enum BenchmarkItemAction { 72 EDIT, DELETE, CLONE, MOVEUP, MOVEDOWN 73 } 74 75 BaseAdapter adapter; 76 SceneInfo[] sceneInfoList; 77 BenchmarkListManager benchmarkListManager; 78 79 @Override onCreate(Bundle savedInstanceState)80 public void onCreate(Bundle savedInstanceState) { 81 super.onCreate(savedInstanceState); 82 setContentView(R.layout.activity_main); 83 ArrayList<String> savedBenchmarks = null; 84 85 if (savedInstanceState != null) 86 savedBenchmarks = savedInstanceState.getStringArrayList("benchmarks"); 87 88 init(savedBenchmarks); 89 } 90 91 @Override onSaveInstanceState(Bundle outState)92 protected void onSaveInstanceState(Bundle outState) { 93 super.onSaveInstanceState(outState); 94 outState.putStringArrayList("benchmarks", benchmarkListManager.getBenchmarkList()); 95 } 96 97 @Override onCreateDialog(int id, Bundle bundle)98 protected Dialog onCreateDialog(int id, Bundle bundle) { 99 final CharSequence[] benchmarkActions = {"Delete", "Clone", "Move Up", "Move Down"}; 100 final BenchmarkItemAction[] benchmarkActionsId = { 101 BenchmarkItemAction.DELETE, BenchmarkItemAction.CLONE, 102 BenchmarkItemAction.MOVEUP, BenchmarkItemAction.MOVEDOWN 103 }; 104 final int finalId = id; 105 106 Dialog dialog; 107 108 switch (id) { 109 case DIALOG_ERROR_ID: 110 { 111 AlertDialog.Builder builder = new AlertDialog.Builder(this); 112 builder.setMessage(bundle.getString("message") + ": " + 113 bundle.getString("detail")); 114 builder.setCancelable(false); 115 builder.setPositiveButton("OK", null); 116 dialog = builder.create(); 117 } 118 break; 119 120 case DIALOG_BENCHMARK_ACTIONS_ID: 121 { 122 final int benchmarkPos = bundle.getInt("benchmark-pos"); 123 AlertDialog.Builder builder = new AlertDialog.Builder(this); 124 builder.setTitle("Pick an action"); 125 builder.setItems(benchmarkActions, new DialogInterface.OnClickListener() { 126 public void onClick(DialogInterface dialog, int item) { 127 doBenchmarkItemAction(benchmarkPos, benchmarkActionsId[item], null); 128 dismissDialog(DIALOG_BENCHMARK_ACTIONS_ID); 129 } 130 }); 131 dialog = builder.create(); 132 } 133 break; 134 135 case DIALOG_SAVE_LIST_ID: 136 { 137 AlertDialog.Builder builder = new AlertDialog.Builder(this); 138 View layout = getLayoutInflater().inflate(R.layout.save_dialog, null); 139 final EditText input = (EditText) layout.findViewById(R.id.listName); 140 final CheckBox checkBox = (CheckBox) layout.findViewById(R.id.external); 141 142 input.setOnEditorActionListener(new OnEditorActionListener() { 143 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 144 if (actionId == EditorInfo.IME_ACTION_DONE || 145 (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && 146 event.getAction() == KeyEvent.ACTION_UP)) 147 { 148 String listName = v.getText().toString(); 149 try { 150 benchmarkListManager.saveBenchmarkList(listName, 151 checkBox.isChecked()); 152 } 153 catch (Exception ex) { 154 Bundle bundle = new Bundle(); 155 bundle.putString("message", "Cannot save list to file " + listName); 156 bundle.putString("detail", ex.getMessage()); 157 showDialog(DIALOG_ERROR_ID, bundle); 158 } 159 dismissDialog(DIALOG_SAVE_LIST_ID); 160 } 161 return true; 162 } 163 }); 164 165 builder.setTitle("Save list as"); 166 builder.setView(layout); 167 168 dialog = builder.create(); 169 dialog.getWindow().setSoftInputMode( 170 WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | 171 WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE 172 ); 173 } 174 break; 175 176 case DIALOG_LOAD_LIST_ID: 177 case DIALOG_DELETE_LIST_ID: 178 { 179 AlertDialog.Builder builder = new AlertDialog.Builder(this); 180 if (id == DIALOG_LOAD_LIST_ID) 181 builder.setTitle("Load list"); 182 else 183 builder.setTitle("Delete list"); 184 final String[] savedLists = benchmarkListManager.getSavedLists(); 185 186 builder.setItems(savedLists, new DialogInterface.OnClickListener() { 187 public void onClick(DialogInterface dialog, int index) { 188 String desc = savedLists[index]; 189 String filename = ""; 190 boolean external = false; 191 192 if (desc.startsWith("internal/")) { 193 filename = desc.replace("internal/", ""); 194 external = false; 195 } 196 else if (desc.startsWith("external/")) { 197 filename = desc.replace("external/", ""); 198 external = true; 199 } 200 201 try { 202 if (finalId == DIALOG_LOAD_LIST_ID) { 203 benchmarkListManager.loadBenchmarkList(filename, external); 204 adapter.notifyDataSetChanged(); 205 } 206 else { 207 benchmarkListManager.deleteBenchmarkList(filename, external); 208 } 209 210 } 211 catch (Exception ex) { 212 Bundle bundle = new Bundle(); 213 if (finalId == DIALOG_LOAD_LIST_ID) 214 bundle.putString("message", "Cannot load list " + desc); 215 else 216 bundle.putString("message", "Cannot delete list " + desc); 217 bundle.putString("detail", ex.getMessage()); 218 showDialog(DIALOG_ERROR_ID, bundle); 219 } 220 dismissDialog(finalId); 221 } 222 }); 223 224 dialog = builder.create(); 225 } 226 break; 227 228 default: 229 dialog = null; 230 break; 231 } 232 233 if (dialog != null) { 234 dialog.setOnDismissListener(new OnDismissListener() { 235 public void onDismiss(DialogInterface dialog) { 236 removeDialog(finalId); 237 } 238 }); 239 } 240 241 return dialog; 242 } 243 244 @Override onCreateOptionsMenu(Menu menu)245 public boolean onCreateOptionsMenu(Menu menu) { 246 MenuInflater inflater = getMenuInflater(); 247 inflater.inflate(R.menu.main_options_menu, menu); 248 return true; 249 } 250 251 @Override onOptionsItemSelected(MenuItem item)252 public boolean onOptionsItemSelected(MenuItem item) { 253 boolean ret = true; 254 255 switch (item.getItemId()) { 256 case R.id.save_benchmark_list: 257 showDialog(DIALOG_SAVE_LIST_ID); 258 ret = true; 259 break; 260 case R.id.load_benchmark_list: 261 showDialog(DIALOG_LOAD_LIST_ID); 262 ret = true; 263 break; 264 case R.id.delete_benchmark_list: 265 showDialog(DIALOG_DELETE_LIST_ID); 266 ret = true; 267 break; 268 case R.id.settings: 269 startActivity(new Intent(MainActivity.this, MainPreferencesActivity.class)); 270 ret = true; 271 break; 272 case R.id.results: 273 startActivity(new Intent(MainActivity.this, ResultsActivity.class)); 274 ret = true; 275 break; 276 case R.id.about: 277 startActivity(new Intent(MainActivity.this, AboutActivity.class)); 278 ret = true; 279 break; 280 default: 281 ret = super.onOptionsItemSelected(item); 282 break; 283 } 284 285 return ret; 286 } 287 288 @Override onActivityResult(int requestCode, int resultCode, Intent data)289 public void onActivityResult(int requestCode, int resultCode, Intent data) { 290 if (requestCode == ACTIVITY_GLMARK2_REQUEST_CODE) 291 { 292 startActivity(new Intent(this, ResultsActivity.class)); 293 return; 294 } 295 else if (requestCode == ACTIVITY_EDITOR_REQUEST_CODE && 296 resultCode == RESULT_OK) 297 { 298 String benchmarkText = data.getStringExtra("benchmark-text"); 299 int benchmarkPos = data.getIntExtra("benchmark-pos", 0); 300 doBenchmarkItemAction(benchmarkPos, BenchmarkItemAction.EDIT, benchmarkText); 301 } 302 } 303 304 /** 305 * Initialize the activity. 306 * 307 * @param savedBenchmarks a list of benchmarks to load the list with (or null) 308 */ init(ArrayList<String> savedBenchmarks)309 private void init(ArrayList<String> savedBenchmarks) 310 { 311 /* Initialize benchmark list manager */ 312 benchmarkListManager = new BenchmarkListManager(this, savedBenchmarks); 313 final ArrayList<String> benchmarks = benchmarkListManager.getBenchmarkList(); 314 315 /* Get Scene information */ 316 sceneInfoList = Glmark2Native.getSceneInfo(getAssets()); 317 318 /* Set up the run button */ 319 Button button = (Button) findViewById(R.id.runButton); 320 button.setOnClickListener(new View.OnClickListener() { 321 public void onClick(View v) { 322 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); 323 Intent intent = new Intent(MainActivity.this, Glmark2Activity.class); 324 String args = ""; 325 for (int i = 0; i < benchmarks.size() - 1; i++) 326 args += "-b \"" + benchmarks.get(i) + "\" "; 327 if (prefs.getBoolean("run_forever", false)) 328 args += "--run-forever "; 329 if (prefs.getBoolean("log_debug", false)) 330 args += "--debug "; 331 if (!args.isEmpty()) 332 intent.putExtra("args", args); 333 334 if (prefs.getBoolean("show_results", true)) 335 startActivityForResult(intent, ACTIVITY_GLMARK2_REQUEST_CODE); 336 else 337 startActivity(intent); 338 } 339 }); 340 341 /* Set up the benchmark list view */ 342 ListView lv = (ListView) findViewById(R.id.benchmarkListView); 343 adapter = new BenchmarkAdapter(this, R.layout.list_item, benchmarks); 344 lv.setAdapter(adapter); 345 346 lv.setOnItemClickListener(new OnItemClickListener() { 347 public void onItemClick(AdapterView<?> parentView, View childView, int position, long id) { 348 Intent intent = new Intent(MainActivity.this, EditorActivity.class); 349 String t = benchmarks.get(position); 350 if (position == benchmarks.size() - 1) 351 t = ""; 352 intent.putExtra("benchmark-text", t); 353 intent.putExtra("benchmark-pos", position); 354 intent.putExtra("scene-info", sceneInfoList); 355 startActivityForResult(intent, ACTIVITY_EDITOR_REQUEST_CODE); 356 } 357 }); 358 359 lv.setOnItemLongClickListener(new OnItemLongClickListener() { 360 public boolean onItemLongClick(AdapterView<?> parentView, View childView, int position, long id) { 361 if (position < benchmarks.size() - 1) { 362 Bundle bundle = new Bundle(); 363 bundle.putInt("benchmark-pos", position); 364 showDialog(DIALOG_BENCHMARK_ACTIONS_ID, bundle); 365 } 366 return true; 367 } 368 }); 369 370 } 371 372 /** 373 * Perform an action on an listview benchmark item. 374 * 375 * @param position the position of the item in the listview 376 * @param action the action to perform 377 * @param data extra data needed by some actions 378 */ doBenchmarkItemAction(int position, BenchmarkItemAction action, String data)379 private void doBenchmarkItemAction(int position, BenchmarkItemAction action, String data) 380 { 381 int scrollPosition = position; 382 final ArrayList<String> benchmarks = benchmarkListManager.getBenchmarkList(); 383 384 switch(action) { 385 case EDIT: 386 if (position == benchmarks.size() - 1) { 387 benchmarks.add(position, data); 388 scrollPosition = position + 1; 389 } 390 else { 391 benchmarks.set(position, data); 392 } 393 break; 394 case DELETE: 395 benchmarks.remove(position); 396 break; 397 case CLONE: 398 { 399 String s = benchmarks.get(position); 400 benchmarks.add(position, s); 401 scrollPosition = position + 1; 402 } 403 break; 404 case MOVEUP: 405 if (position > 0) { 406 String up = benchmarks.get(position - 1); 407 String s = benchmarks.get(position); 408 benchmarks.set(position - 1, s); 409 benchmarks.set(position, up); 410 scrollPosition = position - 1; 411 } 412 break; 413 case MOVEDOWN: 414 if (position < benchmarks.size() - 2) { 415 String down = benchmarks.get(position + 1); 416 String s = benchmarks.get(position); 417 benchmarks.set(position + 1, s); 418 benchmarks.set(position, down); 419 scrollPosition = position + 1; 420 } 421 break; 422 default: 423 break; 424 } 425 426 427 adapter.notifyDataSetChanged(); 428 429 /* Scroll the list view so that the item of interest remains visible */ 430 final int finalScrollPosition = scrollPosition; 431 final ListView lv = (ListView) findViewById(R.id.benchmarkListView); 432 lv.post(new Runnable() { 433 @Override 434 public void run() { 435 lv.smoothScrollToPosition(finalScrollPosition); 436 } 437 }); 438 } 439 440 /** 441 * A ListView adapter that creates item views from benchmark strings. 442 */ 443 private class BenchmarkAdapter extends ArrayAdapter<String> { 444 private ArrayList<String> items; 445 BenchmarkAdapter(Context context, int textViewResourceId, ArrayList<String> items)446 public BenchmarkAdapter(Context context, int textViewResourceId, ArrayList<String> items) { 447 super(context, textViewResourceId, items); 448 this.items = items; 449 } 450 451 @Override getView(int position, View convertView, ViewGroup parent)452 public View getView(int position, View convertView, ViewGroup parent) { 453 /* Get the view/widget to use */ 454 View v = convertView; 455 if (v == null) { 456 LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 457 v = vi.inflate(R.layout.list_item, null); 458 } 459 460 /* Split the benchmark into its scene name and its options */ 461 String benchmark = items.get(position); 462 String[] ba = benchmark.split(":", 2); 463 464 if (ba != null) { 465 TextView title = (TextView) v.findViewById(R.id.title); 466 TextView summary = (TextView) v.findViewById(R.id.summary); 467 title.setText(""); 468 summary.setText(""); 469 470 if (title != null && ba.length > 0) 471 title.setText(ba[0]); 472 if (summary != null && ba.length > 1) 473 summary.setText(ba[1]); 474 } 475 return v; 476 } 477 } 478 479 static { 480 System.loadLibrary("glmark2-android"); 481 } 482 } 483