summaryrefslogtreecommitdiffstats
path: root/core/java/android/hardware/camera2/marshal/MarshalHelpers.java
blob: 35ecc2a037e91a152dbf2e8def69e4b936e0f54a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.hardware.camera2.marshal;

import static android.hardware.camera2.impl.CameraMetadataNative.*;
import static com.android.internal.util.Preconditions.*;

import android.hardware.camera2.impl.CameraMetadataNative;
import android.util.Rational;

/**
 * Static functions in order to help implementing various marshaler functionality.
 *
 * <p>The intention is to statically import everything from this file into another file when
 * implementing a new marshaler (or marshal queryable).</p>
 *
 * <p>The helpers are centered around providing primitive knowledge of the native types,
 * such as the native size, the managed class wrappers, and various precondition checks.</p>
 */
public final class MarshalHelpers {

    public static final int SIZEOF_BYTE = 1;
    public static final int SIZEOF_INT32 = Integer.SIZE / Byte.SIZE;
    public static final int SIZEOF_INT64 = Long.SIZE / Byte.SIZE;
    public static final int SIZEOF_FLOAT = Float.SIZE / Byte.SIZE;
    public static final int SIZEOF_DOUBLE = Double.SIZE / Byte.SIZE;
    public static final int SIZEOF_RATIONAL = SIZEOF_INT32 * 2;

    /**
     * Get the size in bytes for the native camera metadata type.
     *
     * <p>This used to determine how many bytes it would take to encode/decode a single value
     * of that {@link nativeType}.</p>
     *
     * @param nativeType the native type, e.g.
     *        {@link android.hardware.camera2.impl.CameraMetadataNative#TYPE_BYTE TYPE_BYTE}.
     * @return size in bytes >= 1
     *
     * @throws UnsupportedOperationException if nativeType was not one of the built-in types
     */
    public static int getPrimitiveTypeSize(int nativeType) {
        switch (nativeType) {
            case TYPE_BYTE:
                return SIZEOF_BYTE;
            case TYPE_INT32:
                return SIZEOF_INT32;
            case TYPE_FLOAT:
                return SIZEOF_FLOAT;
            case TYPE_INT64:
                return SIZEOF_INT64;
            case TYPE_DOUBLE:
                return SIZEOF_DOUBLE;
            case TYPE_RATIONAL:
                return SIZEOF_RATIONAL;
        }

        throw new UnsupportedOperationException("Unknown type, can't get size for "
                + nativeType);
    }


    /**
     * Ensure that the {@code klass} is one of the metadata-primitive classes.
     *
     * @param klass a non-{@code null} reference
     * @return {@code klass} instance
     *
     * @throws UnsupportedOperationException if klass was not one of the built-in classes
     * @throws NullPointerException if klass was null
     *
     * @see #isPrimitiveClass
     */
    public static <T> Class<T> checkPrimitiveClass(Class<T> klass) {
        checkNotNull(klass, "klass must not be null");

        if (isPrimitiveClass(klass)) {
            return klass;
        }

        throw new UnsupportedOperationException("Unsupported class '" + klass +
                "'; expected a metadata primitive class");
    }

    /**
     * Checks whether or not {@code klass} is one of the metadata-primitive classes.
     *
     * <p>The following types (whether boxed or unboxed) are considered primitive:
     * <ul>
     * <li>byte
     * <li>int
     * <li>float
     * <li>double
     * <li>Rational
     * </ul>
     * </p>
     *
     * <p>This doesn't strictly follow the java understanding of primitive since
     * boxed objects are included, Rational is included, and other types such as char and
     * short are not included.</p>
     *
     * @param klass a {@link Class} instance; using {@code null} will return {@code false}
     * @return {@code true} if primitive, {@code false} otherwise
     */
    public static <T> boolean isPrimitiveClass(Class<T> klass) {
        if (klass == null) {
            return false;
        }

        if (klass == byte.class || klass == Byte.class) {
            return true;
        } else if (klass == int.class || klass == Integer.class) {
            return true;
        } else if (klass == float.class || klass == Float.class) {
            return true;
        } else if (klass == long.class || klass == Long.class) {
            return true;
        } else if (klass == double.class || klass == Double.class) {
            return true;
        } else if (klass == Rational.class) {
            return true;
        }

        return false;
    }

    /**
     * Wrap {@code klass} with its wrapper variant if it was a {@code Class} corresponding
     * to a Java primitive.
     *
     * <p>Non-primitive classes are passed through as-is.</p>
     *
     * <p>For example, for a primitive {@code int.class => Integer.class},
     * but for a non-primitive {@code Rational.class => Rational.class}.</p>
     *
     * @param klass a {@code Class} reference
     *
     * @return wrapped class object, or same class object if non-primitive
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> wrapClassIfPrimitive(Class<T> klass) {
        if (klass == byte.class) {
            return (Class<T>)Byte.class;
        } else if (klass == int.class) {
            return (Class<T>)Integer.class;
        } else if (klass == float.class) {
            return (Class<T>)Float.class;
        } else if (klass == long.class) {
            return (Class<T>)Long.class;
        } else if (klass == double.class) {
            return (Class<T>)Double.class;
        }

        return klass;
    }

    /**
     * Return a human-readable representation of the {@code nativeType}, e.g. "TYPE_INT32"
     *
     * <p>Out-of-range values return a string with "UNKNOWN" as the prefix.</p>
     *
     * @param nativeType the native type
     *
     * @return human readable type name
     */
    public static String toStringNativeType(int nativeType) {
        switch (nativeType) {
            case TYPE_BYTE:
                return "TYPE_BYTE";
            case TYPE_INT32:
                return "TYPE_INT32";
            case TYPE_FLOAT:
                return "TYPE_FLOAT";
            case TYPE_INT64:
                return "TYPE_INT64";
            case TYPE_DOUBLE:
                return "TYPE_DOUBLE";
            case TYPE_RATIONAL:
                return "TYPE_RATIONAL";
        }

        return "UNKNOWN(" + nativeType + ")";
    }

    /**
     * Ensure that the {@code nativeType} is one of the native types supported
     * by {@link CameraMetadataNative}.
     *
     * @param nativeType the native type
     *
     * @return the native type
     *
     * @throws UnsupportedOperationException if the native type was invalid
     */
    public static int checkNativeType(int nativeType) {
        switch (nativeType) {
            case TYPE_BYTE:
            case TYPE_INT32:
            case TYPE_FLOAT:
            case TYPE_INT64:
            case TYPE_DOUBLE:
            case TYPE_RATIONAL:
                return nativeType;
        }

        throw new UnsupportedOperationException("Unknown nativeType " + nativeType);
    }

    /**
     * Ensure that the expected and actual native types are equal.
     *
     * @param expectedNativeType the expected native type
     * @param actualNativeType the actual native type
     * @return the actual native type
     *
     * @throws UnsupportedOperationException if the types are not equal
     */
    public static int checkNativeTypeEquals(int expectedNativeType, int actualNativeType) {
        if (expectedNativeType != actualNativeType) {
            throw new UnsupportedOperationException(
                    String.format("Expected native type %d, but got %d",
                            expectedNativeType, actualNativeType));
        }

        return actualNativeType;
    }

    private MarshalHelpers() {
        throw new AssertionError();
    }
}