Home | History | Annotate | Download | only in impl
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package android.hardware.camera2.marshal.impl;
     17 
     18 import android.hardware.camera2.marshal.Marshaler;
     19 import android.hardware.camera2.marshal.MarshalQueryable;
     20 import android.hardware.camera2.utils.TypeReference;
     21 import android.util.Log;
     22 
     23 import java.nio.ByteBuffer;
     24 import java.nio.charset.Charset;
     25 
     26 import static android.hardware.camera2.impl.CameraMetadataNative.*;
     27 
     28 /**
     29  * Marshal {@link String} to/from {@link #TYPE_BYTE}.
     30  */
     31 public class MarshalQueryableString implements MarshalQueryable<String> {
     32 
     33     private static final String TAG = MarshalQueryableString.class.getSimpleName();
     34     private static final boolean DEBUG = false;
     35 
     36     private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
     37     private static final byte NUL = (byte)'\0'; // used as string terminator
     38 
     39     private class MarshalerString extends Marshaler<String> {
     40 
     41         protected MarshalerString(TypeReference<String> typeReference, int nativeType) {
     42             super(MarshalQueryableString.this, typeReference, nativeType);
     43         }
     44 
     45         @Override
     46         public void marshal(String value, ByteBuffer buffer) {
     47             byte[] arr = value.getBytes(UTF8_CHARSET);
     48 
     49             buffer.put(arr);
     50             buffer.put(NUL); // metadata strings are NUL-terminated
     51         }
     52 
     53         @Override
     54         public int calculateMarshalSize(String value) {
     55             byte[] arr = value.getBytes(UTF8_CHARSET);
     56 
     57             return arr.length + 1; // metadata strings are NUL-terminated
     58         }
     59 
     60         @Override
     61         public String unmarshal(ByteBuffer buffer) {
     62             buffer.mark(); // save the current position
     63 
     64             boolean foundNull = false;
     65             int stringLength = 0;
     66             while (buffer.hasRemaining()) {
     67                 if (buffer.get() == NUL) {
     68                     foundNull = true;
     69                     break;
     70                 }
     71 
     72                 stringLength++;
     73             }
     74 
     75             if (DEBUG) {
     76                 Log.v(TAG,
     77                         "unmarshal - scanned " + stringLength + " characters; found null? "
     78                                 + foundNull);
     79             }
     80 
     81             if (!foundNull) {
     82                 throw new UnsupportedOperationException("Strings must be null-terminated");
     83             }
     84 
     85             buffer.reset(); // go back to the previously marked position
     86 
     87             byte[] strBytes = new byte[stringLength + 1];
     88             buffer.get(strBytes, /*dstOffset*/0, stringLength + 1); // including null character
     89 
     90             // not including null character
     91             return new String(strBytes, /*offset*/0, stringLength, UTF8_CHARSET);
     92         }
     93 
     94         @Override
     95         public int getNativeSize() {
     96             return NATIVE_SIZE_DYNAMIC;
     97         }
     98     }
     99 
    100     @Override
    101     public Marshaler<String> createMarshaler(
    102             TypeReference<String> managedType, int nativeType) {
    103         return new MarshalerString(managedType, nativeType);
    104     }
    105 
    106     @Override
    107     public boolean isTypeMappingSupported(TypeReference<String> managedType, int nativeType) {
    108         return nativeType == TYPE_BYTE && String.class.equals(managedType.getType());
    109     }
    110 }
    111