13c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin/* 23c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Copyright (C) 2014 The Android Open Source Project 33c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 43c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 53c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * you may not use this file except in compliance with the License. 63c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * You may obtain a copy of the License at 73c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 83c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 93c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Unless required by applicable law or agreed to in writing, software 113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * See the License for the specific language governing permissions and 143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * limitations under the License. 153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinpackage android.hardware.camera2.marshal.impl; 173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.Marshaler; 193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.MarshalQueryable; 203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.utils.TypeReference; 213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.os.Parcel; 223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.os.Parcelable; 233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.util.Log; 243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.lang.reflect.Field; 263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.nio.ByteBuffer; 273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin/** 293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Marshal any {@code T extends Parcelable} to/from any native type 303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>Use with extreme caution! File descriptors and binders will not be marshaled across.</p> 323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinpublic class MarshalQueryableParcelable<T extends Parcelable> 343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin implements MarshalQueryable<T> { 353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static final String TAG = "MarshalParcelable"; 37a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala private static final boolean DEBUG = false; 383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static final String FIELD_CREATOR = "CREATOR"; 403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private class MarshalerParcelable extends Marshaler<T> { 423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private final Class<T> mClass; 443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private final Parcelable.Creator<T> mCreator; 453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @SuppressWarnings("unchecked") 473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin protected MarshalerParcelable(TypeReference<T> typeReference, 483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin int nativeType) { 493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin super(MarshalQueryableParcelable.this, typeReference, nativeType); 503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin mClass = (Class<T>)typeReference.getRawType(); 523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Field creatorField; 533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin try { 543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin creatorField = mClass.getDeclaredField(FIELD_CREATOR); 553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } catch (NoSuchFieldException e) { 563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Impossible. All Parcelable implementations must have a 'CREATOR' static field 573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new AssertionError(e); 583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin try { 613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin mCreator = (Parcelable.Creator<T>)creatorField.get(null); 623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } catch (IllegalAccessException e) { 633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Impossible: All 'CREATOR' static fields must be public 643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new AssertionError(e); 653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } catch (IllegalArgumentException e) { 663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // Impossible: This is a static field, so null must be ok 673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new AssertionError(e); 683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public void marshal(T value, ByteBuffer buffer) { 73a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala if (DEBUG) { 743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Log.v(TAG, "marshal " + value); 753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Parcel parcel = Parcel.obtain(); 783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin byte[] parcelContents; 793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin try { 813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin value.writeToParcel(parcel, /*flags*/0); 823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (parcel.hasFileDescriptors()) { 843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new UnsupportedOperationException( 853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin "Parcelable " + value + " must not have file descriptors"); 863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin parcelContents = parcel.marshall(); 893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin finally { 913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin parcel.recycle(); 923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (parcelContents.length == 0) { 953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new AssertionError("No data marshaled for " + value); 963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.put(parcelContents); 993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 1023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public T unmarshal(ByteBuffer buffer) { 103a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala if (DEBUG) { 1043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Log.v(TAG, "unmarshal, buffer remaining " + buffer.remaining()); 1053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin /* 1083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Quadratically slow when marshaling an array of parcelables. 1093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Read out the entire byte buffer as an array, then copy it into the parcel. 1113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Once we unparcel the entire object, advance the byte buffer by only how many 1133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * bytes the parcel actually used up. 1143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Future: If we ever do need to use parcelable arrays, we can do this a little smarter 1163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * by reading out a chunk like 4,8,16,24 each time, but not sure how to detect 1173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * parcels being too short in this case. 1183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * 1193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Future: Alternatively use Parcel#obtain(long) directly into the native 1203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * pointer of a ByteBuffer, which would not copy if the ByteBuffer was direct. 1213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 1223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.mark(); 1233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Parcel parcel = Parcel.obtain(); 1253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin try { 1263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin int maxLength = buffer.remaining(); 1273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin byte[] remaining = new byte[maxLength]; 1293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.get(remaining); 1303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin parcel.unmarshall(remaining, /*offset*/0, maxLength); 1323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin parcel.setDataPosition(/*pos*/0); 1333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin T value = mCreator.createFromParcel(parcel); 1353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin int actualLength = parcel.dataPosition(); 1363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (actualLength == 0) { 1383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new AssertionError("No data marshaled for " + value); 1393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // set the position past the bytes the parcelable actually used 1423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.reset(); 1433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.position(buffer.position() + actualLength); 1443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 145a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala if (DEBUG) { 1463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Log.v(TAG, "unmarshal, parcel length was " + actualLength); 1473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Log.v(TAG, "unmarshal, value is " + value); 1483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return mClass.cast(value); 1513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } finally { 1523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin parcel.recycle(); 1533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 1573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public int getNativeSize() { 1583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return NATIVE_SIZE_DYNAMIC; 1593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 1623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public int calculateMarshalSize(T value) { 1633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Parcel parcel = Parcel.obtain(); 1643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin try { 1653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin value.writeToParcel(parcel, /*flags*/0); 1663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin int length = parcel.marshall().length; 1673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 168a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala if (DEBUG) { 1693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Log.v(TAG, "calculateMarshalSize, length when parceling " 1703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin + value + " is " + length); 1713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return length; 1743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } finally { 1753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin parcel.recycle(); 1763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 1813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public Marshaler<T> createMarshaler(TypeReference<T> managedType, int nativeType) { 1823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return new MarshalerParcelable(managedType, nativeType); 1833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 1863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public boolean isTypeMappingSupported(TypeReference<T> managedType, int nativeType) { 1873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return Parcelable.class.isAssignableFrom(managedType.getRawType()); 1883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin} 191