1 /*
2 * Copyright 2019 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 androidx.camera.integration.antelope
18
19 import androidx.camera.integration.antelope.MainActivity.Companion.antelopeIdlingResource
20 import androidx.camera.integration.antelope.MainActivity.Companion.cameraParams
21 import androidx.camera.integration.antelope.MainActivity.Companion.isSingleTestRunning
22 import androidx.camera.integration.antelope.MainActivity.Companion.logd
23 import androidx.camera.integration.antelope.MainActivity.Companion.testsRemaining
24 import com.google.common.math.Stats
25 import java.text.SimpleDateFormat
26 import java.util.Calendar
27 import kotlin.collections.ArrayList
28 import kotlin.math.roundToInt
29
30 /**
31 * During a multiple-test run, this should be called after each test is completed. Record the result
32 * and call the automatic test runner to start the next test.
33 *
34 * If all test are completed, post result to screen and save the log.
35 */
postTestResultsnull36 fun postTestResults(activity: MainActivity, testConfig: TestConfig) {
37 MainActivity.testRun.add(testConfig.testResults)
38 testsRemaining--
39
40 var log = ""
41 var csv = ""
42
43 if (0 >= testsRemaining) {
44 if (!isSingleTestRunning) {
45 log += testSummaryString(activity, MainActivity.testRun)
46 csv += testSummaryCSV(activity, MainActivity.testRun)
47 }
48
49 for ((index, result) in MainActivity.testRun.withIndex()) {
50 // TODO with test summary we can combine these two cases
51 if (0 == index) {
52 log += result.toString(activity, false)
53 csv += result.toCSV(activity, false)
54 } else {
55 log += result.toString(activity, false)
56 csv += result.toCSV(activity, false)
57 }
58 }
59
60 activity.resetUIAfterTest()
61 activity.updateLog(log)
62 writeCSV(activity, DeviceInfo().deviceShort, csv)
63
64 // Indicate to Espresso that a test run has ended
65 try {
66 logd("Decrementing AntelopeIdlingResource")
67 antelopeIdlingResource.decrement()
68 } catch (ex: IllegalStateException) {
69 logd("Antelope idling resource decremented below 0. This should never happen.")
70 }
71 } else {
72 autoTestRunner(activity)
73 }
74 }
75
76 /** Set up the TestConfig object for a single test */
createSingleTestConfignull77 fun createSingleTestConfig(activity: MainActivity): TestConfig {
78 val config = TestConfig()
79
80 config.apply {
81 when (PrefHelper.getSingleTestType(activity)) {
82 "INIT" -> {
83 testName = "Camera Open/Close"
84 currentRunningTest = TestType.INIT
85 }
86 "PREVIEW" -> {
87 testName = "Preview Start"
88 currentRunningTest = TestType.PREVIEW
89 }
90 "SWITCH_CAMERA" -> {
91 testName = "Switch Cameras"
92 currentRunningTest = TestType.SWITCH_CAMERA
93 }
94 "MULTI_SWITCH" -> {
95 testName = "Switch Cameras (Multiple)"
96 currentRunningTest = TestType.MULTI_SWITCH
97 }
98 "MULTI_PHOTO" -> {
99 testName = "Multiple Captures"
100 currentRunningTest = TestType.MULTI_PHOTO
101 }
102 "MULTI_PHOTO_CHAIN" -> {
103 testName = "Multiple Captures (Chained)"
104 currentRunningTest = TestType.MULTI_PHOTO_CHAIN
105 }
106 else -> {
107 testName = "Single Capture"
108 currentRunningTest = TestType.PHOTO
109 }
110 }
111
112 api = CameraAPI.valueOf(PrefHelper.getSingleTestApi(activity).uppercase())
113 focusMode = FocusMode.valueOf(PrefHelper.getSingleTestFocus(activity).uppercase())
114 imageCaptureSize =
115 ImageCaptureSize.valueOf(PrefHelper.getSingleTestImageSize(activity).uppercase())
116 camera = PrefHelper.getSingleTestCamera(activity)
117 config.setupTestResults()
118 }
119
120 return config
121 }
122
123 /** Create a test configuration given the test's name and the currently selected test values */
createTestConfignull124 fun createTestConfig(testName: String): TestConfig {
125 val config = TestConfig(testName)
126 config.camera = MainActivity.camViewModel.getCurrentCamera().value.toString()
127 config.api = MainActivity.camViewModel.getCurrentAPI().value ?: CameraAPI.CAMERA2
128 config.imageCaptureSize =
129 MainActivity.camViewModel.getCurrentImageCaptureSize().value ?: ImageCaptureSize.MAX
130
131 // If we don't have auto-focus, we set the focus mode to FIXED
132 if (MainActivity.cameraParams.get(config.camera)?.hasAF ?: true)
133 config.focusMode = MainActivity.camViewModel.getCurrentFocusMode().value ?: FocusMode.AUTO
134 else config.focusMode = FocusMode.FIXED
135
136 config.setupTestResults()
137
138 return config
139 }
140
141 /** For multiple tests, configure the list of TestConfigs to run */
setupAutoTestRunnernull142 fun setupAutoTestRunner(activity: MainActivity) {
143 MainActivity.autoTestConfigs.clear()
144 val cameras: ArrayList<String> = PrefHelper.getCameraIds(activity, MainActivity.cameraParams)
145 val logicalCameras: ArrayList<String> =
146 PrefHelper.getLogicalCameraIds(MainActivity.cameraParams)
147 val apis: ArrayList<CameraAPI> = PrefHelper.getAPIs(activity)
148 val imageSizes: ArrayList<ImageCaptureSize> = PrefHelper.getImageSizes(activity)
149 val focusModes: ArrayList<FocusMode> = PrefHelper.getFocusModes(activity)
150 val testTypes: ArrayList<TestType> = ArrayList()
151 val doSwitchTest: Boolean = PrefHelper.getSwitchTest(activity)
152
153 testTypes.add(TestType.MULTI_PHOTO)
154 testTypes.add(TestType.MULTI_PHOTO_CHAIN)
155
156 if (doSwitchTest) testTypes.add(TestType.MULTI_SWITCH)
157
158 MainActivity.testRun.clear()
159
160 for (camera in cameras) {
161 for (api in apis) {
162 // Camera1 does not have access to physical cameras, only logical 0 and 1
163 // Some devices have no camera or only 1 front-facing camera (like Chromebooks)
164 // so we need to make sure they exist
165 if ((CameraAPI.CAMERA1 == api) && !logicalCameras.contains(camera)) continue
166
167 // Currently CameraX only supports FRONT and BACK
168 if ((CameraAPI.CAMERAX == api) && !(camera.equals("0") || camera.equals("1"))) continue
169
170 for (imageSize in imageSizes) {
171 for (focusMode in focusModes) {
172 if (FocusMode.CONTINUOUS == focusMode) {
173 // If camera is fixed-focus, only run the AUTO test
174 if (!(MainActivity.cameraParams.get(camera)?.hasAF ?: true)) continue
175 }
176
177 for (testType in testTypes) {
178 // Camera1 does not have chaining capabilities
179 if ((CameraAPI.CAMERA1 == api) && (TestType.MULTI_PHOTO_CHAIN == testType))
180 continue
181
182 // For now we only test 0->1->0, just add this test for the first "camera"
183 // TODO: figure out a way to test different permutations
184 if ((TestType.MULTI_SWITCH == testType) && !camera.equals(cameras.first()))
185 continue
186
187 // Switch test doesn't do a capture don't repeat for all capture sizes
188 if (imageSize == ImageCaptureSize.MIN && testType == TestType.MULTI_SWITCH)
189 continue
190
191 // Switch test doesn't do a capture so don't repeat for all focus modes
192 if (focusMode != FocusMode.AUTO && testType == TestType.MULTI_SWITCH)
193 continue
194
195 // If this is a fixed focus lens, focusMode here has been set to auto,
196 // set it to fixed in the TestConfig
197 var realFocusMode: FocusMode = focusMode
198 if (!(MainActivity.cameraParams.get(camera)?.hasAF ?: true))
199 realFocusMode = FocusMode.FIXED
200
201 var testName =
202 when (api) {
203 CameraAPI.CAMERA1 -> "Camera1"
204 CameraAPI.CAMERA2 -> "Camera2"
205 CameraAPI.CAMERAX -> "CameraX"
206 }
207
208 testName += " - "
209 testName +=
210 when (imageSize) {
211 ImageCaptureSize.MIN -> "Min"
212 ImageCaptureSize.MAX -> "Max"
213 }
214 testName += " image size - Camera device "
215
216 if (testType != TestType.MULTI_SWITCH) {
217 testName += camera
218 testName += " "
219 }
220
221 testName +=
222 when (realFocusMode) {
223 FocusMode.AUTO -> "(auto-focus)"
224 FocusMode.CONTINUOUS -> "(continuous focus)"
225 else -> "(fixed-focus)"
226 }
227
228 testName += " - "
229 testName +=
230 when (testType) {
231 TestType.MULTI_PHOTO -> "Multiple Captures"
232 TestType.MULTI_PHOTO_CHAIN -> "Multiple Captures (chained)"
233 TestType.MULTI_SWITCH -> "Switch Camera"
234 else -> "unknown test"
235 }
236
237 val testConfig =
238 TestConfig(testName, testType, api, imageSize, realFocusMode, camera)
239 testConfig.setupTestResults()
240 MainActivity.autoTestConfigs.add(testConfig)
241 }
242 }
243 }
244 }
245 }
246
247 // Add Test X of Y string to test names
248 for ((index, testConfig) in MainActivity.autoTestConfigs.withIndex()) {
249 testConfig.testName =
250 "" +
251 (index + 1) +
252 " of " +
253 MainActivity.autoTestConfigs.size +
254 ": " +
255 testConfig.testName
256 }
257
258 testsRemaining = MainActivity.autoTestConfigs.size
259 }
260
261 /** Run the list of tests in autoTestConfigs */
autoTestRunnernull262 fun autoTestRunner(activity: MainActivity) {
263 if (MainActivity.cameras.isEmpty()) {
264 testsRemaining = 0
265 return
266 }
267
268 // If something goes wrong or we are aborted, stop testing
269 if (0 == testsRemaining) return
270
271 val currentTest: Int = MainActivity.autoTestConfigs.size - testsRemaining + 1
272 val currentConfig: TestConfig = MainActivity.autoTestConfigs.get(currentTest - 1)
273 MainActivity.logd("autoTestRun about to run: " + currentConfig.testName)
274
275 activity.runOnUiThread {
276 if (testsRemaining == MainActivity.autoTestConfigs.size)
277 activity.setupUIForTest(currentConfig, false)
278 else activity.setupUIForTest(currentConfig, true)
279 }
280
281 multiCounter = 0
282 initializeTest(activity, cameraParams.get(currentConfig.camera), currentConfig)
283 }
284
285 /**
286 * For an array of TestResults, generate a high-level summary of the most important values.
287 *
288 * This mostly consists of values for default rear camera.
289 */
testSummaryStringnull290 fun testSummaryString(activity: MainActivity, allTestResults: ArrayList<TestResults>): String {
291 var output = ""
292
293 if (allTestResults.isEmpty()) return output
294
295 val mainCamera = getMainCamera(activity, allTestResults)
296
297 val c2Auto =
298 findTest(
299 allTestResults,
300 mainCamera,
301 CameraAPI.CAMERA2,
302 ImageCaptureSize.MAX,
303 FocusMode.AUTO,
304 TestType.MULTI_PHOTO
305 )
306 val c2AutoChain =
307 findTest(
308 allTestResults,
309 mainCamera,
310 CameraAPI.CAMERA2,
311 ImageCaptureSize.MAX,
312 FocusMode.AUTO,
313 TestType.MULTI_PHOTO_CHAIN
314 )
315 val c2Caf =
316 findTest(
317 allTestResults,
318 mainCamera,
319 CameraAPI.CAMERA2,
320 ImageCaptureSize.MAX,
321 FocusMode.CONTINUOUS,
322 TestType.MULTI_PHOTO
323 )
324 val c2CafChain =
325 findTest(
326 allTestResults,
327 mainCamera,
328 CameraAPI.CAMERA2,
329 ImageCaptureSize.MAX,
330 FocusMode.CONTINUOUS,
331 TestType.MULTI_PHOTO_CHAIN
332 )
333 val c2AutoMin =
334 findTest(
335 allTestResults,
336 mainCamera,
337 CameraAPI.CAMERA2,
338 ImageCaptureSize.MIN,
339 FocusMode.AUTO,
340 TestType.MULTI_PHOTO
341 )
342 val c2Switch =
343 findTest(
344 allTestResults,
345 mainCamera,
346 CameraAPI.CAMERA2,
347 ImageCaptureSize.MAX,
348 FocusMode.AUTO,
349 TestType.MULTI_SWITCH
350 )
351 val c1Auto =
352 findTest(
353 allTestResults,
354 mainCamera,
355 CameraAPI.CAMERA1,
356 ImageCaptureSize.MAX,
357 FocusMode.AUTO,
358 TestType.MULTI_PHOTO
359 )
360 val c1Caf =
361 findTest(
362 allTestResults,
363 mainCamera,
364 CameraAPI.CAMERA1,
365 ImageCaptureSize.MAX,
366 FocusMode.CONTINUOUS,
367 TestType.MULTI_PHOTO
368 )
369 val c1Switch =
370 findTest(
371 allTestResults,
372 mainCamera,
373 CameraAPI.CAMERA1,
374 ImageCaptureSize.MAX,
375 FocusMode.AUTO,
376 TestType.MULTI_SWITCH
377 )
378 val cXAuto =
379 findTest(
380 allTestResults,
381 mainCamera,
382 CameraAPI.CAMERAX,
383 ImageCaptureSize.MAX,
384 FocusMode.AUTO,
385 TestType.MULTI_PHOTO
386 )
387 val cXCaf =
388 findTest(
389 allTestResults,
390 mainCamera,
391 CameraAPI.CAMERAX,
392 ImageCaptureSize.MAX,
393 FocusMode.CONTINUOUS,
394 TestType.MULTI_PHOTO
395 )
396 val cXSwitch =
397 findTest(
398 allTestResults,
399 mainCamera,
400 CameraAPI.CAMERAX,
401 ImageCaptureSize.MAX,
402 FocusMode.AUTO,
403 TestType.MULTI_SWITCH
404 )
405
406 // Header
407 val dateFormatter = SimpleDateFormat("d MMM yyyy - kk'h'mm")
408 val cal: Calendar = Calendar.getInstance()
409 output +=
410 "DATE: " + dateFormatter.format(cal.time) + " (Antelope " + getVersionName(activity) + ")\n"
411
412 output += "DEVICE: " + MainActivity.deviceInfo.device + "\n\n"
413 output += "CAMERAS:\n"
414 for (camera in MainActivity.cameras) output += camera + "\n"
415 output += "\n"
416
417 // Test summary
418 output += "HIGH-LEVEL OVERVIEW:\n"
419
420 output +=
421 "Capture (Cam2): " +
422 meanOfSumOfTwoArrays(c2Auto.capture, c2Auto.imageready) +
423 ", Cap chained (Cam2): " +
424 meanOfSumOfTwoArrays(c2AutoChain.capture, c2AutoChain.imageready) +
425 "\nCapture CAF (Cam2): " +
426 meanOfSumOfTwoArrays(c2Caf.capture, c2Caf.imageready) +
427 ", Chained CAF (Cam2): " +
428 meanOfSumOfTwoArrays(c2CafChain.capture, c2CafChain.imageready) +
429 "\nCapture (Cam1): " +
430 meanOfSumOfTwoArrays(c1Auto.capture, c1Auto.imageready) +
431 ", Cap CAF (Cam1): " +
432 meanOfSumOfTwoArrays(c1Caf.capture, c1Caf.imageready) +
433 "\nCapture (CamX): " +
434 meanOfSumOfTwoArrays(cXAuto.capture, cXAuto.imageready) +
435 ", Cap CAF (CamX): " +
436 meanOfSumOfTwoArrays(cXCaf.capture, cXCaf.imageready) +
437 "\nSwitch 1->2 (Cam2): " +
438 mean(c2Switch.switchToSecond) +
439 ", Switch 1->2 (Cam1): " +
440 mean(c1Switch.switchToSecond) +
441 ", Switch 1->2 (CamX): " +
442 mean(cXSwitch.switchToSecond) +
443 ", Switch 2->1 (Cam2): " +
444 mean(c2Switch.switchToFirst) +
445 ", Switch 2->1 (Cam1): " +
446 mean(c1Switch.switchToFirst) +
447 ", Switch 2->1 (CamX): " +
448 mean(cXSwitch.switchToFirst) +
449 "\nCam2 Open: " +
450 meanOfSumOfTwoArrays(c2Auto.initialization, c2Auto.previewStart) +
451 ", Cam1 Open: " +
452 meanOfSumOfTwoArrays(c1Auto.initialization, c1Auto.previewStart) +
453 "\nCam2 Close: " +
454 meanOfSumOfTwoArrays(c2Auto.previewClose, c2Auto.cameraClose) +
455 ", Cam1 Close: " +
456 meanOfSumOfTwoArrays(c1Auto.previewClose, c1Auto.cameraClose) +
457 "\n∆ Min to Max Size: " +
458 (numericalMean(c2Auto.capture) + numericalMean(c2Auto.imageready) -
459 numericalMean(c2AutoMin.capture) -
460 numericalMean(c2AutoMin.imageready)) +
461 ", Init->Image saved (Cam2): " +
462 mean(c2Auto.totalNoPreview) +
463 "\n"
464
465 output += "\n"
466
467 return output
468 }
469
470 /**
471 * For an array of TestResults, generate a high-level summary of the most important values in a
472 * comma-separated .csv string.
473 *
474 * This mostly consists of values for default rear camera.
475 */
testSummaryCSVnull476 fun testSummaryCSV(activity: MainActivity, allTestResults: ArrayList<TestResults>): String {
477 var output = ""
478
479 if (allTestResults.isEmpty()) return output
480
481 val mainCamera = getMainCamera(activity, allTestResults)
482
483 val c2Auto =
484 findTest(
485 allTestResults,
486 mainCamera,
487 CameraAPI.CAMERA2,
488 ImageCaptureSize.MAX,
489 FocusMode.AUTO,
490 TestType.MULTI_PHOTO
491 )
492 val c2AutoChain =
493 findTest(
494 allTestResults,
495 mainCamera,
496 CameraAPI.CAMERA2,
497 ImageCaptureSize.MAX,
498 FocusMode.AUTO,
499 TestType.MULTI_PHOTO_CHAIN
500 )
501 val c2Caf =
502 findTest(
503 allTestResults,
504 mainCamera,
505 CameraAPI.CAMERA2,
506 ImageCaptureSize.MAX,
507 FocusMode.CONTINUOUS,
508 TestType.MULTI_PHOTO
509 )
510 val c2CafChain =
511 findTest(
512 allTestResults,
513 mainCamera,
514 CameraAPI.CAMERA2,
515 ImageCaptureSize.MAX,
516 FocusMode.CONTINUOUS,
517 TestType.MULTI_PHOTO_CHAIN
518 )
519 val c2AutoMin =
520 findTest(
521 allTestResults,
522 mainCamera,
523 CameraAPI.CAMERA2,
524 ImageCaptureSize.MIN,
525 FocusMode.AUTO,
526 TestType.MULTI_PHOTO
527 )
528 val c2Switch =
529 findTest(
530 allTestResults,
531 mainCamera,
532 CameraAPI.CAMERA2,
533 ImageCaptureSize.MAX,
534 FocusMode.AUTO,
535 TestType.MULTI_SWITCH
536 )
537 val c1Auto =
538 findTest(
539 allTestResults,
540 mainCamera,
541 CameraAPI.CAMERA1,
542 ImageCaptureSize.MAX,
543 FocusMode.AUTO,
544 TestType.MULTI_PHOTO
545 )
546 val c1Caf =
547 findTest(
548 allTestResults,
549 mainCamera,
550 CameraAPI.CAMERA1,
551 ImageCaptureSize.MAX,
552 FocusMode.CONTINUOUS,
553 TestType.MULTI_PHOTO
554 )
555 val c1Switch =
556 findTest(
557 allTestResults,
558 mainCamera,
559 CameraAPI.CAMERA1,
560 ImageCaptureSize.MAX,
561 FocusMode.AUTO,
562 TestType.MULTI_SWITCH
563 )
564 val cXAuto =
565 findTest(
566 allTestResults,
567 mainCamera,
568 CameraAPI.CAMERAX,
569 ImageCaptureSize.MAX,
570 FocusMode.AUTO,
571 TestType.MULTI_PHOTO
572 )
573 val cXCaf =
574 findTest(
575 allTestResults,
576 mainCamera,
577 CameraAPI.CAMERAX,
578 ImageCaptureSize.MAX,
579 FocusMode.CONTINUOUS,
580 TestType.MULTI_PHOTO
581 )
582 val cXSwitch =
583 findTest(
584 allTestResults,
585 mainCamera,
586 CameraAPI.CAMERAX,
587 ImageCaptureSize.MAX,
588 FocusMode.AUTO,
589 TestType.MULTI_SWITCH
590 )
591
592 // Header
593 val dateFormatter = SimpleDateFormat("d MMM yyyy - kk'h'mm")
594 val cal: Calendar = Calendar.getInstance()
595 output +=
596 "DATE: " +
597 dateFormatter.format(cal.time) +
598 " (Antelope " +
599 getVersionName(activity) +
600 ")" +
601 "\n"
602
603 output += "DEVICE: " + MainActivity.deviceInfo.device + "\n" + "\n"
604 output += "CAMERAS: " + "\n"
605 for (camera in MainActivity.cameras) output += camera + "\n"
606 output += "\n"
607
608 // Test summary
609 output += "HIGH-LEVEL OVERVIEW:\n"
610
611 output += ","
612 output +=
613 "Capture (Cam2)" +
614 "," +
615 "Cap chained (Cam2)" +
616 "," +
617 "Capture CAF (Cam2)" +
618 "," +
619 "Chained CAF (Cam2)" +
620 "," +
621 "Capture (Cam1)" +
622 "," +
623 "Cap CAF (Cam1)" +
624 "," +
625 "Capture (CamX)" +
626 "," +
627 "Cap CAF (CamX)" +
628 "," +
629 "Switch 1->2 (Cam2)" +
630 "," +
631 "Switch 1->2 (Cam1)" +
632 "," +
633 "Switch 1->2 (CamX)" +
634 "," +
635 "Switch 2->1 (Cam2)" +
636 "," +
637 "Switch 2->1 (Cam1)" +
638 "," +
639 "Switch 2->1 (CamX)" +
640 "," +
641 "Cam2 Open" +
642 "," +
643 "Cam1 Open" +
644 "," +
645 "Cam2 Close" +
646 "," +
647 "Cam1 Close" +
648 "," +
649 "∆ Min to Max Size" +
650 "," +
651 "Init->Image saved (Cam2)" +
652 "\n"
653
654 output += ","
655 output +=
656 "" +
657 meanOfSumOfTwoArrays(c2Auto.capture, c2Auto.imageready) +
658 "," +
659 meanOfSumOfTwoArrays(c2AutoChain.capture, c2AutoChain.imageready)
660 output +=
661 "," +
662 meanOfSumOfTwoArrays(c2Caf.capture, c2Caf.imageready) +
663 "," +
664 meanOfSumOfTwoArrays(c2CafChain.capture, c2CafChain.imageready)
665 output +=
666 "," +
667 meanOfSumOfTwoArrays(c1Auto.capture, c1Auto.imageready) +
668 "," +
669 meanOfSumOfTwoArrays(c1Caf.capture, c1Caf.imageready)
670 output +=
671 "," +
672 meanOfSumOfTwoArrays(cXAuto.capture, cXAuto.imageready) +
673 "," +
674 meanOfSumOfTwoArrays(cXCaf.capture, cXCaf.imageready)
675 output += "," + mean(c2Switch.switchToSecond) + "," + mean(c1Switch.switchToSecond)
676 output += "," + mean(cXSwitch.switchToSecond)
677 output += "," + mean(c2Switch.switchToFirst) + "," + mean(c1Switch.switchToFirst)
678 output += "," + mean(cXSwitch.switchToFirst)
679 output +=
680 "," +
681 meanOfSumOfTwoArrays(c2Auto.initialization, c2Auto.previewStart) +
682 "," +
683 meanOfSumOfTwoArrays(c1Auto.initialization, c1Auto.previewStart)
684 output +=
685 "," +
686 meanOfSumOfTwoArrays(c2Auto.previewClose, c2Auto.cameraClose) +
687 "," +
688 meanOfSumOfTwoArrays(c1Auto.previewClose, c1Auto.cameraClose)
689 output +=
690 "," +
691 (numericalMean(c2Auto.capture) + numericalMean(c2Auto.imageready) -
692 numericalMean(c2AutoMin.capture) -
693 numericalMean(c2AutoMin.imageready))
694 output += "," + mean(c2Auto.totalNoPreview) + "\n"
695
696 output += "\n"
697 return output
698 }
699
700 /** Search an array of TestResults for the first test result that matches the given parameters */
findTestnull701 fun findTest(
702 allTestResults: ArrayList<TestResults>,
703 camera: String,
704 api: CameraAPI,
705 imageCaptureSize: ImageCaptureSize,
706 focusMode: FocusMode,
707 testType: TestType
708 ): TestResults {
709
710 for (testResult in allTestResults) {
711 // Look for the matching test result
712 if (
713 testResult.camera.equals(camera) &&
714 testResult.cameraAPI == api &&
715 testResult.imageCaptureSize == imageCaptureSize &&
716 (testResult.focusMode == focusMode || testResult.focusMode == FocusMode.FIXED) &&
717 testResult.testType == testType
718 ) {
719 return testResult
720 }
721 }
722
723 // Return empty test result
724 return TestResults()
725 }
726
727 /** The mean of a given array of longs, as a string */
meannull728 fun mean(array: ArrayList<Long>): String {
729 if (array.isEmpty()) {
730 return "n/a"
731 } else return Stats.meanOf(array).roundToInt().toString()
732 }
733
734 /** The mean of a given array of longs, as a double */
numericalMeannull735 fun numericalMean(array: ArrayList<Long>): Double {
736 if (array.isEmpty()) return 0.0 else return Stats.meanOf(array)
737 }
738
739 /** The mean of two arrays of longs added together, as a string */
meanOfSumOfTwoArraysnull740 fun meanOfSumOfTwoArrays(array1: ArrayList<Long>, array2: ArrayList<Long>): String {
741 if (array1.isEmpty() && array2.isEmpty()) {
742 return "n/a"
743 }
744 if (array1.isEmpty()) return mean(array2)
745 if (array2.isEmpty()) return mean(array1)
746 else return (Stats.meanOf(array1) + Stats.meanOf(array2)).roundToInt().toString()
747 }
748
749 /**
750 * Find the "main" camera id, priority is: first rear facing physical, first rear-facing logical,
751 * first camera in the system.
752 */
getMainCameranull753 fun getMainCamera(activity: MainActivity, allTestResults: ArrayList<TestResults>): String {
754 val mainCamera = allTestResults.first().cameraId
755
756 // Return the first rear-facing camera
757 for (param in MainActivity.cameraParams) {
758 if (!param.value.isFront && !param.value.isExternal)
759
760 // If only logical cameras, first rear-facing is fine
761 if (PrefHelper.getOnlyLogical(activity)) {
762 logd("The MAIN camera id is:" + param.value.id)
763 return param.value.id
764
765 // Otherwise, make sure this is a physical camera
766 } else {
767 if (param.value.physicalCameras.contains(param.value.id)) {
768 logd("The MAIN camera id is:" + param.value.id)
769 return param.value.id
770 }
771 }
772 }
773
774 return mainCamera
775 }
776
777 /** Return the version name of the Activity */
778 @Suppress("DEPRECATION")
getVersionNamenull779 fun getVersionName(activity: MainActivity): String? {
780 val packageInfo = activity.packageManager.getPackageInfo(activity.packageName, 0)
781 return packageInfo.versionName
782 }
783