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