1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.one.v2.core; 18 19 import android.hardware.camera2.CameraAccessException; 20 import android.hardware.camera2.CameraCaptureSession; 21 import android.hardware.camera2.CaptureFailure; 22 import android.hardware.camera2.CaptureRequest; 23 import android.hardware.camera2.CaptureResult; 24 import android.hardware.camera2.TotalCaptureResult; 25 import android.os.Handler; 26 27 import com.android.camera.one.v2.camera2proxy.CameraCaptureSessionClosedException; 28 import com.android.camera.one.v2.camera2proxy.CameraCaptureSessionProxy; 29 import com.android.camera.one.v2.camera2proxy.CaptureRequestBuilderProxy; 30 import com.google.common.annotations.VisibleForTesting; 31 32 import java.util.ArrayList; 33 import java.util.HashMap; 34 import java.util.List; 35 import java.util.Map; 36 37 /** 38 * Like {@link android.hardware.camera2.CameraCaptureSession}, but takes 39 * {@link Request}s and dispatches to the appropriate {@link ResponseListener} 40 * on a per-request basis, instead of for every {@link CaptureRequest} submitted 41 * at the same time. 42 */ 43 @VisibleForTesting 44 public class TagDispatchCaptureSession implements FrameServer.Session { 45 private static class CaptureCallback implements CameraCaptureSessionProxy.CaptureCallback { 46 private final Map<Object, ResponseListener> mListeners; 47 48 /** 49 * @param listeners A map from tag objects to the listener to be invoked 50 * for events related to the request with that tag. 51 */ 52 public CaptureCallback(Map<Object, ResponseListener> listeners) { 53 mListeners = new HashMap<>(listeners); 54 } 55 56 @Override 57 public void onCaptureStarted(CameraCaptureSessionProxy session, CaptureRequest request, 58 long timestamp, long frameNumber) { 59 Object tag = request.getTag(); 60 mListeners.get(tag).onStarted(timestamp); 61 } 62 63 @Override 64 public void onCaptureProgressed(CameraCaptureSessionProxy session, CaptureRequest request, 65 CaptureResult partialResult) { 66 Object tag = request.getTag(); 67 mListeners.get(tag).onProgressed(partialResult); 68 } 69 70 @Override 71 public void onCaptureCompleted(CameraCaptureSessionProxy session, CaptureRequest request, 72 TotalCaptureResult result) { 73 Object tag = request.getTag(); 74 mListeners.get(tag).onCompleted(result); 75 } 76 77 @Override 78 public void onCaptureFailed(CameraCaptureSessionProxy session, CaptureRequest request, 79 CaptureFailure failure) { 80 Object tag = request.getTag(); 81 mListeners.get(tag).onFailed(failure); 82 } 83 84 @Override 85 public void onCaptureSequenceAborted(CameraCaptureSessionProxy session, int sequenceId) { 86 for (ResponseListener listener : mListeners.values()) { 87 listener.onSequenceAborted(sequenceId); 88 } 89 } 90 91 @Override 92 public void onCaptureSequenceCompleted(CameraCaptureSessionProxy session, int sequenceId, 93 long frameNumber) { 94 for (ResponseListener listener : mListeners.values()) { 95 listener.onSequenceCompleted(sequenceId, frameNumber); 96 } 97 } 98 } 99 100 private final CameraCaptureSessionProxy mCaptureSession; 101 private final Handler mCameraHandler; 102 private long mTagCounter; 103 104 public TagDispatchCaptureSession(CameraCaptureSessionProxy captureSession, Handler 105 cameraHandler) { 106 mCaptureSession = captureSession; 107 mCameraHandler = cameraHandler; 108 mTagCounter = 0; 109 } 110 111 private Object generateTag() { 112 Object tag = Long.valueOf(mTagCounter); 113 mTagCounter++; 114 return tag; 115 } 116 117 /** 118 * Submits the given burst request to the underlying 119 * {@link CameraCaptureSessionProxy}. 120 * <p/> 121 * Note that the Tag associated with the {@link CaptureRequest} from each 122 * {@link Request} will be overwritten. 123 * 124 * @param burstRequests The list of {@link Request}s to send. 125 * @param requestType Whether the request should be sent as a repeating 126 * request. 127 * @throws CameraAccessException See 128 * {@link CameraCaptureSession#captureBurst} and 129 * {@link CameraCaptureSession#setRepeatingBurst}. 130 * @throws InterruptedException if interrupted while waiting to allocate 131 * resources necessary for each {@link Request}. 132 */ 133 public void submitRequest(List<Request> burstRequests, FrameServer.RequestType requestType) 134 throws 135 CameraAccessException, InterruptedException, CameraCaptureSessionClosedException, 136 ResourceAcquisitionFailedException { 137 try { 138 Map<Object, ResponseListener> tagListenerMap = new HashMap<Object, ResponseListener>(); 139 List<CaptureRequest> captureRequests = new ArrayList<>(burstRequests.size()); 140 141 for (Request request : burstRequests) { 142 Object tag = generateTag(); 143 144 tagListenerMap.put(tag, request.getResponseListener()); 145 146 CaptureRequestBuilderProxy builder = request.allocateCaptureRequest(); 147 builder.setTag(tag); 148 captureRequests.add(builder.build()); 149 } 150 151 if (requestType == FrameServer.RequestType.REPEATING) { 152 mCaptureSession.setRepeatingBurst(captureRequests, new 153 CaptureCallback(tagListenerMap), mCameraHandler); 154 } else { 155 mCaptureSession.captureBurst(captureRequests, new 156 CaptureCallback(tagListenerMap), mCameraHandler); 157 } 158 } catch (Exception e) { 159 for (Request r : burstRequests) { 160 r.abort(); 161 } 162 throw e; 163 } 164 } 165 166 public void close() { 167 // Do nothing. 168 } 169 } 170