1 /** 2 * Copyright (c) 2020, 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 package com.android.cameraextensions; 17 18 import android.app.Service; 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.pm.PackageManager; 22 import android.graphics.GraphicBuffer; 23 import android.graphics.Rect; 24 import android.hardware.HardwareBuffer; 25 import android.hardware.camera2.CameraAccessException; 26 import android.hardware.camera2.CameraCharacteristics; 27 import android.hardware.camera2.CameraExtensionCharacteristics; 28 import android.hardware.camera2.CameraManager; 29 import android.hardware.camera2.CaptureRequest; 30 import android.hardware.camera2.CaptureResult; 31 import android.hardware.camera2.TotalCaptureResult; 32 import android.hardware.camera2.extension.CameraOutputConfig; 33 import android.hardware.camera2.extension.CameraSessionConfig; 34 import android.hardware.camera2.extension.CaptureBundle; 35 import android.hardware.camera2.extension.CaptureFailure; 36 import android.hardware.camera2.extension.CaptureStageImpl; 37 import android.hardware.camera2.extension.IAdvancedExtenderImpl; 38 import android.hardware.camera2.extension.ICameraExtensionsProxyService; 39 import android.hardware.camera2.extension.ICaptureCallback; 40 import android.hardware.camera2.extension.ICaptureProcessorImpl; 41 import android.hardware.camera2.extension.IImageCaptureExtenderImpl; 42 import android.hardware.camera2.extension.IImageProcessorImpl; 43 import android.hardware.camera2.extension.IInitializeSessionCallback; 44 import android.hardware.camera2.extension.IPreviewExtenderImpl; 45 import android.hardware.camera2.extension.IPreviewImageProcessorImpl; 46 import android.hardware.camera2.extension.IProcessResultImpl; 47 import android.hardware.camera2.extension.IRequestCallback; 48 import android.hardware.camera2.extension.IRequestProcessorImpl; 49 import android.hardware.camera2.extension.IRequestUpdateProcessorImpl; 50 import android.hardware.camera2.extension.ISessionProcessorImpl; 51 import android.hardware.camera2.extension.LatencyPair; 52 import android.hardware.camera2.extension.LatencyRange; 53 import android.hardware.camera2.extension.OutputConfigId; 54 import android.hardware.camera2.extension.OutputSurface; 55 import android.hardware.camera2.extension.ParcelCaptureResult; 56 import android.hardware.camera2.extension.ParcelImage; 57 import android.hardware.camera2.extension.ParcelTotalCaptureResult; 58 import android.hardware.camera2.extension.Request; 59 import android.hardware.camera2.extension.SizeList; 60 import android.hardware.camera2.impl.CameraMetadataNative; 61 import android.hardware.camera2.impl.PhysicalCaptureResultInfo; 62 import android.hardware.camera2.params.ColorSpaceProfiles; 63 import android.hardware.camera2.params.DynamicRangeProfiles; 64 import android.hardware.camera2.utils.SurfaceUtils; 65 import android.media.Image; 66 import android.media.ImageReader; 67 import android.os.Binder; 68 import android.os.ConditionVariable; 69 import android.os.Handler; 70 import android.os.HandlerExecutor; 71 import android.os.HandlerThread; 72 import android.os.IBinder; 73 import android.os.RemoteException; 74 import android.util.ArraySet; 75 import android.util.Log; 76 import android.util.Pair; 77 import android.util.Range; 78 import android.util.Size; 79 import android.view.Surface; 80 81 import androidx.annotation.NonNull; 82 import androidx.annotation.Nullable; 83 import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl; 84 import androidx.camera.extensions.impl.AutoPreviewExtenderImpl; 85 import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl; 86 import androidx.camera.extensions.impl.BeautyPreviewExtenderImpl; 87 import androidx.camera.extensions.impl.BokehImageCaptureExtenderImpl; 88 import androidx.camera.extensions.impl.BokehPreviewExtenderImpl; 89 import androidx.camera.extensions.impl.CaptureProcessorImpl; 90 import androidx.camera.extensions.impl.ExtensionVersionImpl; 91 import androidx.camera.extensions.impl.HdrImageCaptureExtenderImpl; 92 import androidx.camera.extensions.impl.HdrPreviewExtenderImpl; 93 import androidx.camera.extensions.impl.ImageCaptureExtenderImpl; 94 import androidx.camera.extensions.impl.InitializerImpl; 95 import androidx.camera.extensions.impl.NightImageCaptureExtenderImpl; 96 import androidx.camera.extensions.impl.NightPreviewExtenderImpl; 97 import androidx.camera.extensions.impl.PreviewExtenderImpl; 98 import androidx.camera.extensions.impl.PreviewExtenderImpl.ProcessorType; 99 import androidx.camera.extensions.impl.PreviewImageProcessorImpl; 100 import androidx.camera.extensions.impl.ProcessResultImpl; 101 import androidx.camera.extensions.impl.ProcessorImpl; 102 import androidx.camera.extensions.impl.RequestUpdateProcessorImpl; 103 import androidx.camera.extensions.impl.advanced.AdvancedExtenderImpl; 104 import androidx.camera.extensions.impl.advanced.AutoAdvancedExtenderImpl; 105 import androidx.camera.extensions.impl.advanced.BeautyAdvancedExtenderImpl; 106 import androidx.camera.extensions.impl.advanced.BokehAdvancedExtenderImpl; 107 import androidx.camera.extensions.impl.advanced.Camera2OutputConfigImpl; 108 import androidx.camera.extensions.impl.advanced.Camera2SessionConfigImpl; 109 import androidx.camera.extensions.impl.advanced.EyesFreeVideographyAdvancedExtenderImpl; 110 import androidx.camera.extensions.impl.advanced.HdrAdvancedExtenderImpl; 111 import androidx.camera.extensions.impl.advanced.ImageProcessorImpl; 112 import androidx.camera.extensions.impl.advanced.ImageReaderOutputConfigImpl; 113 import androidx.camera.extensions.impl.advanced.MultiResolutionImageReaderOutputConfigImpl; 114 import androidx.camera.extensions.impl.advanced.NightAdvancedExtenderImpl; 115 import androidx.camera.extensions.impl.advanced.OutputSurfaceConfigurationImpl; 116 import androidx.camera.extensions.impl.advanced.OutputSurfaceImpl; 117 import androidx.camera.extensions.impl.advanced.RequestProcessorImpl; 118 import androidx.camera.extensions.impl.advanced.SessionProcessorImpl; 119 import androidx.camera.extensions.impl.advanced.SurfaceOutputConfigImpl; 120 121 import com.android.internal.camera.flags.Flags; 122 123 import java.io.IOException; 124 import java.util.ArrayList; 125 import java.util.Collections; 126 import java.util.HashMap; 127 import java.util.List; 128 import java.util.Map; 129 import java.util.concurrent.Future; 130 import java.util.concurrent.TimeUnit; 131 import java.util.concurrent.TimeoutException; 132 133 public class CameraExtensionsProxyService extends Service { 134 private static final String TAG = "CameraExtensionsProxyService"; 135 136 private static final String CAMERA_EXTENSION_VERSION_NAME = 137 "androidx.camera.extensions.impl.ExtensionVersionImpl"; 138 private static final String LATEST_VERSION = "1.5.0"; 139 // No support for the init sequence 140 private static final String NON_INIT_VERSION_PREFIX = "1.0"; 141 // Support advanced API and latency queries 142 private static final String ADVANCED_VERSION_PREFIX = "1.2"; 143 // Support for the capture request & result APIs 144 private static final String RESULTS_VERSION_PREFIX = "1.3"; 145 // Support for various latency improvements 146 private static final String LATENCY_VERSION_PREFIX = "1.4"; 147 private static final String EFV_VERSION_PREFIX = "1.5"; 148 private static final String GET_VERSION_PREFIX = "1.5"; 149 private static final String[] ADVANCED_VERSION_PREFIXES = {EFV_VERSION_PREFIX, 150 LATENCY_VERSION_PREFIX, ADVANCED_VERSION_PREFIX, RESULTS_VERSION_PREFIX, 151 GET_VERSION_PREFIX}; 152 private static final String[] SUPPORTED_VERSION_PREFIXES = {EFV_VERSION_PREFIX, 153 LATENCY_VERSION_PREFIX, RESULTS_VERSION_PREFIX, ADVANCED_VERSION_PREFIX, "1.1", 154 NON_INIT_VERSION_PREFIX, GET_VERSION_PREFIX}; 155 private static final boolean EXTENSIONS_PRESENT = checkForExtensions(); 156 private static final String EXTENSIONS_VERSION = EXTENSIONS_PRESENT ? 157 (new ExtensionVersionImpl()).checkApiVersion(LATEST_VERSION) : null; 158 private static final boolean ESTIMATED_LATENCY_API_SUPPORTED = checkForLatencyAPI(); 159 private static final boolean LATENCY_IMPROVEMENTS_SUPPORTED = EXTENSIONS_PRESENT && 160 (EXTENSIONS_VERSION.startsWith(LATENCY_VERSION_PREFIX) || 161 (EXTENSIONS_VERSION.startsWith(EFV_VERSION_PREFIX))); 162 private static final boolean EFV_SUPPORTED = EXTENSIONS_PRESENT && 163 (EXTENSIONS_VERSION.startsWith(EFV_VERSION_PREFIX)); 164 private static final boolean GET_API_SUPPORTED = EXTENSIONS_PRESENT 165 && (EXTENSIONS_VERSION.startsWith(GET_VERSION_PREFIX)); 166 private static final boolean ADVANCED_API_SUPPORTED = checkForAdvancedAPI(); 167 private static final boolean INIT_API_SUPPORTED = EXTENSIONS_PRESENT && 168 (!EXTENSIONS_VERSION.startsWith(NON_INIT_VERSION_PREFIX)); 169 private static final boolean RESULT_API_SUPPORTED = EXTENSIONS_PRESENT && 170 (EXTENSIONS_VERSION.startsWith(RESULTS_VERSION_PREFIX) || 171 EXTENSIONS_VERSION.startsWith(LATENCY_VERSION_PREFIX) || 172 EXTENSIONS_VERSION.startsWith(EFV_VERSION_PREFIX)); 173 174 private HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>(); 175 private CameraManager mCameraManager; 176 checkForLatencyAPI()177 private static boolean checkForLatencyAPI() { 178 if (!EXTENSIONS_PRESENT) { 179 return false; 180 } 181 182 for (String advancedVersions : ADVANCED_VERSION_PREFIXES) { 183 if (EXTENSIONS_VERSION.startsWith(advancedVersions)) { 184 return true; 185 } 186 } 187 188 return false; 189 } 190 checkForAdvancedAPI()191 private static boolean checkForAdvancedAPI() { 192 if (!checkForLatencyAPI()) { 193 return false; 194 } 195 196 try { 197 return (new ExtensionVersionImpl()).isAdvancedExtenderImplemented(); 198 } catch (NoSuchMethodError e) { 199 // This could happen in case device specific extension implementations are using 200 // an older extension API but incorrectly set the extension version. 201 } 202 203 return false; 204 } 205 checkForExtensions()206 private static boolean checkForExtensions() { 207 try { 208 Class.forName(CAMERA_EXTENSION_VERSION_NAME); 209 } catch (ClassNotFoundException e) { 210 return false; 211 } 212 213 String extensionVersion = (new ExtensionVersionImpl()).checkApiVersion(LATEST_VERSION); 214 for (String supportedVersion : SUPPORTED_VERSION_PREFIXES) { 215 if (extensionVersion.startsWith(supportedVersion)) { 216 return true; 217 } 218 } 219 220 return false; 221 } 222 223 /** 224 * A per-process global camera extension manager instance, to track and 225 * initialize/release extensions depending on client activity. 226 */ 227 private static final class CameraExtensionManagerGlobal implements IBinder.DeathRecipient { 228 private static final String TAG = "CameraExtensionManagerGlobal"; 229 private final int EXTENSION_DELAY_MS = 1000; 230 231 private final Handler mHandler; 232 private final HandlerThread mHandlerThread; 233 private final Object mLock = new Object(); 234 235 private ArraySet<IBinder> mActiveClients = new ArraySet<>(); 236 private HashMap<IBinder, ArraySet<IBinder.DeathRecipient>> mClientDeathRecipient = 237 new HashMap<>(); 238 private IInitializeSessionCallback mInitializeCb = null; 239 240 // Singleton instance 241 private static final CameraExtensionManagerGlobal GLOBAL_CAMERA_MANAGER = 242 new CameraExtensionManagerGlobal(); 243 244 // Singleton, don't allow construction CameraExtensionManagerGlobal()245 private CameraExtensionManagerGlobal() { 246 mHandlerThread = new HandlerThread(TAG); 247 mHandlerThread.start(); 248 mHandler = new Handler(mHandlerThread.getLooper()); 249 } 250 251 private final static class InitializeHandler 252 implements InitializerImpl.OnExtensionsInitializedCallback { 253 private final InitializerFuture mStatusFuture; 254 InitializeHandler(InitializerFuture statusFuture)255 public InitializeHandler(InitializerFuture statusFuture) { 256 mStatusFuture = statusFuture; 257 } 258 259 @Override onSuccess()260 public void onSuccess() { 261 mStatusFuture.setStatus(true); 262 } 263 264 @Override onFailure(int error)265 public void onFailure(int error) { 266 mStatusFuture.setStatus(false); 267 } 268 } 269 270 private final static class ReleaseHandler 271 implements InitializerImpl.OnExtensionsDeinitializedCallback { 272 private final InitializerFuture mStatusFuture; 273 ReleaseHandler(InitializerFuture statusFuture)274 public ReleaseHandler(InitializerFuture statusFuture) { 275 mStatusFuture = statusFuture; 276 } 277 onSuccess()278 @Override public void onSuccess() { 279 mStatusFuture.setStatus(true); 280 } 281 282 @Override onFailure(int i)283 public void onFailure(int i) { 284 mStatusFuture.setStatus(false); 285 } 286 } 287 288 private static class InitializerFuture implements Future<Boolean> { 289 private volatile Boolean mStatus; 290 ConditionVariable mCondVar = new ConditionVariable(/*opened*/false); 291 setStatus(boolean status)292 public void setStatus(boolean status) { 293 mStatus = status; 294 mCondVar.open(); 295 } 296 297 @Override cancel(boolean mayInterruptIfRunning)298 public boolean cancel(boolean mayInterruptIfRunning) { 299 return false; // don't allow canceling this task 300 } 301 302 @Override isCancelled()303 public boolean isCancelled() { 304 return false; // can never cancel this task 305 } 306 307 @Override isDone()308 public boolean isDone() { 309 return mStatus != null; 310 } 311 312 @Override get()313 public Boolean get() { 314 mCondVar.block(); 315 return mStatus; 316 } 317 318 @Override get(long timeout, TimeUnit unit)319 public Boolean get(long timeout, TimeUnit unit) throws TimeoutException { 320 long timeoutMs = unit.convert(timeout, TimeUnit.MILLISECONDS); 321 if (!mCondVar.block(timeoutMs)) { 322 throw new TimeoutException( 323 "Failed to receive status after " + timeout + " " + unit); 324 } 325 326 if (mStatus == null) { 327 throw new AssertionError(); 328 } 329 return mStatus; 330 } 331 332 } 333 get()334 public static CameraExtensionManagerGlobal get() { 335 return GLOBAL_CAMERA_MANAGER; 336 } 337 registerClient(Context ctx, IBinder token)338 public boolean registerClient(Context ctx, IBinder token) { 339 synchronized (mLock) { 340 if (mActiveClients.contains(token)) { 341 Log.e(TAG, "Failed to register existing client!"); 342 return false; 343 } 344 345 try { 346 token.linkToDeath(this, 0); 347 } catch (RemoteException e) { 348 Log.e(TAG, "Failed to link to binder token!"); 349 return false; 350 } 351 352 if (INIT_API_SUPPORTED) { 353 if (mActiveClients.isEmpty()) { 354 InitializerFuture status = new InitializerFuture(); 355 InitializerImpl.init(LATEST_VERSION, ctx, new InitializeHandler(status), 356 new HandlerExecutor(mHandler)); 357 boolean initSuccess; 358 try { 359 initSuccess = status.get(EXTENSION_DELAY_MS, 360 TimeUnit.MILLISECONDS); 361 } catch (TimeoutException e) { 362 Log.e(TAG, "Timed out while initializing camera extensions!"); 363 return false; 364 } 365 if (!initSuccess) { 366 Log.e(TAG, "Failed while initializing camera extensions!"); 367 return false; 368 } 369 } 370 } 371 372 mActiveClients.add(token); 373 mClientDeathRecipient.put(token, new ArraySet<>()); 374 375 return true; 376 } 377 } 378 unregisterClient(IBinder token)379 public void unregisterClient(IBinder token) { 380 synchronized (mLock) { 381 if (mActiveClients.remove(token)) { 382 token.unlinkToDeath(this, 0); 383 mClientDeathRecipient.remove(token); 384 if (mActiveClients.isEmpty() && INIT_API_SUPPORTED) { 385 InitializerFuture status = new InitializerFuture(); 386 InitializerImpl.deinit(new ReleaseHandler(status), 387 new HandlerExecutor(mHandler)); 388 boolean releaseSuccess; 389 try { 390 releaseSuccess = status.get(EXTENSION_DELAY_MS, TimeUnit.MILLISECONDS); 391 } catch (TimeoutException e) { 392 Log.e(TAG, "Timed out while releasing camera extensions!"); 393 return; 394 } 395 if (!releaseSuccess) { 396 Log.e(TAG, "Failed while releasing camera extensions!"); 397 } 398 } 399 } 400 } 401 } 402 403 @Override binderDied()404 public void binderDied() { 405 // Do nothing, handled below 406 } 407 408 @Override binderDied(@onNull IBinder who)409 public void binderDied(@NonNull IBinder who) { 410 synchronized (mLock) { 411 if (mClientDeathRecipient.containsKey(who)) { 412 mClientDeathRecipient.get(who).stream().forEach( 413 recipient -> recipient.binderDied(who)); 414 } 415 unregisterClient(who); 416 } 417 } 418 registerDeathRecipient(IBinder token, IBinder.DeathRecipient recipient)419 public void registerDeathRecipient(IBinder token, IBinder.DeathRecipient recipient) { 420 synchronized (mLock) { 421 if (mClientDeathRecipient.containsKey(token)) { 422 ArraySet<IBinder.DeathRecipient> recipients = mClientDeathRecipient.get(token); 423 recipients.add(recipient); 424 } 425 } 426 } 427 unregisterDeathRecipient(IBinder token, IBinder.DeathRecipient recipient)428 public void unregisterDeathRecipient(IBinder token, IBinder.DeathRecipient recipient) { 429 synchronized (mLock) { 430 if (mClientDeathRecipient.containsKey(token)) { 431 ArraySet<IBinder.DeathRecipient> recipients = mClientDeathRecipient.get(token); 432 recipients.remove(recipient); 433 } 434 } 435 } 436 437 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { 438 @Override 439 public void binderDied() { 440 synchronized (mLock) { 441 mInitializeCb = null; 442 } 443 } 444 }; 445 initializeSession(IInitializeSessionCallback cb)446 public boolean initializeSession(IInitializeSessionCallback cb) { 447 synchronized (mLock) { 448 if (mInitializeCb == null) { 449 mInitializeCb = cb; 450 try { 451 mInitializeCb.asBinder().linkToDeath(mDeathRecipient, 0); 452 } catch (RemoteException e) { 453 e.printStackTrace(); 454 } 455 } else { 456 return false; 457 } 458 } 459 return true; 460 } 461 releaseSession()462 public void releaseSession() { 463 synchronized (mLock) { 464 if (mInitializeCb != null) { 465 mInitializeCb.asBinder().unlinkToDeath(mDeathRecipient, 0); 466 mInitializeCb = null; 467 } 468 } 469 } 470 } 471 472 /** 473 * @hide 474 */ registerClient(Context ctx, IBinder token)475 private static boolean registerClient(Context ctx, IBinder token) { 476 if (!EXTENSIONS_PRESENT) { 477 return false; 478 } 479 return CameraExtensionManagerGlobal.get().registerClient(ctx, token); 480 } 481 482 /** 483 * @hide 484 */ unregisterClient(IBinder token)485 public static void unregisterClient(IBinder token) { 486 if (!EXTENSIONS_PRESENT) { 487 return; 488 } 489 CameraExtensionManagerGlobal.get().unregisterClient(token); 490 } 491 492 /** 493 * @hide 494 */ registerDeathRecipient(IBinder token, IBinder.DeathRecipient recipient)495 private static void registerDeathRecipient(IBinder token, IBinder.DeathRecipient recipient) { 496 CameraExtensionManagerGlobal.get().registerDeathRecipient(token, recipient); 497 } 498 499 /** 500 * @hide 501 */ unregisterDeathRecipient(IBinder token, IBinder.DeathRecipient recipient)502 private static void unregisterDeathRecipient(IBinder token, IBinder.DeathRecipient recipient) { 503 CameraExtensionManagerGlobal.get().unregisterDeathRecipient(token, recipient); 504 } 505 506 /** 507 * @hide 508 */ initializeSession(IInitializeSessionCallback cb)509 public static boolean initializeSession(IInitializeSessionCallback cb) { 510 if (!EXTENSIONS_PRESENT) { 511 return false; 512 } 513 return CameraExtensionManagerGlobal.get().initializeSession(cb); 514 } 515 516 /** 517 * @hide 518 */ releaseSession()519 public static void releaseSession() { 520 if (!EXTENSIONS_PRESENT) { 521 return; 522 } 523 CameraExtensionManagerGlobal.get().releaseSession(); 524 } 525 526 /** 527 * @hide 528 */ initializeExtension( int extensionType)529 public static Pair<PreviewExtenderImpl, ImageCaptureExtenderImpl> initializeExtension( 530 int extensionType) { 531 if (Flags.concertModeApi()) { 532 if (extensionType == CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY) { 533 // Basic extensions are deprecated starting with extension version 1.5 534 return new Pair<>(new PreviewExtenderImpl() { 535 @Override 536 public boolean isExtensionAvailable(String cameraId, 537 CameraCharacteristics cameraCharacteristics) { 538 return false; 539 } 540 541 @Override 542 public void init(String cameraId, CameraCharacteristics cameraCharacteristics) { 543 544 } 545 546 @Override 547 public androidx.camera.extensions.impl.CaptureStageImpl getCaptureStage() { 548 return null; 549 } 550 551 @Override 552 public ProcessorType getProcessorType() { 553 return null; 554 } 555 556 @Override 557 public ProcessorImpl getProcessor() { 558 return null; 559 } 560 561 @Nullable 562 @Override 563 public List<Pair<Integer, Size[]>> getSupportedResolutions() { 564 return null; 565 } 566 567 @Override 568 public void onInit(String cameraId, CameraCharacteristics cameraCharacteristics, 569 Context context) { } 570 571 @Override 572 public void onDeInit() { } 573 574 @Override 575 public androidx.camera.extensions.impl.CaptureStageImpl onPresetSession() { 576 return null; 577 } 578 579 @Override 580 public androidx.camera.extensions.impl.CaptureStageImpl onEnableSession() { 581 return null; 582 } 583 584 @Override 585 public androidx.camera.extensions.impl.CaptureStageImpl onDisableSession() { 586 return null; 587 } 588 589 @Override 590 public int onSessionType() { 591 return 0; 592 } 593 }, new ImageCaptureExtenderImpl() { 594 @Override 595 public boolean isExtensionAvailable(String cameraId, 596 CameraCharacteristics cameraCharacteristics) { 597 return false; 598 } 599 600 @Override 601 public void init(String cameraId, 602 CameraCharacteristics cameraCharacteristics) { } 603 604 @Override 605 public CaptureProcessorImpl getCaptureProcessor() { 606 return null; 607 } 608 609 @Override 610 public 611 List<androidx.camera.extensions.impl.CaptureStageImpl> getCaptureStages() { 612 return null; 613 } 614 615 @Override 616 public int getMaxCaptureStage() { 617 return 0; 618 } 619 620 @Override 621 public List<Pair<Integer, Size[]>> getSupportedResolutions() { 622 return null; 623 } 624 625 @Override 626 public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions( 627 Size captureSize) { 628 return null; 629 } 630 631 @Override 632 public Range<Long> getEstimatedCaptureLatencyRange( 633 Size captureOutputSize) { 634 return null; 635 } 636 637 @Override 638 public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() { 639 return null; 640 } 641 642 @Override 643 public List<CaptureResult.Key> getAvailableCaptureResultKeys() { 644 return null; 645 } 646 647 @Override 648 public boolean isCaptureProcessProgressAvailable() { 649 return false; 650 } 651 652 @Override 653 public Pair<Long, Long> getRealtimeCaptureLatency() { 654 return null; 655 } 656 657 @Override 658 public boolean isPostviewAvailable() { 659 return false; 660 } 661 662 @Override 663 public void onInit(String cameraId, 664 CameraCharacteristics cameraCharacteristics, Context context) { } 665 666 @Override 667 public void onDeInit() { } 668 669 @Override 670 public androidx.camera.extensions.impl.CaptureStageImpl onPresetSession() { 671 return null; 672 } 673 674 @Override 675 public androidx.camera.extensions.impl.CaptureStageImpl onEnableSession() { 676 return null; 677 } 678 679 @Override 680 public androidx.camera.extensions.impl.CaptureStageImpl onDisableSession() { 681 return null; 682 } 683 684 @Override 685 public int onSessionType() { 686 return 0; 687 } 688 }); 689 } 690 } 691 692 switch (extensionType) { 693 case CameraExtensionCharacteristics.EXTENSION_AUTOMATIC: 694 return new Pair<>(new AutoPreviewExtenderImpl(), 695 new AutoImageCaptureExtenderImpl()); 696 case CameraExtensionCharacteristics.EXTENSION_FACE_RETOUCH: 697 return new Pair<>(new BeautyPreviewExtenderImpl(), 698 new BeautyImageCaptureExtenderImpl()); 699 case CameraExtensionCharacteristics.EXTENSION_BOKEH: 700 return new Pair<>(new BokehPreviewExtenderImpl(), 701 new BokehImageCaptureExtenderImpl()); 702 case CameraExtensionCharacteristics.EXTENSION_HDR: 703 return new Pair<>(new HdrPreviewExtenderImpl(), new HdrImageCaptureExtenderImpl()); 704 case CameraExtensionCharacteristics.EXTENSION_NIGHT: 705 return new Pair<>(new NightPreviewExtenderImpl(), 706 new NightImageCaptureExtenderImpl()); 707 default: 708 throw new IllegalArgumentException("Unknown extension: " + extensionType); 709 } 710 } 711 712 /** 713 * @hide 714 */ 715 public static AdvancedExtenderImpl initializeAdvancedExtensionImpl(int extensionType) { 716 if (Flags.concertModeApi()) { 717 if (extensionType == CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY) { 718 if (EFV_SUPPORTED) { 719 return new EyesFreeVideographyAdvancedExtenderImpl(); 720 } else { 721 return new AdvancedExtenderImpl() { 722 @Override 723 public boolean isExtensionAvailable(String cameraId, 724 Map<String, CameraCharacteristics> characteristicsMap) { 725 return false; 726 } 727 728 @Override 729 public void init(String cameraId, 730 Map<String, CameraCharacteristics> characteristicsMap) { 731 732 } 733 734 @Override 735 public Range<Long> getEstimatedCaptureLatencyRange(String cameraId, 736 Size captureOutputSize, int imageFormat) { 737 return null; 738 } 739 740 @Override 741 public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions( 742 String cameraId) { 743 return null; 744 } 745 746 @Override 747 public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions( 748 String cameraId) { 749 return null; 750 } 751 752 @Override 753 public Map<Integer, List<Size>> getSupportedPostviewResolutions( 754 Size captureSize) { 755 return null; 756 } 757 758 @Override 759 public List<Size> getSupportedYuvAnalysisResolutions(String cameraId) { 760 return null; 761 } 762 763 @Override 764 public SessionProcessorImpl createSessionProcessor() { 765 return null; 766 } 767 768 @Override 769 public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() { 770 return null; 771 } 772 773 @Override 774 public List<CaptureResult.Key> getAvailableCaptureResultKeys() { 775 return null; 776 } 777 778 @Override 779 public boolean isCaptureProcessProgressAvailable() { 780 return false; 781 } 782 783 @Override 784 public boolean isPostviewAvailable() { 785 return false; 786 } 787 788 @Override 789 public List<Pair<CameraCharacteristics.Key, Object>> 790 getAvailableCharacteristicsKeyValues() { 791 return Collections.emptyList(); 792 } 793 }; 794 } 795 } 796 } 797 798 switch (extensionType) { 799 case CameraExtensionCharacteristics.EXTENSION_AUTOMATIC: 800 return new AutoAdvancedExtenderImpl(); 801 case CameraExtensionCharacteristics.EXTENSION_FACE_RETOUCH: 802 return new BeautyAdvancedExtenderImpl(); 803 case CameraExtensionCharacteristics.EXTENSION_BOKEH: 804 return new BokehAdvancedExtenderImpl(); 805 case CameraExtensionCharacteristics.EXTENSION_HDR: 806 return new HdrAdvancedExtenderImpl(); 807 case CameraExtensionCharacteristics.EXTENSION_NIGHT: 808 return new NightAdvancedExtenderImpl(); 809 default: 810 throw new IllegalArgumentException("Unknown extension: " + extensionType); 811 } 812 } 813 814 @Override 815 public void onCreate() { 816 super.onCreate(); 817 // This will setup the camera vendor tag descriptor in the service process 818 // along with all camera characteristics. 819 try { 820 mCameraManager = getSystemService(CameraManager.class); 821 822 String [] cameraIds = mCameraManager.getCameraIdListNoLazy(); 823 if (cameraIds != null) { 824 for (String cameraId : cameraIds) { 825 CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId); 826 Object thisClass = CameraCharacteristics.Key.class; 827 Class<CameraCharacteristics.Key<?>> keyClass = 828 (Class<CameraCharacteristics.Key<?>>)thisClass; 829 ArrayList<CameraCharacteristics.Key<?>> vendorKeys = 830 chars.getNativeMetadata().getAllVendorKeys(keyClass); 831 if ((vendorKeys != null) && !vendorKeys.isEmpty()) { 832 mMetadataVendorIdMap.put(cameraId, vendorKeys.get(0).getVendorId()); 833 } 834 } 835 } 836 } catch (CameraAccessException e) { 837 Log.e(TAG, "Failed to query camera characteristics!"); 838 } 839 } 840 841 @Override 842 public void onDestroy() { 843 super.onDestroy(); 844 } 845 846 847 @Override 848 public IBinder onBind(Intent intent) { 849 return new CameraExtensionsProxyServiceStub(); 850 } 851 852 private static List<SizeList> initializeParcelable( 853 List<Pair<Integer, android.util.Size[]>> sizes) { 854 if (sizes == null) { 855 return null; 856 } 857 ArrayList<SizeList> ret = new ArrayList<>(sizes.size()); 858 for (Pair<Integer, Size[]> entry : sizes) { 859 SizeList sizeList = new SizeList(); 860 sizeList.format = entry.first; 861 sizeList.sizes = new ArrayList<>(); 862 for (android.util.Size size : entry.second) { 863 android.hardware.camera2.extension.Size sz = 864 new android.hardware.camera2.extension.Size(); 865 sz.width = size.getWidth(); 866 sz.height = size.getHeight(); 867 sizeList.sizes.add(sz); 868 } 869 870 if (!sizeList.sizes.isEmpty()) { 871 ret.add(sizeList); 872 } 873 } 874 875 return ret; 876 } 877 878 private static Map<String, CameraCharacteristics> getCharacteristicsMap( 879 Map<String, CameraMetadataNative> charsMap) { 880 HashMap<String, CameraCharacteristics> ret = new HashMap<>(); 881 for (Map.Entry<String, CameraMetadataNative> entry : charsMap.entrySet()) { 882 ret.put(entry.getKey(), new CameraCharacteristics(entry.getValue())); 883 } 884 return ret; 885 } 886 887 private static List<SizeList> initializeParcelable( 888 Map<Integer, List<android.util.Size>> sizes) { 889 if (sizes == null) { 890 return null; 891 } 892 ArrayList<SizeList> ret = new ArrayList<>(sizes.size()); 893 for (Map.Entry<Integer, List<android.util.Size>> entry : sizes.entrySet()) { 894 SizeList sizeList = new SizeList(); 895 sizeList.format = entry.getKey(); 896 sizeList.sizes = new ArrayList<>(); 897 for (android.util.Size size : entry.getValue()) { 898 android.hardware.camera2.extension.Size sz = 899 new android.hardware.camera2.extension.Size(); 900 sz.width = size.getWidth(); 901 sz.height = size.getHeight(); 902 sizeList.sizes.add(sz); 903 } 904 ret.add(sizeList); 905 } 906 907 return ret; 908 } 909 910 private CameraMetadataNative initializeParcelableMetadata( 911 List<Pair<CaptureRequest.Key, Object>> paramList, String cameraId) { 912 if (paramList == null) { 913 return null; 914 } 915 916 CameraMetadataNative ret = new CameraMetadataNative(); 917 if (mMetadataVendorIdMap.containsKey(cameraId)) { 918 ret.setVendorId(mMetadataVendorIdMap.get(cameraId)); 919 } 920 for (Pair<CaptureRequest.Key, Object> param : paramList) { 921 ret.set(param.first, param.second); 922 } 923 924 return ret; 925 } 926 927 private CameraMetadataNative initializeParcelableMetadata( 928 Map<CaptureRequest.Key<?>, Object> paramMap, String cameraId) { 929 if (paramMap == null) { 930 return null; 931 } 932 933 CameraMetadataNative ret = new CameraMetadataNative(); 934 if (mMetadataVendorIdMap.containsKey(cameraId)) { 935 ret.setVendorId(mMetadataVendorIdMap.get(cameraId)); 936 } 937 for (Map.Entry<CaptureRequest.Key<?>, Object> param : paramMap.entrySet()) { 938 ret.set(((CaptureRequest.Key) param.getKey()), param.getValue()); 939 } 940 941 return ret; 942 } 943 944 private android.hardware.camera2.extension.CaptureStageImpl initializeParcelable( 945 androidx.camera.extensions.impl.CaptureStageImpl captureStage, String cameraId) { 946 if (captureStage == null) { 947 return null; 948 } 949 950 android.hardware.camera2.extension.CaptureStageImpl ret = 951 new android.hardware.camera2.extension.CaptureStageImpl(); 952 ret.id = captureStage.getId(); 953 ret.parameters = initializeParcelableMetadata(captureStage.getParameters(), cameraId); 954 955 return ret; 956 } 957 958 private Request initializeParcelable(RequestProcessorImpl.Request request, int requestId, 959 String cameraId) { 960 Request ret = new Request(); 961 ret.targetOutputConfigIds = new ArrayList<>(); 962 for (int id : request.getTargetOutputConfigIds()) { 963 OutputConfigId configId = new OutputConfigId(); 964 configId.id = id; 965 ret.targetOutputConfigIds.add(configId); 966 } 967 ret.templateId = request.getTemplateId(); 968 ret.parameters = initializeParcelableMetadata(request.getParameters(), cameraId); 969 ret.requestId = requestId; 970 return ret; 971 } 972 973 private class CameraExtensionsProxyServiceStub extends ICameraExtensionsProxyService.Stub { 974 @Override 975 public boolean registerClient(IBinder token) { 976 return CameraExtensionsProxyService.registerClient(CameraExtensionsProxyService.this, 977 token); 978 } 979 980 @Override 981 public void unregisterClient(IBinder token) { 982 CameraExtensionsProxyService.unregisterClient(token); 983 } 984 985 private boolean checkCameraPermission() { 986 int allowed = CameraExtensionsProxyService.this.checkPermission( 987 android.Manifest.permission.CAMERA, Binder.getCallingPid(), 988 Binder.getCallingUid()); 989 return (PackageManager.PERMISSION_GRANTED == allowed); 990 } 991 992 @Override 993 public void initializeSession(IInitializeSessionCallback cb) { 994 try { 995 if (!checkCameraPermission()) { 996 Log.i(TAG, "Camera permission required for initializing capture session"); 997 cb.onFailure(); 998 return; 999 } 1000 1001 if (CameraExtensionsProxyService.initializeSession(cb)) { 1002 cb.onSuccess(); 1003 } else { 1004 cb.onFailure(); 1005 } 1006 } catch (RemoteException e) { 1007 Log.e(TAG, "Client doesn't respond!"); 1008 } 1009 } 1010 1011 @Override 1012 public void releaseSession() { 1013 if (checkCameraPermission()) { 1014 CameraExtensionsProxyService.releaseSession(); 1015 } 1016 } 1017 1018 @Override 1019 public boolean advancedExtensionsSupported() { 1020 return ADVANCED_API_SUPPORTED; 1021 } 1022 1023 @Override 1024 public IAdvancedExtenderImpl initializeAdvancedExtension(int extensionType) { 1025 AdvancedExtenderImpl extension; 1026 try { 1027 extension = initializeAdvancedExtensionImpl(extensionType); 1028 } catch (IllegalArgumentException e) { 1029 return null; 1030 } 1031 1032 return new AdvancedExtenderImplStub(extension); 1033 } 1034 1035 @Override 1036 public IPreviewExtenderImpl initializePreviewExtension(int extensionType) { 1037 Pair<PreviewExtenderImpl, ImageCaptureExtenderImpl> extension; 1038 try { 1039 extension = initializeExtension(extensionType); 1040 } catch (IllegalArgumentException e) { 1041 return null; 1042 } 1043 1044 return new PreviewExtenderImplStub(extension.first); 1045 } 1046 1047 @Override 1048 public IImageCaptureExtenderImpl initializeImageExtension(int extensionType) { 1049 Pair<PreviewExtenderImpl, ImageCaptureExtenderImpl> extension; 1050 try { 1051 extension = initializeExtension(extensionType); 1052 } catch (IllegalArgumentException e) { 1053 return null; 1054 } 1055 1056 return new ImageCaptureExtenderImplStub(extension.second); 1057 } 1058 } 1059 1060 private class AdvancedExtenderImplStub extends IAdvancedExtenderImpl.Stub { 1061 private final AdvancedExtenderImpl mAdvancedExtender; 1062 1063 public AdvancedExtenderImplStub(AdvancedExtenderImpl advancedExtender) { 1064 mAdvancedExtender = advancedExtender; 1065 } 1066 1067 @Override 1068 public boolean isExtensionAvailable(String cameraId, 1069 Map<String, CameraMetadataNative> charsMapNative) { 1070 return mAdvancedExtender.isExtensionAvailable(cameraId, 1071 getCharacteristicsMap(charsMapNative)); 1072 } 1073 1074 @Override 1075 public void init(String cameraId, Map<String, CameraMetadataNative> charsMapNative) { 1076 mAdvancedExtender.init(cameraId, getCharacteristicsMap(charsMapNative)); 1077 } 1078 1079 @Override 1080 public List<SizeList> getSupportedPostviewResolutions( 1081 android.hardware.camera2.extension.Size captureSize) { 1082 Size sz = new Size(captureSize.width, captureSize.height); 1083 Map<Integer, List<Size>> supportedSizesMap = 1084 mAdvancedExtender.getSupportedPostviewResolutions(sz); 1085 if (supportedSizesMap != null) { 1086 return initializeParcelable(supportedSizesMap); 1087 } 1088 1089 return null; 1090 } 1091 1092 @Override 1093 public List<SizeList> getSupportedPreviewOutputResolutions(String cameraId) { 1094 Map<Integer, List<Size>> supportedSizesMap = 1095 mAdvancedExtender.getSupportedPreviewOutputResolutions(cameraId); 1096 if (supportedSizesMap != null) { 1097 return initializeParcelable(supportedSizesMap); 1098 } 1099 1100 return null; 1101 } 1102 1103 @Override 1104 public List<SizeList> getSupportedCaptureOutputResolutions(String cameraId) { 1105 Map<Integer, List<Size>> supportedSizesMap = 1106 mAdvancedExtender.getSupportedCaptureOutputResolutions(cameraId); 1107 if (supportedSizesMap != null) { 1108 return initializeParcelable(supportedSizesMap); 1109 } 1110 1111 return null; 1112 } 1113 1114 @Override 1115 public LatencyRange getEstimatedCaptureLatencyRange(String cameraId, 1116 android.hardware.camera2.extension.Size outputSize, int format) { 1117 Size sz = new Size(outputSize.width, outputSize.height); 1118 Range<Long> latencyRange = mAdvancedExtender.getEstimatedCaptureLatencyRange(cameraId, 1119 sz, format); 1120 if (latencyRange != null) { 1121 LatencyRange ret = new LatencyRange(); 1122 ret.min = latencyRange.getLower(); 1123 ret.max = latencyRange.getUpper(); 1124 return ret; 1125 } 1126 1127 return null; 1128 } 1129 1130 @Override 1131 public ISessionProcessorImpl getSessionProcessor() { 1132 return new SessionProcessorImplStub(mAdvancedExtender.createSessionProcessor()); 1133 } 1134 1135 @Override 1136 public CameraMetadataNative getAvailableCaptureRequestKeys(String cameraId) { 1137 if (RESULT_API_SUPPORTED) { 1138 List<CaptureRequest.Key> supportedCaptureKeys = 1139 mAdvancedExtender.getAvailableCaptureRequestKeys(); 1140 1141 if ((supportedCaptureKeys != null) && !supportedCaptureKeys.isEmpty()) { 1142 CameraMetadataNative ret = new CameraMetadataNative(); 1143 long vendorId = mMetadataVendorIdMap.containsKey(cameraId) ? 1144 mMetadataVendorIdMap.get(cameraId) : Long.MAX_VALUE; 1145 ret.setVendorId(vendorId); 1146 int requestKeyTags [] = new int[supportedCaptureKeys.size()]; 1147 int i = 0; 1148 for (CaptureRequest.Key key : supportedCaptureKeys) { 1149 requestKeyTags[i++] = CameraMetadataNative.getTag(key.getName(), vendorId); 1150 } 1151 ret.set(CameraCharacteristics.REQUEST_AVAILABLE_REQUEST_KEYS, requestKeyTags); 1152 1153 return ret; 1154 } 1155 } 1156 1157 return null; 1158 } 1159 1160 @Override 1161 public CameraMetadataNative getAvailableCaptureResultKeys(String cameraId) { 1162 if (RESULT_API_SUPPORTED) { 1163 List<CaptureResult.Key> supportedResultKeys = 1164 mAdvancedExtender.getAvailableCaptureResultKeys(); 1165 1166 if ((supportedResultKeys != null) && !supportedResultKeys.isEmpty()) { 1167 CameraMetadataNative ret = new CameraMetadataNative(); 1168 long vendorId = mMetadataVendorIdMap.containsKey(cameraId) ? 1169 mMetadataVendorIdMap.get(cameraId) : Long.MAX_VALUE; 1170 ret.setVendorId(vendorId); 1171 int resultKeyTags [] = new int[supportedResultKeys.size()]; 1172 int i = 0; 1173 for (CaptureResult.Key key : supportedResultKeys) { 1174 resultKeyTags[i++] = CameraMetadataNative.getTag(key.getName(), vendorId); 1175 } 1176 ret.set(CameraCharacteristics.REQUEST_AVAILABLE_RESULT_KEYS, resultKeyTags); 1177 1178 return ret; 1179 } 1180 } 1181 1182 return null; 1183 } 1184 1185 @Override 1186 public boolean isCaptureProcessProgressAvailable() { 1187 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 1188 return mAdvancedExtender.isCaptureProcessProgressAvailable(); 1189 } 1190 1191 return false; 1192 } 1193 1194 @Override 1195 public boolean isPostviewAvailable() { 1196 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 1197 return mAdvancedExtender.isPostviewAvailable(); 1198 } 1199 1200 return false; 1201 } 1202 1203 @Override 1204 public CameraMetadataNative getAvailableCharacteristicsKeyValues(String cameraId) { 1205 if (GET_API_SUPPORTED) { 1206 List<Pair<CameraCharacteristics.Key, Object>> entries = 1207 mAdvancedExtender.getAvailableCharacteristicsKeyValues(); 1208 1209 if (entries == null || entries.isEmpty()) { 1210 throw new RuntimeException("A valid set of key/value pairs are required that " 1211 + "are supported by the extension."); 1212 } 1213 1214 CameraMetadataNative ret = new CameraMetadataNative(); 1215 long vendorId = mMetadataVendorIdMap.containsKey(cameraId) 1216 ? mMetadataVendorIdMap.get(cameraId) : Long.MAX_VALUE; 1217 ret.setVendorId(vendorId); 1218 int[] characteristicsKeyTags = new int[entries.size()]; 1219 int i = 0; 1220 for (Pair<CameraCharacteristics.Key, Object> entry : entries) { 1221 int tag = CameraMetadataNative.getTag(entry.first.getName(), vendorId); 1222 characteristicsKeyTags[i++] = tag; 1223 ret.set(entry.first, entry.second); 1224 } 1225 ret.set(CameraCharacteristics.REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, 1226 characteristicsKeyTags); 1227 1228 return ret; 1229 } 1230 1231 return null; 1232 } 1233 } 1234 1235 private class CaptureCallbackStub implements SessionProcessorImpl.CaptureCallback { 1236 private final ICaptureCallback mCaptureCallback; 1237 private final String mCameraId; 1238 1239 private CaptureCallbackStub(ICaptureCallback captureCallback, String cameraId) { 1240 mCaptureCallback = captureCallback; 1241 mCameraId = cameraId; 1242 } 1243 1244 @Override 1245 public void onCaptureStarted(int captureSequenceId, long timestamp) { 1246 if (mCaptureCallback != null) { 1247 try { 1248 mCaptureCallback.onCaptureStarted(captureSequenceId, timestamp); 1249 } catch (RemoteException e) { 1250 Log.e(TAG, "Failed to notify capture start due to remote " + 1251 "exception!"); 1252 } 1253 } 1254 } 1255 1256 @Override 1257 public void onCaptureProcessStarted(int captureSequenceId) { 1258 if (mCaptureCallback != null) { 1259 try { 1260 mCaptureCallback.onCaptureProcessStarted(captureSequenceId); 1261 } catch (RemoteException e) { 1262 Log.e(TAG, "Failed to notify capture process start due to remote " + 1263 "exception!"); 1264 } 1265 } 1266 } 1267 1268 @Override 1269 public void onCaptureFailed(int captureSequenceId) { 1270 if (mCaptureCallback != null) { 1271 try { 1272 mCaptureCallback.onCaptureFailed(captureSequenceId); 1273 } catch (RemoteException e) { 1274 Log.e(TAG, "Failed to notify capture failure due to remote " + 1275 "exception!"); 1276 } 1277 } 1278 } 1279 1280 @Override 1281 public void onCaptureFailed(int captureSequenceId, int reason) { 1282 if (Flags.concertMode()) { 1283 if (mCaptureCallback != null) { 1284 try { 1285 mCaptureCallback.onCaptureProcessFailed(captureSequenceId, reason); 1286 } catch (RemoteException e) { 1287 Log.e(TAG, "Failed to notify capture failure due to remote " + 1288 "exception!"); 1289 } 1290 } 1291 } 1292 } 1293 1294 @Override 1295 public void onCaptureSequenceCompleted(int captureSequenceId) { 1296 if (mCaptureCallback != null) { 1297 try { 1298 mCaptureCallback.onCaptureSequenceCompleted(captureSequenceId); 1299 } catch (RemoteException e) { 1300 Log.e(TAG, "Failed to notify capture sequence end due to remote " + 1301 "exception!"); 1302 } 1303 } 1304 } 1305 1306 @Override 1307 public void onCaptureSequenceAborted(int captureSequenceId) { 1308 if (mCaptureCallback != null) { 1309 try { 1310 mCaptureCallback.onCaptureSequenceAborted(captureSequenceId); 1311 } catch (RemoteException e) { 1312 Log.e(TAG, "Failed to notify capture sequence abort due to remote " + 1313 "exception!"); 1314 } 1315 } 1316 } 1317 1318 @Override 1319 public void onCaptureCompleted(long timestamp, int requestId, 1320 Map<CaptureResult.Key, Object> result) { 1321 1322 if (result == null) { 1323 Log.e(TAG, "Invalid capture result received!"); 1324 } 1325 1326 CameraMetadataNative captureResults = new CameraMetadataNative(); 1327 if (mMetadataVendorIdMap.containsKey(mCameraId)) { 1328 captureResults.setVendorId(mMetadataVendorIdMap.get(mCameraId)); 1329 } 1330 for (Map.Entry<CaptureResult.Key, Object> entry : result.entrySet()) { 1331 captureResults.set(entry.getKey(), entry.getValue()); 1332 } 1333 1334 try { 1335 mCaptureCallback.onCaptureCompleted(timestamp, requestId, captureResults); 1336 } catch (RemoteException e) { 1337 Log.e(TAG, "Failed to notify capture complete due to remote exception!"); 1338 } 1339 } 1340 1341 @Override 1342 public void onCaptureProcessProgressed(int progress) { 1343 try { 1344 mCaptureCallback.onCaptureProcessProgressed(progress); 1345 } catch (RemoteException e) { 1346 Log.e(TAG, "Remote client doesn't respond to capture progress callbacks!"); 1347 } 1348 } 1349 } 1350 1351 private class RequestCallbackStub extends IRequestCallback.Stub { 1352 private final List<RequestProcessorImpl.Request> mRequests; 1353 private final RequestProcessorImpl.Callback mCallback; 1354 1355 public RequestCallbackStub(List<RequestProcessorImpl.Request> requests, 1356 RequestProcessorImpl.Callback callback) { 1357 mCallback = callback; 1358 if (mCallback != null) { 1359 mRequests = requests; 1360 } else { 1361 Log.w(TAG, "No valid request callbacks!"); 1362 mRequests = new ArrayList<>(); 1363 } 1364 } 1365 1366 @Override 1367 public void onCaptureStarted(int requestId, long frameNumber, long timestamp) { 1368 if (mCallback != null) { 1369 if (mRequests.get(requestId) != null) { 1370 mCallback.onCaptureStarted(mRequests.get(requestId), frameNumber, timestamp); 1371 } else { 1372 Log.e(TAG,"Request id: " + requestId + " not found!"); 1373 } 1374 } 1375 } 1376 1377 @Override 1378 public void onCaptureProgressed(int requestId, ParcelCaptureResult partialResult) { 1379 if (mCallback != null) { 1380 if (mRequests.get(requestId) != null) { 1381 CaptureResult result = new CaptureResult(partialResult.cameraId, 1382 partialResult.results, partialResult.parent, partialResult.sequenceId, 1383 partialResult.frameNumber); 1384 mCallback.onCaptureProgressed(mRequests.get(requestId), result); 1385 } else { 1386 Log.e(TAG,"Request id: " + requestId + " not found!"); 1387 } 1388 } 1389 } 1390 1391 @Override 1392 public void onCaptureCompleted(int requestId, ParcelTotalCaptureResult totalCaptureResult) { 1393 if (mCallback != null) { 1394 if (mRequests.get(requestId) != null) { 1395 PhysicalCaptureResultInfo[] physicalResults = new PhysicalCaptureResultInfo[0]; 1396 if ((totalCaptureResult.physicalResult != null) && 1397 (!totalCaptureResult.physicalResult.isEmpty())) { 1398 int count = totalCaptureResult.physicalResult.size(); 1399 physicalResults = new PhysicalCaptureResultInfo[count]; 1400 physicalResults = totalCaptureResult.physicalResult.toArray( 1401 physicalResults); 1402 } 1403 ArrayList<CaptureResult> partials = new ArrayList<>( 1404 totalCaptureResult.partials.size()); 1405 for (ParcelCaptureResult parcelResult : totalCaptureResult.partials) { 1406 partials.add(new CaptureResult(parcelResult.cameraId, parcelResult.results, 1407 parcelResult.parent, parcelResult.sequenceId, 1408 parcelResult.frameNumber)); 1409 } 1410 TotalCaptureResult result = new TotalCaptureResult( 1411 totalCaptureResult.logicalCameraId, totalCaptureResult.results, 1412 totalCaptureResult.parent, totalCaptureResult.sequenceId, 1413 totalCaptureResult.frameNumber, partials, totalCaptureResult.sessionId, 1414 physicalResults); 1415 mCallback.onCaptureCompleted(mRequests.get(requestId), result); 1416 } else { 1417 Log.e(TAG,"Request id: " + requestId + " not found!"); 1418 } 1419 } 1420 } 1421 1422 @Override 1423 public void onCaptureFailed(int requestId, CaptureFailure captureFailure) { 1424 if (mCallback != null) { 1425 if (mRequests.get(requestId) != null) { 1426 android.hardware.camera2.CaptureFailure failure = 1427 new android.hardware.camera2.CaptureFailure(captureFailure.request, 1428 captureFailure.reason, captureFailure.dropped, 1429 captureFailure.sequenceId, captureFailure.frameNumber, 1430 captureFailure.errorPhysicalCameraId); 1431 mCallback.onCaptureFailed(mRequests.get(requestId), failure); 1432 } else { 1433 Log.e(TAG,"Request id: " + requestId + " not found!"); 1434 } 1435 } 1436 } 1437 1438 @Override 1439 public void onCaptureBufferLost(int requestId, long frameNumber, int outputStreamId) { 1440 if (mCallback != null) { 1441 if (mRequests.get(requestId) != null) { 1442 mCallback.onCaptureBufferLost(mRequests.get(requestId), frameNumber, 1443 outputStreamId); 1444 } else { 1445 Log.e(TAG,"Request id: " + requestId + " not found!"); 1446 } 1447 } 1448 } 1449 1450 @Override 1451 public void onCaptureSequenceCompleted(int sequenceId, long frameNumber) { 1452 if (mCallback != null) { 1453 mCallback.onCaptureSequenceCompleted(sequenceId, frameNumber); 1454 } 1455 } 1456 1457 @Override 1458 public void onCaptureSequenceAborted(int sequenceId) { 1459 if (mCallback != null) { 1460 mCallback.onCaptureSequenceAborted(sequenceId); 1461 } 1462 } 1463 } 1464 1465 private class ImageProcessorImplStub extends IImageProcessorImpl.Stub { 1466 private final ImageProcessorImpl mImageProcessor; 1467 1468 public ImageProcessorImplStub(ImageProcessorImpl imageProcessor) { 1469 mImageProcessor = imageProcessor; 1470 } 1471 1472 @Override 1473 public void onNextImageAvailable(OutputConfigId outputConfigId, ParcelImage img, 1474 String physicalCameraId) { 1475 if (mImageProcessor != null) { 1476 mImageProcessor.onNextImageAvailable(outputConfigId.id, img.timestamp, 1477 new ImageReferenceImpl(img), physicalCameraId); 1478 } 1479 } 1480 } 1481 1482 private class RequestProcessorStub implements RequestProcessorImpl { 1483 private final IRequestProcessorImpl mRequestProcessor; 1484 private final String mCameraId; 1485 1486 public RequestProcessorStub(IRequestProcessorImpl requestProcessor, String cameraId) { 1487 mRequestProcessor = requestProcessor; 1488 mCameraId = cameraId; 1489 } 1490 1491 @Override 1492 public void setImageProcessor(int outputConfigId, 1493 ImageProcessorImpl imageProcessor) { 1494 OutputConfigId configId = new OutputConfigId(); 1495 configId.id = outputConfigId; 1496 try { 1497 mRequestProcessor.setImageProcessor(configId, 1498 new ImageProcessorImplStub(imageProcessor)); 1499 } catch (RemoteException e) { 1500 Log.e(TAG, "Failed to set image processor due to remote exception!"); 1501 } 1502 } 1503 1504 @Override 1505 public int submit(Request request, Callback callback) { 1506 ArrayList<Request> requests = new ArrayList<>(); 1507 requests.add(request); 1508 return submit(requests, callback); 1509 } 1510 1511 @Override 1512 public int submit(List<Request> requests, Callback callback) { 1513 ArrayList<android.hardware.camera2.extension.Request> captureRequests = 1514 new ArrayList<>(); 1515 int requestId = 0; 1516 for (Request request : requests) { 1517 captureRequests.add(initializeParcelable(request, requestId, mCameraId)); 1518 requestId++; 1519 } 1520 1521 try { 1522 return mRequestProcessor.submitBurst(captureRequests, 1523 new RequestCallbackStub(requests, callback)); 1524 } catch (RemoteException e) { 1525 Log.e(TAG, "Failed to submit request due to remote exception!"); 1526 } 1527 return -1; 1528 } 1529 1530 @Override 1531 public int setRepeating(Request request, Callback callback) { 1532 try { 1533 ArrayList<Request> requests = new ArrayList<>(); 1534 requests.add(request); 1535 return mRequestProcessor.setRepeating( 1536 initializeParcelable(request, 0, mCameraId), 1537 new RequestCallbackStub(requests, callback)); 1538 } catch (RemoteException e) { 1539 Log.e(TAG, "Failed to submit repeating request due to remote exception!"); 1540 } 1541 1542 return -1; 1543 } 1544 1545 @Override 1546 public void abortCaptures() { 1547 try { 1548 mRequestProcessor.abortCaptures(); 1549 } catch (RemoteException e) { 1550 Log.e(TAG, "Failed to abort requests due to remote exception!"); 1551 } 1552 } 1553 1554 @Override 1555 public void stopRepeating() { 1556 try { 1557 mRequestProcessor.stopRepeating(); 1558 } catch (RemoteException e) { 1559 Log.e(TAG, "Failed to stop repeating request due to remote exception!"); 1560 } 1561 } 1562 } 1563 1564 private class SessionProcessorImplStub extends ISessionProcessorImpl.Stub implements 1565 IBinder.DeathRecipient { 1566 private final SessionProcessorImpl mSessionProcessor; 1567 private String mCameraId = null; 1568 private IBinder mToken; 1569 1570 OutputSurfaceImplStub mOutputPreviewSurfaceImpl; 1571 OutputSurfaceImplStub mOutputImageCaptureSurfaceImpl; 1572 OutputSurfaceImplStub mOutputPostviewSurfaceImpl; 1573 1574 public SessionProcessorImplStub(SessionProcessorImpl sessionProcessor) { 1575 mSessionProcessor = sessionProcessor; 1576 } 1577 1578 @Override 1579 public CameraSessionConfig initSession(IBinder token, String cameraId, 1580 Map<String, CameraMetadataNative> charsMapNative, OutputSurface previewSurface, 1581 OutputSurface imageCaptureSurface, OutputSurface postviewSurface) { 1582 mOutputPreviewSurfaceImpl = new OutputSurfaceImplStub(previewSurface); 1583 mOutputImageCaptureSurfaceImpl = new OutputSurfaceImplStub(imageCaptureSurface); 1584 mOutputPostviewSurfaceImpl = new OutputSurfaceImplStub(postviewSurface); 1585 1586 Camera2SessionConfigImpl sessionConfig; 1587 1588 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 1589 int outputsColorSpace = getColorSpaceFromOutputSurfaces(previewSurface, 1590 imageCaptureSurface, postviewSurface); 1591 OutputSurfaceConfigurationImplStub outputSurfaceConfigs = 1592 new OutputSurfaceConfigurationImplStub(mOutputPreviewSurfaceImpl, 1593 // Image Analysis Output is currently only supported in CameraX 1594 mOutputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/, 1595 mOutputPostviewSurfaceImpl, outputsColorSpace); 1596 1597 sessionConfig = mSessionProcessor.initSession(cameraId, 1598 getCharacteristicsMap(charsMapNative), 1599 getApplicationContext(), outputSurfaceConfigs); 1600 } else { 1601 sessionConfig = mSessionProcessor.initSession(cameraId, 1602 getCharacteristicsMap(charsMapNative), 1603 getApplicationContext(), mOutputPreviewSurfaceImpl, 1604 mOutputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/); 1605 } 1606 1607 List<Camera2OutputConfigImpl> outputConfigs = sessionConfig.getOutputConfigs(); 1608 CameraSessionConfig ret = new CameraSessionConfig(); 1609 ret.outputConfigs = new ArrayList<>(); 1610 for (Camera2OutputConfigImpl output : outputConfigs) { 1611 CameraOutputConfig entry = getCameraOutputConfig(output); 1612 List<Camera2OutputConfigImpl> sharedOutputs = 1613 output.getSurfaceSharingOutputConfigs(); 1614 if ((sharedOutputs != null) && (!sharedOutputs.isEmpty())) { 1615 entry.sharedSurfaceConfigs = new ArrayList<>(); 1616 for (Camera2OutputConfigImpl sharedOutput : sharedOutputs) { 1617 entry.sharedSurfaceConfigs.add(getCameraOutputConfig(sharedOutput)); 1618 } 1619 } 1620 ret.outputConfigs.add(entry); 1621 } 1622 if (Flags.extension10Bit() && EFV_SUPPORTED) { 1623 ret.colorSpace = sessionConfig.getColorSpace(); 1624 } else { 1625 ret.colorSpace = ColorSpaceProfiles.UNSPECIFIED; 1626 } 1627 ret.sessionTemplateId = sessionConfig.getSessionTemplateId(); 1628 ret.sessionType = -1; 1629 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 1630 ret.sessionType = sessionConfig.getSessionType(); 1631 } 1632 ret.sessionParameter = initializeParcelableMetadata( 1633 sessionConfig.getSessionParameters(), cameraId); 1634 mCameraId = cameraId; 1635 mToken = token; 1636 CameraExtensionsProxyService.registerDeathRecipient(mToken, this); 1637 return ret; 1638 } 1639 1640 @Override 1641 public void deInitSession(IBinder token) { 1642 CameraExtensionsProxyService.unregisterDeathRecipient(mToken, this); 1643 mSessionProcessor.deInitSession(); 1644 1645 if (Flags.surfaceLeakFix()) { 1646 if (mOutputImageCaptureSurfaceImpl.mSurface != null) { 1647 mOutputImageCaptureSurfaceImpl.mSurface.release(); 1648 } 1649 if (mOutputPreviewSurfaceImpl.mSurface != null) { 1650 mOutputPreviewSurfaceImpl.mSurface.release(); 1651 } 1652 if (mOutputPostviewSurfaceImpl.mSurface != null) { 1653 mOutputPostviewSurfaceImpl.mSurface.release(); 1654 } 1655 } 1656 } 1657 1658 @Override 1659 public void onCaptureSessionStart(IRequestProcessorImpl requestProcessor, String statsKey) { 1660 mSessionProcessor.onCaptureSessionStart( 1661 new RequestProcessorStub(requestProcessor, mCameraId)); 1662 } 1663 1664 @Override 1665 public void onCaptureSessionEnd() { 1666 mSessionProcessor.onCaptureSessionEnd(); 1667 } 1668 1669 @Override 1670 public int startRepeating(ICaptureCallback callback) { 1671 return mSessionProcessor.startRepeating(new CaptureCallbackStub(callback, mCameraId)); 1672 } 1673 1674 @Override 1675 public void stopRepeating() { 1676 mSessionProcessor.stopRepeating(); 1677 } 1678 1679 @Override 1680 public void setParameters(CaptureRequest captureRequest) { 1681 HashMap<CaptureRequest.Key<?>, Object> paramMap = new HashMap<>(); 1682 for (CaptureRequest.Key captureRequestKey : captureRequest.getKeys()) { 1683 paramMap.put(captureRequestKey, captureRequest.get(captureRequestKey)); 1684 } 1685 1686 mSessionProcessor.setParameters(paramMap); 1687 } 1688 1689 @Override 1690 public int startTrigger(CaptureRequest captureRequest, ICaptureCallback callback) { 1691 HashMap<CaptureRequest.Key<?>, Object> triggerMap = new HashMap<>(); 1692 for (CaptureRequest.Key captureRequestKey : captureRequest.getKeys()) { 1693 triggerMap.put(captureRequestKey, captureRequest.get(captureRequestKey)); 1694 } 1695 1696 return mSessionProcessor.startTrigger(triggerMap, 1697 new CaptureCallbackStub(callback, mCameraId)); 1698 } 1699 1700 @Override 1701 public int startCapture(ICaptureCallback callback, boolean isPostviewRequested) { 1702 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 1703 return isPostviewRequested ? mSessionProcessor.startCaptureWithPostview( 1704 new CaptureCallbackStub(callback, mCameraId)) : 1705 mSessionProcessor.startCapture(new CaptureCallbackStub(callback, 1706 mCameraId)); 1707 } 1708 1709 return mSessionProcessor.startCapture(new CaptureCallbackStub(callback, mCameraId)); 1710 } 1711 1712 @Override 1713 public LatencyPair getRealtimeCaptureLatency() { 1714 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 1715 Pair<Long, Long> latency = mSessionProcessor.getRealtimeCaptureLatency(); 1716 if (latency != null) { 1717 LatencyPair ret = new LatencyPair(); 1718 ret.first = latency.first; 1719 ret.second = latency.second; 1720 return ret; 1721 } 1722 } 1723 1724 return null; 1725 } 1726 1727 @Override 1728 public void binderDied() { 1729 mSessionProcessor.deInitSession(); 1730 } 1731 1732 // Get the color space of the output configurations. All of the OutputSurfaces 1733 // can be assumed to have the same color space so return the color space 1734 // of any non-null OutputSurface 1735 private int getColorSpaceFromOutputSurfaces(OutputSurface previewSurface, 1736 OutputSurface imageCaptureSurface, OutputSurface postviewSurface) { 1737 int colorSpace = ColorSpaceProfiles.UNSPECIFIED; 1738 1739 if (previewSurface.surface != null) { 1740 colorSpace = previewSurface.colorSpace; 1741 } else if (imageCaptureSurface.surface != null) { 1742 colorSpace = imageCaptureSurface.colorSpace; 1743 } else if (postviewSurface.surface != null) { 1744 colorSpace = postviewSurface.colorSpace; 1745 } 1746 1747 return colorSpace; 1748 } 1749 } 1750 1751 private class OutputSurfaceConfigurationImplStub implements OutputSurfaceConfigurationImpl { 1752 private OutputSurfaceImpl mOutputPreviewSurfaceImpl; 1753 private OutputSurfaceImpl mOutputImageCaptureSurfaceImpl; 1754 private OutputSurfaceImpl mOutputImageAnalysisSurfaceImpl; 1755 private OutputSurfaceImpl mOutputPostviewSurfaceImpl; 1756 private int mColorSpace; 1757 1758 public OutputSurfaceConfigurationImplStub(OutputSurfaceImpl previewOutput, 1759 OutputSurfaceImpl imageCaptureOutput, OutputSurfaceImpl imageAnalysisOutput, 1760 OutputSurfaceImpl postviewOutput, int colorSpace) { 1761 mOutputPreviewSurfaceImpl = previewOutput; 1762 mOutputImageCaptureSurfaceImpl = imageCaptureOutput; 1763 mOutputImageAnalysisSurfaceImpl = imageAnalysisOutput; 1764 mOutputPostviewSurfaceImpl = postviewOutput; 1765 mColorSpace = colorSpace; 1766 } 1767 1768 public OutputSurfaceConfigurationImplStub(OutputSurfaceImpl previewOutput, 1769 OutputSurfaceImpl imageCaptureOutput, OutputSurfaceImpl imageAnalysisOutput, 1770 OutputSurfaceImpl postviewOutput) { 1771 mOutputPreviewSurfaceImpl = previewOutput; 1772 mOutputImageCaptureSurfaceImpl = imageCaptureOutput; 1773 mOutputImageAnalysisSurfaceImpl = imageAnalysisOutput; 1774 mOutputPostviewSurfaceImpl = postviewOutput; 1775 mColorSpace = ColorSpaceProfiles.UNSPECIFIED; 1776 } 1777 1778 @Override 1779 public OutputSurfaceImpl getPreviewOutputSurface() { 1780 return mOutputPreviewSurfaceImpl; 1781 } 1782 1783 @Override 1784 public OutputSurfaceImpl getImageCaptureOutputSurface() { 1785 return mOutputImageCaptureSurfaceImpl; 1786 } 1787 1788 @Override 1789 public OutputSurfaceImpl getImageAnalysisOutputSurface() { 1790 return mOutputImageAnalysisSurfaceImpl; 1791 } 1792 1793 @Override 1794 public OutputSurfaceImpl getPostviewOutputSurface() { 1795 return mOutputPostviewSurfaceImpl; 1796 } 1797 1798 @Override 1799 public int getColorSpace() { 1800 return mColorSpace; 1801 } 1802 } 1803 1804 private class OutputSurfaceImplStub implements OutputSurfaceImpl { 1805 private final Surface mSurface; 1806 private final Size mSize; 1807 private final int mImageFormat; 1808 private final int mDataspace; 1809 private final long mUsage; 1810 private final long mDynamicRangeProfile; 1811 1812 public OutputSurfaceImplStub(OutputSurface outputSurface) { 1813 mSurface = outputSurface.surface; 1814 if (mSurface != null) { 1815 mDataspace = SurfaceUtils.getSurfaceDataspace(mSurface); 1816 mUsage = SurfaceUtils.getSurfaceUsage(mSurface); 1817 } else { 1818 mDataspace = -1; 1819 mUsage = 0; 1820 } 1821 mDynamicRangeProfile = outputSurface.dynamicRangeProfile; 1822 mSize = new Size(outputSurface.size.width, outputSurface.size.height); 1823 mImageFormat = outputSurface.imageFormat; 1824 } 1825 1826 @Override 1827 public Surface getSurface() { 1828 return mSurface; 1829 } 1830 1831 @Override 1832 public Size getSize() { 1833 return mSize; 1834 } 1835 1836 @Override 1837 public int getImageFormat() { 1838 return mImageFormat; 1839 } 1840 1841 @Override 1842 public int getDataspace() { 1843 return mDataspace; 1844 } 1845 1846 @Override 1847 public long getUsage() { 1848 return mUsage; 1849 } 1850 1851 @Override 1852 public long getDynamicRangeProfile() { 1853 return mDynamicRangeProfile; 1854 } 1855 1856 } 1857 1858 private class PreviewExtenderImplStub extends IPreviewExtenderImpl.Stub implements 1859 IBinder.DeathRecipient { 1860 private final PreviewExtenderImpl mPreviewExtender; 1861 private String mCameraId = null; 1862 private boolean mSessionEnabled; 1863 private IBinder mToken; 1864 1865 public PreviewExtenderImplStub(PreviewExtenderImpl previewExtender) { 1866 mPreviewExtender = previewExtender; 1867 } 1868 1869 @Override 1870 public void onInit(IBinder token, String cameraId, 1871 CameraMetadataNative cameraCharacteristics) { 1872 mCameraId = cameraId; 1873 CameraCharacteristics chars = new CameraCharacteristics(cameraCharacteristics); 1874 mCameraManager.registerDeviceStateListener(chars); 1875 mPreviewExtender.onInit(cameraId, chars, CameraExtensionsProxyService.this); 1876 mToken = token; 1877 CameraExtensionsProxyService.registerDeathRecipient(mToken, this); 1878 } 1879 1880 @Override 1881 public void onDeInit(IBinder token) { 1882 CameraExtensionsProxyService.unregisterDeathRecipient(mToken, this); 1883 mPreviewExtender.onDeInit(); 1884 } 1885 1886 @Override 1887 public CaptureStageImpl onPresetSession() { 1888 return initializeParcelable(mPreviewExtender.onPresetSession(), mCameraId); 1889 } 1890 1891 @Override 1892 public CaptureStageImpl onEnableSession() { 1893 mSessionEnabled = true; 1894 return initializeParcelable(mPreviewExtender.onEnableSession(), mCameraId); 1895 } 1896 1897 @Override 1898 public CaptureStageImpl onDisableSession() { 1899 mSessionEnabled = false; 1900 return initializeParcelable(mPreviewExtender.onDisableSession(), mCameraId); 1901 } 1902 1903 @Override 1904 public void init(String cameraId, CameraMetadataNative chars) { 1905 CameraCharacteristics c = new CameraCharacteristics(chars); 1906 mCameraManager.registerDeviceStateListener(c); 1907 mPreviewExtender.init(cameraId, c); 1908 } 1909 1910 @Override 1911 public boolean isExtensionAvailable(String cameraId, CameraMetadataNative chars) { 1912 CameraCharacteristics c = new CameraCharacteristics(chars); 1913 mCameraManager.registerDeviceStateListener(c); 1914 return mPreviewExtender.isExtensionAvailable(cameraId, c); 1915 } 1916 1917 @Override 1918 public CaptureStageImpl getCaptureStage() { 1919 return initializeParcelable(mPreviewExtender.getCaptureStage(), mCameraId); 1920 } 1921 1922 @Override 1923 public int getSessionType() { 1924 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 1925 return mPreviewExtender.onSessionType(); 1926 } 1927 1928 return -1; 1929 } 1930 1931 @Override 1932 public int getProcessorType() { 1933 ProcessorType processorType = mPreviewExtender.getProcessorType(); 1934 if (processorType == ProcessorType.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY) { 1935 return IPreviewExtenderImpl.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY; 1936 } else if (processorType == ProcessorType.PROCESSOR_TYPE_IMAGE_PROCESSOR) { 1937 return IPreviewExtenderImpl.PROCESSOR_TYPE_IMAGE_PROCESSOR; 1938 } else { 1939 return IPreviewExtenderImpl.PROCESSOR_TYPE_NONE; 1940 } 1941 } 1942 1943 @Override 1944 public IPreviewImageProcessorImpl getPreviewImageProcessor() { 1945 PreviewImageProcessorImpl processor; 1946 try { 1947 processor = (PreviewImageProcessorImpl) mPreviewExtender.getProcessor(); 1948 } catch (ClassCastException e) { 1949 Log.e(TAG, "Failed casting preview processor!"); 1950 return null; 1951 } 1952 1953 if (processor != null) { 1954 return new PreviewImageProcessorImplStub(processor, mCameraId); 1955 } 1956 1957 return null; 1958 } 1959 1960 @Override 1961 public IRequestUpdateProcessorImpl getRequestUpdateProcessor() { 1962 RequestUpdateProcessorImpl processor; 1963 try { 1964 processor = (RequestUpdateProcessorImpl) mPreviewExtender.getProcessor(); 1965 } catch (ClassCastException e) { 1966 Log.e(TAG, "Failed casting preview processor!"); 1967 return null; 1968 } 1969 1970 if (processor != null) { 1971 return new RequestUpdateProcessorImplStub(processor, mCameraId); 1972 } 1973 1974 return null; 1975 } 1976 1977 @Override 1978 public List<SizeList> getSupportedResolutions() { 1979 if (INIT_API_SUPPORTED) { 1980 List<Pair<Integer, android.util.Size[]>> sizes = 1981 mPreviewExtender.getSupportedResolutions(); 1982 if ((sizes != null) && !sizes.isEmpty()) { 1983 return initializeParcelable(sizes); 1984 } 1985 } 1986 return null; 1987 } 1988 1989 @Override 1990 public void binderDied() { 1991 if (mSessionEnabled) { 1992 mPreviewExtender.onDisableSession(); 1993 } 1994 mPreviewExtender.onDeInit(); 1995 } 1996 } 1997 1998 private class ImageCaptureExtenderImplStub extends IImageCaptureExtenderImpl.Stub implements 1999 IBinder.DeathRecipient { 2000 private final ImageCaptureExtenderImpl mImageExtender; 2001 private String mCameraId = null; 2002 private boolean mSessionEnabled; 2003 private IBinder mToken; 2004 2005 public ImageCaptureExtenderImplStub(ImageCaptureExtenderImpl imageExtender) { 2006 mImageExtender = imageExtender; 2007 } 2008 2009 @Override 2010 public void onInit(IBinder token, String cameraId, 2011 CameraMetadataNative cameraCharacteristics) { 2012 CameraCharacteristics chars = new CameraCharacteristics(cameraCharacteristics); 2013 mCameraManager.registerDeviceStateListener(chars); 2014 mImageExtender.onInit(cameraId, chars, CameraExtensionsProxyService.this); 2015 mCameraId = cameraId; 2016 mToken = token; 2017 CameraExtensionsProxyService.registerDeathRecipient(mToken, this); 2018 } 2019 2020 @Override 2021 public void onDeInit(IBinder token) { 2022 CameraExtensionsProxyService.unregisterDeathRecipient(mToken, this); 2023 mImageExtender.onDeInit(); 2024 } 2025 2026 @Override 2027 public CaptureStageImpl onPresetSession() { 2028 return initializeParcelable(mImageExtender.onPresetSession(), mCameraId); 2029 } 2030 2031 @Override 2032 public boolean isCaptureProcessProgressAvailable() { 2033 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 2034 return mImageExtender.isCaptureProcessProgressAvailable(); 2035 } 2036 2037 return false; 2038 } 2039 2040 @Override 2041 public boolean isPostviewAvailable() { 2042 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 2043 return mImageExtender.isPostviewAvailable(); 2044 } 2045 2046 return false; 2047 } 2048 2049 @Override 2050 public CaptureStageImpl onEnableSession() { 2051 mSessionEnabled = true; 2052 return initializeParcelable(mImageExtender.onEnableSession(), mCameraId); 2053 } 2054 2055 @Override 2056 public CaptureStageImpl onDisableSession() { 2057 mSessionEnabled = false; 2058 return initializeParcelable(mImageExtender.onDisableSession(), mCameraId); 2059 } 2060 2061 @Override 2062 public int getSessionType() { 2063 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 2064 return mImageExtender.onSessionType(); 2065 } 2066 2067 return -1; 2068 } 2069 2070 @Override 2071 public void init(String cameraId, CameraMetadataNative chars) { 2072 CameraCharacteristics c = new CameraCharacteristics(chars); 2073 mCameraManager.registerDeviceStateListener(c); 2074 mImageExtender.init(cameraId, c); 2075 } 2076 2077 @Override 2078 public boolean isExtensionAvailable(String cameraId, CameraMetadataNative chars) { 2079 CameraCharacteristics c = new CameraCharacteristics(chars); 2080 mCameraManager.registerDeviceStateListener(c); 2081 return mImageExtender.isExtensionAvailable(cameraId, c); 2082 } 2083 2084 @Override 2085 public ICaptureProcessorImpl getCaptureProcessor() { 2086 CaptureProcessorImpl captureProcessor = mImageExtender.getCaptureProcessor(); 2087 if (captureProcessor != null) { 2088 return new CaptureProcessorImplStub(captureProcessor, mCameraId); 2089 } 2090 2091 return null; 2092 } 2093 2094 2095 @Override 2096 public List<CaptureStageImpl> getCaptureStages() { 2097 List<androidx.camera.extensions.impl.CaptureStageImpl> captureStages = 2098 mImageExtender.getCaptureStages(); 2099 if (captureStages != null) { 2100 ArrayList<android.hardware.camera2.extension.CaptureStageImpl> ret = 2101 new ArrayList<>(); 2102 for (androidx.camera.extensions.impl.CaptureStageImpl stage : captureStages) { 2103 ret.add(initializeParcelable(stage, mCameraId)); 2104 } 2105 2106 return ret; 2107 } 2108 2109 return null; 2110 } 2111 2112 @Override 2113 public int getMaxCaptureStage() { 2114 return mImageExtender.getMaxCaptureStage(); 2115 } 2116 2117 @Override 2118 public List<SizeList> getSupportedResolutions() { 2119 if (INIT_API_SUPPORTED) { 2120 List<Pair<Integer, android.util.Size[]>> sizes = 2121 mImageExtender.getSupportedResolutions(); 2122 if ((sizes != null) && !sizes.isEmpty()) { 2123 return initializeParcelable(sizes); 2124 } 2125 } 2126 2127 return null; 2128 } 2129 2130 @Override 2131 public List<SizeList> getSupportedPostviewResolutions( 2132 android.hardware.camera2.extension.Size captureSize) { 2133 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 2134 Size sz = new Size(captureSize.width, captureSize.height); 2135 List<Pair<Integer, android.util.Size[]>> sizes = 2136 mImageExtender.getSupportedPostviewResolutions(sz); 2137 if ((sizes != null) && !sizes.isEmpty()) { 2138 return initializeParcelable(sizes); 2139 } 2140 } 2141 2142 return null; 2143 } 2144 2145 @Override 2146 public LatencyRange getEstimatedCaptureLatencyRange( 2147 android.hardware.camera2.extension.Size outputSize) { 2148 if (ESTIMATED_LATENCY_API_SUPPORTED) { 2149 Size sz = new Size(outputSize.width, outputSize.height); 2150 Range<Long> latencyRange = mImageExtender.getEstimatedCaptureLatencyRange(sz); 2151 if (latencyRange != null) { 2152 LatencyRange ret = new LatencyRange(); 2153 ret.min = latencyRange.getLower(); 2154 ret.max = latencyRange.getUpper(); 2155 return ret; 2156 } 2157 } 2158 2159 return null; 2160 } 2161 2162 @Override 2163 public LatencyPair getRealtimeCaptureLatency() { 2164 if (LATENCY_IMPROVEMENTS_SUPPORTED) { 2165 Pair<Long, Long> latency = mImageExtender.getRealtimeCaptureLatency(); 2166 if (latency != null) { 2167 LatencyPair ret = new LatencyPair(); 2168 ret.first = latency.first; 2169 ret.second = latency.second; 2170 return ret; 2171 } 2172 } 2173 2174 return null; 2175 } 2176 2177 @Override 2178 public CameraMetadataNative getAvailableCaptureRequestKeys() { 2179 if (RESULT_API_SUPPORTED) { 2180 List<CaptureRequest.Key> supportedCaptureKeys = 2181 mImageExtender.getAvailableCaptureRequestKeys(); 2182 2183 if ((supportedCaptureKeys != null) && !supportedCaptureKeys.isEmpty()) { 2184 CameraMetadataNative ret = new CameraMetadataNative(); 2185 long vendorId = mMetadataVendorIdMap.containsKey(mCameraId) ? 2186 mMetadataVendorIdMap.get(mCameraId) : Long.MAX_VALUE; 2187 ret.setVendorId(vendorId); 2188 int requestKeyTags [] = new int[supportedCaptureKeys.size()]; 2189 int i = 0; 2190 for (CaptureRequest.Key key : supportedCaptureKeys) { 2191 requestKeyTags[i++] = CameraMetadataNative.getTag(key.getName(), vendorId); 2192 } 2193 ret.set(CameraCharacteristics.REQUEST_AVAILABLE_REQUEST_KEYS, requestKeyTags); 2194 2195 return ret; 2196 } 2197 } 2198 2199 return null; 2200 } 2201 2202 @Override 2203 public CameraMetadataNative getAvailableCaptureResultKeys() { 2204 if (RESULT_API_SUPPORTED) { 2205 List<CaptureResult.Key> supportedResultKeys = 2206 mImageExtender.getAvailableCaptureResultKeys(); 2207 2208 if ((supportedResultKeys != null) && !supportedResultKeys.isEmpty()) { 2209 CameraMetadataNative ret = new CameraMetadataNative(); 2210 long vendorId = mMetadataVendorIdMap.containsKey(mCameraId) ? 2211 mMetadataVendorIdMap.get(mCameraId) : Long.MAX_VALUE; 2212 ret.setVendorId(vendorId); 2213 int resultKeyTags [] = new int[supportedResultKeys.size()]; 2214 int i = 0; 2215 for (CaptureResult.Key key : supportedResultKeys) { 2216 resultKeyTags[i++] = CameraMetadataNative.getTag(key.getName(), vendorId); 2217 } 2218 ret.set(CameraCharacteristics.REQUEST_AVAILABLE_RESULT_KEYS, resultKeyTags); 2219 2220 return ret; 2221 } 2222 } 2223 2224 return null; 2225 } 2226 2227 @Override 2228 public void binderDied() { 2229 if (mSessionEnabled) { 2230 mImageExtender.onDisableSession(); 2231 } 2232 mImageExtender.onDeInit(); 2233 } 2234 } 2235 2236 private class ProcessResultCallback implements ProcessResultImpl { 2237 private final IProcessResultImpl mProcessResult; 2238 private final String mCameraId; 2239 2240 private ProcessResultCallback(IProcessResultImpl processResult, String cameraId) { 2241 mProcessResult = processResult; 2242 mCameraId = cameraId; 2243 } 2244 2245 @Override 2246 public void onCaptureProcessProgressed(int progress) { 2247 try { 2248 mProcessResult.onCaptureProcessProgressed(progress); 2249 } catch (RemoteException e) { 2250 Log.e(TAG, "Remote client doesn't respond to capture progress callbacks!"); 2251 } 2252 } 2253 2254 @Override 2255 public void onCaptureCompleted(long shutterTimestamp, 2256 List<Pair<CaptureResult.Key, Object>> result) { 2257 if (result == null) { 2258 Log.e(TAG, "Invalid capture result received!"); 2259 } 2260 2261 CameraMetadataNative captureResults = new CameraMetadataNative(); 2262 if (mMetadataVendorIdMap.containsKey(mCameraId)) { 2263 captureResults.setVendorId(mMetadataVendorIdMap.get(mCameraId)); 2264 } 2265 for (Pair<CaptureResult.Key, Object> pair : result) { 2266 captureResults.set(pair.first, pair.second); 2267 } 2268 2269 try { 2270 mProcessResult.onCaptureCompleted(shutterTimestamp, captureResults); 2271 } catch (RemoteException e) { 2272 Log.e(TAG, "Remote client doesn't respond to capture results!"); 2273 } 2274 } 2275 } 2276 2277 private class CaptureProcessorImplStub extends ICaptureProcessorImpl.Stub { 2278 private final CaptureProcessorImpl mCaptureProcessor; 2279 private final String mCameraId; 2280 2281 public CaptureProcessorImplStub(CaptureProcessorImpl captureProcessor, String cameraId) { 2282 mCaptureProcessor = captureProcessor; 2283 mCameraId = cameraId; 2284 } 2285 2286 @Override 2287 public void onOutputSurface(Surface surface, int imageFormat) { 2288 mCaptureProcessor.onOutputSurface(surface, imageFormat); 2289 } 2290 2291 @Override 2292 public void onPostviewOutputSurface(Surface surface) { 2293 mCaptureProcessor.onPostviewOutputSurface(surface); 2294 } 2295 2296 @Override 2297 public void onResolutionUpdate(android.hardware.camera2.extension.Size size, 2298 android.hardware.camera2.extension.Size postviewSize) { 2299 if (postviewSize != null) { 2300 mCaptureProcessor.onResolutionUpdate( 2301 new android.util.Size(size.width, size.height), 2302 new android.util.Size(postviewSize.width, postviewSize.height)); 2303 } else { 2304 mCaptureProcessor.onResolutionUpdate( 2305 new android.util.Size(size.width, size.height)); 2306 } 2307 } 2308 2309 @Override 2310 public void onImageFormatUpdate(int imageFormat) { 2311 mCaptureProcessor.onImageFormatUpdate(imageFormat); 2312 } 2313 2314 @Override 2315 public void process(List<CaptureBundle> captureList, IProcessResultImpl resultCallback, 2316 boolean isPostviewRequested) { 2317 HashMap<Integer, Pair<Image, TotalCaptureResult>> captureMap = new HashMap<>(); 2318 for (CaptureBundle captureBundle : captureList) { 2319 captureMap.put(captureBundle.stage, new Pair<> ( 2320 new ExtensionImage(captureBundle.captureImage), 2321 new TotalCaptureResult(captureBundle.captureResult, 2322 captureBundle.sequenceId))); 2323 } 2324 if (!captureMap.isEmpty()) { 2325 if ((LATENCY_IMPROVEMENTS_SUPPORTED) && (isPostviewRequested)) { 2326 ProcessResultCallback processResultCallback = (resultCallback != null) 2327 ? new ProcessResultCallback(resultCallback, mCameraId) : null; 2328 mCaptureProcessor.processWithPostview(captureMap, processResultCallback, 2329 null /*executor*/); 2330 } else if ((resultCallback != null) && (RESULT_API_SUPPORTED)) { 2331 mCaptureProcessor.process(captureMap, new ProcessResultCallback(resultCallback, 2332 mCameraId), null /*executor*/); 2333 } else if (resultCallback == null) { 2334 mCaptureProcessor.process(captureMap); 2335 } else { 2336 Log.e(TAG, "Process requests with capture results are not supported!"); 2337 } 2338 } else { 2339 Log.e(TAG, "Process request with absent capture stages!"); 2340 } 2341 } 2342 } 2343 2344 private class PreviewImageProcessorImplStub extends IPreviewImageProcessorImpl.Stub { 2345 private final PreviewImageProcessorImpl mProcessor; 2346 private final String mCameraId; 2347 2348 public PreviewImageProcessorImplStub(PreviewImageProcessorImpl processor, String cameraId) { 2349 mProcessor = processor; 2350 mCameraId = cameraId; 2351 } 2352 2353 @Override 2354 public void onOutputSurface(Surface surface, int imageFormat) { 2355 mProcessor.onOutputSurface(surface, imageFormat); 2356 } 2357 2358 @Override 2359 public void onResolutionUpdate(android.hardware.camera2.extension.Size size) { 2360 mProcessor.onResolutionUpdate(new android.util.Size(size.width, size.height)); 2361 } 2362 2363 @Override 2364 public void onImageFormatUpdate(int imageFormat) { 2365 mProcessor.onImageFormatUpdate(imageFormat); 2366 } 2367 2368 @Override 2369 public void process(android.hardware.camera2.extension.ParcelImage image, 2370 CameraMetadataNative result, int sequenceId, IProcessResultImpl resultCallback) { 2371 if ((resultCallback != null) && RESULT_API_SUPPORTED) { 2372 mProcessor.process(new ExtensionImage(image), 2373 new TotalCaptureResult(result, sequenceId), 2374 new ProcessResultCallback(resultCallback, mCameraId), null /*executor*/); 2375 } else if (resultCallback == null) { 2376 mProcessor.process(new ExtensionImage(image), 2377 new TotalCaptureResult(result, sequenceId)); 2378 } else { 2379 2380 } 2381 } 2382 } 2383 2384 private class RequestUpdateProcessorImplStub extends IRequestUpdateProcessorImpl.Stub { 2385 private final RequestUpdateProcessorImpl mProcessor; 2386 private final String mCameraId; 2387 2388 public RequestUpdateProcessorImplStub(RequestUpdateProcessorImpl processor, 2389 String cameraId) { 2390 mProcessor = processor; 2391 mCameraId = cameraId; 2392 } 2393 2394 @Override 2395 public void onOutputSurface(Surface surface, int imageFormat) { 2396 mProcessor.onOutputSurface(surface, imageFormat); 2397 } 2398 2399 @Override 2400 public void onResolutionUpdate(android.hardware.camera2.extension.Size size) { 2401 mProcessor.onResolutionUpdate(new android.util.Size(size.width, size.height)); 2402 } 2403 2404 @Override 2405 public void onImageFormatUpdate(int imageFormat) { 2406 mProcessor.onImageFormatUpdate(imageFormat); 2407 } 2408 2409 @Override 2410 public CaptureStageImpl process(CameraMetadataNative result, int sequenceId) { 2411 return initializeParcelable( 2412 mProcessor.process(new TotalCaptureResult(result, sequenceId)), mCameraId); 2413 } 2414 } 2415 2416 private class ImageReferenceImpl extends ExtensionImage 2417 implements androidx.camera.extensions.impl.advanced.ImageReferenceImpl { 2418 2419 private final Object mImageLock = new Object(); 2420 private int mReferenceCount; 2421 2422 private ImageReferenceImpl(ParcelImage parcelImage) { 2423 super(parcelImage); 2424 mReferenceCount = 1; 2425 } 2426 2427 @Override 2428 public boolean increment() { 2429 synchronized (mImageLock) { 2430 if (mReferenceCount <= 0) { 2431 return false; 2432 } 2433 mReferenceCount++; 2434 } 2435 2436 return true; 2437 } 2438 2439 @Override 2440 public boolean decrement() { 2441 synchronized (mImageLock) { 2442 if (mReferenceCount <= 0) { 2443 return false; 2444 } 2445 mReferenceCount--; 2446 2447 if (mReferenceCount <= 0) { 2448 close(); 2449 } 2450 } 2451 2452 return true; 2453 } 2454 2455 @Override 2456 public Image get() { 2457 return this; 2458 } 2459 } 2460 2461 private class ExtensionImage extends android.media.Image { 2462 private final android.hardware.camera2.extension.ParcelImage mParcelImage; 2463 private GraphicBuffer mGraphicBuffer; 2464 private ImageReader.ImagePlane[] mPlanes; 2465 2466 private ExtensionImage(android.hardware.camera2.extension.ParcelImage parcelImage) { 2467 mParcelImage = parcelImage; 2468 mIsImageValid = true; 2469 } 2470 2471 @Override 2472 public int getFormat() { 2473 throwISEIfImageIsInvalid(); 2474 return mParcelImage.format; 2475 } 2476 2477 @Override 2478 public int getWidth() { 2479 throwISEIfImageIsInvalid(); 2480 return mParcelImage.width; 2481 } 2482 2483 @Override 2484 public HardwareBuffer getHardwareBuffer() { 2485 throwISEIfImageIsInvalid(); 2486 return mParcelImage.buffer; 2487 } 2488 2489 @Override 2490 public int getHeight() { 2491 throwISEIfImageIsInvalid(); 2492 return mParcelImage.height; 2493 } 2494 2495 @Override 2496 public long getTimestamp() { 2497 throwISEIfImageIsInvalid(); 2498 return mParcelImage.timestamp; 2499 } 2500 2501 @Override 2502 public int getTransform() { 2503 throwISEIfImageIsInvalid(); 2504 return mParcelImage.transform; 2505 } 2506 2507 @Override 2508 public int getScalingMode() { 2509 throwISEIfImageIsInvalid(); 2510 return mParcelImage.scalingMode; 2511 } 2512 2513 @Override 2514 public Plane[] getPlanes() { 2515 throwISEIfImageIsInvalid(); 2516 if (mPlanes == null) { 2517 int fenceFd = mParcelImage.fence != null ? mParcelImage.fence.detachFd() : -1; 2518 mGraphicBuffer = GraphicBuffer.createFromHardwareBuffer(mParcelImage.buffer); 2519 mPlanes = ImageReader.initializeImagePlanes(mParcelImage.planeCount, mGraphicBuffer, 2520 fenceFd, mParcelImage.format, mParcelImage.timestamp, 2521 mParcelImage.transform, mParcelImage.scalingMode, mParcelImage.crop); 2522 } 2523 // Shallow copy is fine. 2524 return mPlanes.clone(); 2525 } 2526 2527 @Override 2528 protected final void finalize() throws Throwable { 2529 try { 2530 close(); 2531 } finally { 2532 super.finalize(); 2533 } 2534 } 2535 2536 @Override 2537 public boolean isAttachable() { 2538 throwISEIfImageIsInvalid(); 2539 // Clients must always detach parcelable images 2540 return true; 2541 } 2542 2543 @Override 2544 public Rect getCropRect() { 2545 throwISEIfImageIsInvalid(); 2546 return mParcelImage.crop; 2547 } 2548 2549 @Override 2550 public void close() { 2551 mIsImageValid = false; 2552 2553 if (mGraphicBuffer != null) { 2554 try { 2555 ImageReader.unlockGraphicBuffer(mGraphicBuffer); 2556 } catch (RuntimeException e) { 2557 e.printStackTrace(); 2558 } 2559 mGraphicBuffer.destroy(); 2560 mGraphicBuffer = null; 2561 } 2562 2563 if (mPlanes != null) { 2564 mPlanes = null; 2565 } 2566 2567 if (mParcelImage.buffer != null) { 2568 mParcelImage.buffer.close(); 2569 mParcelImage.buffer = null; 2570 } 2571 2572 if (mParcelImage.fence != null) { 2573 try { 2574 mParcelImage.fence.close(); 2575 } catch (IOException e) { 2576 e.printStackTrace(); 2577 } 2578 mParcelImage.fence = null; 2579 } 2580 } 2581 } 2582 2583 private static CameraOutputConfig getCameraOutputConfig(Camera2OutputConfigImpl output) { 2584 CameraOutputConfig ret = new CameraOutputConfig(); 2585 if (Flags.extension10Bit() && EFV_SUPPORTED) { 2586 ret.dynamicRangeProfile = output.getDynamicRangeProfile(); 2587 } else { 2588 ret.dynamicRangeProfile = DynamicRangeProfiles.STANDARD; 2589 } 2590 ret.outputId = new OutputConfigId(); 2591 ret.outputId.id = output.getId(); 2592 ret.physicalCameraId = output.getPhysicalCameraId(); 2593 ret.surfaceGroupId = output.getSurfaceGroupId(); 2594 ret.isMultiResolutionOutput = false; 2595 if (output instanceof SurfaceOutputConfigImpl) { 2596 SurfaceOutputConfigImpl surfaceConfig = (SurfaceOutputConfigImpl) output; 2597 ret.type = CameraOutputConfig.TYPE_SURFACE; 2598 ret.surface = surfaceConfig.getSurface(); 2599 } else if (output instanceof ImageReaderOutputConfigImpl) { 2600 ImageReaderOutputConfigImpl imageReaderOutputConfig = 2601 (ImageReaderOutputConfigImpl) output; 2602 ret.type = CameraOutputConfig.TYPE_IMAGEREADER; 2603 ret.size = new android.hardware.camera2.extension.Size(); 2604 ret.size.width = imageReaderOutputConfig.getSize().getWidth(); 2605 ret.size.height = imageReaderOutputConfig.getSize().getHeight(); 2606 ret.imageFormat = imageReaderOutputConfig.getImageFormat(); 2607 ret.capacity = imageReaderOutputConfig.getMaxImages(); 2608 if (EFV_SUPPORTED) { 2609 ret.usage = imageReaderOutputConfig.getUsage(); 2610 } else { 2611 ret.usage = 0; 2612 } 2613 } else if (output instanceof MultiResolutionImageReaderOutputConfigImpl) { 2614 MultiResolutionImageReaderOutputConfigImpl multiResReaderConfig = 2615 (MultiResolutionImageReaderOutputConfigImpl) output; 2616 ret.type = CameraOutputConfig.TYPE_MULTIRES_IMAGEREADER; 2617 ret.imageFormat = multiResReaderConfig.getImageFormat(); 2618 ret.capacity = multiResReaderConfig.getMaxImages(); 2619 ret.isMultiResolutionOutput = true; 2620 } else { 2621 throw new IllegalStateException("Unknown output config type!"); 2622 } 2623 2624 return ret; 2625 } 2626 } 2627