170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala/*
270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * Copyright (C) 2013 The Android Open Source Project
370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala *
470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License");
570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * you may not use this file except in compliance with the License.
670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * You may obtain a copy of the License at
770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala *
870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala *      http://www.apache.org/licenses/LICENSE-2.0
970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala *
1070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * Unless required by applicable law or agreed to in writing, software
1170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS,
1270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * See the License for the specific language governing permissions and
1470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * limitations under the License.
1570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala */
1670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
1770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalapackage android.hardware.camera2.impl;
1870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
19b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun Heimport android.graphics.ImageFormat;
20b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun Heimport android.graphics.Point;
21b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun Heimport android.graphics.Rect;
22b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun Heimport android.hardware.camera2.CameraCharacteristics;
23d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinimport android.hardware.camera2.CaptureRequest;
24b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun Heimport android.hardware.camera2.CaptureResult;
253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.Marshaler;
263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.MarshalQueryable;
273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.MarshalRegistry;
283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableArray;
293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableBoolean;
3052842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunkimport android.hardware.camera2.marshal.impl.MarshalQueryableBlackLevelPattern;
313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableColorSpaceTransform;
323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableEnum;
3312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yehimport android.hardware.camera2.marshal.impl.MarshalQueryableHighSpeedVideoConfiguration;
343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableMeteringRectangle;
353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableNativeByteToInteger;
365743868e15c88d2886915163652a1571a218bf39Igor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryablePair;
373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableParcelable;
383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryablePrimitive;
393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableRange;
403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableRect;
413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableReprocessFormatsMap;
423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableRggbChannelVector;
433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableSize;
443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableSizeF;
453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableStreamConfiguration;
463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableStreamConfigurationDuration;
473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableString;
4872f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.hardware.camera2.params.Face;
4912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yehimport android.hardware.camera2.params.HighSpeedVideoConfiguration;
50574936894d3044445a272b39f2d925af40ece5d8Ruben Brunkimport android.hardware.camera2.params.LensShadingMap;
510a551f1487e00a598b20b1bc58a1ccd7226e7091Chien-Yu Chenimport android.hardware.camera2.params.ReprocessFormatsMap;
529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.params.StreamConfiguration;
539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.params.StreamConfigurationDuration;
549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.params.StreamConfigurationMap;
558490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yehimport android.hardware.camera2.params.TonemapCurve;
56d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinimport android.hardware.camera2.utils.TypeReference;
57574936894d3044445a272b39f2d925af40ece5d8Ruben Brunkimport android.location.Location;
58574936894d3044445a272b39f2d925af40ece5d8Ruben Brunkimport android.location.LocationManager;
5970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport android.os.Parcelable;
6070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport android.os.Parcel;
615d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.os.ServiceSpecificException;
6270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport android.util.Log;
63574936894d3044445a272b39f2d925af40ece5d8Ruben Brunkimport android.util.Size;
6470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
65d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinimport com.android.internal.util.Preconditions;
66d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
67d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinimport java.io.IOException;
6870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport java.nio.ByteBuffer;
6970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport java.nio.ByteOrder;
7070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport java.util.ArrayList;
71574936894d3044445a272b39f2d925af40ece5d8Ruben Brunkimport java.util.HashMap;
7270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
7370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala/**
7470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * Implementation of camera metadata marshal/unmarshal across Binder to
7570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala * the camera service
7670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala */
77d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinpublic class CameraMetadataNative implements Parcelable {
78d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
79d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public static class Key<T> {
80d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        private boolean mHasTag;
81d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        private int mTag;
82de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        private long mVendorId = Long.MAX_VALUE;
83d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        private final Class<T> mType;
84d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        private final TypeReference<T> mTypeReference;
85d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        private final String mName;
86d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        private final int mHash;
87de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
88de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        /**
89de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev         * @hide
90de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev         */
91de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        public Key(String name, Class<T> type, long vendorId) {
92de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            if (name == null) {
93de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                throw new NullPointerException("Key needs a valid name");
94de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            } else if (type == null) {
95de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                throw new NullPointerException("Type needs to be non-null");
96de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            }
97de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            mName = name;
98de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            mType = type;
99de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            mVendorId = vendorId;
100de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            mTypeReference = TypeReference.createSpecializedTypeReference(type);
101de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            mHash = mName.hashCode() ^ mTypeReference.hashCode();
102de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        }
103de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
104d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        /**
105d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * Visible for testing only.
106d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
107d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>Use the CameraCharacteristics.Key, CaptureResult.Key, or CaptureRequest.Key
108d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * for application code or vendor-extended keys.</p>
109d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         */
110d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        public Key(String name, Class<T> type) {
111d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (name == null) {
112d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                throw new NullPointerException("Key needs a valid name");
113d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            } else if (type == null) {
114d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                throw new NullPointerException("Type needs to be non-null");
115d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
116d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            mName = name;
117d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            mType = type;
118d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            mTypeReference = TypeReference.createSpecializedTypeReference(type);
119d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            mHash = mName.hashCode() ^ mTypeReference.hashCode();
120d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
121d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
122d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        /**
123d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * Visible for testing only.
124d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
125d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>Use the CameraCharacteristics.Key, CaptureResult.Key, or CaptureRequest.Key
126d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * for application code or vendor-extended keys.</p>
127d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         */
128d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        @SuppressWarnings("unchecked")
129d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        public Key(String name, TypeReference<T> typeReference) {
130d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (name == null) {
131d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                throw new NullPointerException("Key needs a valid name");
132d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            } else if (typeReference == null) {
133d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                throw new NullPointerException("TypeReference needs to be non-null");
134d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
135d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            mName = name;
136d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            mType = (Class<T>)typeReference.getRawType();
137d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            mTypeReference = typeReference;
138d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            mHash = mName.hashCode() ^ mTypeReference.hashCode();
139d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
140d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
141d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        /**
142d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * Return a camelCase, period separated name formatted like:
143d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * {@code "root.section[.subsections].name"}.
144d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
145d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>Built-in keys exposed by the Android SDK are always prefixed with {@code "android."};
146d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * keys that are device/platform-specific are prefixed with {@code "com."}.</p>
147d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
148d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>For example, {@code CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP} would
149d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * have a name of {@code "android.scaler.streamConfigurationMap"}; whereas a device
150d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * specific key might look like {@code "com.google.nexus.data.private"}.</p>
151d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
152d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * @return String representation of the key name
153d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         */
154d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        public final String getName() {
155d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            return mName;
156d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
157d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
158d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        /**
159d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * {@inheritDoc}
160d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         */
161d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        @Override
162d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        public final int hashCode() {
163d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            return mHash;
164d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
165d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
166d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        /**
167d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * Compare this key against other native keys, request keys, result keys, and
168d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * characteristics keys.
169d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
170d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>Two keys are considered equal if their name and type reference are equal.</p>
171d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
172d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>Note that the equality against non-native keys is one-way. A native key may be equal
173d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * to a result key; but that same result key will not be equal to a native key.</p>
174d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         */
175d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        @SuppressWarnings("rawtypes")
176d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        @Override
177d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        public final boolean equals(Object o) {
178d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (this == o) {
179d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                return true;
180d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
181d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
182d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            if (o == null || this.hashCode() != o.hashCode()) {
183d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                return false;
184d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            }
185d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk
186d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            Key<?> lhs;
187d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
188d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (o instanceof CaptureResult.Key) {
189d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                lhs = ((CaptureResult.Key)o).getNativeKey();
190d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            } else if (o instanceof CaptureRequest.Key) {
191d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                lhs = ((CaptureRequest.Key)o).getNativeKey();
192d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            } else if (o instanceof CameraCharacteristics.Key) {
193d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                lhs = ((CameraCharacteristics.Key)o).getNativeKey();
194d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            } else if ((o instanceof Key)) {
195d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                lhs = (Key<?>)o;
196d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            } else {
197d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                return false;
198d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
199d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
200d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            return mName.equals(lhs.mName) && mTypeReference.equals(lhs.mTypeReference);
201d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
202d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
203d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        /**
204d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>
205d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * Get the tag corresponding to this key. This enables insertion into the
206d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * native metadata.
207d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * </p>
208d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
209d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>This value is looked up the first time, and cached subsequently.</p>
210d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
211d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * @return The tag numeric value corresponding to the string
212d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         */
213d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        public final int getTag() {
214d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (!mHasTag) {
215de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                mTag = CameraMetadataNative.getTag(mName, mVendorId);
216d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                mHasTag = true;
217d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
218d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            return mTag;
219d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
220d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
221d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        /**
222d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * Get the raw class backing the type {@code T} for this key.
223d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
224d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>The distinction is only important if {@code T} is a generic, e.g.
225d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * {@code Range<Integer>} since the nested type will be erased.</p>
226d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         */
227d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        public final Class<T> getType() {
228d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            // TODO: remove this; other places should use #getTypeReference() instead
229d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            return mType;
230d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
231d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
232d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        /**
233de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev         * Get the vendor tag provider id.
234de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev         *
235de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev         * @hide
236de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev         */
237de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        public final long getVendorId() {
238de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            return mVendorId;
239de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        }
240de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
241de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        /**
242d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * Get the type reference backing the type {@code T} for this key.
243d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         *
244d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * <p>The distinction is only important if {@code T} is a generic, e.g.
245d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         * {@code Range<Integer>} since the nested type will be retained.</p>
246d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin         */
247d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        public final TypeReference<T> getTypeReference() {
248d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            return mTypeReference;
249d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
250d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
25170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
25270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private static final String TAG = "CameraMetadataJV";
253a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala    private static final boolean DEBUG = false;
254a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala
255b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    // this should be in sync with HAL_PIXEL_FORMAT_BLOB defined in graphics.h
256feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public static final int NATIVE_JPEG_FORMAT = 0x21;
25770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
258574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    private static final String CELLID_PROCESS = "CELLID";
259574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    private static final String GPS_PROCESS = "GPS";
2600a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private static final int FACE_LANDMARK_SIZE = 6;
261574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
262574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    private static String translateLocationProviderToProcess(final String provider) {
263574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        if (provider == null) {
264574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            return null;
265574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        }
266574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        switch(provider) {
267574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            case LocationManager.GPS_PROVIDER:
268574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk                return GPS_PROCESS;
269574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            case LocationManager.NETWORK_PROVIDER:
270574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk                return CELLID_PROCESS;
271574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            default:
272574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk                return null;
273574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        }
274574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    }
275574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
276574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    private static String translateProcessToLocationProvider(final String process) {
277574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        if (process == null) {
278574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            return null;
279574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        }
280574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        switch(process) {
281574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            case GPS_PROCESS:
282574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk                return LocationManager.GPS_PROVIDER;
283574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            case CELLID_PROCESS:
284574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk                return LocationManager.NETWORK_PROVIDER;
285574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            default:
286574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk                return null;
287574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        }
288574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    }
289574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
29070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public CameraMetadataNative() {
29170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        super();
29270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        mMetadataPtr = nativeAllocate();
29370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        if (mMetadataPtr == 0) {
29470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            throw new OutOfMemoryError("Failed to allocate native CameraMetadata");
29570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
29670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
29770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
29870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
29970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * Copy constructor - clone metadata
30070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
30170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public CameraMetadataNative(CameraMetadataNative other) {
30270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        super();
30370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        mMetadataPtr = nativeAllocateCopy(other);
30470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        if (mMetadataPtr == 0) {
30570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            throw new OutOfMemoryError("Failed to allocate native CameraMetadata");
30670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
30770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
30870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
309d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /**
310d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Move the contents from {@code other} into a new camera metadata instance.</p>
311d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
312d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * <p>After this call, {@code other} will become empty.</p>
313d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
314d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * @param other the previous metadata instance which will get pilfered
315d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * @return a new metadata instance with the values from {@code other} moved into it
316d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
317d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public static CameraMetadataNative move(CameraMetadataNative other) {
318d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        CameraMetadataNative newObject = new CameraMetadataNative();
319d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        newObject.swap(other);
320d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return newObject;
321d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
322d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
32370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public static final Parcelable.Creator<CameraMetadataNative> CREATOR =
32470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            new Parcelable.Creator<CameraMetadataNative>() {
32570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        @Override
32670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        public CameraMetadataNative createFromParcel(Parcel in) {
32770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadataNative metadata = new CameraMetadataNative();
32870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            metadata.readFromParcel(in);
32970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            return metadata;
33070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
33170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
33270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        @Override
33370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        public CameraMetadataNative[] newArray(int size) {
33470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            return new CameraMetadataNative[size];
33570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
33670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    };
33770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
33870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    @Override
33970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public int describeContents() {
34070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        return 0;
34170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
34270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
34370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    @Override
34470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public void writeToParcel(Parcel dest, int flags) {
34570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        nativeWriteToParcel(dest);
34670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
34770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
348d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /**
349d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * @hide
350d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
351d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public <T> T get(CameraCharacteristics.Key<T> key) {
352d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return get(key.getNativeKey());
353d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
354d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
355d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /**
356d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * @hide
357d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
358d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public <T> T get(CaptureResult.Key<T> key) {
359d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return get(key.getNativeKey());
360d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
361d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
362d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /**
363d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * @hide
364d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
365d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public <T> T get(CaptureRequest.Key<T> key) {
366d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return get(key.getNativeKey());
367d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
368d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
369d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /**
370d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Look-up a metadata field value by its key.
371d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
372d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * @param key a non-{@code null} key instance
373d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * @return the field corresponding to the {@code key}, or {@code null} if no value was set
374d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
37570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public <T> T get(Key<T> key) {
376d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        Preconditions.checkNotNull(key, "key must not be null");
377d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
378d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        // Check if key has been overridden to use a wrapper class on the java side.
379d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        GetCommand g = sGetCommandMap.get(key);
380d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        if (g != null) {
3810a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            return g.getValue(this, key);
38270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
383b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        return getBase(key);
38470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
38570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
38670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public void readFromParcel(Parcel in) {
38770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        nativeReadFromParcel(in);
38870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
38970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
39070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
39185c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk     * Set the global client-side vendor tag descriptor to allow use of vendor
39285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk     * tags in camera applications.
39385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk     *
3945d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala     * @throws ServiceSpecificException
39585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk     * @hide
39685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk     */
3975d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public static void setupGlobalVendorTagDescriptor() throws ServiceSpecificException {
3985d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        int err = nativeSetupGlobalVendorTagDescriptor();
3995d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        if (err != 0) {
4005d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(err, "Failure to set up global vendor tags");
4015d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        }
4025d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    }
4035d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala
4045d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    /**
4055d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala     * Set the global client-side vendor tag descriptor to allow use of vendor
4065d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala     * tags in camera applications.
4075d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala     *
4085d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala     * @return int An error code corresponding to one of the
4095d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala     * {@link ICameraService} error constants, or 0 on success.
4105d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala     */
4115d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    private static native int nativeSetupGlobalVendorTagDescriptor();
41285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
41385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    /**
41470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * Set a camera metadata field to a value. The field definitions can be
41568f40066c914aefc1f88819dd46dd1135fb9f5bcIgor Murashkin     * found in {@link CameraCharacteristics}, {@link CaptureResult}, and
41670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * {@link CaptureRequest}.
41770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
41870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @param key The metadata field to write.
41970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @param value The value to set the field to, which must be of a matching
42070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * type to the key.
42170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
42270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public <T> void set(Key<T> key, T value) {
423d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        SetCommand s = sSetCommandMap.get(key);
424d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        if (s != null) {
425d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            s.setValue(this, value);
42670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            return;
42770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
42870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
429b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        setBase(key, value);
43070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
43170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
432d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public <T> void set(CaptureRequest.Key<T> key, T value) {
433d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        set(key.getNativeKey(), value);
434d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
435d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
436d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public <T> void set(CaptureResult.Key<T> key, T value) {
437d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        set(key.getNativeKey(), value);
438d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
439d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
440d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public <T> void set(CameraCharacteristics.Key<T> key, T value) {
441d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        set(key.getNativeKey(), value);
442d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
443d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
44470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    // Keep up-to-date with camera_metadata.h
44570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
44670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
44770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
44870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public static final int TYPE_BYTE = 0;
44970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
45070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
45170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
45270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public static final int TYPE_INT32 = 1;
45370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
45470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
45570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
45670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public static final int TYPE_FLOAT = 2;
45770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
45870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
45970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
46070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public static final int TYPE_INT64 = 3;
46170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
46270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
46370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
46470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public static final int TYPE_DOUBLE = 4;
46570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
46670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
46770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
46870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public static final int TYPE_RATIONAL = 5;
46970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
47070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
47170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
47270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public static final int NUM_TYPES = 6;
47370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
47470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private void close() {
47570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        // this sets mMetadataPtr to 0
47670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        nativeClose();
47770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        mMetadataPtr = 0; // set it to 0 again to prevent eclipse from making this field final
47870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
47970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
480d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    private <T> T getBase(CameraCharacteristics.Key<T> key) {
481d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return getBase(key.getNativeKey());
482d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
483d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
484d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    private <T> T getBase(CaptureResult.Key<T> key) {
485d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return getBase(key.getNativeKey());
486d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
487d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
488d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    private <T> T getBase(CaptureRequest.Key<T> key) {
489d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return getBase(key.getNativeKey());
490d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
491d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
492b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    private <T> T getBase(Key<T> key) {
493de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        int tag = nativeGetTagFromKeyLocal(key.getName());
494b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        byte[] values = readValues(tag);
495b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        if (values == null) {
496b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            return null;
497b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
498b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
499de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        int nativeType = nativeGetTypeFromTagLocal(tag);
500de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        Marshaler<T> marshaler = getMarshalerForKey(key, nativeType);
501b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder());
5023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return marshaler.unmarshal(buffer);
503b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    }
504b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
505d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk    // Use Command pattern here to avoid lots of expensive if/equals checks in get for overridden
506d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk    // metadata.
507d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk    private static final HashMap<Key<?>, GetCommand> sGetCommandMap =
508d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            new HashMap<Key<?>, GetCommand>();
509d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk    static {
510d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
511d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CameraCharacteristics.SCALER_AVAILABLE_FORMATS.getNativeKey(), new GetCommand() {
512d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
513d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
514d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
515d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getAvailableFormats();
516d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
517d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
518d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
519d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CaptureResult.STATISTICS_FACES.getNativeKey(), new GetCommand() {
520d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
521d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
522d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
52340001f5dac10c8b71af5ef051dc1a95d58bea743Ruben Brunk                        return (T) metadata.getFaces();
524d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
525d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
526d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
527d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CaptureResult.STATISTICS_FACE_RECTANGLES.getNativeKey(), new GetCommand() {
528d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
529d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
530d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
53140001f5dac10c8b71af5ef051dc1a95d58bea743Ruben Brunk                        return (T) metadata.getFaceRectangles();
532d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
533d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
534d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
535d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP.getNativeKey(),
536d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        new GetCommand() {
537d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
538d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
539d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
540d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getStreamConfigurationMap();
541d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
542d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
543d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
544d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CameraCharacteristics.CONTROL_MAX_REGIONS_AE.getNativeKey(), new GetCommand() {
545d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
546d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
547d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
548d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getMaxRegions(key);
549d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
550d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
551d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
552d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CameraCharacteristics.CONTROL_MAX_REGIONS_AWB.getNativeKey(), new GetCommand() {
553d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
554d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
555d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
556d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getMaxRegions(key);
557d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
558d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
559d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
560d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CameraCharacteristics.CONTROL_MAX_REGIONS_AF.getNativeKey(), new GetCommand() {
561d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
562d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
563d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
564d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getMaxRegions(key);
565d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
566d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
567d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
568d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW.getNativeKey(), new GetCommand() {
569d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
570d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
571d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
572d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getMaxNumOutputs(key);
573d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
574d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
575d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
576d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC.getNativeKey(), new GetCommand() {
577d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
578d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
579d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
580d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getMaxNumOutputs(key);
581d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
582d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
583d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
584d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING.getNativeKey(),
585d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        new GetCommand() {
586d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
587d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
588d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
589d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getMaxNumOutputs(key);
590d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
591d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
592d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
593d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CaptureRequest.TONEMAP_CURVE.getNativeKey(), new GetCommand() {
594d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
595d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
596d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
597d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getTonemapCurve();
598d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
599d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
600d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
601d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CaptureResult.JPEG_GPS_LOCATION.getNativeKey(), new GetCommand() {
602d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
603d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
604d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
605d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getGpsLocation();
606d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
607d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
608d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sGetCommandMap.put(
609d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP.getNativeKey(),
610d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        new GetCommand() {
611d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @Override
612d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    @SuppressWarnings("unchecked")
613d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
614d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                        return (T) metadata.getLensShadingMap();
615d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                    }
616d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                });
617b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    }
618b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
619b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    private int[] getAvailableFormats() {
620b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] availableFormats = getBase(CameraCharacteristics.SCALER_AVAILABLE_FORMATS);
6212f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He        if (availableFormats != null) {
6222f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He            for (int i = 0; i < availableFormats.length; i++) {
6232f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He                // JPEG has different value between native and managed side, need override.
6242f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He                if (availableFormats[i] == NATIVE_JPEG_FORMAT) {
6252f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He                    availableFormats[i] = ImageFormat.JPEG;
6262f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He                }
627b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            }
628b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
6292f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He
630b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        return availableFormats;
631b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    }
632b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
6330a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private boolean setFaces(Face[] faces) {
6340a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        if (faces == null) {
6350a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            return false;
6360a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
6370a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6380a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        int numFaces = faces.length;
6390a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6400a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        // Detect if all faces are SIMPLE or not; count # of valid faces
6410a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        boolean fullMode = true;
6420a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        for (Face face : faces) {
6430a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            if (face == null) {
6440a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                numFaces--;
6450a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                Log.w(TAG, "setFaces - null face detected, skipping");
6460a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                continue;
6470a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
6480a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6490a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            if (face.getId() == Face.ID_UNSUPPORTED) {
6500a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                fullMode = false;
6510a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
6520a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
6530a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6540a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        Rect[] faceRectangles = new Rect[numFaces];
6550a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        byte[] faceScores = new byte[numFaces];
6560a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        int[] faceIds = null;
6570a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        int[] faceLandmarks = null;
6580a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6590a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        if (fullMode) {
6600a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            faceIds = new int[numFaces];
6610a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            faceLandmarks = new int[numFaces * FACE_LANDMARK_SIZE];
6620a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
6630a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6640a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        int i = 0;
6650a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        for (Face face : faces) {
6660a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            if (face == null) {
6670a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                continue;
6680a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
6690a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6700a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            faceRectangles[i] = face.getBounds();
6710a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            faceScores[i] = (byte)face.getScore();
6720a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6730a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            if (fullMode) {
6740a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                faceIds[i] = face.getId();
675b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
6760a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                int j = 0;
6770a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6780a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                faceLandmarks[i * FACE_LANDMARK_SIZE + j++] = face.getLeftEyePosition().x;
6790a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                faceLandmarks[i * FACE_LANDMARK_SIZE + j++] = face.getLeftEyePosition().y;
6800a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                faceLandmarks[i * FACE_LANDMARK_SIZE + j++] = face.getRightEyePosition().x;
6810a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                faceLandmarks[i * FACE_LANDMARK_SIZE + j++] = face.getRightEyePosition().y;
6820a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                faceLandmarks[i * FACE_LANDMARK_SIZE + j++] = face.getMouthPosition().x;
6830a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                faceLandmarks[i * FACE_LANDMARK_SIZE + j++] = face.getMouthPosition().y;
6840a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
6850a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6860a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            i++;
6870a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
6880a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6890a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        set(CaptureResult.STATISTICS_FACE_RECTANGLES, faceRectangles);
6900a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        set(CaptureResult.STATISTICS_FACE_IDS, faceIds);
6910a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        set(CaptureResult.STATISTICS_FACE_LANDMARKS, faceLandmarks);
6920a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        set(CaptureResult.STATISTICS_FACE_SCORES, faceScores);
6930a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6940a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        return true;
6950a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    }
6960a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
6970a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private Face[] getFaces() {
69858216c2650c9536f93467d6ab347ca3f7720deddZhijun He        Integer faceDetectMode = get(CaptureResult.STATISTICS_FACE_DETECT_MODE);
699d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        byte[] faceScores = get(CaptureResult.STATISTICS_FACE_SCORES);
700d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        Rect[] faceRectangles = get(CaptureResult.STATISTICS_FACE_RECTANGLES);
701d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        int[] faceIds = get(CaptureResult.STATISTICS_FACE_IDS);
702d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        int[] faceLandmarks = get(CaptureResult.STATISTICS_FACE_LANDMARKS);
703d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh
704d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        if (areValuesAllNull(faceDetectMode, faceScores, faceRectangles, faceIds, faceLandmarks)) {
705d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh            return null;
706d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        }
707d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh
708b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        if (faceDetectMode == null) {
70958216c2650c9536f93467d6ab347ca3f7720deddZhijun He            Log.w(TAG, "Face detect mode metadata is null, assuming the mode is SIMPLE");
71058216c2650c9536f93467d6ab347ca3f7720deddZhijun He            faceDetectMode = CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE;
71158216c2650c9536f93467d6ab347ca3f7720deddZhijun He        } else {
71258216c2650c9536f93467d6ab347ca3f7720deddZhijun He            if (faceDetectMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_OFF) {
71358216c2650c9536f93467d6ab347ca3f7720deddZhijun He                return new Face[0];
71458216c2650c9536f93467d6ab347ca3f7720deddZhijun He            }
71558216c2650c9536f93467d6ab347ca3f7720deddZhijun He            if (faceDetectMode != CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE &&
71658216c2650c9536f93467d6ab347ca3f7720deddZhijun He                    faceDetectMode != CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL) {
71758216c2650c9536f93467d6ab347ca3f7720deddZhijun He                Log.w(TAG, "Unknown face detect mode: " + faceDetectMode);
71858216c2650c9536f93467d6ab347ca3f7720deddZhijun He                return new Face[0];
71958216c2650c9536f93467d6ab347ca3f7720deddZhijun He            }
720b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
721b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
722b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        // Face scores and rectangles are required by SIMPLE and FULL mode.
723b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        if (faceScores == null || faceRectangles == null) {
72458216c2650c9536f93467d6ab347ca3f7720deddZhijun He            Log.w(TAG, "Expect face scores and rectangles to be non-null");
72558216c2650c9536f93467d6ab347ca3f7720deddZhijun He            return new Face[0];
726b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        } else if (faceScores.length != faceRectangles.length) {
72758216c2650c9536f93467d6ab347ca3f7720deddZhijun He            Log.w(TAG, String.format("Face score size(%d) doesn match face rectangle size(%d)!",
72858216c2650c9536f93467d6ab347ca3f7720deddZhijun He                    faceScores.length, faceRectangles.length));
729b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
730b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
73158216c2650c9536f93467d6ab347ca3f7720deddZhijun He        // To be safe, make number of faces is the minimal of all face info metadata length.
73258216c2650c9536f93467d6ab347ca3f7720deddZhijun He        int numFaces = Math.min(faceScores.length, faceRectangles.length);
733b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        // Face id and landmarks are only required by FULL mode.
734b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        if (faceDetectMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL) {
735b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            if (faceIds == null || faceLandmarks == null) {
73658216c2650c9536f93467d6ab347ca3f7720deddZhijun He                Log.w(TAG, "Expect face ids and landmarks to be non-null for FULL mode," +
73758216c2650c9536f93467d6ab347ca3f7720deddZhijun He                        "fallback to SIMPLE mode");
73858216c2650c9536f93467d6ab347ca3f7720deddZhijun He                faceDetectMode = CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE;
73958216c2650c9536f93467d6ab347ca3f7720deddZhijun He            } else {
74058216c2650c9536f93467d6ab347ca3f7720deddZhijun He                if (faceIds.length != numFaces ||
74158216c2650c9536f93467d6ab347ca3f7720deddZhijun He                        faceLandmarks.length != numFaces * FACE_LANDMARK_SIZE) {
74258216c2650c9536f93467d6ab347ca3f7720deddZhijun He                    Log.w(TAG, String.format("Face id size(%d), or face landmark size(%d) don't" +
74358216c2650c9536f93467d6ab347ca3f7720deddZhijun He                            "match face number(%d)!",
74458216c2650c9536f93467d6ab347ca3f7720deddZhijun He                            faceIds.length, faceLandmarks.length * FACE_LANDMARK_SIZE, numFaces));
74558216c2650c9536f93467d6ab347ca3f7720deddZhijun He                }
74658216c2650c9536f93467d6ab347ca3f7720deddZhijun He                // To be safe, make number of faces is the minimal of all face info metadata length.
74758216c2650c9536f93467d6ab347ca3f7720deddZhijun He                numFaces = Math.min(numFaces, faceIds.length);
74858216c2650c9536f93467d6ab347ca3f7720deddZhijun He                numFaces = Math.min(numFaces, faceLandmarks.length / FACE_LANDMARK_SIZE);
749b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            }
750b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
751b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
752844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He        ArrayList<Face> faceList = new ArrayList<Face>();
753b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        if (faceDetectMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE) {
754b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            for (int i = 0; i < numFaces; i++) {
755844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                if (faceScores[i] <= Face.SCORE_MAX &&
756844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                        faceScores[i] >= Face.SCORE_MIN) {
757844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                    faceList.add(new Face(faceRectangles[i], faceScores[i]));
758844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                }
759b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            }
760b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        } else {
761b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            // CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL
762b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            for (int i = 0; i < numFaces; i++) {
763844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                if (faceScores[i] <= Face.SCORE_MAX &&
764844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                        faceScores[i] >= Face.SCORE_MIN &&
765844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                        faceIds[i] >= 0) {
7660a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    Point leftEye = new Point(faceLandmarks[i*FACE_LANDMARK_SIZE],
7670a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                            faceLandmarks[i*FACE_LANDMARK_SIZE+1]);
7680a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    Point rightEye = new Point(faceLandmarks[i*FACE_LANDMARK_SIZE+2],
7690a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                            faceLandmarks[i*FACE_LANDMARK_SIZE+3]);
7700a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    Point mouth = new Point(faceLandmarks[i*FACE_LANDMARK_SIZE+4],
7710a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                            faceLandmarks[i*FACE_LANDMARK_SIZE+5]);
772844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                    Face face = new Face(faceRectangles[i], faceScores[i], faceIds[i],
773844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                            leftEye, rightEye, mouth);
774844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                    faceList.add(face);
775844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He                }
776b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            }
777b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
778844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He        Face[] faces = new Face[faceList.size()];
779844b3520cc31dbca40f282e5a0e3e6d442d4c686Zhijun He        faceList.toArray(faces);
780b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        return faces;
781b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    }
782b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
783615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala    // Face rectangles are defined as (left, top, right, bottom) instead of
784615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala    // (left, top, width, height) at the native level, so the normal Rect
785615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala    // conversion that does (l, t, w, h) -> (l, t, r, b) is unnecessary. Undo
786615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala    // that conversion here for just the faces.
7872f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He    private Rect[] getFaceRectangles() {
788615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala        Rect[] faceRectangles = getBase(CaptureResult.STATISTICS_FACE_RECTANGLES);
789615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala        if (faceRectangles == null) return null;
790615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala
791615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala        Rect[] fixedFaceRectangles = new Rect[faceRectangles.length];
792615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala        for (int i = 0; i < faceRectangles.length; i++) {
793615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala            fixedFaceRectangles[i] = new Rect(
794615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala                    faceRectangles[i].left,
795615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala                    faceRectangles[i].top,
796615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala                    faceRectangles[i].right - faceRectangles[i].left,
797615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala                    faceRectangles[i].bottom - faceRectangles[i].top);
798615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala        }
799615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala        return fixedFaceRectangles;
800615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala    }
801615b75f3351065845f95f6a2339461813f530ae9Eino-Ville Talvala
802574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    private LensShadingMap getLensShadingMap() {
803574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        float[] lsmArray = getBase(CaptureResult.STATISTICS_LENS_SHADING_MAP);
804d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        Size s = get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE);
805d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh
806d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        // Do not warn if lsmArray is null while s is not. This is valid.
807574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        if (lsmArray == null) {
808574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            return null;
809574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        }
810d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh
811d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        if (s == null) {
812d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh            Log.w(TAG, "getLensShadingMap - Lens shading map size was null.");
813d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh            return null;
814d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        }
815d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh
816574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        LensShadingMap map = new LensShadingMap(lsmArray, s.getHeight(), s.getWidth());
817574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        return map;
818574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    }
819574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
820574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    private Location getGpsLocation() {
821574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        String processingMethod = get(CaptureResult.JPEG_GPS_PROCESSING_METHOD);
822574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        double[] coords = get(CaptureResult.JPEG_GPS_COORDINATES);
823d00847992067eab6d871a0110af01c0d7a788b8eEmilian Peev        Long timeStamp = get(CaptureResult.JPEG_GPS_TIMESTAMP);
824574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
825d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        if (areValuesAllNull(processingMethod, coords, timeStamp)) {
826d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh            return null;
827d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        }
828d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh
829d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        Location l = new Location(translateProcessToLocationProvider(processingMethod));
830574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        if (timeStamp != null) {
831d00847992067eab6d871a0110af01c0d7a788b8eEmilian Peev            // Location expects timestamp in [ms.]
832d00847992067eab6d871a0110af01c0d7a788b8eEmilian Peev            l.setTime(timeStamp * 1000);
833574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        } else {
834574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            Log.w(TAG, "getGpsLocation - No timestamp for GPS location.");
835574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        }
836574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
837574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        if (coords != null) {
838574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            l.setLatitude(coords[0]);
839574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            l.setLongitude(coords[1]);
840574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            l.setAltitude(coords[2]);
841574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        } else {
842574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            Log.w(TAG, "getGpsLocation - No coordinates for GPS location");
843574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        }
844574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
845574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        return l;
846574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    }
847574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
848574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    private boolean setGpsLocation(Location l) {
849574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        if (l == null) {
850574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            return false;
851574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        }
852574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
853574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        double[] coords = { l.getLatitude(), l.getLongitude(), l.getAltitude() };
854574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        String processMethod = translateLocationProviderToProcess(l.getProvider());
8558f240961cc4f57bee94373de0c8da39f4662c4aeEmilian Peev        //JPEG_GPS_TIMESTAMP expects sec. instead of msec.
8568f240961cc4f57bee94373de0c8da39f4662c4aeEmilian Peev        long timestamp = l.getTime() / 1000;
857574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
858574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        set(CaptureRequest.JPEG_GPS_TIMESTAMP, timestamp);
859574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        set(CaptureRequest.JPEG_GPS_COORDINATES, coords);
860574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
861574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        if (processMethod == null) {
862574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            Log.w(TAG, "setGpsLocation - No process method, Location is not from a GPS or NETWORK" +
863574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk                    "provider");
864574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        } else {
865574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk            setBase(CaptureRequest.JPEG_GPS_PROCESSING_METHOD, processMethod);
866574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        }
867574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk        return true;
868574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk    }
869574936894d3044445a272b39f2d925af40ece5d8Ruben Brunk
8709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private StreamConfigurationMap getStreamConfigurationMap() {
8719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        StreamConfiguration[] configurations = getBase(
8729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
8739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        StreamConfigurationDuration[] minFrameDurations = getBase(
8749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
8759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        StreamConfigurationDuration[] stallDurations = getBase(
8769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS);
877456432ead7e262f72565d02ac46fd5e498844b92Eino-Ville Talvala        StreamConfiguration[] depthConfigurations = getBase(
878456432ead7e262f72565d02ac46fd5e498844b92Eino-Ville Talvala                CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
879456432ead7e262f72565d02ac46fd5e498844b92Eino-Ville Talvala        StreamConfigurationDuration[] depthMinFrameDurations = getBase(
880456432ead7e262f72565d02ac46fd5e498844b92Eino-Ville Talvala                CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS);
881456432ead7e262f72565d02ac46fd5e498844b92Eino-Ville Talvala        StreamConfigurationDuration[] depthStallDurations = getBase(
882456432ead7e262f72565d02ac46fd5e498844b92Eino-Ville Talvala                CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS);
88312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase(
88412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
8850a551f1487e00a598b20b1bc58a1ccd7226e7091Chien-Yu Chen        ReprocessFormatsMap inputOutputFormatsMap = getBase(
8860a551f1487e00a598b20b1bc58a1ccd7226e7091Chien-Yu Chen                CameraCharacteristics.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP);
8870819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala        int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
8880819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala        boolean listHighResolution = false;
8890819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala        for (int capability : capabilities) {
8900819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala            if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) {
8910819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala                listHighResolution = true;
8920819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala                break;
8930819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala            }
8940819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala        }
89512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        return new StreamConfigurationMap(
896456432ead7e262f72565d02ac46fd5e498844b92Eino-Ville Talvala                configurations, minFrameDurations, stallDurations,
897456432ead7e262f72565d02ac46fd5e498844b92Eino-Ville Talvala                depthConfigurations, depthMinFrameDurations, depthStallDurations,
8980819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala                highSpeedVideoConfigurations, inputOutputFormatsMap,
8990819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala                listHighResolution);
9009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
9019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
90278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    private <T> Integer getMaxRegions(Key<T> key) {
90378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        final int AE = 0;
90478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        final int AWB = 1;
90578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        final int AF = 2;
90678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
90778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // The order of the elements is: (AE, AWB, AF)
90878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        int[] maxRegions = getBase(CameraCharacteristics.CONTROL_MAX_REGIONS);
90978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
91078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        if (maxRegions == null) {
91178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            return null;
91278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        }
91378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
91478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        if (key.equals(CameraCharacteristics.CONTROL_MAX_REGIONS_AE)) {
91578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            return maxRegions[AE];
91678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        } else if (key.equals(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB)) {
91778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            return maxRegions[AWB];
91878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        } else if (key.equals(CameraCharacteristics.CONTROL_MAX_REGIONS_AF)) {
91978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            return maxRegions[AF];
92078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        } else {
92178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            throw new AssertionError("Invalid key " + key);
92278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        }
92378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
92478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
92578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    private <T> Integer getMaxNumOutputs(Key<T> key) {
92678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        final int RAW = 0;
92778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        final int PROC = 1;
92878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        final int PROC_STALLING = 2;
92978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
93078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // The order of the elements is: (raw, proc+nonstalling, proc+stalling)
93178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        int[] maxNumOutputs = getBase(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS);
93278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
93378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        if (maxNumOutputs == null) {
93478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            return null;
93578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        }
93678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
93778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        if (key.equals(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW)) {
93878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            return maxNumOutputs[RAW];
93978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        } else if (key.equals(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC)) {
94078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            return maxNumOutputs[PROC];
94178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        } else if (key.equals(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING)) {
94278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            return maxNumOutputs[PROC_STALLING];
94378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        } else {
94478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin            throw new AssertionError("Invalid key " + key);
94578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        }
94678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
94778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
9488490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh    private <T> TonemapCurve getTonemapCurve() {
9498490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] red = getBase(CaptureRequest.TONEMAP_CURVE_RED);
9508490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] green = getBase(CaptureRequest.TONEMAP_CURVE_GREEN);
9518490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] blue = getBase(CaptureRequest.TONEMAP_CURVE_BLUE);
952d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh
953d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        if (areValuesAllNull(red, green, blue)) {
954d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh            return null;
955d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        }
956d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh
9578490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        if (red == null || green == null || blue == null) {
958d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh            Log.w(TAG, "getTonemapCurve - missing tone curve components");
9598490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh            return null;
9608490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        }
9618490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        TonemapCurve tc = new TonemapCurve(red, green, blue);
9628490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        return tc;
9638490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh    }
9648490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh
965d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    private <T> void setBase(CameraCharacteristics.Key<T> key, T value) {
966d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        setBase(key.getNativeKey(), value);
967d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
968d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
969d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    private <T> void setBase(CaptureResult.Key<T> key, T value) {
970d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        setBase(key.getNativeKey(), value);
971d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
972d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
973d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    private <T> void setBase(CaptureRequest.Key<T> key, T value) {
974d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        setBase(key.getNativeKey(), value);
975d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
976d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
977b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    private <T> void setBase(Key<T> key, T value) {
978de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        int tag = nativeGetTagFromKeyLocal(key.getName());
979b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        if (value == null) {
9803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            // Erase the entry
9813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            writeValues(tag, /*src*/null);
982b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            return;
9833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        } // else update the entry to a new value
984b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
985de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        int nativeType = nativeGetTypeFromTagLocal(tag);
986de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        Marshaler<T> marshaler = getMarshalerForKey(key, nativeType);
9873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int size = marshaler.calculateMarshalSize(value);
988b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
989b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        // TODO: Optimization. Cache the byte[] and reuse if the size is big enough.
990b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        byte[] values = new byte[size];
991b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
992b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder());
9933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        marshaler.marshal(value, buffer);
994b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
995b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        writeValues(tag, values);
996b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    }
997b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
998d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk    // Use Command pattern here to avoid lots of expensive if/equals checks in get for overridden
999d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk    // metadata.
1000d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk    private static final HashMap<Key<?>, SetCommand> sSetCommandMap =
1001d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            new HashMap<Key<?>, SetCommand>();
1002d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk    static {
1003d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sSetCommandMap.put(CameraCharacteristics.SCALER_AVAILABLE_FORMATS.getNativeKey(),
1004d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                new SetCommand() {
1005d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            @Override
1006d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            public <T> void setValue(CameraMetadataNative metadata, T value) {
1007d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                metadata.setAvailableFormats((int[]) value);
1008d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            }
1009d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        });
1010d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sSetCommandMap.put(CaptureResult.STATISTICS_FACE_RECTANGLES.getNativeKey(),
1011d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                new SetCommand() {
1012d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            @Override
1013d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            public <T> void setValue(CameraMetadataNative metadata, T value) {
1014d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                metadata.setFaceRectangles((Rect[]) value);
1015d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            }
1016d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        });
10170a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        sSetCommandMap.put(CaptureResult.STATISTICS_FACES.getNativeKey(),
10180a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                new SetCommand() {
10190a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            @Override
10200a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            public <T> void setValue(CameraMetadataNative metadata, T value) {
10210a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                metadata.setFaces((Face[])value);
10220a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
10230a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        });
1024d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sSetCommandMap.put(CaptureRequest.TONEMAP_CURVE.getNativeKey(), new SetCommand() {
1025d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            @Override
1026d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            public <T> void setValue(CameraMetadataNative metadata, T value) {
1027d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                metadata.setTonemapCurve((TonemapCurve) value);
1028d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            }
1029d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        });
1030d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        sSetCommandMap.put(CaptureResult.JPEG_GPS_LOCATION.getNativeKey(), new SetCommand() {
1031d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            @Override
1032d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            public <T> void setValue(CameraMetadataNative metadata, T value) {
1033d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk                metadata.setGpsLocation((Location) value);
1034d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk            }
1035d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk        });
1036b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    }
1037b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
1038b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    private boolean setAvailableFormats(int[] value) {
1039b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] availableFormat = value;
1040b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        if (value == null) {
1041b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            // Let setBase() to handle the null value case.
1042b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            return false;
1043b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1044b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
1045b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] newValues = new int[availableFormat.length];
1046b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (int i = 0; i < availableFormat.length; i++) {
1047b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            newValues[i] = availableFormat[i];
1048b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            if (availableFormat[i] == ImageFormat.JPEG) {
1049b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                newValues[i] = NATIVE_JPEG_FORMAT;
1050b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            }
1051b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1052b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
1053b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        setBase(CameraCharacteristics.SCALER_AVAILABLE_FORMATS, newValues);
1054b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        return true;
1055b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    }
1056b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
10572f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He    /**
10582f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     * Convert Face Rectangles from managed side to native side as they have different definitions.
10592f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     * <p>
10602f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     * Managed side face rectangles are defined as: left, top, width, height.
10612f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     * Native side face rectangles are defined as: left, top, right, bottom.
10622f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     * The input face rectangle need to be converted to native side definition when set is called.
10632f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     * </p>
10642f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     *
10652f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     * @param faceRects Input face rectangles.
10662f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     * @return true if face rectangles can be set successfully. Otherwise, Let the caller
10672f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     *             (setBase) to handle it appropriately.
10682f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He     */
10692f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He    private boolean setFaceRectangles(Rect[] faceRects) {
10702f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He        if (faceRects == null) {
10712f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He            return false;
10722f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He        }
10732f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He
10742f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He        Rect[] newFaceRects = new Rect[faceRects.length];
10752f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He        for (int i = 0; i < newFaceRects.length; i++) {
10762f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He            newFaceRects[i] = new Rect(
10772f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He                    faceRects[i].left,
10782f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He                    faceRects[i].top,
10792f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He                    faceRects[i].right + faceRects[i].left,
10802f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He                    faceRects[i].bottom + faceRects[i].top);
10812f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He        }
10822f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He
10832f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He        setBase(CaptureResult.STATISTICS_FACE_RECTANGLES, newFaceRects);
10842f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He        return true;
10852f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He    }
10862f1680be3d5963dc1026c8e5bcda491b77d71734Zhijun He
10878490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh    private <T> boolean setTonemapCurve(TonemapCurve tc) {
10888490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        if (tc == null) {
10898490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh            return false;
10908490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        }
10918490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh
10928490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[][] curve = new float[3][];
10938490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        for (int i = TonemapCurve.CHANNEL_RED; i <= TonemapCurve.CHANNEL_BLUE; i++) {
10948490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh            int pointCount = tc.getPointCount(i);
10958490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh            curve[i] = new float[pointCount * TonemapCurve.POINT_SIZE];
10968490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh            tc.copyColorCurve(i, curve[i], 0);
10978490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        }
10988490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        setBase(CaptureRequest.TONEMAP_CURVE_RED, curve[0]);
10998490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        setBase(CaptureRequest.TONEMAP_CURVE_GREEN, curve[1]);
11008490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        setBase(CaptureRequest.TONEMAP_CURVE_BLUE, curve[2]);
11018490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh
11028490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        return true;
11038490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh    }
11048490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh
110570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private long mMetadataPtr; // native CameraMetadata*
110670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
110770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native long nativeAllocate();
110870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native long nativeAllocateCopy(CameraMetadataNative other)
110970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            throws NullPointerException;
111070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
111170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native synchronized void nativeWriteToParcel(Parcel dest);
111270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native synchronized void nativeReadFromParcel(Parcel source);
111370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native synchronized void nativeSwap(CameraMetadataNative other)
111470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            throws NullPointerException;
111570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native synchronized void nativeClose();
111670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native synchronized boolean nativeIsEmpty();
111770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native synchronized int nativeGetEntryCount();
111870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
111970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native synchronized byte[] nativeReadValues(int tag);
112070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    private native synchronized void nativeWriteValues(int tag, byte[] src);
1121d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    private native synchronized void nativeDump() throws IOException; // dump to ALOGD
112270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
1123de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    private native synchronized ArrayList nativeGetAllVendorKeys(Class keyClass);
1124de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    private native synchronized int nativeGetTagFromKeyLocal(String keyName)
112570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            throws IllegalArgumentException;
1126de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    private native synchronized int nativeGetTypeFromTagLocal(int tag)
1127de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            throws IllegalArgumentException;
1128de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    private static native int nativeGetTagFromKey(String keyName, long vendorId)
1129de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            throws IllegalArgumentException;
1130de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    private static native int nativeGetTypeFromTag(int tag, long vendorId)
113170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            throws IllegalArgumentException;
113270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
113370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
113470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * <p>Perform a 0-copy swap of the internal metadata with another object.</p>
113570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
113670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * <p>Useful to convert a CameraMetadata into e.g. a CaptureRequest.</p>
113770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
113870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @param other Metadata to swap with
113970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @throws NullPointerException if other was null
114070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
114170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
114270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public void swap(CameraMetadataNative other) {
114370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        nativeSwap(other);
114470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
114570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
114670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
114770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
114870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
114970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public int getEntryCount() {
115070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        return nativeGetEntryCount();
115170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
115270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
115370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
115470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * Does this metadata contain at least 1 entry?
115570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
115670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
115770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
115870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public boolean isEmpty() {
115970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        return nativeIsEmpty();
116070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
116170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
1162c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
1163c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    /**
1164c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk     * Return a list containing keys of the given key class for all defined vendor tags.
1165c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk     *
1166c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk     * @hide
1167c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk     */
1168de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    public <K>  ArrayList<K> getAllVendorKeys(Class<K> keyClass) {
1169c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        if (keyClass == null) {
1170c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            throw new NullPointerException();
1171c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        }
1172c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        return (ArrayList<K>) nativeGetAllVendorKeys(keyClass);
1173c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
1174c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
117570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
117670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * Convert a key string into the equivalent native tag.
117770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
117870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @throws IllegalArgumentException if the key was not recognized
117970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @throws NullPointerException if the key was null
118070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
118170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
118270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
118370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public static int getTag(String key) {
1184de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        return nativeGetTagFromKey(key, Long.MAX_VALUE);
1185de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    }
1186de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
1187de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    /**
1188de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev     * Convert a key string into the equivalent native tag.
1189de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev     *
1190de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev     * @throws IllegalArgumentException if the key was not recognized
1191de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev     * @throws NullPointerException if the key was null
1192de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev     *
1193de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev     * @hide
1194de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev     */
1195de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    public static int getTag(String key, long vendorId) {
1196de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        return nativeGetTagFromKey(key, vendorId);
119770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
119870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
119970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
120070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * Get the underlying native type for a tag.
120170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
120270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @param tag An integer tag, see e.g. {@link #getTag}
1203de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev     * @param vendorId A vendor tag provider id
120470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @return An int enum for the metadata type, see e.g. {@link #TYPE_BYTE}
120570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
120670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
120770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
1208de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    public static int getNativeType(int tag, long vendorId) {
1209de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        return nativeGetTypeFromTag(tag, vendorId);
121070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
121170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
121270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
121370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * <p>Updates the existing entry for tag with the new bytes pointed by src, erasing
121470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * the entry if src was null.</p>
121570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
121670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * <p>An empty array can be passed in to update the entry to 0 elements.</p>
121770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
121870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @param tag An integer tag, see e.g. {@link #getTag}
121970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @param src An array of bytes, or null to erase the entry
122070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
122170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
122270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
122370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public void writeValues(int tag, byte[] src) {
122470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        nativeWriteValues(tag, src);
122570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
122670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
122770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
122870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * <p>Returns a byte[] of data corresponding to this tag. Use a wrapped bytebuffer to unserialize
122970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * the data properly.</p>
123070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
123170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * <p>An empty array can be returned to denote an existing entry with 0 elements.</p>
123270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
123370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @param tag An integer tag, see e.g. {@link #getTag}
123470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
123570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @return {@code null} if there were 0 entries for this tag, a byte[] otherwise.
123670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     * @hide
123770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
123870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    public byte[] readValues(int tag) {
1239b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        // TODO: Optimization. Native code returns a ByteBuffer instead.
124070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        return nativeReadValues(tag);
124170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
124270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
1243d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /**
1244d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Dumps the native metadata contents to logcat.
1245d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
1246d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * <p>Visibility for testing/debugging only. The results will not
1247d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * include any synthesized keys, as they are invisible to the native layer.</p>
1248d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
1249d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * @hide
1250d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
1251d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public void dumpToLog() {
1252d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        try {
1253d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            nativeDump();
1254d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        } catch (IOException e) {
1255d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            Log.wtf(TAG, "Dump logging failed", e);
1256d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
1257d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
1258d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
125970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    @Override
126070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    protected void finalize() throws Throwable {
126170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        try {
126270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            close();
126370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        } finally {
126470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            super.finalize();
126570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
126670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
126770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
126870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    /**
12693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Get the marshaler compatible with the {@code key} and type {@code T}.
127070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     *
12713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @throws UnsupportedOperationException
12723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *          if the native/managed type combination for {@code key} is not supported
127370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala     */
1274de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    private static <T> Marshaler<T> getMarshalerForKey(Key<T> key, int nativeType) {
12753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return MarshalRegistry.getMarshaler(key.getTypeReference(),
1276de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                nativeType);
127770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
127870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
12793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SuppressWarnings({ "unchecked", "rawtypes" })
12803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private static void registerAllMarshalers() {
1281a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala        if (DEBUG) {
12823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            Log.v(TAG, "Shall register metadata marshalers");
128370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
128470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
12853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        MarshalQueryable[] queryList = new MarshalQueryable[] {
12863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                // marshalers for standard types
12873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryablePrimitive(),
12883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableEnum(),
12893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableArray(),
12903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
12913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                // pseudo standard types, that expand/narrow the native type into a managed type
12923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableBoolean(),
12933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableNativeByteToInteger(),
12943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
12953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                // marshalers for custom types
12963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableRect(),
12973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableSize(),
12983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableSizeF(),
12993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableString(),
13003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableReprocessFormatsMap(),
13013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableRange(),
13025743868e15c88d2886915163652a1571a218bf39Igor Murashkin                new MarshalQueryablePair(),
13033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableMeteringRectangle(),
13043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableColorSpaceTransform(),
13053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableStreamConfiguration(),
13063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableStreamConfigurationDuration(),
13073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableRggbChannelVector(),
130852842e7a6f0e922185db04ae8b91c776a234acf1Ruben Brunk                new MarshalQueryableBlackLevelPattern(),
130912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                new MarshalQueryableHighSpeedVideoConfiguration(),
13103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
13113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                // generic parcelable marshaler (MUST BE LAST since it has lowest priority)
13123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MarshalQueryableParcelable(),
13133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        };
13143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
13153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        for (MarshalQueryable query : queryList) {
13163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            MarshalRegistry.registerMarshalQueryable(query);
131770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
1318a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala        if (DEBUG) {
13193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            Log.v(TAG, "Registered metadata marshalers");
132070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        }
132170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
132270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
1323d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh    /** Check if input arguments are all {@code null}.
1324d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh     *
1325d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh     * @param objs Input arguments for null check
1326d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh     * @return {@code true} if input arguments are all {@code null}, otherwise {@code false}
1327d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh     */
1328d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh    private static boolean areValuesAllNull(Object... objs) {
1329d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        for (Object o : objs) {
1330d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh            if (o != null) return false;
1331d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        }
1332d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh        return true;
1333d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh    }
1334d47699a47a77781c8883f31c48ffae88ba878cf8Yin-Chia Yeh
133570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    static {
13363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        registerAllMarshalers();
133770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    }
133870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala}
1339