1 /* 2 * Copyright (C) 2025 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 android.hardware.multiprocess.camera.cts; 18 19 import static android.hardware.camera2.cts.CameraTestUtils.*; 20 21 import static org.mockito.Mockito.*; 22 23 import android.graphics.ImageFormat; 24 import android.hardware.camera2.CameraAccessException; 25 import android.hardware.camera2.CameraCaptureSession; 26 import android.hardware.camera2.CameraCharacteristics; 27 import android.hardware.camera2.CameraDevice; 28 import android.hardware.camera2.CameraExtensionCharacteristics; 29 import android.hardware.camera2.CameraExtensionSession; 30 import android.hardware.camera2.CameraManager; 31 import android.hardware.camera2.CameraOfflineSession; 32 import android.hardware.camera2.CameraSharedCaptureSession; 33 import android.hardware.camera2.CaptureRequest; 34 import android.hardware.camera2.cts.Camera2SurfaceViewCtsActivity; 35 import android.hardware.camera2.cts.CameraTestUtils; 36 import android.hardware.camera2.cts.CameraTestUtils.HandlerExecutor; 37 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback; 38 import android.hardware.camera2.params.ExtensionSessionConfiguration; 39 import android.hardware.camera2.params.InputConfiguration; 40 import android.hardware.camera2.params.OutputConfiguration; 41 import android.hardware.camera2.params.SessionConfiguration; 42 import android.hardware.camera2.params.SharedSessionConfiguration; 43 import android.hardware.camera2.params.SharedSessionConfiguration.SharedOutputConfiguration; 44 import android.media.ImageReader; 45 import android.os.Bundle; 46 import android.os.Handler; 47 import android.os.HandlerThread; 48 import android.os.Message; 49 import android.os.Messenger; 50 import android.os.Process; 51 import android.os.ResultReceiver; 52 import android.util.Log; 53 import android.util.Size; 54 import android.view.Surface; 55 import android.view.SurfaceHolder; 56 57 import com.android.ex.camera2.blocking.BlockingExtensionSessionCallback; 58 import com.android.ex.camera2.blocking.BlockingSessionCallback; 59 import com.android.ex.camera2.utils.StateWaiter; 60 61 import java.util.ArrayList; 62 import java.util.List; 63 import java.util.concurrent.Executor; 64 65 /** 66 * Activity implementing basic access of the shared camera API. 67 * 68 * <p>This will log all errors to {@link 69 * android.hardware.multiprocess.camera.cts.ErrorLoggingService}. 70 */ 71 public class SharedCameraActivity extends Camera2SurfaceViewCtsActivity { 72 private static final String TAG = "SharedCameraActivity"; 73 private static final int CAPTURE_RESULT_TIMEOUT_MS = 3000; 74 private static final int NUM_MAX_IMAGES = 10; 75 ErrorLoggingService.ErrorServiceConnection mErrorServiceConnection; 76 CameraManager mCameraManager; 77 StateCallback mStateCallback; 78 SessionCallback mSessionCallback; 79 Handler mCameraHandler; 80 HandlerThread mCameraHandlerThread; 81 String mCameraId; 82 Messenger mMessenger; 83 CameraDevice mCameraDevice; 84 CameraSharedCaptureSession mSession; 85 BlockingSessionCallback mSessionMockListener; 86 CaptureRequest.Builder mCaptureRequestBuilder; 87 Surface mPreviewSurface; 88 int mCaptureSequenceId; 89 SimpleCaptureCallback mCaptureListener; 90 SimpleImageReaderListener mImageListener; 91 SharedSessionConfiguration mSharedSessionConfig; 92 ImageReader mReader; 93 Surface mReaderSurface; 94 boolean mIsSurfaceViewPresent = false; 95 boolean mIsImageReaderPresent = false; 96 Size mImageReaderSize; 97 int mImageReaderFormat; 98 Size mSurfaceViewSize; 99 boolean mIsPrimary = true; 100 101 @Override onCreate(Bundle savedInstanceState)102 protected void onCreate(Bundle savedInstanceState) { 103 Log.i(TAG, "onCreate called: uid " + Process.myUid() + "."); 104 super.onCreate(savedInstanceState); 105 106 mMessenger = new Messenger(new IncomingHandler()); 107 ResultReceiver resultReceiver = getIntent().getParcelableExtra( 108 TestConstants.EXTRA_RESULT_RECEIVER); 109 Bundle resultData = new Bundle(); 110 resultData.putParcelable(TestConstants.EXTRA_REMOTE_MESSENGER, mMessenger); 111 resultReceiver.send(RESULT_OK, resultData); 112 mCameraHandlerThread = new HandlerThread("CameraHandlerThread"); 113 mCameraHandlerThread.start(); 114 mCameraHandler = new Handler(mCameraHandlerThread.getLooper()); 115 mErrorServiceConnection = new ErrorLoggingService.ErrorServiceConnection(this); 116 mErrorServiceConnection.start(); 117 } 118 119 @Override onResume()120 protected void onResume() { 121 Log.i(TAG, "onResume called."); 122 super.onResume(); 123 mCameraManager = getSystemService(CameraManager.class); 124 if (mCameraManager == null) { 125 mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, TAG 126 + " could not connect camera service"); 127 return; 128 } 129 } 130 131 @Override onDestroy()132 protected void onDestroy() { 133 Log.i(TAG, "onDestroy called."); 134 super.onDestroy(); 135 136 if (mSession != null) { 137 mSession.close(); 138 mSession = null; 139 } 140 mCameraHandlerThread.quitSafely(); 141 142 if (mErrorServiceConnection != null) { 143 mErrorServiceConnection.stop(); 144 mErrorServiceConnection = null; 145 } 146 } 147 148 private class StateCallback extends CameraDevice.StateCallback { 149 String mChosenCameraId; 150 StateCallback(String camId)151 StateCallback(String camId) { 152 mChosenCameraId = camId; 153 } 154 155 @Override onOpened(CameraDevice cameraDevice)156 public void onOpened(CameraDevice cameraDevice) { 157 mCameraDevice = cameraDevice; 158 mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_CONNECT, mChosenCameraId); 159 Log.i(TAG, "Camera " + mChosenCameraId + " is opened"); 160 } 161 162 @Override onOpenedInSharedMode(CameraDevice cameraDevice, boolean isPrimary)163 public void onOpenedInSharedMode(CameraDevice cameraDevice, boolean isPrimary) { 164 mCameraDevice = cameraDevice; 165 mIsPrimary = isPrimary; 166 if (isPrimary) { 167 mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_CONNECT_SHARED_PRIMARY, 168 mChosenCameraId); 169 } else { 170 mErrorServiceConnection.logAsync( 171 TestConstants.EVENT_CAMERA_CONNECT_SHARED_SECONDARY, mChosenCameraId); 172 } 173 Log.i( 174 TAG, 175 "Camera " + mChosenCameraId + " is opened in shared mode primary=" + isPrimary); 176 } 177 178 @Override onClosed(CameraDevice cameraDevice)179 public void onClosed(CameraDevice cameraDevice) { 180 mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_CLOSED, mChosenCameraId); 181 Log.i(TAG, "Camera " + mChosenCameraId + " is closed"); 182 } 183 184 @Override onDisconnected(CameraDevice cameraDevice)185 public void onDisconnected(CameraDevice cameraDevice) { 186 mErrorServiceConnection.logAsync( 187 TestConstants.EVENT_CAMERA_DISCONNECTED, mChosenCameraId); 188 Log.i(TAG, "Camera " + mChosenCameraId + " is disconnected"); 189 } 190 191 @Override onError(CameraDevice cameraDevice, int i)192 public void onError(CameraDevice cameraDevice, int i) { 193 mErrorServiceConnection.logAsync( 194 TestConstants.EVENT_CAMERA_ERROR, 195 TAG + " Camera " + mChosenCameraId + " experienced error " + i); 196 Log.e(TAG, "Camera " + mChosenCameraId + " onError called with error " + i); 197 } 198 199 @Override onClientSharedAccessPriorityChanged(CameraDevice camera, boolean isPrimary)200 public void onClientSharedAccessPriorityChanged(CameraDevice camera, boolean isPrimary) { 201 mIsPrimary = isPrimary; 202 if (isPrimary) { 203 mErrorServiceConnection.logAsync( 204 TestConstants.EVENT_CLIENT_ACCESS_PRIORITIES_CHANGED_TO_PRIMARY, 205 mChosenCameraId); 206 } else { 207 mErrorServiceConnection.logAsync( 208 TestConstants.EVENT_CLIENT_ACCESS_PRIORITIES_CHANGED_TO_SECONDARY, 209 mChosenCameraId); 210 } 211 Log.i( 212 TAG, 213 "Camera " 214 + mChosenCameraId 215 + " onClientSharedAccessPriorityChanged primary=" 216 + isPrimary); 217 } 218 } 219 220 private class SessionCallback extends CameraCaptureSession.StateCallback { 221 String mChosenCameraId; 222 SessionCallback(String camId)223 SessionCallback(String camId) { 224 mChosenCameraId = camId; 225 } 226 227 @Override onClosed(CameraCaptureSession session)228 public void onClosed(CameraCaptureSession session) { 229 mSession = null; 230 mErrorServiceConnection.logAsync( 231 TestConstants.EVENT_CAMERA_SESSION_CLOSED, mChosenCameraId); 232 Log.i(TAG, "Camera capture session for camera " + mChosenCameraId + " is closed"); 233 } 234 235 @Override onConfigured(CameraCaptureSession session)236 public void onConfigured(CameraCaptureSession session) { 237 mSession = (CameraSharedCaptureSession) session; 238 mErrorServiceConnection.logAsync( 239 TestConstants.EVENT_CAMERA_SESSION_CONFIGURED, mChosenCameraId); 240 Log.i(TAG, "Camera capture session for camera " + mChosenCameraId + " is configured"); 241 } 242 243 @Override onConfigureFailed(CameraCaptureSession session)244 public void onConfigureFailed(CameraCaptureSession session) { 245 mSession = null; 246 mErrorServiceConnection.logAsync( 247 TestConstants.EVENT_CAMERA_SESSION_CONFIGURE_FAILED, mChosenCameraId); 248 Log.i(TAG, "Camera capture session creation for camera " + mChosenCameraId + " failed"); 249 } 250 } 251 252 private static class ExtensionSessionCallback extends CameraExtensionSession.StateCallback { 253 254 @Override onClosed(CameraExtensionSession session)255 public void onClosed(CameraExtensionSession session) { 256 // do nothing 257 } 258 259 @Override onConfigured(CameraExtensionSession session)260 public void onConfigured(CameraExtensionSession session) { 261 // do nothing 262 } 263 264 @Override onConfigureFailed(CameraExtensionSession session)265 public void onConfigureFailed(CameraExtensionSession session) { 266 // do nothing 267 } 268 } 269 270 private static class OfflineSessionCallback 271 extends CameraOfflineSession.CameraOfflineSessionCallback { 272 273 @Override onReady(CameraOfflineSession session)274 public void onReady(CameraOfflineSession session) { 275 // do nothing 276 } 277 278 @Override onSwitchFailed(CameraOfflineSession session)279 public void onSwitchFailed(CameraOfflineSession session) { 280 // do nothing 281 } 282 283 @Override onIdle(CameraOfflineSession session)284 public void onIdle(CameraOfflineSession session) { 285 // do nothing 286 } 287 288 @Override onError(CameraOfflineSession session, int status)289 public void onError(CameraOfflineSession session, int status) { 290 // do nothing 291 } 292 293 @Override onClosed(CameraOfflineSession session)294 public void onClosed(CameraOfflineSession session) { 295 // do nothing 296 } 297 } 298 updatePreviewSurface(Size sz)299 private void updatePreviewSurface(Size sz) { 300 final SurfaceHolder holder = getSurfaceView().getHolder(); 301 mPreviewSurface = holder.getSurface(); 302 holder.setFixedSize(sz.getWidth(), sz.getHeight()); 303 } 304 305 class IncomingHandler extends Handler { 306 createImageReader(Size sz, int format)307 private void createImageReader(Size sz, int format) { 308 mImageListener = new SimpleImageReaderListener(/*asyncMode*/true, NUM_MAX_IMAGES); 309 mReader = makeImageReader(sz, format, NUM_MAX_IMAGES, mImageListener, mCameraHandler); 310 mReaderSurface = mReader.getSurface(); 311 } 312 closeImageReader()313 private void closeImageReader() { 314 CameraTestUtils.closeImageReader(mReader); 315 if (mImageListener != null) { 316 mImageListener.drain(); 317 mImageListener = null; 318 } 319 mReader = null; 320 mReaderSurface = null; 321 } 322 checkValidSurfaceIsPresent()323 private void checkValidSurfaceIsPresent() { 324 for (SharedOutputConfiguration sharedStreamInfo : 325 mSharedSessionConfig.getOutputStreamsInformation()) { 326 if (sharedStreamInfo.getSurfaceType() == TestConstants.SURFACE_TYPE_SURFACE_VIEW) { 327 mIsSurfaceViewPresent = true; 328 mSurfaceViewSize = sharedStreamInfo.getSize(); 329 } 330 if (sharedStreamInfo.getSurfaceType() == TestConstants.SURFACE_TYPE_IMAGE_READER) { 331 mIsImageReaderPresent = true; 332 mImageReaderSize = sharedStreamInfo.getSize(); 333 mImageReaderFormat = sharedStreamInfo.getFormat(); 334 } 335 } 336 } 337 338 @Override handleMessage(Message msg)339 public void handleMessage(Message msg) { 340 final Executor executor = new HandlerExecutor(mCameraHandler); 341 342 switch (msg.what) { 343 case TestConstants.OP_OPEN_CAMERA: 344 mCameraId = msg.getData().getString(TestConstants.EXTRA_CAMERA_ID); 345 try { 346 if (mStateCallback == null || mStateCallback.mChosenCameraId != mCameraId) { 347 mStateCallback = new StateCallback(mCameraId); 348 mCameraManager.openCamera(mCameraId, executor, mStateCallback); 349 } 350 } catch (CameraAccessException e) { 351 mErrorServiceConnection.logAsync( 352 TestConstants.EVENT_CAMERA_ERROR, 353 TAG + " camera exception during connection: " + e); 354 Log.e(TAG, "Access exception: " + e); 355 } 356 break; 357 358 case TestConstants.OP_OPEN_CAMERA_SHARED: 359 mCameraId = msg.getData().getString(TestConstants.EXTRA_CAMERA_ID); 360 try { 361 boolean sharingEnabled = 362 mCameraManager.isCameraDeviceSharingSupported(mCameraId); 363 if (!sharingEnabled) { 364 mErrorServiceConnection.logAsync( 365 TestConstants.EVENT_CAMERA_ERROR, 366 TAG + " camera device does not support shared mode"); 367 Log.e(TAG, "camera device does not support shared mode"); 368 return; 369 } 370 if (mStateCallback == null || mStateCallback.mChosenCameraId != mCameraId) { 371 mStateCallback = new StateCallback(mCameraId); 372 mCameraManager.openSharedCamera(mCameraId, executor, mStateCallback); 373 CameraCharacteristics props = 374 mCameraManager.getCameraCharacteristics(mCameraId); 375 mSharedSessionConfig = props.get( 376 CameraCharacteristics.SHARED_SESSION_CONFIGURATION); 377 if (mSharedSessionConfig == null) { 378 mErrorServiceConnection.logAsync( 379 TestConstants.EVENT_CAMERA_ERROR, 380 TAG + " shared session config is null"); 381 Log.e(TAG, "shared session config is null"); 382 return; 383 } 384 checkValidSurfaceIsPresent(); 385 if (mIsSurfaceViewPresent) { 386 updatePreviewSurface(mSurfaceViewSize); 387 } 388 if (mIsImageReaderPresent) { 389 createImageReader(mImageReaderSize, mImageReaderFormat); 390 } 391 } 392 } catch (CameraAccessException e) { 393 mErrorServiceConnection.logAsync( 394 TestConstants.EVENT_CAMERA_ERROR, 395 TAG + " camera exception during connection: " + e); 396 Log.e(TAG, "Access exception: " + e); 397 } 398 break; 399 400 case TestConstants.OP_CLOSE_CAMERA: 401 if (mSession != null) { 402 mSession.close(); 403 mSession = null; 404 mSessionMockListener = null; 405 mCaptureListener = null; 406 mSessionCallback = null; 407 } 408 closeImageReader(); 409 if (mCameraDevice != null) { 410 mCameraDevice.close(); 411 mCameraDevice = null; 412 mStateCallback = null; 413 } 414 break; 415 416 case TestConstants.OP_CREATE_SHARED_SESSION: 417 if (mCameraDevice == null) { 418 mErrorServiceConnection.logAsync( 419 TestConstants.EVENT_CAMERA_ERROR, TAG + "camera device is null"); 420 Log.e(TAG, "camera device is null"); 421 return; 422 } 423 List<Integer> sharedStreamArray = 424 msg.getData() 425 .getIntegerArrayList(TestConstants.EXTRA_SHARED_STREAM_ARRAY); 426 if (sharedStreamArray == null) { 427 mErrorServiceConnection.logAsync( 428 TestConstants.EVENT_CAMERA_ERROR, 429 TAG + " shared stream index array is null"); 430 Log.e(TAG, "shared stream index array is null"); 431 return; 432 } 433 try { 434 List<OutputConfiguration> outputs = new ArrayList<>(); 435 if (mIsPrimary) { 436 mCaptureRequestBuilder = mCameraDevice.createCaptureRequest( 437 CameraDevice.TEMPLATE_PREVIEW); 438 } 439 for (int i = 0; i < sharedStreamArray.size(); i++) { 440 Integer surfaceType = sharedStreamArray.get(i); 441 if (surfaceType == TestConstants.SURFACE_TYPE_SURFACE_VIEW) { 442 outputs.add(new OutputConfiguration(mPreviewSurface)); 443 } 444 if (surfaceType == TestConstants.SURFACE_TYPE_IMAGE_READER) { 445 outputs.add(new OutputConfiguration(mReaderSurface)); 446 } 447 } 448 if (outputs.isEmpty()) { 449 mErrorServiceConnection.logAsync( 450 TestConstants.EVENT_CAMERA_ERROR, 451 TAG + " shared output configuration is empty"); 452 Log.e(TAG, "shared output configuration is empty"); 453 return; 454 } 455 if (mSessionCallback == null 456 || mSessionCallback.mChosenCameraId != mCameraId) { 457 mSessionCallback = new SessionCallback(mCameraId); 458 } 459 mSessionMockListener = spy(new BlockingSessionCallback(mSessionCallback)); 460 StateWaiter sessionWaiter = mSessionMockListener.getStateWaiter(); 461 SessionConfiguration sessionConfig = 462 new SessionConfiguration( 463 SessionConfiguration.SESSION_SHARED, 464 outputs, 465 executor, 466 mSessionMockListener); 467 if (mIsPrimary) { 468 sessionConfig.setSessionParameters(mCaptureRequestBuilder.build()); 469 } 470 mCameraDevice.createCaptureSession(sessionConfig); 471 sessionWaiter.waitForState( 472 BlockingSessionCallback.SESSION_CONFIGURED, 473 SESSION_CONFIGURE_TIMEOUT_MS); 474 } catch (Exception e) { 475 mErrorServiceConnection.logAsync( 476 TestConstants.EVENT_CAMERA_ERROR, 477 TAG + " exception during creating shared session: " + e); 478 Log.e(TAG, "exception during creating shared session: " + e); 479 } 480 break; 481 482 case TestConstants.OP_CREATE_SHARED_SESSION_INVALID_CONFIGS: 483 if (mCameraDevice == null) { 484 mErrorServiceConnection.logAsync( 485 TestConstants.EVENT_CAMERA_ERROR, TAG + "camera device is null"); 486 Log.e(TAG, "camera device is null"); 487 return; 488 } 489 if (!mIsSurfaceViewPresent && !mIsImageReaderPresent) { 490 mErrorServiceConnection.logAsync( 491 TestConstants.EVENT_CAMERA_ERROR, 492 TAG + " shared output configuration is empty"); 493 Log.e(TAG, "shared output configuration is empty"); 494 return; 495 } 496 if (mSessionCallback == null || mSessionCallback.mChosenCameraId != mCameraId) { 497 mSessionCallback = new SessionCallback(mCameraId); 498 } 499 mSessionMockListener = spy(new BlockingSessionCallback(mSessionCallback)); 500 501 // tests that using enableSurfaceSharing() returns an error 502 try { 503 StateWaiter sessionWaiter = mSessionMockListener.getStateWaiter(); 504 List<OutputConfiguration> outputs = new ArrayList<>(); 505 if (mIsImageReaderPresent) { 506 OutputConfiguration imageReaderOutputConfig = 507 new OutputConfiguration(mReaderSurface); 508 imageReaderOutputConfig.enableSurfaceSharing(); 509 outputs.add(imageReaderOutputConfig); 510 } else if (mIsSurfaceViewPresent) { 511 OutputConfiguration surfaceViewOutputConfig = 512 new OutputConfiguration(mPreviewSurface); 513 surfaceViewOutputConfig.enableSurfaceSharing(); 514 outputs.add(surfaceViewOutputConfig); 515 } 516 517 SessionConfiguration sessionConfig = 518 new SessionConfiguration( 519 SessionConfiguration.SESSION_SHARED, 520 outputs, 521 executor, 522 mSessionMockListener); 523 mCameraDevice.createCaptureSession(sessionConfig); 524 sessionWaiter.waitForState( 525 BlockingSessionCallback.SESSION_CONFIGURED, 526 SESSION_CONFIGURE_TIMEOUT_MS); 527 return; 528 } catch (Exception e) { 529 mErrorServiceConnection.logAsync( 530 TestConstants.EVENT_CAMERA_SESSION_CONFIGURE_FAILED, 531 TAG 532 + " Expected exception when calling" 533 + " enableSurfaceSharing(): " 534 + e); 535 } 536 537 // tests that using setInputConfiguration() returns an error 538 try { 539 StateWaiter sessionWaiter = mSessionMockListener.getStateWaiter(); 540 List<OutputConfiguration> outputs = new ArrayList<>(); 541 if (mIsImageReaderPresent) { 542 outputs.add(new OutputConfiguration(mReaderSurface)); 543 } else if (mIsSurfaceViewPresent) { 544 outputs.add(new OutputConfiguration(mPreviewSurface)); 545 } 546 547 SessionConfiguration sessionConfig = 548 new SessionConfiguration( 549 SessionConfiguration.SESSION_SHARED, 550 outputs, 551 executor, 552 mSessionMockListener); 553 sessionConfig.setInputConfiguration( 554 new InputConfiguration( 555 /* width */ 7680, 556 /* height */ 4320, 557 /* format */ ImageFormat.PRIVATE)); 558 mCameraDevice.createCaptureSession(sessionConfig); 559 sessionWaiter.waitForState( 560 BlockingSessionCallback.SESSION_CONFIGURED, 561 SESSION_CONFIGURE_TIMEOUT_MS); 562 return; 563 } catch (Exception e) { 564 mErrorServiceConnection.logAsync( 565 TestConstants.EVENT_CAMERA_SESSION_CONFIGURE_FAILED, 566 TAG 567 + " Expected exception when calling" 568 + " setInputConfiguration(): " 569 + e); 570 } 571 572 // tests that using an image reader surface with a different size than the one 573 // provided in the shared session config returns an error 574 if (mIsImageReaderPresent) { 575 ImageReader newReader = null; 576 try { 577 StateWaiter sessionWaiter = mSessionMockListener.getStateWaiter(); 578 newReader = ImageReader.newInstance( 579 mReader.getWidth() + 1, 580 mReader.getHeight() + 1, /* format */ 581 ImageFormat.YUV_420_888, 582 /* maxImages */ 2); 583 List<OutputConfiguration> outputs = new ArrayList<>(); 584 outputs.add(new OutputConfiguration(newReader.getSurface())); 585 SessionConfiguration sessionConfig = 586 new SessionConfiguration( 587 SessionConfiguration.SESSION_SHARED, 588 outputs, 589 executor, 590 mSessionMockListener); 591 mCameraDevice.createCaptureSession(sessionConfig); 592 sessionWaiter.waitForState( 593 BlockingSessionCallback.SESSION_CONFIGURED, 594 SESSION_CONFIGURE_TIMEOUT_MS); 595 596 return; 597 } catch (Exception e) { 598 mErrorServiceConnection.logAsync( 599 TestConstants.EVENT_CAMERA_SESSION_CONFIGURE_FAILED, 600 TAG 601 + " Expected exception when using different size and" 602 + " format than shared session config: " 603 + e); 604 } finally { 605 CameraTestUtils.closeImageReader(newReader); 606 } 607 } 608 break; 609 610 case TestConstants.OP_PERFORM_UNSUPPORTED_COMMANDS: 611 if (mCameraDevice == null) { 612 mErrorServiceConnection.logAsync( 613 TestConstants.EVENT_CAMERA_ERROR, TAG + "camera device is null"); 614 Log.e(TAG, "camera device is null"); 615 return; 616 } 617 if (!mIsSurfaceViewPresent && !mIsImageReaderPresent) { 618 mErrorServiceConnection.logAsync( 619 TestConstants.EVENT_CAMERA_ERROR, 620 TAG + " shared output configuration is empty"); 621 Log.e(TAG, "shared output configuration is empty"); 622 return; 623 } 624 625 if (mSessionCallback == null || mSessionCallback.mChosenCameraId != mCameraId) { 626 mSessionCallback = new SessionCallback(mCameraId); 627 } 628 mSessionMockListener = spy(new BlockingSessionCallback(mSessionCallback)); 629 630 StateWaiter sessionWaiterUnsupportedOps = mSessionMockListener.getStateWaiter(); 631 List<OutputConfiguration> outputsConfigs = new ArrayList<>(); 632 if (mIsImageReaderPresent) { 633 outputsConfigs.add(new OutputConfiguration(mReaderSurface)); 634 } else if (mIsSurfaceViewPresent) { 635 outputsConfigs.add(new OutputConfiguration(mPreviewSurface)); 636 } 637 try { 638 SessionConfiguration sessionConfig = 639 new SessionConfiguration( 640 SessionConfiguration.SESSION_HIGH_SPEED, 641 outputsConfigs, 642 executor, 643 mSessionMockListener); 644 mCameraDevice.createCaptureSession(sessionConfig); 645 sessionWaiterUnsupportedOps.waitForState( 646 BlockingSessionCallback.SESSION_CONFIGURED, 647 SESSION_CONFIGURE_TIMEOUT_MS); 648 return; 649 } catch (Exception e) { 650 mErrorServiceConnection.logAsync( 651 TestConstants.EVENT_CAMERA_SESSION_CONFIGURE_FAILED, 652 TAG 653 + " Expected exception from creating SESSION_HIGH_SPEED" 654 + " session: " 655 + e); 656 } 657 658 try { 659 SessionConfiguration sessionConfig = 660 new SessionConfiguration( 661 SessionConfiguration.SESSION_REGULAR, 662 outputsConfigs, 663 executor, 664 mSessionMockListener); 665 mCameraDevice.createCaptureSession(sessionConfig); 666 sessionWaiterUnsupportedOps.waitForState( 667 BlockingSessionCallback.SESSION_CONFIGURED, 668 SESSION_CONFIGURE_TIMEOUT_MS); 669 return; 670 } catch (Exception e) { 671 mErrorServiceConnection.logAsync( 672 TestConstants.EVENT_CAMERA_SESSION_CONFIGURE_FAILED, 673 TAG 674 + " Expected exception from creating SESSION_REGULAR" 675 + " session: " 676 + e); 677 } 678 679 try { 680 BlockingExtensionSessionCallback extensionSessionMockListener = 681 spy( 682 new BlockingExtensionSessionCallback( 683 new ExtensionSessionCallback())); 684 StateWaiter extensionSessionWaiter = 685 extensionSessionMockListener.getStateWaiter(); 686 ExtensionSessionConfiguration extensionSessionConfig = 687 new ExtensionSessionConfiguration( 688 CameraExtensionCharacteristics.EXTENSION_AUTOMATIC, 689 outputsConfigs, 690 executor, 691 extensionSessionMockListener); 692 mCameraDevice.createExtensionSession(extensionSessionConfig); 693 extensionSessionWaiter.waitForState( 694 BlockingExtensionSessionCallback.SESSION_CONFIGURED, 695 SESSION_CONFIGURE_TIMEOUT_MS); 696 return; 697 } catch (Exception e) { 698 mErrorServiceConnection.logAsync( 699 TestConstants.EVENT_CAMERA_SESSION_CONFIGURE_FAILED, 700 TAG 701 + " Expected exception from running" 702 + " createExtensionSession" 703 + e); 704 } 705 706 try { 707 List<Surface> surfaces = new ArrayList<>(); 708 if (mIsImageReaderPresent) { 709 surfaces.add(mReaderSurface); 710 } else if (mIsSurfaceViewPresent) { 711 surfaces.add(mPreviewSurface); 712 } 713 InputConfiguration inputConfig = 714 new InputConfiguration( 715 /* width */ 7680, 716 /* height */ 4320, 717 /* format */ ImageFormat.YUV_420_888); 718 mCameraDevice.createReprocessableCaptureSession( 719 inputConfig, surfaces, mSessionMockListener, mCameraHandler); 720 sessionWaiterUnsupportedOps.waitForState( 721 BlockingSessionCallback.SESSION_CONFIGURED, 722 SESSION_CONFIGURE_TIMEOUT_MS); 723 return; 724 } catch (Exception e) { 725 mErrorServiceConnection.logAsync( 726 TestConstants.EVENT_CAMERA_SESSION_CONFIGURE_FAILED, 727 TAG 728 + " Expected exception from running" 729 + " createReprocessableCaptureSession" 730 + e); 731 } 732 733 try { 734 List<Surface> surfaces = new ArrayList<>(); 735 if (mIsImageReaderPresent) { 736 surfaces.add(mReaderSurface); 737 } else if (mIsSurfaceViewPresent) { 738 surfaces.add(mPreviewSurface); 739 } 740 mCameraDevice.createConstrainedHighSpeedCaptureSession( 741 surfaces, mSessionMockListener, mCameraHandler); 742 sessionWaiterUnsupportedOps.waitForState( 743 BlockingSessionCallback.SESSION_CONFIGURED, 744 SESSION_CONFIGURE_TIMEOUT_MS); 745 return; 746 } catch (Exception e) { 747 mErrorServiceConnection.logAsync( 748 TestConstants.EVENT_CAMERA_SESSION_CONFIGURE_FAILED, 749 TAG 750 + " Expected exception from running" 751 + " createConstrainedHighSpeedCaptureSession" 752 + e); 753 } 754 break; 755 756 case TestConstants.OP_PERFORM_UNSUPPORTED_CAPTURE_SESSION_COMMANDS: 757 if (mCameraDevice == null || mSession == null) { 758 mErrorServiceConnection.logAsync( 759 TestConstants.EVENT_CAMERA_ERROR, 760 TAG + "No active camera device or session is present"); 761 Log.e(TAG, "No active camera device or session is present"); 762 return; 763 } 764 List<CaptureRequest> captureRequests = new ArrayList<>(); 765 captureRequests.add(mCaptureRequestBuilder.build()); 766 mCaptureListener = new SimpleCaptureCallback(); 767 try { 768 mCaptureSequenceId = 769 mSession.captureBurst( 770 captureRequests, mCaptureListener, mCameraHandler); 771 mErrorServiceConnection.logAsync( 772 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 773 TAG + " Activity started."); 774 return; 775 } catch (Exception e) { 776 mErrorServiceConnection.logAsync( 777 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 778 TAG + " Expected exception from running captureBurst: " + e); 779 } 780 781 try { 782 mCaptureSequenceId = 783 mSession.captureBurstRequests( 784 captureRequests, executor, mCaptureListener); 785 mErrorServiceConnection.logAsync( 786 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 787 TAG + " Activity started."); 788 return; 789 } catch (Exception e) { 790 mErrorServiceConnection.logAsync( 791 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 792 TAG 793 + " Expected exception from running" 794 + " captureBurstRequest: " 795 + e); 796 } 797 798 try { 799 mCaptureSequenceId = 800 mSession.setRepeatingBurst( 801 captureRequests, mCaptureListener, mCameraHandler); 802 mErrorServiceConnection.logAsync( 803 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 804 TAG + " Activity started."); 805 return; 806 } catch (Exception e) { 807 mErrorServiceConnection.logAsync( 808 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 809 TAG + " Expected exception from running setRepeatingBurst: " + e); 810 } 811 812 try { 813 mCaptureSequenceId = 814 mSession.setRepeatingBurstRequests( 815 captureRequests, executor, mCaptureListener); 816 mErrorServiceConnection.logAsync( 817 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 818 TAG + " Activity started."); 819 return; 820 } catch (Exception e) { 821 mErrorServiceConnection.logAsync( 822 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 823 TAG 824 + " Expected exception from running" 825 + " setRepeatingBurstRequests: " 826 + e); 827 } 828 829 if (mSession.supportsOfflineProcessing(mPreviewSurface)) { 830 mErrorServiceConnection.logAsync( 831 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 832 TAG + " Activity started."); 833 return; 834 } else { 835 mErrorServiceConnection.logAsync( 836 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 837 TAG + " Expected false from running supportsOfflineProcessing"); 838 } 839 840 try { 841 List<Surface> surfaces = new ArrayList<>(); 842 surfaces.add(mPreviewSurface); 843 mSession.switchToOffline(surfaces, executor, new OfflineSessionCallback()); 844 mErrorServiceConnection.logAsync( 845 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 846 TAG + " Activity started."); 847 return; 848 } catch (Exception e) { 849 mErrorServiceConnection.logAsync( 850 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 851 TAG 852 + " Expected exception from running" 853 + " supportsOfflineProcessing: " 854 + e); 855 } 856 857 try { 858 OutputConfiguration outputConfig = new OutputConfiguration(mPreviewSurface); 859 mSession.updateOutputConfiguration(outputConfig); 860 mErrorServiceConnection.logAsync( 861 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 862 TAG + " Activity started."); 863 return; 864 } catch (Exception e) { 865 mErrorServiceConnection.logAsync( 866 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 867 TAG 868 + " Expected exception from running" 869 + " updateOutputConfiguration: " 870 + e); 871 } 872 873 try { 874 List<OutputConfiguration> outputConfigs = new ArrayList<>(); 875 outputConfigs.add(new OutputConfiguration(mPreviewSurface)); 876 mSession.finalizeOutputConfigurations(outputConfigs); 877 mErrorServiceConnection.logAsync( 878 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 879 TAG + " Activity started."); 880 return; 881 } catch (Exception e) { 882 mErrorServiceConnection.logAsync( 883 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 884 TAG 885 + " Expected exception from running" 886 + " finalizeOutputConfigurations: " 887 + e); 888 } 889 890 if (mSession.isReprocessable()) { 891 mErrorServiceConnection.logAsync( 892 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 893 TAG + " Activity started."); 894 return; 895 } else { 896 mErrorServiceConnection.logAsync( 897 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 898 TAG + " Expected false from running isReprocessable"); 899 } 900 901 if (mSession.getInputSurface() != null) { 902 mErrorServiceConnection.logAsync( 903 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 904 TAG + " Activity started."); 905 return; 906 } else { 907 mErrorServiceConnection.logAsync( 908 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 909 TAG + " Expected null from running getInputSurface"); 910 } 911 912 try { 913 mSession.prepare(mPreviewSurface); 914 mErrorServiceConnection.logAsync( 915 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_STARTED, 916 TAG + " Activity started."); 917 return; 918 } catch (Exception e) { 919 mErrorServiceConnection.logAsync( 920 TestConstants.EVENT_CAMERA_UNSUPPORTED_ACTIVITY_FAILED, 921 TAG + " Expected exception from running" + " prepare: " + e); 922 } 923 break; 924 925 case TestConstants.OP_START_PREVIEW: 926 if (mCameraDevice == null || mSession == null) { 927 mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, 928 TAG + " No active camera device or session is present"); 929 Log.e(TAG, "No active camera device or session is present"); 930 return; 931 } 932 try { 933 mCaptureListener = new SimpleCaptureCallback(); 934 List<Integer> previewStreamArray = msg.getData().getIntegerArrayList( 935 TestConstants.EXTRA_SHARED_STREAM_ARRAY); 936 if (previewStreamArray == null) { 937 mErrorServiceConnection.logAsync( 938 TestConstants.EVENT_CAMERA_ERROR, 939 TAG + " preview stream index array is null"); 940 Log.e(TAG, "preview stream index array is null"); 941 return; 942 } 943 List<Surface> surfaces = new ArrayList<>(); 944 boolean imageReaderUsed = false; 945 if (mIsPrimary && (mCaptureRequestBuilder == null)) { 946 mCaptureRequestBuilder = mCameraDevice.createCaptureRequest( 947 CameraDevice.TEMPLATE_PREVIEW); 948 } 949 for (int i = 0; i < previewStreamArray.size(); i++) { 950 Integer surfaceType = previewStreamArray.get(i); 951 if (surfaceType == TestConstants.SURFACE_TYPE_SURFACE_VIEW) { 952 if (mIsPrimary) { 953 mCaptureRequestBuilder.addTarget(mPreviewSurface); 954 } else { 955 surfaces.add(mPreviewSurface); 956 } 957 } 958 if (surfaceType == TestConstants.SURFACE_TYPE_IMAGE_READER) { 959 imageReaderUsed = true; 960 if (mIsPrimary) { 961 mCaptureRequestBuilder.addTarget(mReaderSurface); 962 } else { 963 surfaces.add(mReaderSurface); 964 } 965 } 966 } 967 if (mIsPrimary) { 968 mCaptureSequenceId = 969 mSession.setRepeatingRequest( 970 mCaptureRequestBuilder.build(), 971 mCaptureListener, 972 mCameraHandler); 973 } else { 974 mCaptureSequenceId = 975 mSession.startStreaming(surfaces, executor, mCaptureListener); 976 } 977 mCaptureListener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS); 978 if (imageReaderUsed) { 979 mImageListener.getImage(CAPTURE_RESULT_TIMEOUT_MS).close(); 980 } 981 982 mErrorServiceConnection.logAsync( 983 TestConstants.EVENT_CAMERA_PREVIEW_STARTED, 984 Integer.toString(mCaptureSequenceId)); 985 } catch (Exception e) { 986 mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, 987 TAG + " exception during start preview: " + e); 988 Log.e(TAG, "exception during start preview: " + e); 989 } 990 break; 991 992 case TestConstants.OP_STOP_PREVIEW: 993 if (mCameraDevice == null || mSession == null) { 994 mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, 995 TAG + " No active camera device or session is present"); 996 Log.e(TAG, "No active camera device or session is present"); 997 return; 998 } 999 try { 1000 if (mIsPrimary) { 1001 mSession.stopRepeating(); 1002 } else { 1003 mSession.stopStreaming(); 1004 } 1005 mCaptureListener.getCaptureSequenceLastFrameNumber( 1006 mCaptureSequenceId, CAPTURE_RESULT_TIMEOUT_MS); 1007 mCaptureListener.drain(); 1008 mImageListener.drain(); 1009 mErrorServiceConnection.logAsync( 1010 TestConstants.EVENT_CAMERA_PREVIEW_COMPLETED, 1011 Integer.toString(mCaptureSequenceId)); 1012 mCaptureSequenceId = -1; 1013 } catch (Exception e) { 1014 mErrorServiceConnection.logAsync( 1015 TestConstants.EVENT_CAMERA_ERROR, 1016 TAG + " exception during stop preview: " + e); 1017 Log.e(TAG, "exception during stop preview: " + e); 1018 } 1019 break; 1020 1021 default: 1022 super.handleMessage(msg); 1023 } 1024 } 1025 } 1026 } 1027