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.util.Log; 223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.nio.ByteBuffer; 243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.nio.charset.Charset; 253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport static android.hardware.camera2.impl.CameraMetadataNative.*; 273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin/** 293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Marshal {@link String} to/from {@link #TYPE_BYTE}. 303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */ 313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinpublic class MarshalQueryableString implements MarshalQueryable<String> { 323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static final String TAG = MarshalQueryableString.class.getSimpleName(); 34a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala private static final boolean DEBUG = false; 353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 3608e6c34cf72acbffd560fab21dc6ecf351aaf61bAndreas Gampe private static class PreloadHolder { 3708e6c34cf72acbffd560fab21dc6ecf351aaf61bAndreas Gampe public static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); 3808e6c34cf72acbffd560fab21dc6ecf351aaf61bAndreas Gampe } 393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private static final byte NUL = (byte)'\0'; // used as string terminator 403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin private class MarshalerString extends Marshaler<String> { 423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin protected MarshalerString(TypeReference<String> typeReference, int nativeType) { 443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin super(MarshalQueryableString.this, typeReference, nativeType); 453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public void marshal(String value, ByteBuffer buffer) { 4908e6c34cf72acbffd560fab21dc6ecf351aaf61bAndreas Gampe byte[] arr = value.getBytes(PreloadHolder.UTF8_CHARSET); 503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.put(arr); 523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.put(NUL); // metadata strings are NUL-terminated 533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public int calculateMarshalSize(String value) { 5708e6c34cf72acbffd560fab21dc6ecf351aaf61bAndreas Gampe byte[] arr = value.getBytes(PreloadHolder.UTF8_CHARSET); 583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return arr.length + 1; // metadata strings are NUL-terminated 603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public String unmarshal(ByteBuffer buffer) { 643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.mark(); // save the current position 653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin boolean foundNull = false; 673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin int stringLength = 0; 683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin while (buffer.hasRemaining()) { 693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (buffer.get() == NUL) { 703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin foundNull = true; 713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin break; 723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin stringLength++; 753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 77a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala if (DEBUG) { 783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin Log.v(TAG, 793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin "unmarshal - scanned " + stringLength + " characters; found null? " 803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin + foundNull); 813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin if (!foundNull) { 843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin throw new UnsupportedOperationException("Strings must be null-terminated"); 853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.reset(); // go back to the previously marked position 883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin byte[] strBytes = new byte[stringLength + 1]; 903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin buffer.get(strBytes, /*dstOffset*/0, stringLength + 1); // including null character 913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin // not including null character 9308e6c34cf72acbffd560fab21dc6ecf351aaf61bAndreas Gampe return new String(strBytes, /*offset*/0, stringLength, PreloadHolder.UTF8_CHARSET); 943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public int getNativeSize() { 983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return NATIVE_SIZE_DYNAMIC; 993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 1033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public Marshaler<String> createMarshaler( 1043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin TypeReference<String> managedType, int nativeType) { 1053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return new MarshalerString(managedType, nativeType); 1063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin 1083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin @Override 1093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin public boolean isTypeMappingSupported(TypeReference<String> managedType, int nativeType) { 1103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin return nativeType == TYPE_BYTE && String.class.equals(managedType.getType()); 1113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin } 1123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin} 113