All Downloads are FREE. Search and download functionalities are using the official Maven repository.

android.hardware.camera2.marshal.impl.MarshalQueryableArray Maven / Gradle / Ivy

Go to download

A library jar that provides APIs for Applications written for the Google Android Platform.

There is a newer version: 14-robolectric-10818077
Show newest version
/*
 * 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.impl;

import android.hardware.camera2.marshal.Marshaler;
import android.hardware.camera2.marshal.MarshalQueryable;
import android.hardware.camera2.marshal.MarshalRegistry;
import android.hardware.camera2.utils.TypeReference;
import android.util.Log;

import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.ArrayList;

import static android.hardware.camera2.impl.CameraMetadataNative.*;
import static android.hardware.camera2.marshal.MarshalHelpers.*;

/**
 * Marshal any array {@code T}.
 *
 * 

To marshal any {@code T} to/from a native type, the marshaler for T to/from that native type * also has to exist.

* *

{@code T} can be either a T2[] where T2 is an object type, or a P[] where P is a * built-in primitive (e.g. int[], float[], etc).

* @param the type of the array (e.g. T = int[], or T = Rational[]) */ public class MarshalQueryableArray implements MarshalQueryable { private static final String TAG = MarshalQueryableArray.class.getSimpleName(); private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); private class MarshalerArray extends Marshaler { private final Class mClass; private final Marshaler mComponentMarshaler; private final Class mComponentClass; @SuppressWarnings("unchecked") protected MarshalerArray(TypeReference typeReference, int nativeType) { super(MarshalQueryableArray.this, typeReference, nativeType); mClass = (Class)typeReference.getRawType(); TypeReference componentToken = typeReference.getComponentType(); mComponentMarshaler = MarshalRegistry.getMarshaler(componentToken, mNativeType); mComponentClass = componentToken.getRawType(); } @Override public void marshal(T value, ByteBuffer buffer) { int length = Array.getLength(value); for (int i = 0; i < length; ++i) { marshalArrayElement(mComponentMarshaler, buffer, value, i); } } @Override public T unmarshal(ByteBuffer buffer) { Object array; int elementSize = mComponentMarshaler.getNativeSize(); if (elementSize != Marshaler.NATIVE_SIZE_DYNAMIC) { int remaining = buffer.remaining(); int arraySize = remaining / elementSize; if (remaining % elementSize != 0) { throw new UnsupportedOperationException("Arrays for " + mTypeReference + " must be packed tighly into a multiple of " + elementSize + "; but there are " + (remaining % elementSize) + " left over bytes"); } if (VERBOSE) { Log.v(TAG, String.format( "Attempting to unpack array (count = %d, element size = %d, bytes " + "remaining = %d) for type %s", arraySize, elementSize, remaining, mClass)); } array = Array.newInstance(mComponentClass, arraySize); for (int i = 0; i < arraySize; ++i) { Object elem = mComponentMarshaler.unmarshal(buffer); Array.set(array, i, elem); } } else { // Dynamic size, use an array list. ArrayList arrayList = new ArrayList(); // Assumes array is packed tightly; no unused bytes allowed while (buffer.hasRemaining()) { Object elem = mComponentMarshaler.unmarshal(buffer); arrayList.add(elem); } int arraySize = arrayList.size(); array = copyListToArray(arrayList, Array.newInstance(mComponentClass, arraySize)); } if (buffer.remaining() != 0) { Log.e(TAG, "Trailing bytes (" + buffer.remaining() + ") left over after unpacking " + mClass); } return mClass.cast(array); } @Override public int getNativeSize() { return NATIVE_SIZE_DYNAMIC; } @Override public int calculateMarshalSize(T value) { int elementSize = mComponentMarshaler.getNativeSize(); int arrayLength = Array.getLength(value); if (elementSize != Marshaler.NATIVE_SIZE_DYNAMIC) { // The fast way. Every element size is uniform. return elementSize * arrayLength; } else { // The slow way. Accumulate size for each element. int size = 0; for (int i = 0; i < arrayLength; ++i) { size += calculateElementMarshalSize(mComponentMarshaler, value, i); } return size; } } /* * Helpers to avoid compiler errors regarding types with wildcards (?) */ @SuppressWarnings("unchecked") private void marshalArrayElement(Marshaler marshaler, ByteBuffer buffer, Object array, int index) { marshaler.marshal((TElem)Array.get(array, index), buffer); } @SuppressWarnings("unchecked") private Object copyListToArray(ArrayList arrayList, Object arrayDest) { return arrayList.toArray((T[]) arrayDest); } @SuppressWarnings("unchecked") private int calculateElementMarshalSize(Marshaler marshaler, Object array, int index) { Object elem = Array.get(array, index); return marshaler.calculateMarshalSize((TElem) elem); } } @Override public Marshaler createMarshaler(TypeReference managedType, int nativeType) { return new MarshalerArray(managedType, nativeType); } @Override public boolean isTypeMappingSupported(TypeReference managedType, int nativeType) { // support both ConcreteType[] and GenericType[] return managedType.getRawType().isArray(); // TODO: Should this recurse deeper and check that there is // a valid marshaler for the ConcreteType as well? } }