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 android.hardware.camera2.legacy;
18 
19 import android.hardware.camera2.CaptureRequest;
20 import android.hardware.camera2.impl.CameraMetadataNative;
21 import android.util.Log;
22 import android.view.Surface;
23 
24 import java.util.Collection;
25 
26 import static com.android.internal.util.Preconditions.*;
27 
28 /**
29  * Semi-immutable container for a single capture request and associated information,
30  * the only mutable characteristic of this container is whether or not is has been
31  * marked as "failed" using {@code #failRequest}.
32  */
33 public class RequestHolder {
34     private static final String TAG = "RequestHolder";
35 
36     private final boolean mRepeating;
37     private final CaptureRequest mRequest;
38     private final int mRequestId;
39     private final int mSubsequeceId;
40     private final long mFrameNumber;
41     private final int mNumJpegTargets;
42     private final int mNumPreviewTargets;
43     private volatile boolean mFailed = false;
44 
45     /**
46      * A builder class for {@link RequestHolder} objects.
47      *
48      * <p>
49      * This allows per-request queries to be cached for repeating {@link CaptureRequest} objects.
50      * </p>
51      */
52     public final static class Builder {
53         private final int mRequestId;
54         private final int mSubsequenceId;
55         private final CaptureRequest mRequest;
56         private final boolean mRepeating;
57         private final int mNumJpegTargets;
58         private final int mNumPreviewTargets;
59         private final Collection<Long> mJpegSurfaceIds;
60 
61         /**
62          * Construct a new {@link Builder} to generate {@link RequestHolder} objects.
63          *
64          * @param requestId the ID to set in {@link RequestHolder} objects.
65          * @param subsequenceId the sequence ID to set in {@link RequestHolder} objects.
66          * @param request the original {@link CaptureRequest} to set in {@link RequestHolder}
67          *                objects.
68          * @param repeating {@code true} if the request is repeating.
69          */
Builder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating, Collection<Long> jpegSurfaceIds)70         public Builder(int requestId, int subsequenceId, CaptureRequest request,
71                        boolean repeating, Collection<Long> jpegSurfaceIds) {
72             checkNotNull(request, "request must not be null");
73             mRequestId = requestId;
74             mSubsequenceId = subsequenceId;
75             mRequest = request;
76             mRepeating = repeating;
77             mJpegSurfaceIds = jpegSurfaceIds;
78             mNumJpegTargets = numJpegTargets(mRequest);
79             mNumPreviewTargets = numPreviewTargets(mRequest);
80         }
81 
82         /**
83          * Returns true if the given surface requires jpeg buffers.
84          *
85          * @param s a {@link android.view.Surface} to check.
86          * @return true if the surface requires a jpeg buffer.
87          */
jpegType(Surface s)88         private boolean jpegType(Surface s)
89                 throws LegacyExceptionUtils.BufferQueueAbandonedException {
90             return LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds);
91         }
92 
93         /**
94          * Returns true if the given surface requires non-jpeg buffer types.
95          *
96          * <p>
97          * "Jpeg buffer" refers to the buffers returned in the jpeg
98          * {@link android.hardware.Camera.PictureCallback}.  Non-jpeg buffers are created using a tee
99          * of the preview stream drawn to the surface
100          * set via {@link android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)} or
101          * equivalent methods.
102          * </p>
103          * @param s a {@link android.view.Surface} to check.
104          * @return true if the surface requires a non-jpeg buffer type.
105          */
previewType(Surface s)106         private boolean previewType(Surface s)
107                 throws LegacyExceptionUtils.BufferQueueAbandonedException {
108             return !jpegType(s);
109         }
110 
111         /**
112          * Returns the number of surfaces targeted by the request that require jpeg buffers.
113          */
numJpegTargets(CaptureRequest request)114         private int numJpegTargets(CaptureRequest request) {
115             int count = 0;
116             for (Surface s : request.getTargets()) {
117                 try {
118                     if (jpegType(s)) {
119                         ++count;
120                     }
121                 } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
122                     Log.d(TAG, "Surface abandoned, skipping...", e);
123                 }
124             }
125             return count;
126         }
127 
128         /**
129          * Returns the number of surfaces targeted by the request that require non-jpeg buffers.
130          */
numPreviewTargets(CaptureRequest request)131         private int numPreviewTargets(CaptureRequest request) {
132             int count = 0;
133             for (Surface s : request.getTargets()) {
134                 try {
135                     if (previewType(s)) {
136                         ++count;
137                     }
138                 } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
139                     Log.d(TAG, "Surface abandoned, skipping...", e);
140                 }
141             }
142             return count;
143         }
144 
145         /**
146          * Build a new {@link RequestHolder} using with parameters generated from this
147          *      {@link Builder}.
148          *
149          * @param frameNumber the {@code framenumber} to generate in the {@link RequestHolder}.
150          * @return a {@link RequestHolder} constructed with the {@link Builder}'s parameters.
151          */
build(long frameNumber)152         public RequestHolder build(long frameNumber) {
153             return new RequestHolder(mRequestId, mSubsequenceId, mRequest, mRepeating, frameNumber,
154                     mNumJpegTargets, mNumPreviewTargets);
155         }
156     }
157 
RequestHolder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating, long frameNumber, int numJpegTargets, int numPreviewTargets)158     private RequestHolder(int requestId, int subsequenceId, CaptureRequest request,
159                           boolean repeating, long frameNumber, int numJpegTargets,
160                           int numPreviewTargets) {
161         mRepeating = repeating;
162         mRequest = request;
163         mRequestId = requestId;
164         mSubsequeceId = subsequenceId;
165         mFrameNumber = frameNumber;
166         mNumJpegTargets = numJpegTargets;
167         mNumPreviewTargets = numPreviewTargets;
168     }
169 
170     /**
171      * Return the request id for the contained {@link CaptureRequest}.
172      */
getRequestId()173     public int getRequestId() {
174         return mRequestId;
175     }
176 
177     /**
178      * Returns true if the contained request is repeating.
179      */
isRepeating()180     public boolean isRepeating() {
181         return mRepeating;
182     }
183 
184     /**
185      * Return the subsequence id for this request.
186      */
getSubsequeceId()187     public int getSubsequeceId() {
188         return mSubsequeceId;
189     }
190 
191     /**
192      * Returns the frame number for this request.
193      */
getFrameNumber()194     public long getFrameNumber() {
195         return mFrameNumber;
196     }
197 
198     /**
199      * Returns the contained request.
200      */
getRequest()201     public CaptureRequest getRequest() {
202         return mRequest;
203     }
204 
205     /**
206      * Returns a read-only collection of the surfaces targeted by the contained request.
207      */
getHolderTargets()208     public Collection<Surface> getHolderTargets() {
209         return getRequest().getTargets();
210     }
211 
212     /**
213      * Returns true if any of the surfaces targeted by the contained request require jpeg buffers.
214      */
hasJpegTargets()215     public boolean hasJpegTargets() {
216         return mNumJpegTargets > 0;
217     }
218 
219     /**
220      * Returns true if any of the surfaces targeted by the contained request require a
221      * non-jpeg buffer type.
222      */
hasPreviewTargets()223     public boolean hasPreviewTargets(){
224         return mNumPreviewTargets > 0;
225     }
226 
227     /**
228      * Return the number of jpeg-type surfaces targeted by this request.
229      */
numJpegTargets()230     public int numJpegTargets() {
231         return mNumJpegTargets;
232     }
233 
234     /**
235      * Return the number of non-jpeg-type surfaces targeted by this request.
236      */
numPreviewTargets()237     public int numPreviewTargets() {
238         return mNumPreviewTargets;
239     }
240 
241     /**
242      * Mark this request as failed.
243      */
failRequest()244     public void failRequest() {
245         Log.w(TAG, "Capture failed for request: " + getRequestId());
246         mFailed = true;
247     }
248 
249     /**
250      * Return {@code true} if this request failed.
251      */
requestFailed()252     public boolean requestFailed() {
253         return mFailed;
254     }
255 
256 }
257