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.rs.imagejb; 18 19 import android.app.Activity; 20 import android.content.Intent; 21 import android.graphics.Point; 22 import android.graphics.SurfaceTexture; 23 import android.os.Bundle; 24 import android.renderscript.Allocation; 25 import android.renderscript.RenderScript; 26 import android.util.Log; 27 import android.view.Surface; 28 import android.view.TextureView; 29 import android.view.View; 30 import android.view.WindowManager; 31 import android.widget.SeekBar; 32 import android.widget.Spinner; 33 import android.widget.TextView; 34 35 import androidx.test.InstrumentationRegistry; 36 37 public class ImageProcessingActivityJB extends Activity 38 implements SeekBar.OnSeekBarChangeListener, 39 TextureView.SurfaceTextureListener { 40 private final String TAG = "Img"; 41 42 private Spinner mSpinner; 43 private SeekBar mBar1; 44 private SeekBar mBar2; 45 private SeekBar mBar3; 46 private SeekBar mBar4; 47 private SeekBar mBar5; 48 49 private int mBars[] = new int[5]; 50 private int mBarsOld[] = new int[5]; 51 52 private TextView mText1; 53 private TextView mText2; 54 private TextView mText3; 55 private TextView mText4; 56 private TextView mText5; 57 private SizedTV mDisplayView; 58 59 private int mTestList[]; 60 private float mTestResults[]; 61 62 private boolean mToggleIO; 63 private boolean mToggleDVFS; 64 private boolean mToggleLong; 65 private boolean mTogglePause; 66 private boolean mToggleAnimate; 67 private boolean mToggleDisplay; 68 private int mBitmapWidth; 69 private int mBitmapHeight; 70 private boolean mDemoMode; 71 private float mMinTestRuntime; 72 private int mMinTestIterations; 73 74 // Updates pending is a counter of how many kernels have been 75 // sent to RS for processing 76 // 77 // In benchmark this is incremented each time a kernel is launched and 78 // decremented each time a kernel completes 79 // 80 // In demo mode, each UI input increments the counter and it is zeroed 81 // when the latest settings are sent to RS for processing. 82 private int mUpdatesPending; 83 84 // In demo mode this is used to count updates in the pipeline. It's 85 // incremented when work is submitted to RS and decremented when invalidate is 86 // called to display a result. 87 private int mShowsPending; 88 89 // Initialize the parameters for Instrumentation tests. prepareInstrumentationTest()90 protected void prepareInstrumentationTest() { 91 mTestList = new int[1]; 92 mBitmapWidth = 1920; 93 mBitmapHeight = 1080; 94 mTestResults = new float[1]; 95 96 startProcessor(); 97 } 98 99 static public class SizedTV extends TextureView { 100 int mWidth; 101 int mHeight; 102 SizedTV(android.content.Context c)103 public SizedTV(android.content.Context c) { 104 super(c); 105 mWidth = 800; 106 mHeight = 450; 107 } 108 SizedTV(android.content.Context c, android.util.AttributeSet attrs)109 public SizedTV(android.content.Context c, android.util.AttributeSet attrs) { 110 super(c, attrs); 111 mWidth = 800; 112 mHeight = 450; 113 } 114 SizedTV(android.content.Context c, android.util.AttributeSet attrs, int f)115 public SizedTV(android.content.Context c, android.util.AttributeSet attrs, int f) { 116 super(c, attrs, f); 117 mWidth = 800; 118 mHeight = 450; 119 } 120 onMeasure(int w, int h)121 protected void onMeasure(int w, int h) { 122 setMeasuredDimension(mWidth, mHeight); 123 } 124 } 125 126 ///////////////////////////////////////////////////////////////////////// 127 128 // Message processor to handle notifications for when kernel completes 129 private class MessageProcessor extends RenderScript.RSMessageHandler { MessageProcessor()130 MessageProcessor() { 131 } 132 run()133 public void run() { 134 synchronized(mProcessor) { 135 // In demo mode, decrement the pending displays and notify the 136 // UI processor it can now enqueue more work if additional updates 137 // are blocked by a full pipeline. 138 if (mShowsPending > 0) { 139 mShowsPending --; 140 mProcessor.notifyAll(); 141 } 142 } 143 } 144 } 145 146 147 ///////////////////////////////////////////////////////////////////////// 148 // Processor is a helper thread for running the work without 149 // blocking the UI thread. 150 class Processor extends Thread { 151 RenderScript mRS; 152 Allocation mInPixelsAllocation; 153 Allocation mInPixelsAllocation2; 154 Allocation mOutDisplayAllocation; 155 Allocation mOutPixelsAllocation; 156 157 private Surface mOutSurface; 158 private float mLastResult; 159 private boolean mRun = true; 160 private boolean mDoingBenchmark; 161 private TestBase mTest; 162 private TextureView mDisplayView; 163 164 private boolean mBenchmarkMode; 165 166 // We don't want to call the "changed" methods excessively as this 167 // can cause extra work for drivers. Before running a test update 168 // any bars which have changed. runTest()169 void runTest() { 170 if (mBars[0] != mBarsOld[0]) { 171 mTest.onBar1Changed(mBars[0]); 172 mBarsOld[0] = mBars[0]; 173 } 174 if (mBars[1] != mBarsOld[1]) { 175 mTest.onBar2Changed(mBars[1]); 176 mBarsOld[1] = mBars[1]; 177 } 178 if (mBars[2] != mBarsOld[2]) { 179 mTest.onBar3Changed(mBars[2]); 180 mBarsOld[2] = mBars[2]; 181 } 182 if (mBars[3] != mBarsOld[3]) { 183 mTest.onBar4Changed(mBars[3]); 184 mBarsOld[3] = mBars[3]; 185 } 186 if (mBars[4] != mBarsOld[4]) { 187 mTest.onBar5Changed(mBars[4]); 188 mBarsOld[4] = mBars[4]; 189 } 190 mTest.runTest(); 191 } 192 Processor(RenderScript rs, TextureView v, boolean benchmarkMode)193 Processor(RenderScript rs, TextureView v, boolean benchmarkMode) { 194 mRS = rs; 195 mDisplayView = v; 196 197 mRS.setMessageHandler(new MessageProcessor()); 198 199 switch(mBitmapWidth) { 200 case 3840: 201 mInPixelsAllocation = Allocation.createFromBitmapResource( 202 mRS, getResources(), R.drawable.img3840x2160a); 203 mInPixelsAllocation2 = Allocation.createFromBitmapResource( 204 mRS, getResources(), R.drawable.img3840x2160b); 205 break; 206 case 1920: 207 mInPixelsAllocation = Allocation.createFromBitmapResource( 208 mRS, getResources(), R.drawable.img1920x1080a); 209 mInPixelsAllocation2 = Allocation.createFromBitmapResource( 210 mRS, getResources(), R.drawable.img1920x1080b); 211 break; 212 case 1280: 213 mInPixelsAllocation = Allocation.createFromBitmapResource( 214 mRS, getResources(), R.drawable.img1280x720a); 215 mInPixelsAllocation2 = Allocation.createFromBitmapResource( 216 mRS, getResources(), R.drawable.img1280x720b); 217 break; 218 case 800: 219 mInPixelsAllocation = Allocation.createFromBitmapResource( 220 mRS, getResources(), R.drawable.img800x450a); 221 mInPixelsAllocation2 = Allocation.createFromBitmapResource( 222 mRS, getResources(), R.drawable.img800x450b); 223 break; 224 } 225 226 // We create the output allocation using USAGE_IO_OUTPUT so we can share the 227 // bits with a TextureView. This is more efficient than using a bitmap. 228 mOutDisplayAllocation = Allocation.createTyped(mRS, mInPixelsAllocation.getType(), 229 Allocation.MipmapControl.MIPMAP_NONE, 230 Allocation.USAGE_SCRIPT | 231 Allocation.USAGE_IO_OUTPUT); 232 mOutPixelsAllocation = mOutDisplayAllocation; 233 234 if (!mToggleIO) { 235 // Not using USAGE_IO for the script so create a non-io kernel to copy from 236 mOutPixelsAllocation = Allocation.createTyped(mRS, mInPixelsAllocation.getType(), 237 Allocation.MipmapControl.MIPMAP_NONE, 238 Allocation.USAGE_SCRIPT); 239 } 240 241 mBenchmarkMode = benchmarkMode; 242 start(); 243 } 244 245 // Run one loop of kernels for at least the specified minimum time. 246 // The function returns the average time in ms for the test run runBenchmarkLoop(float minTime, int minIter)247 private Result runBenchmarkLoop(float minTime, int minIter) { 248 mUpdatesPending = 0; 249 Result r = new Result(); 250 251 long t = java.lang.System.nanoTime(); 252 do { 253 synchronized(this) { 254 // Shows pending is used to track the number of kernels in the RS pipeline 255 // We throttle it to 2. This provide some buffering to allow a kernel to be started 256 // before we are nofitied the previous finished. However, larger numbers are uncommon 257 // in interactive apps as they introduce 'lag' between user input and display. 258 mShowsPending++; 259 if (mShowsPending > 2) { 260 try { 261 this.wait(); 262 } catch(InterruptedException e) { 263 } 264 } 265 } 266 267 // If animations are enabled update the test state. 268 if (mToggleAnimate) { 269 mTest.animateBars(r.getTotalTime()); 270 } 271 272 // Run the kernel 273 mTest.runTest(); 274 275 if (mToggleDisplay) { 276 // If we are not outputting directly to the TextureView we need to copy from 277 // our temporary buffer. 278 if (mOutDisplayAllocation != mOutPixelsAllocation) { 279 mOutDisplayAllocation.copyFrom(mOutPixelsAllocation); 280 } 281 282 // queue the update of the TextureView with the allocation contents 283 mOutDisplayAllocation.ioSend(); 284 } 285 286 // Send our RS message handler a message so we know when this work has completed 287 mRS.sendMessage(0, null); 288 289 // Finish previous iteration before recording the time. Without this, the first 290 // few iterations finish very quickly and the later iterations take much longer 291 mRS.finish(); 292 293 long t2 = java.lang.System.nanoTime(); 294 r.add((t2 - t) / 1000000000.f); 295 t = t2; 296 } while (r.getTotalTime() < minTime || r.getIterations() < minIter); 297 298 // Wait for any stray operations to complete and update the final time 299 mRS.finish(); 300 return r; 301 } 302 303 // Method to retreive benchmark results for instrumentation tests. getInstrumentationResult(IPTestListJB.TestName t)304 Result getInstrumentationResult(IPTestListJB.TestName t) { 305 mTest = changeTest(t, false); 306 return getBenchmark(); 307 } 308 309 // Get a benchmark result for a specific test getBenchmark()310 private Result getBenchmark() { 311 mDoingBenchmark = true; 312 mUpdatesPending = 0; 313 314 if (mToggleDVFS) { 315 mDvfsWar.go(); 316 } 317 318 // We run a short bit of work before starting the actual test 319 // this is to let any power management do its job and respond 320 runBenchmarkLoop(0.3f, 0); 321 322 // Run the actual benchmark 323 Result r = runBenchmarkLoop(mMinTestRuntime, mMinTestIterations); 324 325 Log.v("rs", "Test: time=" + r.getTotalTime() + "s, frames=" + r.getIterations() + 326 ", avg=" + r.getAvg() * 1000.f + ", stdcoef=" + r.getStdCoef() * 100.0f + "%"); 327 328 mDoingBenchmark = false; 329 return r; 330 } 331 run()332 public void run() { 333 Surface lastSurface = null; 334 while (mRun) { 335 // Our loop for launching tests or benchmarks 336 synchronized(this) { 337 // If we have no work to do, or we have displays pending, wait 338 if ((mUpdatesPending == 0) || (mShowsPending != 0)) { 339 try { 340 this.wait(); 341 } catch(InterruptedException e) { 342 } 343 } 344 345 // We may have been asked to exit while waiting 346 if (!mRun) return; 347 348 // During startup we may not have a surface yet to display, if 349 // this is the case, wait. 350 if ((mOutSurface == null) || (mOutPixelsAllocation == null)) { 351 continue; 352 } 353 354 // Our display surface changed, set it. 355 if (lastSurface != mOutSurface) { 356 mOutDisplayAllocation.setSurface(mOutSurface); 357 lastSurface = mOutSurface; 358 } 359 } 360 361 if (mBenchmarkMode) { 362 // Loop over the tests we want to benchmark 363 for (int ct=0; (ct < mTestList.length) && mRun; ct++) { 364 365 // For reproducibility we wait a short time for any sporadic work 366 // created by the user touching the screen to launch the test to pass. 367 // Also allows for things to settle after the test changes. 368 mRS.finish(); 369 try { 370 sleep(250); 371 } catch(InterruptedException e) { 372 } 373 374 // If we just ran a test, we destroy it here to relieve some memory pressure 375 if (mTest != null) { 376 mTest.destroy(); 377 } 378 379 // Select the next test 380 mTest = changeTest(mTestList[ct], false); 381 382 // If the user selected the "long pause" option, wait 383 if (mTogglePause) { 384 for (int i=0; (i < 100) && mRun; i++) { 385 try { 386 sleep(100); 387 } catch(InterruptedException e) { 388 } 389 } 390 } 391 392 // Run the test 393 mTestResults[ct] = getBenchmark().getAvg() * 1000.0f; 394 } 395 onBenchmarkFinish(mRun); 396 } else { 397 boolean update = false; 398 synchronized(this) { 399 // If we have updates to process and are not blocked by pending shows, 400 // start the next kernel 401 if ((mUpdatesPending > 0) && (mShowsPending == 0)) { 402 mUpdatesPending = 0; 403 update = true; 404 mShowsPending++; 405 } 406 } 407 408 if (update) { 409 // Run the kernel 410 runTest(); 411 412 // If we are not outputting directly to the TextureView we need to copy from 413 // our temporary buffer. 414 if (mOutDisplayAllocation != mOutPixelsAllocation) { 415 mOutDisplayAllocation.copyFrom(mOutPixelsAllocation); 416 } 417 418 // queue the update of the TextureView with the allocation contents 419 mOutDisplayAllocation.ioSend(); 420 421 // Send our RS message handler a message so we know when this work has completed 422 mRS.sendMessage(0, null); 423 } 424 } 425 } 426 427 } 428 update()429 public void update() { 430 // something UI related has changed, enqueue an update if one is not 431 // already pending. Wake the worker if needed 432 synchronized(this) { 433 if (mUpdatesPending < 2) { 434 mUpdatesPending++; 435 notifyAll(); 436 } 437 } 438 } 439 setSurface(Surface s)440 public void setSurface(Surface s) { 441 mOutSurface = s; 442 update(); 443 } 444 exit()445 public void exit() { 446 mRun = false; 447 448 synchronized(this) { 449 notifyAll(); 450 } 451 452 try { 453 this.join(); 454 } catch(InterruptedException e) { 455 } 456 457 mInPixelsAllocation.destroy(); 458 mInPixelsAllocation2.destroy(); 459 if (mOutPixelsAllocation != mOutDisplayAllocation) { 460 mOutPixelsAllocation.destroy(); 461 } 462 463 if (mTest != null) { 464 mTest.destroy(); 465 mTest = null; 466 } 467 mOutDisplayAllocation.destroy(); 468 mRS.destroy(); 469 470 mInPixelsAllocation = null; 471 mInPixelsAllocation2 = null; 472 mOutPixelsAllocation = null; 473 mOutDisplayAllocation = null; 474 mRS = null; 475 } 476 } 477 478 /////////////////////////////////////////////////////////////////////////////////////// 479 480 static class DVFSWorkaround { 481 static class spinner extends Thread { 482 boolean mRun = true; 483 long mNextSleep; 484 spinner()485 spinner() { 486 setPriority(MIN_PRIORITY); 487 start(); 488 } 489 run()490 public void run() { 491 while (mRun) { 492 Thread.yield(); 493 synchronized(this) { 494 long t = java.lang.System.currentTimeMillis(); 495 if (t > mNextSleep) { 496 try { 497 this.wait(); 498 } catch(InterruptedException e) { 499 } 500 } 501 } 502 } 503 } 504 go(long t)505 public void go(long t) { 506 synchronized(this) { 507 mNextSleep = t; 508 notifyAll(); 509 } 510 } 511 } 512 513 spinner s1; DVFSWorkaround()514 DVFSWorkaround() { 515 s1 = new spinner(); 516 } 517 go()518 void go() { 519 long t = java.lang.System.currentTimeMillis() + 2000; 520 s1.go(t); 521 } 522 destroy()523 void destroy() { 524 synchronized(this) { 525 s1.mRun = false; 526 notifyAll(); 527 } 528 } 529 } 530 DVFSWorkaround mDvfsWar = new DVFSWorkaround(); 531 532 /////////////////////////////////////////////////////////// 533 534 535 private boolean mDoingBenchmark; 536 public Processor mProcessor; 537 changeTest(IPTestListJB.TestName t, boolean setupUI)538 TestBase changeTest(IPTestListJB.TestName t, boolean setupUI) { 539 TestBase tb = IPTestListJB.newTest(t); 540 541 tb.createBaseTest(this); 542 if (setupUI) { 543 setupBars(tb); 544 } 545 return tb; 546 } 547 changeTest(int id, boolean setupUI)548 TestBase changeTest(int id, boolean setupUI) { 549 IPTestListJB.TestName t = IPTestListJB.TestName.values()[id]; 550 return changeTest(t, setupUI); 551 } 552 onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)553 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 554 if (fromUser) { 555 if (seekBar == mBar1) { 556 mBars[0] = progress; 557 } else if (seekBar == mBar2) { 558 mBars[1] = progress; 559 } else if (seekBar == mBar3) { 560 mBars[2] = progress; 561 } else if (seekBar == mBar4) { 562 mBars[3] = progress; 563 } else if (seekBar == mBar5) { 564 mBars[4] = progress; 565 } 566 mProcessor.update(); 567 } 568 } 569 onStartTrackingTouch(SeekBar seekBar)570 public void onStartTrackingTouch(SeekBar seekBar) { 571 } 572 onStopTrackingTouch(SeekBar seekBar)573 public void onStopTrackingTouch(SeekBar seekBar) { 574 } 575 setupBars(TestBase t)576 void setupBars(TestBase t) { 577 mSpinner.setVisibility(View.VISIBLE); 578 t.onSpinner1Setup(mSpinner); 579 580 mBar1.setVisibility(View.VISIBLE); 581 mText1.setVisibility(View.VISIBLE); 582 t.onBar1Setup(mBar1, mText1); 583 584 mBar2.setVisibility(View.VISIBLE); 585 mText2.setVisibility(View.VISIBLE); 586 t.onBar2Setup(mBar2, mText2); 587 588 mBar3.setVisibility(View.VISIBLE); 589 mText3.setVisibility(View.VISIBLE); 590 t.onBar3Setup(mBar3, mText3); 591 592 mBar4.setVisibility(View.VISIBLE); 593 mText4.setVisibility(View.VISIBLE); 594 t.onBar4Setup(mBar4, mText4); 595 596 mBar5.setVisibility(View.VISIBLE); 597 mText5.setVisibility(View.VISIBLE); 598 t.onBar5Setup(mBar5, mText5); 599 } 600 hideBars()601 void hideBars() { 602 mSpinner.setVisibility(View.INVISIBLE); 603 604 mBar1.setVisibility(View.INVISIBLE); 605 mText1.setVisibility(View.INVISIBLE); 606 607 mBar2.setVisibility(View.INVISIBLE); 608 mText2.setVisibility(View.INVISIBLE); 609 610 mBar3.setVisibility(View.INVISIBLE); 611 mText3.setVisibility(View.INVISIBLE); 612 613 mBar4.setVisibility(View.INVISIBLE); 614 mText4.setVisibility(View.INVISIBLE); 615 616 mBar5.setVisibility(View.INVISIBLE); 617 mText5.setVisibility(View.INVISIBLE); 618 } 619 620 @Override onCreate(Bundle savedInstanceState)621 protected void onCreate(Bundle savedInstanceState) { 622 super.onCreate(savedInstanceState); 623 setContentView(R.layout.main); 624 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 625 626 mDisplayView = findViewById(R.id.display); 627 628 mSpinner = findViewById(R.id.spinner1); 629 630 mBar1 = findViewById(R.id.slider1); 631 mBar2 = findViewById(R.id.slider2); 632 mBar3 = findViewById(R.id.slider3); 633 mBar4 = findViewById(R.id.slider4); 634 mBar5 = findViewById(R.id.slider5); 635 636 mBar1.setOnSeekBarChangeListener(this); 637 mBar2.setOnSeekBarChangeListener(this); 638 mBar3.setOnSeekBarChangeListener(this); 639 mBar4.setOnSeekBarChangeListener(this); 640 mBar5.setOnSeekBarChangeListener(this); 641 642 mText1 = findViewById(R.id.slider1Text); 643 mText2 = findViewById(R.id.slider2Text); 644 mText3 = findViewById(R.id.slider3Text); 645 mText4 = findViewById(R.id.slider4Text); 646 mText5 = findViewById(R.id.slider5Text); 647 } 648 649 @Override onPause()650 protected void onPause() { 651 super.onPause(); 652 if (mProcessor != null) { 653 mProcessor.exit(); 654 mProcessor = null; 655 } 656 } 657 onBenchmarkFinish(boolean ok)658 public void onBenchmarkFinish(boolean ok) { 659 if (ok) { 660 Intent intent = new Intent(); 661 intent.putExtra("tests", mTestList); 662 intent.putExtra("results", mTestResults); 663 setResult(RESULT_OK, intent); 664 } else { 665 setResult(RESULT_CANCELED); 666 } 667 finish(); 668 } 669 670 startProcessor()671 void startProcessor() { 672 Point size = new Point(); 673 getWindowManager().getDefaultDisplay().getSize(size); 674 675 int mScreenWidth = size.x; 676 int mScreenHeight = size.y; 677 678 int tw = mBitmapWidth; 679 int th = mBitmapHeight; 680 681 if (tw > mScreenWidth || th > mScreenHeight) { 682 float s1 = (float)tw / (float)mScreenWidth; 683 float s2 = (float)th / (float)mScreenHeight; 684 685 if (s1 > s2) { 686 tw /= s1; 687 th /= s1; 688 } else { 689 tw /= s2; 690 th /= s2; 691 } 692 } 693 694 android.util.Log.v("rs", "TV sizes " + tw + ", " + th); 695 696 mDisplayView.mWidth = tw; 697 mDisplayView.mHeight = th; 698 //mDisplayView.setTransform(new android.graphics.Matrix()); 699 700 mProcessor = new Processor(RenderScript.create(this), mDisplayView, !mDemoMode); 701 mDisplayView.setSurfaceTextureListener(this); 702 703 if (mDemoMode) { 704 mProcessor.mTest = changeTest(mTestList[0], true); 705 } 706 } 707 708 @Override onResume()709 protected void onResume() { 710 super.onResume(); 711 Intent i = getIntent(); 712 mTestList = i.getIntArrayExtra("tests"); 713 714 mToggleIO = i.getBooleanExtra("enable io", false); 715 mToggleDVFS = i.getBooleanExtra("enable dvfs", false); 716 mToggleLong = i.getBooleanExtra("enable long", false); 717 mTogglePause = i.getBooleanExtra("enable pause", false); 718 mToggleAnimate = i.getBooleanExtra("enable animate", false); 719 mToggleDisplay = i.getBooleanExtra("enable display", false); 720 mBitmapWidth = i.getIntExtra("resolution X", 0); 721 mBitmapHeight = i.getIntExtra("resolution Y", 0); 722 mDemoMode = i.getBooleanExtra("demo", false); 723 724 // Default values 725 mMinTestRuntime = 1.0f; 726 mMinTestIterations = 2; 727 728 // Pass in arguments from "am instrumentation ..." if present 729 // This is wrapped in a try..catch because there was an exception thrown whenever 730 // instrumentation was not used (ie. when the graphical interface was used) 731 try { 732 Bundle extras = InstrumentationRegistry.getArguments(); 733 String passedInString = null; 734 if ( extras != null ) { 735 if ( extras.containsKey ("minimum_test_runtime") ) { 736 mMinTestRuntime = Float.parseFloat(extras.getString("minimum_test_runtime")); 737 } 738 if ( extras.containsKey ("minimum_test_iterations") ) { 739 mMinTestIterations = Integer.parseInt( 740 extras.getString("minimum_test_iterations")); 741 } 742 } 743 } catch(Exception e) { 744 } 745 746 // User chose the longer pre-set runtime 747 if (mToggleLong) { 748 mMinTestRuntime = 10.f; 749 } 750 751 // Hide the bars in demo mode. 752 // Calling from onResume() to make sure the operation is on the UI thread. 753 if (!mDemoMode) { 754 hideBars(); 755 } 756 // Start the processor only when a non-empty list received from the intent. 757 if (mTestList != null) { 758 mTestResults = new float[mTestList.length]; 759 startProcessor(); 760 } 761 } 762 onDestroy()763 protected void onDestroy() { 764 super.onDestroy(); 765 } 766 767 768 @Override onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)769 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 770 mProcessor.setSurface(new Surface(surface)); 771 } 772 773 @Override onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)774 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 775 mProcessor.setSurface(new Surface(surface)); 776 } 777 778 @Override onSurfaceTextureDestroyed(SurfaceTexture surface)779 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 780 if (mProcessor != null) { 781 mProcessor.setSurface(null); 782 } 783 return true; 784 } 785 786 @Override onSurfaceTextureUpdated(SurfaceTexture surface)787 public void onSurfaceTextureUpdated(SurfaceTexture surface) { 788 } 789 } 790