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