18ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher/* 28ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Copyright (C) 2014 The Android Open Source Project 38ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 48ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Licensed under the Apache License, Version 2.0 (the "License"); 58ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * you may not use this file except in compliance with the License. 68ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * You may obtain a copy of the License at 78ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 88ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * http://www.apache.org/licenses/LICENSE-2.0 98ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 108ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Unless required by applicable law or agreed to in writing, software 118ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * distributed under the License is distributed on an "AS IS" BASIS, 128ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * See the License for the specific language governing permissions and 148ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * limitations under the License. 158ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 168ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 178ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherpackage com.android.ex.camera2.utils; 188ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 198ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherimport android.hardware.camera2.CameraAccessException; 208ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherimport android.hardware.camera2.CameraDevice; 218ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherimport android.hardware.camera2.CaptureRequest; 228ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherimport android.hardware.camera2.CaptureRequest.Builder; 238ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherimport android.hardware.camera2.CaptureRequest.Key; 248ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherimport android.view.Surface; 258ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 268ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherimport java.util.HashMap; 278ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherimport java.util.Map; 288ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherimport java.util.Objects; 298ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 308ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher/** 318ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * A set of settings to be used when filing a {@link CaptureRequest}. 328ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 338ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucherpublic class Camera2RequestSettingsSet { 348ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher private final Map<Key<?>, Object> mDictionary; 358ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher private long mRevision; 368ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 378ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher /** 388ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Create a new instance with no settings defined. 398ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 408ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * <p>Creating a request from this object without first specifying any 418ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * properties on it is equivalent to just creating a request directly 428ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * from the template of choice. Its revision identifier is initially 438ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * {@code 0}, and will remain thus until its first modification.</p> 448ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 458ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher public Camera2RequestSettingsSet() { 468ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher mDictionary = new HashMap<>(); 478ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher mRevision = 0; 488ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 498ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 508ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher /** 518ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Perform a deep copy of the defined settings and revision number. 528ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 538ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param other The reference instance. 548ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 558ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @throws NullPointerException If {@code other} is {@code null}. 568ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 578ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher public Camera2RequestSettingsSet(Camera2RequestSettingsSet other) { 588ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (other == null) { 598ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher throw new NullPointerException("Tried to copy null Camera2RequestSettingsSet"); 608ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 618ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 628ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher mDictionary = new HashMap<>(other.mDictionary); 638ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher mRevision = other.mRevision; 648ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 658ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 668ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher /** 678ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Specify a setting, potentially overriding the template's default choice. 688ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 698ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * <p>Providing a {@code null} {@code value} will indicate a forced use of 708ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * the template's selection for that {@code key}; the difference here is 718ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * that this information will be propagated with unions as documented in 728ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * {@link #union}. This method increments the revision identifier if the new 738ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * choice is different than the existing selection.</p> 748ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 758ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param key Which setting to alter. 768ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param value The new selection for that setting, or {@code null} to force 778ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * the use of the template's default selection for this field. 788ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @return Whether the settings were updated, which only occurs if the 798ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * {@code value} is different from any already stored. 808ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 818ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @throws NullPointerException If {@code key} is {@code null}. 828ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 838ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher public <T> boolean set(Key<T> key, T value) { 848ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (key == null) { 858ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher throw new NullPointerException("Received a null key"); 868ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 878ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 888ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher Object currentValue = get(key); 898ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher // Only save the value if it's different from the one we already have 908ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (!mDictionary.containsKey(key) || !Objects.equals(value, currentValue)) { 918ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher mDictionary.put(key, value); 928ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher ++mRevision; 938ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return true; 948ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 958ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return false; 968ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 978ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 988ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher /** 998ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Unsets a setting, preventing it from being propagated with unions or from 1008ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * overriding the default when creating a capture request. 1018ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 1028ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * <p>This method increments the revision identifier if a selection had 1038ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * previously been made for that parameter.</p> 1048ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 1058ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param key Which setting to reset. 1068ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @return Whether the settings were updated, which only occurs if the 1078ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * specified setting already had a value or was forced to default. 1088ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 1098ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @throws NullPointerException If {@code key} is {@code null}. 1108ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 1118ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher public boolean unset(Key<?> key) { 1128ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (key == null) { 1138ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher throw new NullPointerException("Received a null key"); 1148ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 1158ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 1168ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (mDictionary.containsKey(key)) { 1178ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher mDictionary.remove(key); 1188ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher ++mRevision; 1198ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return true; 1208ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 1218ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return false; 1228ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 1238ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 1248ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher /** 1258ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Interrogate the current specialization of a setting. 1268ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 1278ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param key Which setting to check. 1288ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @return The current selection for that setting, or {@code null} if the 1298ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * setting is unset or forced to the template-defined default. 1308ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 1318ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @throws NullPointerException If {@code key} is {@code null}. 1328ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 1338ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher @SuppressWarnings("unchecked") 1348ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher public <T> T get(Key<T> key) { 1358ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (key == null) { 1368ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher throw new NullPointerException("Received a null key"); 1378ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 1388ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return (T) mDictionary.get(key); 1398ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 1408ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 1418ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher /** 1428ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Query this instance for whether it prefers a particular choice for the 1438ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * given request parameter. 1448ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 1458ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * <p>This method can be used to detect whether a particular field is forced 1468ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * to its default value or simply unset. While {@link #get} will return 1478ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * {@code null} in both these cases, this method will return {@code true} 1488ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * and {@code false}, respectively.</p> 149984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 1508ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param key Which setting to look for. 1518ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @return Whether that setting has a value that will propagate with unions. 1528ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 1538ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @throws NullPointerException If {@code key} is {@code null}. 1548ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 1558ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher public boolean contains(Key<?> key) { 1568ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (key == null) { 1578ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher throw new NullPointerException("Received a null key"); 1588ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 1598ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return mDictionary.containsKey(key); 1608ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 1618ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 1628ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher /** 163984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * Check whether the value of the specified setting matches the given one. 164984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 165984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * <p>This method uses the {@code T} type's {@code equals} method, but is 166984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * {@code null}-tolerant.</p> 167984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 168984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @param key Which of this class's settings to check. 169984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @param value Value to test for equality against. 170984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @return Whether they are the same. 171984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 172984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public <T> boolean matches(Key<T> key, T value) { 173984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher return Objects.equals(get(key), value); 174984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 175984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 176984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 1778ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Get this set of settings's revision identifier, which can be compared 1788ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * against cached past values to determine whether it has been modified. 179984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 1808ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * <p>Distinct revisions across the same object do not necessarily indicate 1818ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * that the object's key/value pairs have changed at all, but the same 1828ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * revision on the same object does imply that they've stayed the same.</p> 1838ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 1848ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @return The number of modifications made since the beginning of this 1858ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * object's heritage. 1868ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 1878ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher public long getRevision() { 1888ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return mRevision; 1898ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 1908ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 1918ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher /** 1928ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Add all settings choices defined by {@code moreSettings} to this object. 1938ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 1948ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * <p>For any settings defined in both, the choice stored in the argument 1958ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * to this method take precedence. Unset settings are not propagated, but 1968ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * those forced to default as described in {@link set} are also forced to 1978ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * default in {@code this} set. Invoking this method increments {@code this} 1988ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * object's revision counter, but leaves the argument's unchanged.</p> 1998ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 2008ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param moreSettings The source of the additional settings ({@code null} 2018ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * is allowed here). 2028ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @return Whether these settings were updated, which can only fail if the 2038ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * target itself is also given as the argument. 2048ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 2058ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher public boolean union(Camera2RequestSettingsSet moreSettings) { 2068ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (moreSettings == null || moreSettings == this) { 2078ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return false; 2088ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 2098ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 2108ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher mDictionary.putAll(moreSettings.mDictionary); 2118ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher ++mRevision; 2128ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return true; 2138ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 2148ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 2158ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher /** 2168ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * Create a {@link CaptureRequest} specialized for the specified 2178ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * {@link CameraDevice} and targeting the given {@link Surface}s. 2188ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 2198ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param camera The camera from which to capture. 2208ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param template A {@link CaptureRequest} template defined in 2218ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * {@link CameraDevice}. 2228ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @param targets The location(s) to draw the resulting image onto. 2238ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @return The request, ready to be passed to the camera framework. 2248ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * 2258ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @throws CameraAccessException Upon an underlying framework API failure. 2268ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher * @throws NullPointerException If any argument is {@code null}. 2278ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher */ 2288ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher public CaptureRequest createRequest(CameraDevice camera, int template, Surface... targets) 2298ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher throws CameraAccessException { 2308ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (camera == null) { 2318ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher throw new NullPointerException("Tried to create request using null CameraDevice"); 2328ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 2338ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 2348ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher Builder reqBuilder = camera.createCaptureRequest(template); 2358ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher for (Key<?> key : mDictionary.keySet()) { 2368ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher setRequestFieldIfNonNull(reqBuilder, key); 2378ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 2388ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher for (Surface target : targets) { 2398ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (target == null) { 2408ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher throw new NullPointerException("Tried to add null Surface as request target"); 2418ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 2428ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher reqBuilder.addTarget(target); 2438ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 2448ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher return reqBuilder.build(); 2458ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 2468ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher 2478ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher private <T> void setRequestFieldIfNonNull(Builder requestBuilder, Key<T> key) { 2488ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher T value = get(key); 2498ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher if (value != null) { 2508ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher requestBuilder.set(key, value); 2518ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 2528ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher } 2538ba391e3f88936557ad6d44bbef32cb08f4ca310Sol Boucher} 254