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.Camera; 23 import android.graphics.GraphicBuffer; 24 import android.graphics.Rect; 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.extension.CameraOutputConfig; 32 import android.hardware.camera2.extension.CameraSessionConfig; 33 import android.hardware.camera2.extension.CaptureBundle; 34 import android.hardware.camera2.extension.CaptureFailure; 35 import android.hardware.camera2.extension.CaptureStageImpl; 36 import android.hardware.camera2.extension.IAdvancedExtenderImpl; 37 import android.hardware.camera2.extension.ICameraExtensionsProxyService; 38 import android.hardware.camera2.extension.ICaptureCallback; 39 import android.hardware.camera2.extension.ICaptureProcessorImpl; 40 import android.hardware.camera2.extension.IPreviewExtenderImpl; 41 import android.hardware.camera2.extension.IPreviewImageProcessorImpl; 42 import android.hardware.camera2.extension.IRequestCallback; 43 import android.hardware.camera2.extension.IRequestProcessorImpl; 44 import android.hardware.camera2.extension.IRequestUpdateProcessorImpl; 45 import android.hardware.camera2.extension.IImageCaptureExtenderImpl; 46 import android.hardware.camera2.extension.IImageProcessorImpl; 47 import android.hardware.camera2.extension.IInitializeSessionCallback; 48 import android.hardware.camera2.extension.ISessionProcessorImpl; 49 import android.hardware.camera2.extension.LatencyRange; 50 import android.hardware.camera2.extension.OutputConfigId; 51 import android.hardware.camera2.extension.OutputSurface; 52 import android.hardware.camera2.extension.ParcelCaptureResult; 53 import android.hardware.camera2.extension.ParcelImage; 54 import android.hardware.camera2.extension.ParcelTotalCaptureResult; 55 import android.hardware.camera2.extension.Request; 56 import android.hardware.camera2.extension.SizeList; 57 import android.hardware.camera2.impl.CameraMetadataNative; 58 import android.hardware.camera2.TotalCaptureResult; 59 import android.hardware.HardwareBuffer; 60 import android.hardware.camera2.impl.PhysicalCaptureResultInfo; 61 import android.media.Image; 62 import android.media.ImageReader; 63 import android.os.Binder; 64 import android.os.ConditionVariable; 65 import android.os.Handler; 66 import android.os.HandlerExecutor; 67 import android.os.HandlerThread; 68 import android.os.IBinder; 69 import android.os.RemoteException; 70 import android.util.ArraySet; 71 import android.util.Log; 72 import android.util.Pair; 73 import android.util.Range; 74 import android.util.Size; 75 import android.view.Surface; 76 77 import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl; 78 import androidx.camera.extensions.impl.AutoPreviewExtenderImpl; 79 import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl; 80 import androidx.camera.extensions.impl.BeautyPreviewExtenderImpl; 81 import androidx.camera.extensions.impl.BokehImageCaptureExtenderImpl; 82 import androidx.camera.extensions.impl.BokehPreviewExtenderImpl; 83 import androidx.camera.extensions.impl.CaptureProcessorImpl; 84 import androidx.camera.extensions.impl.ExtensionVersionImpl; 85 import androidx.camera.extensions.impl.HdrImageCaptureExtenderImpl; 86 import androidx.camera.extensions.impl.HdrPreviewExtenderImpl; 87 import androidx.camera.extensions.impl.ImageCaptureExtenderImpl; 88 import androidx.camera.extensions.impl.InitializerImpl; 89 import androidx.camera.extensions.impl.NightImageCaptureExtenderImpl; 90 import androidx.camera.extensions.impl.NightPreviewExtenderImpl; 91 import androidx.camera.extensions.impl.PreviewExtenderImpl; 92 import androidx.camera.extensions.impl.PreviewExtenderImpl.ProcessorType; 93 import androidx.camera.extensions.impl.PreviewImageProcessorImpl; 94 import androidx.camera.extensions.impl.RequestUpdateProcessorImpl; 95 import androidx.camera.extensions.impl.advanced.AdvancedExtenderImpl; 96 import androidx.camera.extensions.impl.advanced.AutoAdvancedExtenderImpl; 97 import androidx.camera.extensions.impl.advanced.BeautyAdvancedExtenderImpl; 98 import androidx.camera.extensions.impl.advanced.BokehAdvancedExtenderImpl; 99 import androidx.camera.extensions.impl.advanced.Camera2OutputConfigImpl; 100 import androidx.camera.extensions.impl.advanced.Camera2SessionConfigImpl; 101 import androidx.camera.extensions.impl.advanced.HdrAdvancedExtenderImpl; 102 import androidx.camera.extensions.impl.advanced.ImageProcessorImpl; 103 import androidx.camera.extensions.impl.advanced.ImageReaderOutputConfigImpl; 104 import androidx.camera.extensions.impl.advanced.MultiResolutionImageReaderOutputConfigImpl; 105 import androidx.camera.extensions.impl.advanced.NightAdvancedExtenderImpl; 106 import androidx.camera.extensions.impl.advanced.OutputSurfaceImpl; 107 import androidx.camera.extensions.impl.advanced.RequestProcessorImpl; 108 import androidx.camera.extensions.impl.advanced.SessionProcessorImpl; 109 import androidx.camera.extensions.impl.advanced.SurfaceOutputConfigImpl; 110 111 import java.io.IOException; 112 import java.util.ArrayList; 113 import java.util.HashMap; 114 import java.util.Map; 115 import java.util.concurrent.Future; 116 import java.util.concurrent.TimeUnit; 117 import java.util.concurrent.TimeoutException; 118 import java.util.List; 119 120 public class CameraExtensionsProxyService extends Service { 121 private static final String TAG = "CameraExtensionsProxyService"; 122 123 private static final String CAMERA_EXTENSION_VERSION_NAME = 124 "androidx.camera.extensions.impl.ExtensionVersionImpl"; 125 private static final String LATEST_VERSION = "1.2.0"; 126 private static final String NON_INIT_VERSION_PREFIX = "1.0"; 127 private static final String ADVANCED_VERSION_PREFIX = "1.2"; 128 private static final String[] SUPPORTED_VERSION_PREFIXES = {ADVANCED_VERSION_PREFIX, 129 "1.1", NON_INIT_VERSION_PREFIX}; 130 private static final boolean EXTENSIONS_PRESENT = checkForExtensions(); 131 private static final String EXTENSIONS_VERSION = EXTENSIONS_PRESENT ? 132 (new ExtensionVersionImpl()).checkApiVersion(LATEST_VERSION) : null; 133 private static final boolean ADVANCED_API_SUPPORTED = checkForAdvancedAPI(); 134 private static final boolean INIT_API_SUPPORTED = EXTENSIONS_PRESENT && 135 (!EXTENSIONS_VERSION.startsWith(NON_INIT_VERSION_PREFIX)); 136 137 private HashMap<String, CameraCharacteristics> mCharacteristicsHashMap = new HashMap<>(); 138 private HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>(); 139 private CameraManager mCameraManager; 140 checkForAdvancedAPI()141 private static boolean checkForAdvancedAPI() { 142 if (EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) { 143 try { 144 return (new ExtensionVersionImpl()).isAdvancedExtenderImplemented(); 145 } catch (NoSuchMethodError e) { 146 // This could happen in case device specific extension implementations are using an 147 // older extension API but incorrectly set the extension version. 148 } 149 } 150 151 return false; 152 } 153 checkForExtensions()154 private static boolean checkForExtensions() { 155 try { 156 Class.forName(CAMERA_EXTENSION_VERSION_NAME); 157 } catch (ClassNotFoundException e) { 158 return false; 159 } 160 161 String extensionVersion = (new ExtensionVersionImpl()).checkApiVersion(LATEST_VERSION); 162 for (String supportedVersion : SUPPORTED_VERSION_PREFIXES) { 163 if (extensionVersion.startsWith(supportedVersion)) { 164 return true; 165 } 166 } 167 168 return false; 169 } 170 171 /** 172 * A per-process global camera extension manager instance, to track and 173 * initialize/release extensions depending on client activity. 174 */ 175 private static final class CameraExtensionManagerGlobal { 176 private static final String TAG = "CameraExtensionManagerGlobal"; 177 private final int EXTENSION_DELAY_MS = 1000; 178 179 private final Handler mHandler; 180 private final HandlerThread mHandlerThread; 181 private final Object mLock = new Object(); 182 183 private long mCurrentClientCount = 0; 184 private ArraySet<Long> mActiveClients = new ArraySet<>(); 185 private IInitializeSessionCallback mInitializeCb = null; 186 187 // Singleton instance 188 private static final CameraExtensionManagerGlobal GLOBAL_CAMERA_MANAGER = 189 new CameraExtensionManagerGlobal(); 190 191 // Singleton, don't allow construction CameraExtensionManagerGlobal()192 private CameraExtensionManagerGlobal() { 193 mHandlerThread = new HandlerThread(TAG); 194 mHandlerThread.start(); 195 mHandler = new Handler(mHandlerThread.getLooper()); 196 } 197 198 private final static class InitializeHandler 199 implements InitializerImpl.OnExtensionsInitializedCallback { 200 private final InitializerFuture mStatusFuture; 201 InitializeHandler(InitializerFuture statusFuture)202 public InitializeHandler(InitializerFuture statusFuture) { 203 mStatusFuture = statusFuture; 204 } 205 206 @Override onSuccess()207 public void onSuccess() { 208 mStatusFuture.setStatus(true); 209 } 210 211 @Override onFailure(int error)212 public void onFailure(int error) { 213 mStatusFuture.setStatus(false); 214 } 215 } 216 217 private final static class ReleaseHandler 218 implements InitializerImpl.OnExtensionsDeinitializedCallback { 219 private final InitializerFuture mStatusFuture; 220 ReleaseHandler(InitializerFuture statusFuture)221 public ReleaseHandler(InitializerFuture statusFuture) { 222 mStatusFuture = statusFuture; 223 } 224 onSuccess()225 @Override public void onSuccess() { 226 mStatusFuture.setStatus(true); 227 } 228 229 @Override onFailure(int i)230 public void onFailure(int i) { 231 mStatusFuture.setStatus(false); 232 } 233 } 234 235 private static class InitializerFuture implements Future<Boolean> { 236 private volatile Boolean mStatus; 237 ConditionVariable mCondVar = new ConditionVariable(/*opened*/false); 238 setStatus(boolean status)239 public void setStatus(boolean status) { 240 mStatus = status; 241 mCondVar.open(); 242 } 243 244 @Override cancel(boolean mayInterruptIfRunning)245 public boolean cancel(boolean mayInterruptIfRunning) { 246 return false; // don't allow canceling this task 247 } 248 249 @Override isCancelled()250 public boolean isCancelled() { 251 return false; // can never cancel this task 252 } 253 254 @Override isDone()255 public boolean isDone() { 256 return mStatus != null; 257 } 258 259 @Override get()260 public Boolean get() { 261 mCondVar.block(); 262 return mStatus; 263 } 264 265 @Override get(long timeout, TimeUnit unit)266 public Boolean get(long timeout, TimeUnit unit) throws TimeoutException { 267 long timeoutMs = unit.convert(timeout, TimeUnit.MILLISECONDS); 268 if (!mCondVar.block(timeoutMs)) { 269 throw new TimeoutException( 270 "Failed to receive status after " + timeout + " " + unit); 271 } 272 273 if (mStatus == null) { 274 throw new AssertionError(); 275 } 276 return mStatus; 277 } 278 279 } 280 get()281 public static CameraExtensionManagerGlobal get() { 282 return GLOBAL_CAMERA_MANAGER; 283 } 284 registerClient(Context ctx)285 public long registerClient(Context ctx) { 286 synchronized (mLock) { 287 if (INIT_API_SUPPORTED) { 288 if (mActiveClients.isEmpty()) { 289 InitializerFuture status = new InitializerFuture(); 290 InitializerImpl.init(EXTENSIONS_VERSION, ctx, new InitializeHandler(status), 291 new HandlerExecutor(mHandler)); 292 boolean initSuccess; 293 try { 294 initSuccess = status.get(EXTENSION_DELAY_MS, 295 TimeUnit.MILLISECONDS); 296 } catch (TimeoutException e) { 297 Log.e(TAG, "Timed out while initializing camera extensions!"); 298 return -1; 299 } 300 if (!initSuccess) { 301 Log.e(TAG, "Failed while initializing camera extensions!"); 302 return -1; 303 } 304 } 305 } 306 307 long ret = mCurrentClientCount; 308 mCurrentClientCount++; 309 if (mCurrentClientCount < 0) { 310 mCurrentClientCount = 0; 311 } 312 mActiveClients.add(ret); 313 314 return ret; 315 } 316 } 317 unregisterClient(long clientId)318 public void unregisterClient(long clientId) { 319 synchronized (mLock) { 320 if (mActiveClients.remove(clientId) && mActiveClients.isEmpty() && 321 INIT_API_SUPPORTED) { 322 InitializerFuture status = new InitializerFuture(); 323 InitializerImpl.deinit(new ReleaseHandler(status), 324 new HandlerExecutor(mHandler)); 325 boolean releaseSuccess; 326 try { 327 releaseSuccess = status.get(EXTENSION_DELAY_MS, TimeUnit.MILLISECONDS); 328 } catch (TimeoutException e) { 329 Log.e(TAG, "Timed out while releasing camera extensions!"); 330 return; 331 } 332 if (!releaseSuccess) { 333 Log.e(TAG, "Failed while releasing camera extensions!"); 334 } 335 } 336 } 337 } 338 339 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { 340 @Override 341 public void binderDied() { 342 synchronized (mLock) { 343 mInitializeCb = null; 344 } 345 } 346 }; 347 initializeSession(IInitializeSessionCallback cb)348 public boolean initializeSession(IInitializeSessionCallback cb) { 349 synchronized (mLock) { 350 if (mInitializeCb == null) { 351 mInitializeCb = cb; 352 try { 353 mInitializeCb.asBinder().linkToDeath(mDeathRecipient, 0); 354 } catch (RemoteException e) { 355 e.printStackTrace(); 356 } 357 } else { 358 return false; 359 } 360 } 361 return true; 362 } 363 releaseSession()364 public void releaseSession() { 365 synchronized (mLock) { 366 if (mInitializeCb != null) { 367 mInitializeCb.asBinder().unlinkToDeath(mDeathRecipient, 0); 368 mInitializeCb = null; 369 } 370 } 371 } 372 } 373 374 /** 375 * @hide 376 */ registerClient(Context ctx)377 private static long registerClient(Context ctx) { 378 if (!EXTENSIONS_PRESENT) { 379 return -1; 380 } 381 return CameraExtensionManagerGlobal.get().registerClient(ctx); 382 } 383 384 /** 385 * @hide 386 */ unregisterClient(long clientId)387 public static void unregisterClient(long clientId) { 388 if (!EXTENSIONS_PRESENT) { 389 return; 390 } 391 CameraExtensionManagerGlobal.get().unregisterClient(clientId); 392 } 393 394 /** 395 * @hide 396 */ initializeSession(IInitializeSessionCallback cb)397 public static boolean initializeSession(IInitializeSessionCallback cb) { 398 if (!EXTENSIONS_PRESENT) { 399 return false; 400 } 401 return CameraExtensionManagerGlobal.get().initializeSession(cb); 402 } 403 404 /** 405 * @hide 406 */ releaseSession()407 public static void releaseSession() { 408 if (!EXTENSIONS_PRESENT) { 409 return; 410 } 411 CameraExtensionManagerGlobal.get().releaseSession(); 412 } 413 414 /** 415 * @hide 416 */ initializeExtension( int extensionType)417 public static Pair<PreviewExtenderImpl, ImageCaptureExtenderImpl> initializeExtension( 418 int extensionType) { 419 switch (extensionType) { 420 case CameraExtensionCharacteristics.EXTENSION_AUTOMATIC: 421 return new Pair<>(new AutoPreviewExtenderImpl(), 422 new AutoImageCaptureExtenderImpl()); 423 case CameraExtensionCharacteristics.EXTENSION_BEAUTY: 424 return new Pair<>(new BeautyPreviewExtenderImpl(), 425 new BeautyImageCaptureExtenderImpl()); 426 case CameraExtensionCharacteristics.EXTENSION_BOKEH: 427 return new Pair<>(new BokehPreviewExtenderImpl(), 428 new BokehImageCaptureExtenderImpl()); 429 case CameraExtensionCharacteristics.EXTENSION_HDR: 430 return new Pair<>(new HdrPreviewExtenderImpl(), new HdrImageCaptureExtenderImpl()); 431 case CameraExtensionCharacteristics.EXTENSION_NIGHT: 432 return new Pair<>(new NightPreviewExtenderImpl(), 433 new NightImageCaptureExtenderImpl()); 434 default: 435 throw new IllegalArgumentException("Unknown extension: " + extensionType); 436 } 437 } 438 439 /** 440 * @hide 441 */ initializeAdvancedExtensionImpl(int extensionType)442 public static AdvancedExtenderImpl initializeAdvancedExtensionImpl(int extensionType) { 443 switch (extensionType) { 444 case CameraExtensionCharacteristics.EXTENSION_AUTOMATIC: 445 return new AutoAdvancedExtenderImpl(); 446 case CameraExtensionCharacteristics.EXTENSION_BEAUTY: 447 return new BeautyAdvancedExtenderImpl(); 448 case CameraExtensionCharacteristics.EXTENSION_BOKEH: 449 return new BokehAdvancedExtenderImpl(); 450 case CameraExtensionCharacteristics.EXTENSION_HDR: 451 return new HdrAdvancedExtenderImpl(); 452 case CameraExtensionCharacteristics.EXTENSION_NIGHT: 453 return new NightAdvancedExtenderImpl(); 454 default: 455 throw new IllegalArgumentException("Unknown extension: " + extensionType); 456 } 457 } 458 459 @Override onCreate()460 public void onCreate() { 461 super.onCreate(); 462 // This will setup the camera vendor tag descriptor in the service process 463 // along with all camera characteristics. 464 try { 465 mCameraManager = getSystemService(CameraManager.class); 466 467 String [] cameraIds = mCameraManager.getCameraIdListNoLazy(); 468 if (cameraIds != null) { 469 for (String cameraId : cameraIds) { 470 CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId); 471 mCharacteristicsHashMap.put(cameraId, chars); 472 Object thisClass = CameraCharacteristics.Key.class; 473 Class<CameraCharacteristics.Key<?>> keyClass = 474 (Class<CameraCharacteristics.Key<?>>)thisClass; 475 ArrayList<CameraCharacteristics.Key<?>> vendorKeys = 476 chars.getNativeMetadata().getAllVendorKeys(keyClass); 477 if ((vendorKeys != null) && !vendorKeys.isEmpty()) { 478 mMetadataVendorIdMap.put(cameraId, vendorKeys.get(0).getVendorId()); 479 } 480 } 481 } 482 } catch (CameraAccessException e) { 483 Log.e(TAG, "Failed to query camera characteristics!"); 484 } 485 } 486 487 @Override onDestroy()488 public void onDestroy() { 489 super.onDestroy(); 490 } 491 492 493 @Override onBind(Intent intent)494 public IBinder onBind(Intent intent) { 495 return new CameraExtensionsProxyServiceStub(); 496 } 497 initializeParcelable( List<Pair<Integer, android.util.Size[]>> sizes)498 private static List<SizeList> initializeParcelable( 499 List<Pair<Integer, android.util.Size[]>> sizes) { 500 if (sizes == null) { 501 return null; 502 } 503 ArrayList<SizeList> ret = new ArrayList<>(sizes.size()); 504 for (Pair<Integer, Size[]> entry : sizes) { 505 SizeList sizeList = new SizeList(); 506 sizeList.format = entry.first; 507 sizeList.sizes = new ArrayList<>(); 508 for (android.util.Size size : entry.second) { 509 android.hardware.camera2.extension.Size sz = 510 new android.hardware.camera2.extension.Size(); 511 sz.width = size.getWidth(); 512 sz.height = size.getHeight(); 513 sizeList.sizes.add(sz); 514 } 515 } 516 517 return ret; 518 } 519 initializeParcelable( Map<Integer, List<android.util.Size>> sizes)520 private static List<SizeList> initializeParcelable( 521 Map<Integer, List<android.util.Size>> sizes) { 522 if (sizes == null) { 523 return null; 524 } 525 ArrayList<SizeList> ret = new ArrayList<>(sizes.size()); 526 for (Map.Entry<Integer, List<android.util.Size>> entry : sizes.entrySet()) { 527 SizeList sizeList = new SizeList(); 528 sizeList.format = entry.getKey(); 529 sizeList.sizes = new ArrayList<>(); 530 for (android.util.Size size : entry.getValue()) { 531 android.hardware.camera2.extension.Size sz = 532 new android.hardware.camera2.extension.Size(); 533 sz.width = size.getWidth(); 534 sz.height = size.getHeight(); 535 sizeList.sizes.add(sz); 536 } 537 ret.add(sizeList); 538 } 539 540 return ret; 541 } 542 initializeParcelableMetadata( List<Pair<CaptureRequest.Key, Object>> paramList, String cameraId)543 private CameraMetadataNative initializeParcelableMetadata( 544 List<Pair<CaptureRequest.Key, Object>> paramList, String cameraId) { 545 if (paramList == null) { 546 return null; 547 } 548 549 CameraMetadataNative ret = new CameraMetadataNative(); 550 if (mMetadataVendorIdMap.containsKey(cameraId)) { 551 ret.setVendorId(mMetadataVendorIdMap.get(cameraId)); 552 } 553 for (Pair<CaptureRequest.Key, Object> param : paramList) { 554 ret.set(param.first, param.second); 555 } 556 557 return ret; 558 } 559 initializeParcelableMetadata( Map<CaptureRequest.Key<?>, Object> paramMap, String cameraId)560 private CameraMetadataNative initializeParcelableMetadata( 561 Map<CaptureRequest.Key<?>, Object> paramMap, String cameraId) { 562 if (paramMap == null) { 563 return null; 564 } 565 566 CameraMetadataNative ret = new CameraMetadataNative(); 567 if (mMetadataVendorIdMap.containsKey(cameraId)) { 568 ret.setVendorId(mMetadataVendorIdMap.get(cameraId)); 569 } 570 for (Map.Entry<CaptureRequest.Key<?>, Object> param : paramMap.entrySet()) { 571 ret.set(((CaptureRequest.Key) param.getKey()), param.getValue()); 572 } 573 574 return ret; 575 } 576 initializeParcelable( androidx.camera.extensions.impl.CaptureStageImpl captureStage, String cameraId)577 private android.hardware.camera2.extension.CaptureStageImpl initializeParcelable( 578 androidx.camera.extensions.impl.CaptureStageImpl captureStage, String cameraId) { 579 if (captureStage == null) { 580 return null; 581 } 582 583 android.hardware.camera2.extension.CaptureStageImpl ret = 584 new android.hardware.camera2.extension.CaptureStageImpl(); 585 ret.id = captureStage.getId(); 586 ret.parameters = initializeParcelableMetadata(captureStage.getParameters(), cameraId); 587 588 return ret; 589 } 590 initializeParcelable(RequestProcessorImpl.Request request, int requestId, String cameraId)591 private Request initializeParcelable(RequestProcessorImpl.Request request, int requestId, 592 String cameraId) { 593 Request ret = new Request(); 594 ret.targetOutputConfigIds = new ArrayList<>(); 595 for (int id : request.getTargetOutputConfigIds()) { 596 OutputConfigId configId = new OutputConfigId(); 597 configId.id = id; 598 ret.targetOutputConfigIds.add(configId); 599 } 600 ret.templateId = request.getTemplateId(); 601 ret.parameters = initializeParcelableMetadata(request.getParameters(), cameraId); 602 ret.requestId = requestId; 603 return ret; 604 } 605 606 private class CameraExtensionsProxyServiceStub extends ICameraExtensionsProxyService.Stub { 607 @Override registerClient()608 public long registerClient() { 609 return CameraExtensionsProxyService.registerClient(CameraExtensionsProxyService.this); 610 } 611 612 @Override unregisterClient(long clientId)613 public void unregisterClient(long clientId) { 614 CameraExtensionsProxyService.unregisterClient(clientId); 615 } 616 checkCameraPermission()617 private boolean checkCameraPermission() { 618 int allowed = CameraExtensionsProxyService.this.checkPermission( 619 android.Manifest.permission.CAMERA, Binder.getCallingPid(), 620 Binder.getCallingUid()); 621 return (PackageManager.PERMISSION_GRANTED == allowed); 622 } 623 624 @Override initializeSession(IInitializeSessionCallback cb)625 public void initializeSession(IInitializeSessionCallback cb) { 626 try { 627 if (!checkCameraPermission()) { 628 Log.i(TAG, "Camera permission required for initializing capture session"); 629 cb.onFailure(); 630 return; 631 } 632 633 if (CameraExtensionsProxyService.initializeSession(cb)) { 634 cb.onSuccess(); 635 } else { 636 cb.onFailure(); 637 } 638 } catch (RemoteException e) { 639 Log.e(TAG, "Client doesn't respond!"); 640 } 641 } 642 643 @Override releaseSession()644 public void releaseSession() { 645 if (checkCameraPermission()) { 646 CameraExtensionsProxyService.releaseSession(); 647 } 648 } 649 650 @Override advancedExtensionsSupported()651 public boolean advancedExtensionsSupported() { 652 return ADVANCED_API_SUPPORTED; 653 } 654 655 @Override initializeAdvancedExtension(int extensionType)656 public IAdvancedExtenderImpl initializeAdvancedExtension(int extensionType) { 657 AdvancedExtenderImpl extension; 658 try { 659 extension = initializeAdvancedExtensionImpl(extensionType); 660 } catch (IllegalArgumentException e) { 661 return null; 662 } 663 664 return new AdvancedExtenderImplStub(extension); 665 } 666 667 @Override initializePreviewExtension(int extensionType)668 public IPreviewExtenderImpl initializePreviewExtension(int extensionType) { 669 Pair<PreviewExtenderImpl, ImageCaptureExtenderImpl> extension; 670 try { 671 extension = initializeExtension(extensionType); 672 } catch (IllegalArgumentException e) { 673 return null; 674 } 675 676 return new PreviewExtenderImplStub(extension.first); 677 } 678 679 @Override initializeImageExtension(int extensionType)680 public IImageCaptureExtenderImpl initializeImageExtension(int extensionType) { 681 Pair<PreviewExtenderImpl, ImageCaptureExtenderImpl> extension; 682 try { 683 extension = initializeExtension(extensionType); 684 } catch (IllegalArgumentException e) { 685 return null; 686 } 687 688 return new ImageCaptureExtenderImplStub(extension.second); 689 } 690 } 691 692 private class AdvancedExtenderImplStub extends IAdvancedExtenderImpl.Stub { 693 private final AdvancedExtenderImpl mAdvancedExtender; 694 AdvancedExtenderImplStub(AdvancedExtenderImpl advancedExtender)695 public AdvancedExtenderImplStub(AdvancedExtenderImpl advancedExtender) { 696 mAdvancedExtender = advancedExtender; 697 } 698 699 @Override isExtensionAvailable(String cameraId)700 public boolean isExtensionAvailable(String cameraId) { 701 return mAdvancedExtender.isExtensionAvailable(cameraId, mCharacteristicsHashMap); 702 } 703 704 @Override init(String cameraId)705 public void init(String cameraId) { 706 mAdvancedExtender.init(cameraId, mCharacteristicsHashMap); 707 } 708 709 @Override getSupportedPreviewOutputResolutions(String cameraId)710 public List<SizeList> getSupportedPreviewOutputResolutions(String cameraId) { 711 Map<Integer, List<Size>> supportedSizesMap = 712 mAdvancedExtender.getSupportedPreviewOutputResolutions(cameraId); 713 if (supportedSizesMap != null) { 714 return initializeParcelable(supportedSizesMap); 715 } 716 717 return null; 718 } 719 720 @Override getSupportedCaptureOutputResolutions(String cameraId)721 public List<SizeList> getSupportedCaptureOutputResolutions(String cameraId) { 722 Map<Integer, List<Size>> supportedSizesMap = 723 mAdvancedExtender.getSupportedCaptureOutputResolutions(cameraId); 724 if (supportedSizesMap != null) { 725 return initializeParcelable(supportedSizesMap); 726 } 727 728 return null; 729 } 730 731 @Override getEstimatedCaptureLatencyRange(String cameraId, android.hardware.camera2.extension.Size outputSize, int format)732 public LatencyRange getEstimatedCaptureLatencyRange(String cameraId, 733 android.hardware.camera2.extension.Size outputSize, int format) { 734 Size sz = new Size(outputSize.width, outputSize.height); 735 Range<Long> latencyRange = mAdvancedExtender.getEstimatedCaptureLatencyRange(cameraId, 736 sz, format); 737 if (latencyRange != null) { 738 LatencyRange ret = new LatencyRange(); 739 ret.min = latencyRange.getLower(); 740 ret.max = latencyRange.getUpper(); 741 return ret; 742 } 743 744 return null; 745 } 746 747 @Override getSessionProcessor()748 public ISessionProcessorImpl getSessionProcessor() { 749 return new SessionProcessorImplStub(mAdvancedExtender.createSessionProcessor()); 750 } 751 } 752 753 private class CaptureCallbackStub implements SessionProcessorImpl.CaptureCallback { 754 private final ICaptureCallback mCaptureCallback; 755 CaptureCallbackStub(ICaptureCallback captureCallback)756 private CaptureCallbackStub(ICaptureCallback captureCallback) { 757 mCaptureCallback = captureCallback; 758 } 759 760 @Override onCaptureStarted(int captureSequenceId, long timestamp)761 public void onCaptureStarted(int captureSequenceId, long timestamp) { 762 if (mCaptureCallback != null) { 763 try { 764 mCaptureCallback.onCaptureStarted(captureSequenceId, timestamp); 765 } catch (RemoteException e) { 766 Log.e(TAG, "Failed to notify capture start due to remote " + 767 "exception!"); 768 } 769 } 770 } 771 772 @Override onCaptureProcessStarted(int captureSequenceId)773 public void onCaptureProcessStarted(int captureSequenceId) { 774 if (mCaptureCallback != null) { 775 try { 776 mCaptureCallback.onCaptureProcessStarted(captureSequenceId); 777 } catch (RemoteException e) { 778 Log.e(TAG, "Failed to notify capture process start due to remote " + 779 "exception!"); 780 } 781 } 782 } 783 784 @Override onCaptureFailed(int captureSequenceId)785 public void onCaptureFailed(int captureSequenceId) { 786 if (mCaptureCallback != null) { 787 try { 788 mCaptureCallback.onCaptureFailed(captureSequenceId); 789 } catch (RemoteException e) { 790 Log.e(TAG, "Failed to notify capture failure due to remote " + 791 "exception!"); 792 } 793 } 794 } 795 796 @Override onCaptureSequenceCompleted(int captureSequenceId)797 public void onCaptureSequenceCompleted(int captureSequenceId) { 798 if (mCaptureCallback != null) { 799 try { 800 mCaptureCallback.onCaptureSequenceCompleted(captureSequenceId); 801 } catch (RemoteException e) { 802 Log.e(TAG, "Failed to notify capture sequence end due to remote " + 803 "exception!"); 804 } 805 } 806 } 807 808 @Override onCaptureSequenceAborted(int captureSequenceId)809 public void onCaptureSequenceAborted(int captureSequenceId) { 810 if (mCaptureCallback != null) { 811 try { 812 mCaptureCallback.onCaptureSequenceAborted(captureSequenceId); 813 } catch (RemoteException e) { 814 Log.e(TAG, "Failed to notify capture sequence abort due to remote " + 815 "exception!"); 816 } 817 } 818 } 819 } 820 821 private class RequestCallbackStub extends IRequestCallback.Stub { 822 private final List<RequestProcessorImpl.Request> mRequests; 823 private final RequestProcessorImpl.Callback mCallback; 824 RequestCallbackStub(List<RequestProcessorImpl.Request> requests, RequestProcessorImpl.Callback callback)825 public RequestCallbackStub(List<RequestProcessorImpl.Request> requests, 826 RequestProcessorImpl.Callback callback) { 827 mCallback = callback; 828 if (mCallback != null) { 829 mRequests = requests; 830 } else { 831 Log.w(TAG, "No valid request callbacks!"); 832 mRequests = new ArrayList<>(); 833 } 834 } 835 836 @Override onCaptureStarted(int requestId, long frameNumber, long timestamp)837 public void onCaptureStarted(int requestId, long frameNumber, long timestamp) { 838 if (mCallback != null) { 839 if (mRequests.get(requestId) != null) { 840 mCallback.onCaptureStarted(mRequests.get(requestId), frameNumber, timestamp); 841 } else { 842 Log.e(TAG,"Request id: " + requestId + " not found!"); 843 } 844 } 845 } 846 847 @Override onCaptureProgressed(int requestId, ParcelCaptureResult partialResult)848 public void onCaptureProgressed(int requestId, ParcelCaptureResult partialResult) { 849 if (mCallback != null) { 850 if (mRequests.get(requestId) != null) { 851 CaptureResult result = new CaptureResult(partialResult.cameraId, 852 partialResult.results, partialResult.parent, partialResult.sequenceId, 853 partialResult.frameNumber); 854 mCallback.onCaptureProgressed(mRequests.get(requestId), result); 855 } else { 856 Log.e(TAG,"Request id: " + requestId + " not found!"); 857 } 858 } 859 } 860 861 @Override onCaptureCompleted(int requestId, ParcelTotalCaptureResult totalCaptureResult)862 public void onCaptureCompleted(int requestId, ParcelTotalCaptureResult totalCaptureResult) { 863 if (mCallback != null) { 864 if (mRequests.get(requestId) != null) { 865 PhysicalCaptureResultInfo[] physicalResults = new PhysicalCaptureResultInfo[0]; 866 if ((totalCaptureResult.physicalResult != null) && 867 (!totalCaptureResult.physicalResult.isEmpty())) { 868 int count = totalCaptureResult.physicalResult.size(); 869 physicalResults = new PhysicalCaptureResultInfo[count]; 870 physicalResults = totalCaptureResult.physicalResult.toArray( 871 physicalResults); 872 } 873 ArrayList<CaptureResult> partials = new ArrayList<>( 874 totalCaptureResult.partials.size()); 875 for (ParcelCaptureResult parcelResult : totalCaptureResult.partials) { 876 partials.add(new CaptureResult(parcelResult.cameraId, parcelResult.results, 877 parcelResult.parent, parcelResult.sequenceId, 878 parcelResult.frameNumber)); 879 } 880 TotalCaptureResult result = new TotalCaptureResult( 881 totalCaptureResult.logicalCameraId, totalCaptureResult.results, 882 totalCaptureResult.parent, totalCaptureResult.sequenceId, 883 totalCaptureResult.frameNumber, partials, totalCaptureResult.sessionId, 884 physicalResults); 885 mCallback.onCaptureCompleted(mRequests.get(requestId), result); 886 } else { 887 Log.e(TAG,"Request id: " + requestId + " not found!"); 888 } 889 } 890 } 891 892 @Override onCaptureFailed(int requestId, CaptureFailure captureFailure)893 public void onCaptureFailed(int requestId, CaptureFailure captureFailure) { 894 if (mCallback != null) { 895 if (mRequests.get(requestId) != null) { 896 android.hardware.camera2.CaptureFailure failure = 897 new android.hardware.camera2.CaptureFailure(captureFailure.request, 898 captureFailure.reason, captureFailure.dropped, 899 captureFailure.sequenceId, captureFailure.frameNumber, 900 captureFailure.errorPhysicalCameraId); 901 mCallback.onCaptureFailed(mRequests.get(requestId), failure); 902 } else { 903 Log.e(TAG,"Request id: " + requestId + " not found!"); 904 } 905 } 906 } 907 908 @Override onCaptureBufferLost(int requestId, long frameNumber, int outputStreamId)909 public void onCaptureBufferLost(int requestId, long frameNumber, int outputStreamId) { 910 if (mCallback != null) { 911 if (mRequests.get(requestId) != null) { 912 mCallback.onCaptureBufferLost(mRequests.get(requestId), frameNumber, 913 outputStreamId); 914 } else { 915 Log.e(TAG,"Request id: " + requestId + " not found!"); 916 } 917 } 918 } 919 920 @Override onCaptureSequenceCompleted(int sequenceId, long frameNumber)921 public void onCaptureSequenceCompleted(int sequenceId, long frameNumber) { 922 if (mCallback != null) { 923 mCallback.onCaptureSequenceCompleted(sequenceId, frameNumber); 924 } 925 } 926 927 @Override onCaptureSequenceAborted(int sequenceId)928 public void onCaptureSequenceAborted(int sequenceId) { 929 if (mCallback != null) { 930 mCallback.onCaptureSequenceAborted(sequenceId); 931 } 932 } 933 } 934 935 private class ImageProcessorImplStub extends IImageProcessorImpl.Stub { 936 private final ImageProcessorImpl mImageProcessor; 937 ImageProcessorImplStub(ImageProcessorImpl imageProcessor)938 public ImageProcessorImplStub(ImageProcessorImpl imageProcessor) { 939 mImageProcessor = imageProcessor; 940 } 941 942 @Override onNextImageAvailable(OutputConfigId outputConfigId, ParcelImage img, String physicalCameraId)943 public void onNextImageAvailable(OutputConfigId outputConfigId, ParcelImage img, 944 String physicalCameraId) { 945 if (mImageProcessor != null) { 946 mImageProcessor.onNextImageAvailable(outputConfigId.id, img.timestamp, 947 new ImageReferenceImpl(img), physicalCameraId); 948 } 949 } 950 } 951 952 private class RequestProcessorStub implements RequestProcessorImpl { 953 private final IRequestProcessorImpl mRequestProcessor; 954 private final String mCameraId; 955 RequestProcessorStub(IRequestProcessorImpl requestProcessor, String cameraId)956 public RequestProcessorStub(IRequestProcessorImpl requestProcessor, String cameraId) { 957 mRequestProcessor = requestProcessor; 958 mCameraId = cameraId; 959 } 960 961 @Override setImageProcessor(int outputConfigId, ImageProcessorImpl imageProcessor)962 public void setImageProcessor(int outputConfigId, 963 ImageProcessorImpl imageProcessor) { 964 OutputConfigId configId = new OutputConfigId(); 965 configId.id = outputConfigId; 966 try { 967 mRequestProcessor.setImageProcessor(configId, 968 new ImageProcessorImplStub(imageProcessor)); 969 } catch (RemoteException e) { 970 Log.e(TAG, "Failed to set image processor due to remote exception!"); 971 } 972 } 973 974 @Override submit(Request request, Callback callback)975 public int submit(Request request, Callback callback) { 976 ArrayList<Request> requests = new ArrayList<>(); 977 requests.add(request); 978 return submit(requests, callback); 979 } 980 981 @Override submit(List<Request> requests, Callback callback)982 public int submit(List<Request> requests, Callback callback) { 983 ArrayList<android.hardware.camera2.extension.Request> captureRequests = 984 new ArrayList<>(); 985 int requestId = 0; 986 for (Request request : requests) { 987 captureRequests.add(initializeParcelable(request, requestId, mCameraId)); 988 requestId++; 989 } 990 991 try { 992 return mRequestProcessor.submitBurst(captureRequests, 993 new RequestCallbackStub(requests, callback)); 994 } catch (RemoteException e) { 995 Log.e(TAG, "Failed to submit request due to remote exception!"); 996 } 997 return -1; 998 } 999 1000 @Override setRepeating(Request request, Callback callback)1001 public int setRepeating(Request request, Callback callback) { 1002 try { 1003 ArrayList<Request> requests = new ArrayList<>(); 1004 requests.add(request); 1005 return mRequestProcessor.setRepeating( 1006 initializeParcelable(request, 0, mCameraId), 1007 new RequestCallbackStub(requests, callback)); 1008 } catch (RemoteException e) { 1009 Log.e(TAG, "Failed to submit repeating request due to remote exception!"); 1010 } 1011 1012 return -1; 1013 } 1014 1015 @Override abortCaptures()1016 public void abortCaptures() { 1017 try { 1018 mRequestProcessor.abortCaptures(); 1019 } catch (RemoteException e) { 1020 Log.e(TAG, "Failed to abort requests due to remote exception!"); 1021 } 1022 } 1023 1024 @Override stopRepeating()1025 public void stopRepeating() { 1026 try { 1027 mRequestProcessor.stopRepeating(); 1028 } catch (RemoteException e) { 1029 Log.e(TAG, "Failed to stop repeating request due to remote exception!"); 1030 } 1031 } 1032 } 1033 1034 private class SessionProcessorImplStub extends ISessionProcessorImpl.Stub { 1035 private final SessionProcessorImpl mSessionProcessor; 1036 private String mCameraId = null; 1037 SessionProcessorImplStub(SessionProcessorImpl sessionProcessor)1038 public SessionProcessorImplStub(SessionProcessorImpl sessionProcessor) { 1039 mSessionProcessor = sessionProcessor; 1040 } 1041 1042 @Override initSession(String cameraId, OutputSurface previewSurface, OutputSurface burstSurface)1043 public CameraSessionConfig initSession(String cameraId, OutputSurface previewSurface, 1044 OutputSurface burstSurface) { 1045 OutputSurfaceImplStub outputPreviewSurfaceImpl = 1046 new OutputSurfaceImplStub(previewSurface); 1047 OutputSurfaceImplStub outputBurstSurfaceImpl = 1048 new OutputSurfaceImplStub(burstSurface); 1049 1050 Camera2SessionConfigImpl sessionConfig = mSessionProcessor.initSession(cameraId, 1051 mCharacteristicsHashMap, getApplicationContext(), outputPreviewSurfaceImpl, 1052 outputBurstSurfaceImpl, null /*imageAnalysisSurfaceConfig*/); 1053 1054 List<Camera2OutputConfigImpl> outputConfigs = sessionConfig.getOutputConfigs(); 1055 CameraSessionConfig ret = new CameraSessionConfig(); 1056 ret.outputConfigs = new ArrayList<>(); 1057 for (Camera2OutputConfigImpl output : outputConfigs) { 1058 CameraOutputConfig entry = new CameraOutputConfig(); 1059 entry.outputId = new OutputConfigId(); 1060 entry.outputId.id = output.getId(); 1061 entry.physicalCameraId = output.getPhysicalCameraId(); 1062 entry.surfaceGroupId = output.getSurfaceGroupId(); 1063 if (output instanceof SurfaceOutputConfigImpl) { 1064 SurfaceOutputConfigImpl surfaceConfig = (SurfaceOutputConfigImpl) output; 1065 entry.type = CameraOutputConfig.TYPE_SURFACE; 1066 entry.surface = surfaceConfig.getSurface(); 1067 } else if (output instanceof ImageReaderOutputConfigImpl) { 1068 ImageReaderOutputConfigImpl imageReaderOutputConfig = 1069 (ImageReaderOutputConfigImpl) output; 1070 entry.type = CameraOutputConfig.TYPE_IMAGEREADER; 1071 entry.size = new android.hardware.camera2.extension.Size(); 1072 entry.size.width = imageReaderOutputConfig.getSize().getWidth(); 1073 entry.size.height = imageReaderOutputConfig.getSize().getHeight(); 1074 entry.imageFormat = imageReaderOutputConfig.getImageFormat(); 1075 entry.capacity = imageReaderOutputConfig.getMaxImages(); 1076 } else if (output instanceof MultiResolutionImageReaderOutputConfigImpl) { 1077 MultiResolutionImageReaderOutputConfigImpl multiResReaderConfig = 1078 (MultiResolutionImageReaderOutputConfigImpl) output; 1079 entry.type = CameraOutputConfig.TYPE_MULTIRES_IMAGEREADER; 1080 entry.imageFormat = multiResReaderConfig.getImageFormat(); 1081 entry.capacity = multiResReaderConfig.getMaxImages(); 1082 } else { 1083 throw new IllegalStateException("Unknown output config type!"); 1084 } 1085 List<Camera2OutputConfigImpl> sharedOutputs = 1086 output.getSurfaceSharingOutputConfigs(); 1087 if ((sharedOutputs != null) && (!sharedOutputs.isEmpty())) { 1088 entry.surfaceSharingOutputConfigs = new ArrayList<>(); 1089 for (Camera2OutputConfigImpl sharedOutput : sharedOutputs) { 1090 OutputConfigId outputId = new OutputConfigId(); 1091 outputId.id = sharedOutput.getId(); 1092 entry.surfaceSharingOutputConfigs.add(outputId); 1093 } 1094 } 1095 ret.outputConfigs.add(entry); 1096 } 1097 ret.sessionTemplateId = sessionConfig.getSessionTemplateId(); 1098 ret.sessionParameter = initializeParcelableMetadata( 1099 sessionConfig.getSessionParameters(), cameraId); 1100 mCameraId = cameraId; 1101 1102 return ret; 1103 } 1104 1105 @Override deInitSession()1106 public void deInitSession() { 1107 mSessionProcessor.deInitSession(); 1108 } 1109 1110 @Override onCaptureSessionStart(IRequestProcessorImpl requestProcessor)1111 public void onCaptureSessionStart(IRequestProcessorImpl requestProcessor) { 1112 mSessionProcessor.onCaptureSessionStart( 1113 new RequestProcessorStub(requestProcessor, mCameraId)); 1114 } 1115 1116 @Override onCaptureSessionEnd()1117 public void onCaptureSessionEnd() { 1118 mSessionProcessor.onCaptureSessionEnd(); 1119 } 1120 1121 @Override startRepeating(ICaptureCallback callback)1122 public int startRepeating(ICaptureCallback callback) { 1123 return mSessionProcessor.startRepeating(new CaptureCallbackStub(callback)); 1124 } 1125 1126 @Override stopRepeating()1127 public void stopRepeating() { 1128 mSessionProcessor.stopRepeating(); 1129 } 1130 1131 @Override startCapture(ICaptureCallback callback, int jpegRotation, int jpegQuality)1132 public int startCapture(ICaptureCallback callback, int jpegRotation, int jpegQuality) { 1133 HashMap<CaptureRequest.Key<?>, Object> paramMap = new HashMap<>(); 1134 paramMap.put(CaptureRequest.JPEG_ORIENTATION, jpegRotation); 1135 paramMap.put(CaptureRequest.JPEG_QUALITY, jpegQuality); 1136 mSessionProcessor.setParameters(paramMap); 1137 return mSessionProcessor.startCapture(new CaptureCallbackStub(callback)); 1138 } 1139 } 1140 1141 private class OutputSurfaceImplStub implements OutputSurfaceImpl { 1142 private final Surface mSurface; 1143 private final Size mSize; 1144 private final int mImageFormat; 1145 OutputSurfaceImplStub(OutputSurface outputSurface)1146 public OutputSurfaceImplStub(OutputSurface outputSurface) { 1147 mSurface = outputSurface.surface; 1148 mSize = new Size(outputSurface.size.width, outputSurface.size.height); 1149 mImageFormat = outputSurface.imageFormat; 1150 } 1151 1152 @Override getSurface()1153 public Surface getSurface() { 1154 return mSurface; 1155 } 1156 1157 @Override getSize()1158 public Size getSize() { 1159 return mSize; 1160 } 1161 1162 @Override getImageFormat()1163 public int getImageFormat() { 1164 return mImageFormat; 1165 } 1166 } 1167 1168 private class PreviewExtenderImplStub extends IPreviewExtenderImpl.Stub { 1169 private final PreviewExtenderImpl mPreviewExtender; 1170 private String mCameraId = null; 1171 PreviewExtenderImplStub(PreviewExtenderImpl previewExtender)1172 public PreviewExtenderImplStub(PreviewExtenderImpl previewExtender) { 1173 mPreviewExtender = previewExtender; 1174 } 1175 1176 @Override onInit(String cameraId, CameraMetadataNative cameraCharacteristics)1177 public void onInit(String cameraId, CameraMetadataNative cameraCharacteristics) { 1178 mCameraId = cameraId; 1179 CameraCharacteristics chars = new CameraCharacteristics(cameraCharacteristics); 1180 mCameraManager.registerDeviceStateListener(chars); 1181 mPreviewExtender.onInit(cameraId, chars, CameraExtensionsProxyService.this); 1182 } 1183 1184 @Override onDeInit()1185 public void onDeInit() { 1186 mPreviewExtender.onDeInit(); 1187 } 1188 1189 @Override onPresetSession()1190 public CaptureStageImpl onPresetSession() { 1191 return initializeParcelable(mPreviewExtender.onPresetSession(), mCameraId); 1192 } 1193 1194 @Override onEnableSession()1195 public CaptureStageImpl onEnableSession() { 1196 return initializeParcelable(mPreviewExtender.onEnableSession(), mCameraId); 1197 } 1198 1199 @Override onDisableSession()1200 public CaptureStageImpl onDisableSession() { 1201 return initializeParcelable(mPreviewExtender.onDisableSession(), mCameraId); 1202 } 1203 1204 @Override init(String cameraId, CameraMetadataNative chars)1205 public void init(String cameraId, CameraMetadataNative chars) { 1206 CameraCharacteristics c = new CameraCharacteristics(chars); 1207 mCameraManager.registerDeviceStateListener(c); 1208 mPreviewExtender.init(cameraId, c); 1209 } 1210 1211 @Override isExtensionAvailable(String cameraId, CameraMetadataNative chars)1212 public boolean isExtensionAvailable(String cameraId, CameraMetadataNative chars) { 1213 CameraCharacteristics c = new CameraCharacteristics(chars); 1214 mCameraManager.registerDeviceStateListener(c); 1215 return mPreviewExtender.isExtensionAvailable(cameraId, c); 1216 } 1217 1218 @Override getCaptureStage()1219 public CaptureStageImpl getCaptureStage() { 1220 return initializeParcelable(mPreviewExtender.getCaptureStage(), mCameraId); 1221 } 1222 1223 @Override getProcessorType()1224 public int getProcessorType() { 1225 ProcessorType processorType = mPreviewExtender.getProcessorType(); 1226 if (processorType == ProcessorType.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY) { 1227 return IPreviewExtenderImpl.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY; 1228 } else if (processorType == ProcessorType.PROCESSOR_TYPE_IMAGE_PROCESSOR) { 1229 return IPreviewExtenderImpl.PROCESSOR_TYPE_IMAGE_PROCESSOR; 1230 } else { 1231 return IPreviewExtenderImpl.PROCESSOR_TYPE_NONE; 1232 } 1233 } 1234 1235 @Override getPreviewImageProcessor()1236 public IPreviewImageProcessorImpl getPreviewImageProcessor() { 1237 PreviewImageProcessorImpl processor; 1238 try { 1239 processor = (PreviewImageProcessorImpl) mPreviewExtender.getProcessor(); 1240 } catch (ClassCastException e) { 1241 Log.e(TAG, "Failed casting preview processor!"); 1242 return null; 1243 } 1244 1245 if (processor != null) { 1246 return new PreviewImageProcessorImplStub(processor); 1247 } 1248 1249 return null; 1250 } 1251 1252 @Override getRequestUpdateProcessor()1253 public IRequestUpdateProcessorImpl getRequestUpdateProcessor() { 1254 RequestUpdateProcessorImpl processor; 1255 try { 1256 processor = (RequestUpdateProcessorImpl) mPreviewExtender.getProcessor(); 1257 } catch (ClassCastException e) { 1258 Log.e(TAG, "Failed casting preview processor!"); 1259 return null; 1260 } 1261 1262 if (processor != null) { 1263 return new RequestUpdateProcessorImplStub(processor, mCameraId); 1264 } 1265 1266 return null; 1267 } 1268 1269 @Override getSupportedResolutions()1270 public List<SizeList> getSupportedResolutions() { 1271 if (INIT_API_SUPPORTED) { 1272 List<Pair<Integer, android.util.Size[]>> sizes = 1273 mPreviewExtender.getSupportedResolutions(); 1274 if ((sizes != null) && !sizes.isEmpty()) { 1275 return initializeParcelable(sizes); 1276 } 1277 } 1278 return null; 1279 } 1280 } 1281 1282 private class ImageCaptureExtenderImplStub extends IImageCaptureExtenderImpl.Stub { 1283 private final ImageCaptureExtenderImpl mImageExtender; 1284 private String mCameraId = null; 1285 ImageCaptureExtenderImplStub(ImageCaptureExtenderImpl imageExtender)1286 public ImageCaptureExtenderImplStub(ImageCaptureExtenderImpl imageExtender) { 1287 mImageExtender = imageExtender; 1288 } 1289 1290 @Override onInit(String cameraId, CameraMetadataNative cameraCharacteristics)1291 public void onInit(String cameraId, CameraMetadataNative cameraCharacteristics) { 1292 CameraCharacteristics chars = new CameraCharacteristics(cameraCharacteristics); 1293 mCameraManager.registerDeviceStateListener(chars); 1294 mImageExtender.onInit(cameraId, chars, CameraExtensionsProxyService.this); 1295 mCameraId = cameraId; 1296 } 1297 1298 @Override onDeInit()1299 public void onDeInit() { 1300 mImageExtender.onDeInit(); 1301 } 1302 1303 @Override onPresetSession()1304 public CaptureStageImpl onPresetSession() { 1305 return initializeParcelable(mImageExtender.onPresetSession(), mCameraId); 1306 } 1307 1308 @Override onEnableSession()1309 public CaptureStageImpl onEnableSession() { 1310 return initializeParcelable(mImageExtender.onEnableSession(), mCameraId); 1311 } 1312 1313 @Override onDisableSession()1314 public CaptureStageImpl onDisableSession() { 1315 return initializeParcelable(mImageExtender.onDisableSession(), mCameraId); 1316 } 1317 1318 @Override init(String cameraId, CameraMetadataNative chars)1319 public void init(String cameraId, CameraMetadataNative chars) { 1320 CameraCharacteristics c = new CameraCharacteristics(chars); 1321 mCameraManager.registerDeviceStateListener(c); 1322 mImageExtender.init(cameraId, c); 1323 } 1324 1325 @Override isExtensionAvailable(String cameraId, CameraMetadataNative chars)1326 public boolean isExtensionAvailable(String cameraId, CameraMetadataNative chars) { 1327 CameraCharacteristics c = new CameraCharacteristics(chars); 1328 mCameraManager.registerDeviceStateListener(c); 1329 return mImageExtender.isExtensionAvailable(cameraId, c); 1330 } 1331 1332 @Override getCaptureProcessor()1333 public ICaptureProcessorImpl getCaptureProcessor() { 1334 CaptureProcessorImpl captureProcessor = mImageExtender.getCaptureProcessor(); 1335 if (captureProcessor != null) { 1336 return new CaptureProcessorImplStub(captureProcessor); 1337 } 1338 1339 return null; 1340 } 1341 1342 1343 @Override getCaptureStages()1344 public List<CaptureStageImpl> getCaptureStages() { 1345 List<androidx.camera.extensions.impl.CaptureStageImpl> captureStages = 1346 mImageExtender.getCaptureStages(); 1347 if (captureStages != null) { 1348 ArrayList<android.hardware.camera2.extension.CaptureStageImpl> ret = 1349 new ArrayList<>(); 1350 for (androidx.camera.extensions.impl.CaptureStageImpl stage : captureStages) { 1351 ret.add(initializeParcelable(stage, mCameraId)); 1352 } 1353 1354 return ret; 1355 } 1356 1357 return null; 1358 } 1359 1360 @Override getMaxCaptureStage()1361 public int getMaxCaptureStage() { 1362 return mImageExtender.getMaxCaptureStage(); 1363 } 1364 1365 @Override getSupportedResolutions()1366 public List<SizeList> getSupportedResolutions() { 1367 if (INIT_API_SUPPORTED) { 1368 List<Pair<Integer, android.util.Size[]>> sizes = 1369 mImageExtender.getSupportedResolutions(); 1370 if ((sizes != null) && !sizes.isEmpty()) { 1371 return initializeParcelable(sizes); 1372 } 1373 } 1374 1375 return null; 1376 } 1377 1378 @Override getEstimatedCaptureLatencyRange( android.hardware.camera2.extension.Size outputSize)1379 public LatencyRange getEstimatedCaptureLatencyRange( 1380 android.hardware.camera2.extension.Size outputSize) { 1381 if (EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) { 1382 Size sz = new Size(outputSize.width, outputSize.height); 1383 Range<Long> latencyRange = mImageExtender.getEstimatedCaptureLatencyRange(sz); 1384 if (latencyRange != null) { 1385 LatencyRange ret = new LatencyRange(); 1386 ret.min = latencyRange.getLower(); 1387 ret.max = latencyRange.getUpper(); 1388 return ret; 1389 } 1390 } 1391 1392 return null; 1393 } 1394 } 1395 1396 private class CaptureProcessorImplStub extends ICaptureProcessorImpl.Stub { 1397 private final CaptureProcessorImpl mCaptureProcessor; 1398 CaptureProcessorImplStub(CaptureProcessorImpl captureProcessor)1399 public CaptureProcessorImplStub(CaptureProcessorImpl captureProcessor) { 1400 mCaptureProcessor = captureProcessor; 1401 } 1402 1403 @Override onOutputSurface(Surface surface, int imageFormat)1404 public void onOutputSurface(Surface surface, int imageFormat) { 1405 mCaptureProcessor.onOutputSurface(surface, imageFormat); 1406 } 1407 1408 @Override onResolutionUpdate(android.hardware.camera2.extension.Size size)1409 public void onResolutionUpdate(android.hardware.camera2.extension.Size size) { 1410 mCaptureProcessor.onResolutionUpdate(new android.util.Size(size.width, size.height)); 1411 } 1412 1413 @Override onImageFormatUpdate(int imageFormat)1414 public void onImageFormatUpdate(int imageFormat) { 1415 mCaptureProcessor.onImageFormatUpdate(imageFormat); 1416 } 1417 1418 @Override process(List<CaptureBundle> captureList)1419 public void process(List<CaptureBundle> captureList) { 1420 HashMap<Integer, Pair<Image, TotalCaptureResult>> captureMap = new HashMap<>(); 1421 for (CaptureBundle captureBundle : captureList) { 1422 captureMap.put(captureBundle.stage, new Pair<> ( 1423 new ExtensionImage(captureBundle.captureImage), 1424 new TotalCaptureResult(captureBundle.captureResult, 1425 captureBundle.sequenceId))); 1426 } 1427 if (!captureMap.isEmpty()) { 1428 mCaptureProcessor.process(captureMap); 1429 } else { 1430 Log.e(TAG, "Process request with absent capture stages!"); 1431 } 1432 } 1433 } 1434 1435 private class PreviewImageProcessorImplStub extends IPreviewImageProcessorImpl.Stub { 1436 private final PreviewImageProcessorImpl mProcessor; 1437 PreviewImageProcessorImplStub(PreviewImageProcessorImpl processor)1438 public PreviewImageProcessorImplStub(PreviewImageProcessorImpl processor) { 1439 mProcessor = processor; 1440 } 1441 1442 @Override onOutputSurface(Surface surface, int imageFormat)1443 public void onOutputSurface(Surface surface, int imageFormat) { 1444 mProcessor.onOutputSurface(surface, imageFormat); 1445 } 1446 1447 @Override onResolutionUpdate(android.hardware.camera2.extension.Size size)1448 public void onResolutionUpdate(android.hardware.camera2.extension.Size size) { 1449 mProcessor.onResolutionUpdate(new android.util.Size(size.width, size.height)); 1450 } 1451 1452 @Override onImageFormatUpdate(int imageFormat)1453 public void onImageFormatUpdate(int imageFormat) { 1454 mProcessor.onImageFormatUpdate(imageFormat); 1455 } 1456 1457 @Override process(android.hardware.camera2.extension.ParcelImage image, CameraMetadataNative result, int sequenceId)1458 public void process(android.hardware.camera2.extension.ParcelImage image, 1459 CameraMetadataNative result, int sequenceId) { 1460 mProcessor.process(new ExtensionImage(image), 1461 new TotalCaptureResult(result, sequenceId)); 1462 } 1463 } 1464 1465 private class RequestUpdateProcessorImplStub extends IRequestUpdateProcessorImpl.Stub { 1466 private final RequestUpdateProcessorImpl mProcessor; 1467 private final String mCameraId; 1468 RequestUpdateProcessorImplStub(RequestUpdateProcessorImpl processor, String cameraId)1469 public RequestUpdateProcessorImplStub(RequestUpdateProcessorImpl processor, 1470 String cameraId) { 1471 mProcessor = processor; 1472 mCameraId = cameraId; 1473 } 1474 1475 @Override onOutputSurface(Surface surface, int imageFormat)1476 public void onOutputSurface(Surface surface, int imageFormat) { 1477 mProcessor.onOutputSurface(surface, imageFormat); 1478 } 1479 1480 @Override onResolutionUpdate(android.hardware.camera2.extension.Size size)1481 public void onResolutionUpdate(android.hardware.camera2.extension.Size size) { 1482 mProcessor.onResolutionUpdate(new android.util.Size(size.width, size.height)); 1483 } 1484 1485 @Override onImageFormatUpdate(int imageFormat)1486 public void onImageFormatUpdate(int imageFormat) { 1487 mProcessor.onImageFormatUpdate(imageFormat); 1488 } 1489 1490 @Override process(CameraMetadataNative result, int sequenceId)1491 public CaptureStageImpl process(CameraMetadataNative result, int sequenceId) { 1492 return initializeParcelable( 1493 mProcessor.process(new TotalCaptureResult(result, sequenceId)), mCameraId); 1494 } 1495 } 1496 1497 private class ImageReferenceImpl extends ExtensionImage 1498 implements androidx.camera.extensions.impl.advanced.ImageReferenceImpl { 1499 1500 private final Object mImageLock = new Object(); 1501 private int mReferenceCount; 1502 ImageReferenceImpl(ParcelImage parcelImage)1503 private ImageReferenceImpl(ParcelImage parcelImage) { 1504 super(parcelImage); 1505 mReferenceCount = 1; 1506 } 1507 1508 @Override increment()1509 public boolean increment() { 1510 synchronized (mImageLock) { 1511 if (mReferenceCount <= 0) { 1512 return false; 1513 } 1514 mReferenceCount++; 1515 } 1516 1517 return true; 1518 } 1519 1520 @Override decrement()1521 public boolean decrement() { 1522 synchronized (mImageLock) { 1523 if (mReferenceCount <= 0) { 1524 return false; 1525 } 1526 mReferenceCount--; 1527 1528 if (mReferenceCount <= 0) { 1529 close(); 1530 } 1531 } 1532 1533 return true; 1534 } 1535 1536 @Override get()1537 public Image get() { 1538 return this; 1539 } 1540 } 1541 1542 private class ExtensionImage extends android.media.Image { 1543 private final android.hardware.camera2.extension.ParcelImage mParcelImage; 1544 private GraphicBuffer mGraphicBuffer; 1545 private ImageReader.ImagePlane[] mPlanes; 1546 ExtensionImage(android.hardware.camera2.extension.ParcelImage parcelImage)1547 private ExtensionImage(android.hardware.camera2.extension.ParcelImage parcelImage) { 1548 mParcelImage = parcelImage; 1549 mIsImageValid = true; 1550 } 1551 1552 @Override getFormat()1553 public int getFormat() { 1554 throwISEIfImageIsInvalid(); 1555 return mParcelImage.format; 1556 } 1557 1558 @Override getWidth()1559 public int getWidth() { 1560 throwISEIfImageIsInvalid(); 1561 return mParcelImage.width; 1562 } 1563 1564 @Override getHardwareBuffer()1565 public HardwareBuffer getHardwareBuffer() { 1566 throwISEIfImageIsInvalid(); 1567 return mParcelImage.buffer; 1568 } 1569 1570 @Override getHeight()1571 public int getHeight() { 1572 throwISEIfImageIsInvalid(); 1573 return mParcelImage.height; 1574 } 1575 1576 @Override getTimestamp()1577 public long getTimestamp() { 1578 throwISEIfImageIsInvalid(); 1579 return mParcelImage.timestamp; 1580 } 1581 1582 @Override getTransform()1583 public int getTransform() { 1584 throwISEIfImageIsInvalid(); 1585 return mParcelImage.transform; 1586 } 1587 1588 @Override getScalingMode()1589 public int getScalingMode() { 1590 throwISEIfImageIsInvalid(); 1591 return mParcelImage.scalingMode; 1592 } 1593 1594 @Override getPlanes()1595 public Plane[] getPlanes() { 1596 throwISEIfImageIsInvalid(); 1597 if (mPlanes == null) { 1598 int fenceFd = mParcelImage.fence != null ? mParcelImage.fence.getFd() : -1; 1599 mGraphicBuffer = GraphicBuffer.createFromHardwareBuffer(mParcelImage.buffer); 1600 mPlanes = ImageReader.initializeImagePlanes(mParcelImage.planeCount, mGraphicBuffer, 1601 fenceFd, mParcelImage.format, mParcelImage.timestamp, 1602 mParcelImage.transform, mParcelImage.scalingMode, mParcelImage.crop); 1603 } 1604 // Shallow copy is fine. 1605 return mPlanes.clone(); 1606 } 1607 1608 @Override finalize()1609 protected final void finalize() throws Throwable { 1610 try { 1611 close(); 1612 } finally { 1613 super.finalize(); 1614 } 1615 } 1616 1617 @Override isAttachable()1618 public boolean isAttachable() { 1619 throwISEIfImageIsInvalid(); 1620 // Clients must always detach parcelable images 1621 return true; 1622 } 1623 1624 @Override getCropRect()1625 public Rect getCropRect() { 1626 throwISEIfImageIsInvalid(); 1627 return mParcelImage.crop; 1628 } 1629 1630 @Override close()1631 public void close() { 1632 mIsImageValid = false; 1633 1634 if (mGraphicBuffer != null) { 1635 ImageReader.unlockGraphicBuffer(mGraphicBuffer); 1636 mGraphicBuffer.destroy(); 1637 mGraphicBuffer = null; 1638 } 1639 1640 if (mPlanes != null) { 1641 mPlanes = null; 1642 } 1643 1644 if (mParcelImage.buffer != null) { 1645 mParcelImage.buffer.close(); 1646 mParcelImage.buffer = null; 1647 } 1648 1649 if (mParcelImage.fence != null) { 1650 try { 1651 mParcelImage.fence.close(); 1652 } catch (IOException e) { 1653 e.printStackTrace(); 1654 } 1655 mParcelImage.fence = null; 1656 } 1657 } 1658 } 1659 } 1660