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