Home | History | Annotate | Download | only in core
      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