aboutsummaryrefslogtreecommitdiff
path: root/apps/CameraITS/service/src/com/android/camera2/its
diff options
context:
space:
mode:
Diffstat (limited to 'apps/CameraITS/service/src/com/android/camera2/its')
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsException.java34
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsSerializer.java714
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsService.java1319
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java215
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/Logt.java39
5 files changed, 0 insertions, 2321 deletions
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsException.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsException.java
deleted file mode 100644
index 87af0b5..0000000
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.camera2.its;
-
-/**
- * All exceptions are converted to ItsExceptions.
- */
-class ItsException extends Exception {
- public ItsException(Throwable cause) {
- super(cause);
- }
-
- public ItsException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public ItsException(String message) {
- super(message);
- }
-}
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsSerializer.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsSerializer.java
deleted file mode 100644
index 943a73f..0000000
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsSerializer.java
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.camera2.its;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraMetadata;
-import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.TotalCaptureResult;
-import android.hardware.camera2.params.BlackLevelPattern;
-import android.hardware.camera2.params.ColorSpaceTransform;
-import android.hardware.camera2.params.Face;
-import android.hardware.camera2.params.LensShadingMap;
-import android.hardware.camera2.params.MeteringRectangle;
-import android.hardware.camera2.params.RggbChannelVector;
-import android.hardware.camera2.params.StreamConfigurationMap;
-import android.hardware.camera2.params.TonemapCurve;
-import android.location.Location;
-import android.util.Log;
-import android.util.Pair;
-import android.util.Rational;
-import android.util.Size;
-import android.util.SizeF;
-import android.util.Range;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Class to deal with serializing and deserializing between JSON and Camera2 objects.
- */
-public class ItsSerializer {
- public static final String TAG = ItsSerializer.class.getSimpleName();
-
- private static class MetadataEntry {
- public MetadataEntry(String k, Object v) {
- key = k;
- value = v;
- }
- public String key;
- public Object value;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeRational(Rational rat) throws org.json.JSONException {
- JSONObject ratObj = new JSONObject();
- ratObj.put("numerator", rat.getNumerator());
- ratObj.put("denominator", rat.getDenominator());
- return ratObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeSize(Size size) throws org.json.JSONException {
- JSONObject sizeObj = new JSONObject();
- sizeObj.put("width", size.getWidth());
- sizeObj.put("height", size.getHeight());
- return sizeObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeSizeF(SizeF size) throws org.json.JSONException {
- JSONObject sizeObj = new JSONObject();
- sizeObj.put("width", size.getWidth());
- sizeObj.put("height", size.getHeight());
- return sizeObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeRect(Rect rect) throws org.json.JSONException {
- JSONObject rectObj = new JSONObject();
- rectObj.put("left", rect.left);
- rectObj.put("right", rect.right);
- rectObj.put("top", rect.top);
- rectObj.put("bottom", rect.bottom);
- return rectObj;
- }
-
- private static Object serializePoint(Point point) throws org.json.JSONException {
- JSONObject pointObj = new JSONObject();
- pointObj.put("x", point.x);
- pointObj.put("y", point.y);
- return pointObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeFace(Face face)
- throws org.json.JSONException {
- JSONObject faceObj = new JSONObject();
- faceObj.put("bounds", serializeRect(face.getBounds()));
- faceObj.put("score", face.getScore());
- faceObj.put("id", face.getId());
- faceObj.put("leftEye", serializePoint(face.getLeftEyePosition()));
- faceObj.put("rightEye", serializePoint(face.getRightEyePosition()));
- faceObj.put("mouth", serializePoint(face.getMouthPosition()));
- return faceObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeStreamConfigurationMap(
- StreamConfigurationMap map)
- throws org.json.JSONException {
- // TODO: Serialize the rest of the StreamConfigurationMap fields.
- JSONObject mapObj = new JSONObject();
- JSONArray cfgArray = new JSONArray();
- int fmts[] = map.getOutputFormats();
- if (fmts != null) {
- for (int fi = 0; fi < Array.getLength(fmts); fi++) {
- Size sizes[] = map.getOutputSizes(fmts[fi]);
- if (sizes != null) {
- for (int si = 0; si < Array.getLength(sizes); si++) {
- JSONObject obj = new JSONObject();
- obj.put("format", fmts[fi]);
- obj.put("width",sizes[si].getWidth());
- obj.put("height", sizes[si].getHeight());
- obj.put("input", false);
- obj.put("minFrameDuration",
- map.getOutputMinFrameDuration(fmts[fi],sizes[si]));
- cfgArray.put(obj);
- }
- }
- }
- }
- mapObj.put("availableStreamConfigurations", cfgArray);
- return mapObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeMeteringRectangle(MeteringRectangle rect)
- throws org.json.JSONException {
- JSONObject rectObj = new JSONObject();
- rectObj.put("x", rect.getX());
- rectObj.put("y", rect.getY());
- rectObj.put("width", rect.getWidth());
- rectObj.put("height", rect.getHeight());
- rectObj.put("weight", rect.getMeteringWeight());
- return rectObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializePair(Pair pair)
- throws org.json.JSONException {
- JSONArray pairObj = new JSONArray();
- pairObj.put(pair.first);
- pairObj.put(pair.second);
- return pairObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeRange(Range range)
- throws org.json.JSONException {
- JSONArray rangeObj = new JSONArray();
- rangeObj.put(range.getLower());
- rangeObj.put(range.getUpper());
- return rangeObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeColorSpaceTransform(ColorSpaceTransform xform)
- throws org.json.JSONException {
- JSONArray xformObj = new JSONArray();
- for (int row = 0; row < 3; row++) {
- for (int col = 0; col < 3; col++) {
- xformObj.put(serializeRational(xform.getElement(col,row)));
- }
- }
- return xformObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeTonemapCurve(TonemapCurve curve)
- throws org.json.JSONException {
- JSONObject curveObj = new JSONObject();
- String names[] = {"red", "green", "blue"};
- for (int ch = 0; ch < 3; ch++) {
- JSONArray curveArr = new JSONArray();
- int len = curve.getPointCount(ch);
- for (int i = 0; i < len; i++) {
- curveArr.put(curve.getPoint(ch,i).x);
- curveArr.put(curve.getPoint(ch,i).y);
- }
- curveObj.put(names[ch], curveArr);
- }
- return curveObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeRggbChannelVector(RggbChannelVector vec)
- throws org.json.JSONException {
- JSONArray vecObj = new JSONArray();
- vecObj.put(vec.getRed());
- vecObj.put(vec.getGreenEven());
- vecObj.put(vec.getGreenOdd());
- vecObj.put(vec.getBlue());
- return vecObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeBlackLevelPattern(BlackLevelPattern pat)
- throws org.json.JSONException {
- int patVals[] = new int[4];
- pat.copyTo(patVals, 0);
- JSONArray patObj = new JSONArray();
- patObj.put(patVals[0]);
- patObj.put(patVals[1]);
- patObj.put(patVals[2]);
- patObj.put(patVals[3]);
- return patObj;
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeLocation(Location loc)
- throws org.json.JSONException {
- return loc.toString();
- }
-
- @SuppressWarnings("unchecked")
- private static Object serializeLensShadingMap(LensShadingMap map)
- throws org.json.JSONException {
- JSONArray mapObj = new JSONArray();
- for (int row = 0; row < map.getRowCount(); row++) {
- for (int col = 0; col < map.getColumnCount(); col++) {
- for (int ch = 0; ch < 4; ch++) {
- mapObj.put(map.getGainFactor(ch, col, row));
- }
- }
- }
- return mapObj;
- }
-
- private static String getKeyName(Object keyObj) throws ItsException {
- if (keyObj.getClass() == CaptureResult.Key.class
- || keyObj.getClass() == TotalCaptureResult.class) {
- return ((CaptureResult.Key)keyObj).getName();
- } else if (keyObj.getClass() == CaptureRequest.Key.class) {
- return ((CaptureRequest.Key)keyObj).getName();
- } else if (keyObj.getClass() == CameraCharacteristics.Key.class) {
- return ((CameraCharacteristics.Key)keyObj).getName();
- }
- throw new ItsException("Invalid key object");
- }
-
- private static Object getKeyValue(CameraMetadata md, Object keyObj) throws ItsException {
- if (md.getClass() == CaptureResult.class || md.getClass() == TotalCaptureResult.class) {
- return ((CaptureResult)md).get((CaptureResult.Key)keyObj);
- } else if (md.getClass() == CaptureRequest.class) {
- return ((CaptureRequest)md).get((CaptureRequest.Key)keyObj);
- } else if (md.getClass() == CameraCharacteristics.class) {
- return ((CameraCharacteristics)md).get((CameraCharacteristics.Key)keyObj);
- }
- throw new ItsException("Invalid key object");
- }
-
- @SuppressWarnings("unchecked")
- private static MetadataEntry serializeEntry(Type keyType, Object keyObj, CameraMetadata md)
- throws ItsException {
- String keyName = getKeyName(keyObj);
-
- try {
- Object keyValue = getKeyValue(md, keyObj);
- if (keyValue == null) {
- return new MetadataEntry(keyName, JSONObject.NULL);
- } else if (keyType == Float.class) {
- // The JSON serializer doesn't handle floating point NaN or Inf.
- if (((Float)keyValue).isInfinite() || ((Float)keyValue).isNaN()) {
- Logt.w(TAG, "Inf/NaN floating point value serialized: " + keyName);
- return null;
- }
- return new MetadataEntry(keyName, keyValue);
- } else if (keyType == Integer.class || keyType == Long.class || keyType == Byte.class ||
- keyType == Boolean.class || keyType == String.class) {
- return new MetadataEntry(keyName, keyValue);
- } else if (keyType == Rational.class) {
- return new MetadataEntry(keyName, serializeRational((Rational)keyValue));
- } else if (keyType == Size.class) {
- return new MetadataEntry(keyName, serializeSize((Size)keyValue));
- } else if (keyType == SizeF.class) {
- return new MetadataEntry(keyName, serializeSizeF((SizeF)keyValue));
- } else if (keyType == Rect.class) {
- return new MetadataEntry(keyName, serializeRect((Rect)keyValue));
- } else if (keyType == Face.class) {
- return new MetadataEntry(keyName, serializeFace((Face)keyValue));
- } else if (keyType == StreamConfigurationMap.class) {
- return new MetadataEntry(keyName,
- serializeStreamConfigurationMap((StreamConfigurationMap)keyValue));
- } else if (keyType instanceof ParameterizedType &&
- ((ParameterizedType)keyType).getRawType() == Range.class) {
- return new MetadataEntry(keyName, serializeRange((Range)keyValue));
- } else if (keyType == ColorSpaceTransform.class) {
- return new MetadataEntry(keyName,
- serializeColorSpaceTransform((ColorSpaceTransform)keyValue));
- } else if (keyType == MeteringRectangle.class) {
- return new MetadataEntry(keyName,
- serializeMeteringRectangle((MeteringRectangle)keyValue));
- } else if (keyType == Location.class) {
- return new MetadataEntry(keyName,
- serializeLocation((Location)keyValue));
- } else if (keyType == RggbChannelVector.class) {
- return new MetadataEntry(keyName,
- serializeRggbChannelVector((RggbChannelVector)keyValue));
- } else if (keyType == BlackLevelPattern.class) {
- return new MetadataEntry(keyName,
- serializeBlackLevelPattern((BlackLevelPattern)keyValue));
- } else if (keyType == TonemapCurve.class) {
- return new MetadataEntry(keyName,
- serializeTonemapCurve((TonemapCurve)keyValue));
- } else if (keyType == Point.class) {
- return new MetadataEntry(keyName,
- serializePoint((Point)keyValue));
- } else if (keyType == LensShadingMap.class) {
- return new MetadataEntry(keyName,
- serializeLensShadingMap((LensShadingMap)keyValue));
- } else {
- Logt.w(TAG, String.format("Serializing unsupported key type: " + keyType));
- return null;
- }
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error for key: " + keyName + ": ", e);
- }
- }
-
- @SuppressWarnings("unchecked")
- private static MetadataEntry serializeArrayEntry(Type keyType, Object keyObj, CameraMetadata md)
- throws ItsException {
- String keyName = getKeyName(keyObj);
- try {
- Object keyValue = getKeyValue(md, keyObj);
- if (keyValue == null) {
- return new MetadataEntry(keyName, JSONObject.NULL);
- }
- int arrayLen = Array.getLength(keyValue);
- Type elmtType = ((GenericArrayType)keyType).getGenericComponentType();
- if (elmtType == int.class || elmtType == float.class || elmtType == byte.class ||
- elmtType == long.class || elmtType == double.class || elmtType == boolean.class) {
- return new MetadataEntry(keyName, new JSONArray(keyValue));
- } else if (elmtType == Rational.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeRational((Rational)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType == Size.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeSize((Size)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType == Rect.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeRect((Rect)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType == Face.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeFace((Face)Array.get(keyValue, i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType == StreamConfigurationMap.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeStreamConfigurationMap(
- (StreamConfigurationMap)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType instanceof ParameterizedType &&
- ((ParameterizedType)elmtType).getRawType() == Range.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeRange((Range)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType instanceof ParameterizedType &&
- ((ParameterizedType)elmtType).getRawType() == Pair.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializePair((Pair)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType == MeteringRectangle.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeMeteringRectangle(
- (MeteringRectangle)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType == Location.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeLocation((Location)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType == RggbChannelVector.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeRggbChannelVector(
- (RggbChannelVector)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType == BlackLevelPattern.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializeBlackLevelPattern(
- (BlackLevelPattern)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else if (elmtType == Point.class) {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < arrayLen; i++) {
- jsonArray.put(serializePoint((Point)Array.get(keyValue,i)));
- }
- return new MetadataEntry(keyName, jsonArray);
- } else {
- Logt.w(TAG, String.format("Serializing unsupported array type: " + elmtType));
- return null;
- }
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error for key: " + keyName + ": ", e);
- }
- }
-
- @SuppressWarnings("unchecked")
- public static JSONObject serialize(CameraMetadata md)
- throws ItsException {
- JSONObject jsonObj = new JSONObject();
- Field[] allFields = md.getClass().getDeclaredFields();
- if (md.getClass() == TotalCaptureResult.class) {
- allFields = CaptureResult.class.getDeclaredFields();
- }
- for (Field field : allFields) {
- if (Modifier.isPublic(field.getModifiers()) &&
- Modifier.isStatic(field.getModifiers()) &&
- (field.getType() == CaptureRequest.Key.class
- || field.getType() == CaptureResult.Key.class
- || field.getType() == TotalCaptureResult.Key.class
- || field.getType() == CameraCharacteristics.Key.class) &&
- field.getGenericType() instanceof ParameterizedType) {
- ParameterizedType paramType = (ParameterizedType)field.getGenericType();
- Type[] argTypes = paramType.getActualTypeArguments();
- if (argTypes.length > 0) {
- try {
- Type keyType = argTypes[0];
- Object keyObj = field.get(md);
- MetadataEntry entry;
- if (keyType instanceof GenericArrayType) {
- entry = serializeArrayEntry(keyType, keyObj, md);
- } else {
- entry = serializeEntry(keyType, keyObj, md);
- }
-
- // TODO: Figure this weird case out.
- // There is a weird case where the entry is non-null but the toString
- // of the entry is null, and if this happens, the null-ness spreads like
- // a virus and makes the whole JSON object null from the top level down.
- // Not sure if it's a bug in the library or I'm just not using it right.
- // Workaround by checking for this case explicitly and not adding the
- // value to the jsonObj when it is detected.
- if (entry != null && entry.key != null && entry.value != null
- && entry.value.toString() == null) {
- Logt.w(TAG, "Error encountered serializing value for key: " + entry.key);
- } else if (entry != null) {
- jsonObj.put(entry.key, entry.value);
- } else {
- // Ignore.
- }
- } catch (IllegalAccessException e) {
- throw new ItsException(
- "Access error for field: " + field + ": ", e);
- } catch (org.json.JSONException e) {
- throw new ItsException(
- "JSON error for field: " + field + ": ", e);
- }
- }
- }
- }
- return jsonObj;
- }
-
- @SuppressWarnings("unchecked")
- public static CaptureRequest.Builder deserialize(CaptureRequest.Builder mdDefault,
- JSONObject jsonReq) throws ItsException {
- try {
- Logt.i(TAG, "Parsing JSON capture request ...");
-
- // Iterate over the CaptureRequest reflected fields.
- CaptureRequest.Builder md = mdDefault;
- Field[] allFields = CaptureRequest.class.getDeclaredFields();
- for (Field field : allFields) {
- if (Modifier.isPublic(field.getModifiers()) &&
- Modifier.isStatic(field.getModifiers()) &&
- field.getType() == CaptureRequest.Key.class &&
- field.getGenericType() instanceof ParameterizedType) {
- ParameterizedType paramType = (ParameterizedType)field.getGenericType();
- Type[] argTypes = paramType.getActualTypeArguments();
- if (argTypes.length > 0) {
- CaptureRequest.Key key = (CaptureRequest.Key)field.get(md);
- String keyName = key.getName();
- Type keyType = argTypes[0];
-
- // For each reflected CaptureRequest entry, look inside the JSON object
- // to see if it is being set. If it is found, remove the key from the
- // JSON object. After this process, there should be no keys left in the
- // JSON (otherwise an invalid key was specified).
-
- if (jsonReq.has(keyName) && !jsonReq.isNull(keyName)) {
- if (keyType instanceof GenericArrayType) {
- Type elmtType =
- ((GenericArrayType)keyType).getGenericComponentType();
- JSONArray ja = jsonReq.getJSONArray(keyName);
- Object val[] = new Object[ja.length()];
- for (int i = 0; i < ja.length(); i++) {
- if (elmtType == int.class) {
- Array.set(val, i, ja.getInt(i));
- } else if (elmtType == byte.class) {
- Array.set(val, i, (byte)ja.getInt(i));
- } else if (elmtType == float.class) {
- Array.set(val, i, (float)ja.getDouble(i));
- } else if (elmtType == long.class) {
- Array.set(val, i, ja.getLong(i));
- } else if (elmtType == double.class) {
- Array.set(val, i, ja.getDouble(i));
- } else if (elmtType == boolean.class) {
- Array.set(val, i, ja.getBoolean(i));
- } else if (elmtType == String.class) {
- Array.set(val, i, ja.getString(i));
- } else if (elmtType == Size.class){
- JSONObject obj = ja.getJSONObject(i);
- Array.set(val, i, new Size(
- obj.getInt("width"), obj.getInt("height")));
- } else if (elmtType == Rect.class) {
- JSONObject obj = ja.getJSONObject(i);
- Array.set(val, i, new Rect(
- obj.getInt("left"), obj.getInt("top"),
- obj.getInt("bottom"), obj.getInt("right")));
- } else if (elmtType == Rational.class) {
- JSONObject obj = ja.getJSONObject(i);
- Array.set(val, i, new Rational(
- obj.getInt("numerator"),
- obj.getInt("denominator")));
- } else if (elmtType == RggbChannelVector.class) {
- JSONArray arr = ja.getJSONArray(i);
- Array.set(val, i, new RggbChannelVector(
- (float)arr.getDouble(0),
- (float)arr.getDouble(1),
- (float)arr.getDouble(2),
- (float)arr.getDouble(3)));
- } else if (elmtType == ColorSpaceTransform.class) {
- JSONArray arr = ja.getJSONArray(i);
- Rational xform[] = new Rational[9];
- for (int j = 0; j < 9; j++) {
- xform[j] = new Rational(
- arr.getJSONObject(j).getInt("numerator"),
- arr.getJSONObject(j).getInt("denominator"));
- }
- Array.set(val, i, new ColorSpaceTransform(xform));
- } else if (elmtType == MeteringRectangle.class) {
- JSONObject obj = ja.getJSONObject(i);
- Array.set(val, i, new MeteringRectangle(
- obj.getInt("x"),
- obj.getInt("y"),
- obj.getInt("width"),
- obj.getInt("height"),
- obj.getInt("weight")));
- } else {
- throw new ItsException(
- "Failed to parse key from JSON: " + keyName);
- }
- }
- if (val != null) {
- Logt.i(TAG, "Set: "+keyName+" -> "+Arrays.toString(val));
- md.set(key, val);
- jsonReq.remove(keyName);
- }
- } else {
- Object val = null;
- if (keyType == Integer.class) {
- val = jsonReq.getInt(keyName);
- } else if (keyType == Byte.class) {
- val = (byte)jsonReq.getInt(keyName);
- } else if (keyType == Double.class) {
- val = jsonReq.getDouble(keyName);
- } else if (keyType == Long.class) {
- val = jsonReq.getLong(keyName);
- } else if (keyType == Float.class) {
- val = (float)jsonReq.getDouble(keyName);
- } else if (keyType == Boolean.class) {
- val = jsonReq.getBoolean(keyName);
- } else if (keyType == String.class) {
- val = jsonReq.getString(keyName);
- } else if (keyType == Size.class) {
- JSONObject obj = jsonReq.getJSONObject(keyName);
- val = new Size(
- obj.getInt("width"), obj.getInt("height"));
- } else if (keyType == Rect.class) {
- JSONObject obj = jsonReq.getJSONObject(keyName);
- val = new Rect(
- obj.getInt("left"), obj.getInt("top"),
- obj.getInt("right"), obj.getInt("bottom"));
- } else if (keyType == Rational.class) {
- JSONObject obj = jsonReq.getJSONObject(keyName);
- val = new Rational(obj.getInt("numerator"),
- obj.getInt("denominator"));
- } else if (keyType == RggbChannelVector.class) {
- JSONObject obj = jsonReq.optJSONObject(keyName);
- JSONArray arr = jsonReq.optJSONArray(keyName);
- if (arr != null) {
- val = new RggbChannelVector(
- (float)arr.getDouble(0),
- (float)arr.getDouble(1),
- (float)arr.getDouble(2),
- (float)arr.getDouble(3));
- } else if (obj != null) {
- val = new RggbChannelVector(
- (float)obj.getDouble("red"),
- (float)obj.getDouble("greenEven"),
- (float)obj.getDouble("greenOdd"),
- (float)obj.getDouble("blue"));
- } else {
- throw new ItsException("Invalid RggbChannelVector object");
- }
- } else if (keyType == ColorSpaceTransform.class) {
- JSONArray arr = jsonReq.getJSONArray(keyName);
- Rational a[] = new Rational[9];
- for (int i = 0; i < 9; i++) {
- a[i] = new Rational(
- arr.getJSONObject(i).getInt("numerator"),
- arr.getJSONObject(i).getInt("denominator"));
- }
- val = new ColorSpaceTransform(a);
- } else if (keyType instanceof ParameterizedType &&
- ((ParameterizedType)keyType).getRawType() == Range.class &&
- ((ParameterizedType)keyType).getActualTypeArguments().length == 1 &&
- ((ParameterizedType)keyType).getActualTypeArguments()[0] == Integer.class) {
- JSONArray arr = jsonReq.getJSONArray(keyName);
- val = new Range<Integer>(arr.getInt(0), arr.getInt(1));
- } else {
- throw new ItsException(
- "Failed to parse key from JSON: " +
- keyName + ", " + keyType);
- }
- if (val != null) {
- Logt.i(TAG, "Set: " + keyName + " -> " + val);
- md.set(key ,val);
- jsonReq.remove(keyName);
- }
- }
- }
- }
- }
- }
-
- // Ensure that there were no invalid keys in the JSON request object.
- if (jsonReq.length() != 0) {
- throw new ItsException("Invalid JSON key(s): " + jsonReq.toString());
- }
-
- Logt.i(TAG, "Parsing JSON capture request completed");
- return md;
- } catch (java.lang.IllegalAccessException e) {
- throw new ItsException("Access error: ", e);
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error: ", e);
- }
- }
-
- @SuppressWarnings("unchecked")
- public static List<CaptureRequest.Builder> deserializeRequestList(
- CameraDevice device, JSONObject jsonObjTop)
- throws ItsException {
- try {
- List<CaptureRequest.Builder> requests = null;
- JSONArray jsonReqs = jsonObjTop.getJSONArray("captureRequests");
- requests = new LinkedList<CaptureRequest.Builder>();
- for (int i = 0; i < jsonReqs.length(); i++) {
- CaptureRequest.Builder templateReq = device.createCaptureRequest(
- CameraDevice.TEMPLATE_STILL_CAPTURE);
- requests.add(
- deserialize(templateReq, jsonReqs.getJSONObject(i)));
- }
- return requests;
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error: ", e);
- } catch (android.hardware.camera2.CameraAccessException e) {
- throw new ItsException("Access error: ", e);
- }
- }
-}
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
deleted file mode 100644
index 1c497ea..0000000
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
+++ /dev/null
@@ -1,1319 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.camera2.its;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.ImageFormat;
-import android.hardware.camera2.CameraCaptureSession;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CaptureFailure;
-import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.DngCreator;
-import android.hardware.camera2.TotalCaptureResult;
-import android.hardware.camera2.params.MeteringRectangle;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.media.Image;
-import android.media.ImageReader;
-import android.net.Uri;
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Vibrator;
-import android.util.Log;
-import android.util.Rational;
-import android.util.Size;
-import android.view.Surface;
-
-import com.android.ex.camera2.blocking.BlockingCameraManager;
-import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
-import com.android.ex.camera2.blocking.BlockingStateCallback;
-import com.android.ex.camera2.blocking.BlockingSessionCallback;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.math.BigInteger;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketTimeoutException;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.security.MessageDigest;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class ItsService extends Service implements SensorEventListener {
- public static final String TAG = ItsService.class.getSimpleName();
-
- // Timeouts, in seconds.
- public static final int TIMEOUT_CALLBACK = 3;
- public static final int TIMEOUT_3A = 10;
-
- // State transition timeouts, in ms.
- private static final long TIMEOUT_IDLE_MS = 2000;
- private static final long TIMEOUT_STATE_MS = 500;
-
- // Timeout to wait for a capture result after the capture buffer has arrived, in ms.
- private static final long TIMEOUT_CAP_RES = 2000;
-
- private static final int MAX_CONCURRENT_READER_BUFFERS = 8;
-
- // Supports at most RAW+YUV+JPEG, one surface each.
- private static final int MAX_NUM_OUTPUT_SURFACES = 3;
-
- public static final int SERVERPORT = 6000;
-
- public static final String REGION_KEY = "regions";
- public static final String REGION_AE_KEY = "ae";
- public static final String REGION_AWB_KEY = "awb";
- public static final String REGION_AF_KEY = "af";
- public static final String LOCK_AE_KEY = "aeLock";
- public static final String LOCK_AWB_KEY = "awbLock";
- public static final String TRIGGER_KEY = "triggers";
- public static final String TRIGGER_AE_KEY = "ae";
- public static final String TRIGGER_AF_KEY = "af";
- public static final String VIB_PATTERN_KEY = "pattern";
-
- private CameraManager mCameraManager = null;
- private HandlerThread mCameraThread = null;
- private Handler mCameraHandler = null;
- private BlockingCameraManager mBlockingCameraManager = null;
- private BlockingStateCallback mCameraListener = null;
- private CameraDevice mCamera = null;
- private CameraCaptureSession mSession = null;
- private ImageReader[] mCaptureReaders = null;
- private CameraCharacteristics mCameraCharacteristics = null;
-
- private Vibrator mVibrator = null;
-
- private HandlerThread mSaveThreads[] = new HandlerThread[MAX_NUM_OUTPUT_SURFACES];
- private Handler mSaveHandlers[] = new Handler[MAX_NUM_OUTPUT_SURFACES];
- private HandlerThread mResultThread = null;
- private Handler mResultHandler = null;
-
- private volatile boolean mThreadExitFlag = false;
-
- private volatile ServerSocket mSocket = null;
- private volatile SocketRunnable mSocketRunnableObj = null;
- private volatile BlockingQueue<ByteBuffer> mSocketWriteQueue =
- new LinkedBlockingDeque<ByteBuffer>();
- private final Object mSocketWriteEnqueueLock = new Object();
- private final Object mSocketWriteDrainLock = new Object();
-
- private volatile BlockingQueue<Object[]> mSerializerQueue =
- new LinkedBlockingDeque<Object[]>();
-
- private AtomicInteger mCountCallbacksRemaining = new AtomicInteger();
- private AtomicInteger mCountRawOrDng = new AtomicInteger();
- private AtomicInteger mCountRaw10 = new AtomicInteger();
- private AtomicInteger mCountJpg = new AtomicInteger();
- private AtomicInteger mCountYuv = new AtomicInteger();
- private AtomicInteger mCountCapRes = new AtomicInteger();
- private boolean mCaptureRawIsDng;
- private CaptureResult mCaptureResults[] = null;
-
- private volatile ConditionVariable mInterlock3A = new ConditionVariable(true);
- private volatile boolean mIssuedRequest3A = false;
- private volatile boolean mConvergedAE = false;
- private volatile boolean mConvergedAF = false;
- private volatile boolean mConvergedAWB = false;
- private volatile boolean mLockedAE = false;
- private volatile boolean mLockedAWB = false;
- private volatile boolean mNeedsLockedAE = false;
- private volatile boolean mNeedsLockedAWB = false;
-
- class MySensorEvent {
- public Sensor sensor;
- public int accuracy;
- public long timestamp;
- public float values[];
- }
-
- // For capturing motion sensor traces.
- private SensorManager mSensorManager = null;
- private Sensor mAccelSensor = null;
- private Sensor mMagSensor = null;
- private Sensor mGyroSensor = null;
- private volatile LinkedList<MySensorEvent> mEvents = null;
- private volatile Object mEventLock = new Object();
- private volatile boolean mEventsEnabled = false;
-
- public interface CaptureCallback {
- void onCaptureAvailable(Image capture);
- }
-
- public abstract class CaptureResultListener extends CameraCaptureSession.CaptureCallback {}
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public void onCreate() {
- try {
- mThreadExitFlag = false;
-
- // Get handle to camera manager.
- mCameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);
- if (mCameraManager == null) {
- throw new ItsException("Failed to connect to camera manager");
- }
- mBlockingCameraManager = new BlockingCameraManager(mCameraManager);
- mCameraListener = new BlockingStateCallback();
-
- // Register for motion events.
- mEvents = new LinkedList<MySensorEvent>();
- mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
- mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- mMagSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
- mGyroSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
- mSensorManager.registerListener(this, mAccelSensor, SensorManager.SENSOR_DELAY_FASTEST);
- mSensorManager.registerListener(this, mMagSensor, SensorManager.SENSOR_DELAY_FASTEST);
- mSensorManager.registerListener(this, mGyroSensor, SensorManager.SENSOR_DELAY_FASTEST);
-
- // Get a handle to the system vibrator.
- mVibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
-
- // Create threads to receive images and save them.
- for (int i = 0; i < MAX_NUM_OUTPUT_SURFACES; i++) {
- mSaveThreads[i] = new HandlerThread("SaveThread" + i);
- mSaveThreads[i].start();
- mSaveHandlers[i] = new Handler(mSaveThreads[i].getLooper());
- }
-
- // Create a thread to handle object serialization.
- (new Thread(new SerializerRunnable())).start();;
-
- // Create a thread to receive capture results and process them.
- mResultThread = new HandlerThread("ResultThread");
- mResultThread.start();
- mResultHandler = new Handler(mResultThread.getLooper());
-
- // Create a thread for the camera device.
- mCameraThread = new HandlerThread("ItsCameraThread");
- mCameraThread.start();
- mCameraHandler = new Handler(mCameraThread.getLooper());
-
- // Create a thread to process commands, listening on a TCP socket.
- mSocketRunnableObj = new SocketRunnable();
- (new Thread(mSocketRunnableObj)).start();
- } catch (ItsException e) {
- Logt.e(TAG, "Service failed to start: ", e);
- }
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- try {
- // Just log a message indicating that the service is running and is able to accept
- // socket connections.
- while (!mThreadExitFlag && mSocket==null) {
- Thread.sleep(1);
- }
- if (!mThreadExitFlag){
- Logt.i(TAG, "ItsService ready");
- } else {
- Logt.e(TAG, "Starting ItsService in bad state");
- }
- } catch (java.lang.InterruptedException e) {
- Logt.e(TAG, "Error starting ItsService (interrupted)", e);
- }
- return START_STICKY;
- }
-
- @Override
- public void onDestroy() {
- mThreadExitFlag = true;
- for (int i = 0; i < MAX_NUM_OUTPUT_SURFACES; i++) {
- if (mSaveThreads[i] != null) {
- mSaveThreads[i].quit();
- mSaveThreads[i] = null;
- }
- }
- if (mResultThread != null) {
- mResultThread.quitSafely();
- mResultThread = null;
- }
- if (mCameraThread != null) {
- mCameraThread.quitSafely();
- mCameraThread = null;
- }
- }
-
- public void openCameraDevice(int cameraId) throws ItsException {
- Logt.i(TAG, String.format("Opening camera %d", cameraId));
-
- String[] devices;
- try {
- devices = mCameraManager.getCameraIdList();
- if (devices == null || devices.length == 0) {
- throw new ItsException("No camera devices");
- }
- } catch (CameraAccessException e) {
- throw new ItsException("Failed to get device ID list", e);
- }
-
- try {
- mCamera = mBlockingCameraManager.openCamera(devices[cameraId],
- mCameraListener, mCameraHandler);
- mCameraCharacteristics = mCameraManager.getCameraCharacteristics(
- devices[cameraId]);
- } catch (CameraAccessException e) {
- throw new ItsException("Failed to open camera", e);
- } catch (BlockingOpenException e) {
- throw new ItsException("Failed to open camera (after blocking)", e);
- }
- mSocketRunnableObj.sendResponse("cameraOpened", "");
- }
-
- public void closeCameraDevice() throws ItsException {
- try {
- if (mCamera != null) {
- Logt.i(TAG, "Closing camera");
- mCamera.close();
- mCamera = null;
- }
- } catch (Exception e) {
- throw new ItsException("Failed to close device");
- }
- mSocketRunnableObj.sendResponse("cameraClosed", "");
- }
-
- class SerializerRunnable implements Runnable {
- // Use a separate thread to perform JSON serialization (since this can be slow due to
- // the reflection).
- @Override
- public void run() {
- Logt.i(TAG, "Serializer thread starting");
- while (! mThreadExitFlag) {
- try {
- Object objs[] = mSerializerQueue.take();
- JSONObject jsonObj = new JSONObject();
- String tag = null;
- for (int i = 0; i < objs.length; i++) {
- Object obj = objs[i];
- if (obj instanceof String) {
- if (tag != null) {
- throw new ItsException("Multiple tags for socket response");
- }
- tag = (String)obj;
- } else if (obj instanceof CameraCharacteristics) {
- jsonObj.put("cameraProperties", ItsSerializer.serialize(
- (CameraCharacteristics)obj));
- } else if (obj instanceof CaptureRequest) {
- jsonObj.put("captureRequest", ItsSerializer.serialize(
- (CaptureRequest)obj));
- } else if (obj instanceof CaptureResult) {
- jsonObj.put("captureResult", ItsSerializer.serialize(
- (CaptureResult)obj));
- } else if (obj instanceof JSONArray) {
- jsonObj.put("outputs", (JSONArray)obj);
- } else {
- throw new ItsException("Invalid object received for serialiation");
- }
- }
- if (tag == null) {
- throw new ItsException("No tag provided for socket response");
- }
- mSocketRunnableObj.sendResponse(tag, null, jsonObj, null);
- Logt.i(TAG, String.format("Serialized %s", tag));
- } catch (org.json.JSONException e) {
- Logt.e(TAG, "Error serializing object", e);
- break;
- } catch (ItsException e) {
- Logt.e(TAG, "Error serializing object", e);
- break;
- } catch (java.lang.InterruptedException e) {
- Logt.e(TAG, "Error serializing object (interrupted)", e);
- break;
- }
- }
- Logt.i(TAG, "Serializer thread terminated");
- }
- }
-
- class SocketWriteRunnable implements Runnable {
-
- // Use a separate thread to service a queue of objects to be written to the socket,
- // writing each sequentially in order. This is needed since different handler functions
- // (called on different threads) will need to send data back to the host script.
-
- public Socket mOpenSocket = null;
-
- public SocketWriteRunnable(Socket openSocket) {
- mOpenSocket = openSocket;
- }
-
- public void setOpenSocket(Socket openSocket) {
- mOpenSocket = openSocket;
- }
-
- @Override
- public void run() {
- Logt.i(TAG, "Socket writer thread starting");
- while (true) {
- try {
- ByteBuffer b = mSocketWriteQueue.take();
- synchronized(mSocketWriteDrainLock) {
- if (mOpenSocket == null) {
- continue;
- }
- if (b.hasArray()) {
- mOpenSocket.getOutputStream().write(b.array());
- } else {
- byte[] barray = new byte[b.capacity()];
- b.get(barray);
- mOpenSocket.getOutputStream().write(barray);
- }
- mOpenSocket.getOutputStream().flush();
- Logt.i(TAG, String.format("Wrote to socket: %d bytes", b.capacity()));
- }
- } catch (IOException e) {
- Logt.e(TAG, "Error writing to socket", e);
- break;
- } catch (java.lang.InterruptedException e) {
- Logt.e(TAG, "Error writing to socket (interrupted)", e);
- break;
- }
- }
- Logt.i(TAG, "Socket writer thread terminated");
- }
- }
-
- class SocketRunnable implements Runnable {
-
- // Format of sent messages (over the socket):
- // * Serialized JSON object on a single line (newline-terminated)
- // * For byte buffers, the binary data then follows
- //
- // Format of received messages (from the socket):
- // * Serialized JSON object on a single line (newline-terminated)
-
- private Socket mOpenSocket = null;
- private SocketWriteRunnable mSocketWriteRunnable = null;
-
- @Override
- public void run() {
- Logt.i(TAG, "Socket thread starting");
- try {
- mSocket = new ServerSocket(SERVERPORT);
- } catch (IOException e) {
- Logt.e(TAG, "Failed to create socket", e);
- }
-
- // Create a new thread to handle writes to this socket.
- mSocketWriteRunnable = new SocketWriteRunnable(null);
- (new Thread(mSocketWriteRunnable)).start();
-
- while (!mThreadExitFlag) {
- // Receive the socket-open request from the host.
- try {
- Logt.i(TAG, "Waiting for client to connect to socket");
- mOpenSocket = mSocket.accept();
- if (mOpenSocket == null) {
- Logt.e(TAG, "Socket connection error");
- break;
- }
- mSocketWriteQueue.clear();
- mSocketWriteRunnable.setOpenSocket(mOpenSocket);
- Logt.i(TAG, "Socket connected");
- } catch (IOException e) {
- Logt.e(TAG, "Socket open error: ", e);
- break;
- }
-
- // Process commands over the open socket.
- while (!mThreadExitFlag) {
- try {
- BufferedReader input = new BufferedReader(
- new InputStreamReader(mOpenSocket.getInputStream()));
- if (input == null) {
- Logt.e(TAG, "Failed to get socket input stream");
- break;
- }
- String line = input.readLine();
- if (line == null) {
- Logt.i(TAG, "Socket readline retuned null (host disconnected)");
- break;
- }
- processSocketCommand(line);
- } catch (IOException e) {
- Logt.e(TAG, "Socket read error: ", e);
- break;
- } catch (ItsException e) {
- Logt.e(TAG, "Script error: ", e);
- break;
- }
- }
-
- // Close socket and go back to waiting for a new connection.
- try {
- synchronized(mSocketWriteDrainLock) {
- mSocketWriteQueue.clear();
- mOpenSocket.close();
- mOpenSocket = null;
- Logt.i(TAG, "Socket disconnected");
- }
- } catch (java.io.IOException e) {
- Logt.e(TAG, "Exception closing socket");
- }
- }
-
- // It's an overall error state if the code gets here; no recevery.
- // Try to do some cleanup, but the service probably needs to be restarted.
- Logt.i(TAG, "Socket server loop exited");
- mThreadExitFlag = true;
- try {
- if (mOpenSocket != null) {
- mOpenSocket.close();
- mOpenSocket = null;
- }
- } catch (java.io.IOException e) {
- Logt.w(TAG, "Exception closing socket");
- }
- try {
- if (mSocket != null) {
- mSocket.close();
- mSocket = null;
- }
- } catch (java.io.IOException e) {
- Logt.w(TAG, "Exception closing socket");
- }
- }
-
- public void processSocketCommand(String cmd)
- throws ItsException {
- // Each command is a serialized JSON object.
- try {
- JSONObject cmdObj = new JSONObject(cmd);
- if ("open".equals(cmdObj.getString("cmdName"))) {
- int cameraId = cmdObj.getInt("cameraId");
- openCameraDevice(cameraId);
- } else if ("close".equals(cmdObj.getString("cmdName"))) {
- closeCameraDevice();
- } else if ("getCameraProperties".equals(cmdObj.getString("cmdName"))) {
- doGetProps();
- } else if ("startSensorEvents".equals(cmdObj.getString("cmdName"))) {
- doStartSensorEvents();
- } else if ("getSensorEvents".equals(cmdObj.getString("cmdName"))) {
- doGetSensorEvents();
- } else if ("do3A".equals(cmdObj.getString("cmdName"))) {
- do3A(cmdObj);
- } else if ("doCapture".equals(cmdObj.getString("cmdName"))) {
- doCapture(cmdObj);
- } else if ("doVibrate".equals(cmdObj.getString("cmdName"))) {
- doVibrate(cmdObj);
- } else {
- throw new ItsException("Unknown command: " + cmd);
- }
- } catch (org.json.JSONException e) {
- Logt.e(TAG, "Invalid command: ", e);
- }
- }
-
- public void sendResponse(String tag, String str, JSONObject obj, ByteBuffer bbuf)
- throws ItsException {
- try {
- JSONObject jsonObj = new JSONObject();
- jsonObj.put("tag", tag);
- if (str != null) {
- jsonObj.put("strValue", str);
- }
- if (obj != null) {
- jsonObj.put("objValue", obj);
- }
- if (bbuf != null) {
- jsonObj.put("bufValueSize", bbuf.capacity());
- }
- ByteBuffer bstr = ByteBuffer.wrap(
- (jsonObj.toString()+"\n").getBytes(Charset.defaultCharset()));
- synchronized(mSocketWriteEnqueueLock) {
- if (bstr != null) {
- mSocketWriteQueue.put(bstr);
- }
- if (bbuf != null) {
- mSocketWriteQueue.put(bbuf);
- }
- }
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error: ", e);
- } catch (java.lang.InterruptedException e) {
- throw new ItsException("Socket error: ", e);
- }
- }
-
- public void sendResponse(String tag, String str)
- throws ItsException {
- sendResponse(tag, str, null, null);
- }
-
- public void sendResponse(String tag, JSONObject obj)
- throws ItsException {
- sendResponse(tag, null, obj, null);
- }
-
- public void sendResponseCaptureBuffer(String tag, ByteBuffer bbuf)
- throws ItsException {
- sendResponse(tag, null, null, bbuf);
- }
-
- public void sendResponse(LinkedList<MySensorEvent> events)
- throws ItsException {
- try {
- JSONArray accels = new JSONArray();
- JSONArray mags = new JSONArray();
- JSONArray gyros = new JSONArray();
- for (MySensorEvent event : events) {
- JSONObject obj = new JSONObject();
- obj.put("time", event.timestamp);
- obj.put("x", event.values[0]);
- obj.put("y", event.values[1]);
- obj.put("z", event.values[2]);
- if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
- accels.put(obj);
- } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
- mags.put(obj);
- } else if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
- gyros.put(obj);
- }
- }
- JSONObject obj = new JSONObject();
- obj.put("accel", accels);
- obj.put("mag", mags);
- obj.put("gyro", gyros);
- sendResponse("sensorEvents", null, obj, null);
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error: ", e);
- }
- }
-
- public void sendResponse(CameraCharacteristics props)
- throws ItsException {
- try {
- Object objs[] = new Object[2];
- objs[0] = "cameraProperties";
- objs[1] = props;
- mSerializerQueue.put(objs);
- } catch (InterruptedException e) {
- throw new ItsException("Interrupted: ", e);
- }
- }
-
- public void sendResponseCaptureResult(CameraCharacteristics props,
- CaptureRequest request,
- CaptureResult result,
- ImageReader[] readers)
- throws ItsException {
- try {
- JSONArray jsonSurfaces = new JSONArray();
- for (int i = 0; i < readers.length; i++) {
- JSONObject jsonSurface = new JSONObject();
- jsonSurface.put("width", readers[i].getWidth());
- jsonSurface.put("height", readers[i].getHeight());
- int format = readers[i].getImageFormat();
- if (format == ImageFormat.RAW_SENSOR) {
- jsonSurface.put("format", "raw");
- } else if (format == ImageFormat.RAW10) {
- jsonSurface.put("format", "raw10");
- } else if (format == ImageFormat.JPEG) {
- jsonSurface.put("format", "jpeg");
- } else if (format == ImageFormat.YUV_420_888) {
- jsonSurface.put("format", "yuv");
- } else {
- throw new ItsException("Invalid format");
- }
- jsonSurfaces.put(jsonSurface);
- }
-
- Object objs[] = new Object[5];
- objs[0] = "captureResults";
- objs[1] = props;
- objs[2] = request;
- objs[3] = result;
- objs[4] = jsonSurfaces;
- mSerializerQueue.put(objs);
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error: ", e);
- } catch (InterruptedException e) {
- throw new ItsException("Interrupted: ", e);
- }
- }
- }
-
- public ImageReader.OnImageAvailableListener
- createAvailableListener(final CaptureCallback listener) {
- return new ImageReader.OnImageAvailableListener() {
- @Override
- public void onImageAvailable(ImageReader reader) {
- Image i = null;
- try {
- i = reader.acquireNextImage();
- listener.onCaptureAvailable(i);
- } finally {
- if (i != null) {
- i.close();
- }
- }
- }
- };
- }
-
- private ImageReader.OnImageAvailableListener
- createAvailableListenerDropper(final CaptureCallback listener) {
- return new ImageReader.OnImageAvailableListener() {
- @Override
- public void onImageAvailable(ImageReader reader) {
- Image i = reader.acquireNextImage();
- i.close();
- }
- };
- }
-
- private void doStartSensorEvents() throws ItsException {
- synchronized(mEventLock) {
- mEventsEnabled = true;
- }
- mSocketRunnableObj.sendResponse("sensorEventsStarted", "");
- }
-
- private void doGetSensorEvents() throws ItsException {
- synchronized(mEventLock) {
- mSocketRunnableObj.sendResponse(mEvents);
- mEvents.clear();
- mEventsEnabled = false;
- }
- }
-
- private void doGetProps() throws ItsException {
- mSocketRunnableObj.sendResponse(mCameraCharacteristics);
- }
-
- private void prepareCaptureReader(int[] widths, int[] heights, int formats[], int numSurfaces) {
- if (mCaptureReaders != null) {
- for (int i = 0; i < mCaptureReaders.length; i++) {
- if (mCaptureReaders[i] != null) {
- mCaptureReaders[i].close();
- }
- }
- }
- mCaptureReaders = new ImageReader[numSurfaces];
- for (int i = 0; i < numSurfaces; i++) {
- mCaptureReaders[i] = ImageReader.newInstance(widths[i], heights[i], formats[i],
- MAX_CONCURRENT_READER_BUFFERS);
- }
- }
-
- private void do3A(JSONObject params) throws ItsException {
- try {
- // Start a 3A action, and wait for it to converge.
- // Get the converged values for each "A", and package into JSON result for caller.
-
- // 3A happens on full-res frames.
- Size sizes[] = ItsUtils.getYuvOutputSizes(mCameraCharacteristics);
- int widths[] = new int[1];
- int heights[] = new int[1];
- int formats[] = new int[1];
- widths[0] = sizes[0].getWidth();
- heights[0] = sizes[0].getHeight();
- formats[0] = ImageFormat.YUV_420_888;
- int width = widths[0];
- int height = heights[0];
-
- prepareCaptureReader(widths, heights, formats, 1);
- List<Surface> outputSurfaces = new ArrayList<Surface>(1);
- outputSurfaces.add(mCaptureReaders[0].getSurface());
- BlockingSessionCallback sessionListener = new BlockingSessionCallback();
- mCamera.createCaptureSession(outputSurfaces, sessionListener, mCameraHandler);
- mSession = sessionListener.waitAndGetSession(TIMEOUT_IDLE_MS);
-
- // Add a listener that just recycles buffers; they aren't saved anywhere.
- ImageReader.OnImageAvailableListener readerListener =
- createAvailableListenerDropper(mCaptureCallback);
- mCaptureReaders[0].setOnImageAvailableListener(readerListener, mSaveHandlers[0]);
-
- // Get the user-specified regions for AE, AWB, AF.
- // Note that the user specifies normalized [x,y,w,h], which is converted below
- // to an [x0,y0,x1,y1] region in sensor coords. The capture request region
- // also has a fifth "weight" element: [x0,y0,x1,y1,w].
- MeteringRectangle[] regionAE = new MeteringRectangle[]{
- new MeteringRectangle(0,0,width,height,1)};
- MeteringRectangle[] regionAF = new MeteringRectangle[]{
- new MeteringRectangle(0,0,width,height,1)};
- MeteringRectangle[] regionAWB = new MeteringRectangle[]{
- new MeteringRectangle(0,0,width,height,1)};
- if (params.has(REGION_KEY)) {
- JSONObject regions = params.getJSONObject(REGION_KEY);
- if (regions.has(REGION_AE_KEY)) {
- regionAE = ItsUtils.getJsonWeightedRectsFromArray(
- regions.getJSONArray(REGION_AE_KEY), true, width, height);
- }
- if (regions.has(REGION_AF_KEY)) {
- regionAF = ItsUtils.getJsonWeightedRectsFromArray(
- regions.getJSONArray(REGION_AF_KEY), true, width, height);
- }
- if (regions.has(REGION_AWB_KEY)) {
- regionAWB = ItsUtils.getJsonWeightedRectsFromArray(
- regions.getJSONArray(REGION_AWB_KEY), true, width, height);
- }
- }
-
- // If AE or AWB lock is specified, then the 3A will converge first and then lock these
- // values, waiting until the HAL has reported that the lock was successful.
- mNeedsLockedAE = params.optBoolean(LOCK_AE_KEY, false);
- mNeedsLockedAWB = params.optBoolean(LOCK_AWB_KEY, false);
-
- // By default, AE and AF both get triggered, but the user can optionally override this.
- // Also, AF won't get triggered if the lens is fixed-focus.
- boolean doAE = true;
- boolean doAF = true;
- if (params.has(TRIGGER_KEY)) {
- JSONObject triggers = params.getJSONObject(TRIGGER_KEY);
- if (triggers.has(TRIGGER_AE_KEY)) {
- doAE = triggers.getBoolean(TRIGGER_AE_KEY);
- }
- if (triggers.has(TRIGGER_AF_KEY)) {
- doAF = triggers.getBoolean(TRIGGER_AF_KEY);
- }
- }
- if (doAF && mCameraCharacteristics.get(
- CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) == 0) {
- // Send a dummy result back for the code that is waiting for this message to see
- // that AF has converged.
- Logt.i(TAG, "Ignoring request for AF on fixed-focus camera");
- mSocketRunnableObj.sendResponse("afResult", "0.0");
- doAF = false;
- }
-
- mInterlock3A.open();
- mIssuedRequest3A = false;
- mConvergedAE = false;
- mConvergedAWB = false;
- mConvergedAF = false;
- mLockedAE = false;
- mLockedAWB = false;
- long tstart = System.currentTimeMillis();
- boolean triggeredAE = false;
- boolean triggeredAF = false;
-
- Logt.i(TAG, String.format("Initiating 3A: AE:%d, AF:%d, AWB:1, AELOCK:%d, AWBLOCK:%d",
- doAE?1:0, doAF?1:0, mNeedsLockedAE?1:0, mNeedsLockedAWB?1:0));
-
- // Keep issuing capture requests until 3A has converged.
- while (true) {
-
- // Block until can take the next 3A frame. Only want one outstanding frame
- // at a time, to simplify the logic here.
- if (!mInterlock3A.block(TIMEOUT_3A * 1000) ||
- System.currentTimeMillis() - tstart > TIMEOUT_3A * 1000) {
- throw new ItsException("3A failed to converge (timeout)");
- }
- mInterlock3A.close();
-
- // If not converged yet, issue another capture request.
- if ( (doAE && (!triggeredAE || !mConvergedAE))
- || !mConvergedAWB
- || (doAF && (!triggeredAF || !mConvergedAF))
- || (doAE && mNeedsLockedAE && !mLockedAE)
- || (mNeedsLockedAWB && !mLockedAWB)) {
-
- // Baseline capture request for 3A.
- CaptureRequest.Builder req = mCamera.createCaptureRequest(
- CameraDevice.TEMPLATE_PREVIEW);
- req.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
- req.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
- req.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
- CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
- req.set(CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_MODE_ON);
- req.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
- req.set(CaptureRequest.CONTROL_AE_LOCK, false);
- req.set(CaptureRequest.CONTROL_AE_REGIONS, regionAE);
- req.set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_AUTO);
- req.set(CaptureRequest.CONTROL_AF_REGIONS, regionAF);
- req.set(CaptureRequest.CONTROL_AWB_MODE,
- CaptureRequest.CONTROL_AWB_MODE_AUTO);
- req.set(CaptureRequest.CONTROL_AWB_LOCK, false);
- req.set(CaptureRequest.CONTROL_AWB_REGIONS, regionAWB);
-
- if (mConvergedAE && mNeedsLockedAE) {
- req.set(CaptureRequest.CONTROL_AE_LOCK, true);
- }
- if (mConvergedAWB && mNeedsLockedAWB) {
- req.set(CaptureRequest.CONTROL_AWB_LOCK, true);
- }
-
- // Trigger AE first.
- if (doAE && !triggeredAE) {
- Logt.i(TAG, "Triggering AE");
- req.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
- CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
- triggeredAE = true;
- }
-
- // After AE has converged, trigger AF.
- if (doAF && !triggeredAF && (!doAE || (triggeredAE && mConvergedAE))) {
- Logt.i(TAG, "Triggering AF");
- req.set(CaptureRequest.CONTROL_AF_TRIGGER,
- CaptureRequest.CONTROL_AF_TRIGGER_START);
- triggeredAF = true;
- }
-
- req.addTarget(mCaptureReaders[0].getSurface());
-
- mIssuedRequest3A = true;
- mSession.capture(req.build(), mCaptureResultListener, mResultHandler);
- } else {
- mSocketRunnableObj.sendResponse("3aConverged", "");
- Logt.i(TAG, "3A converged");
- break;
- }
- }
- } catch (android.hardware.camera2.CameraAccessException e) {
- throw new ItsException("Access error: ", e);
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error: ", e);
- } finally {
- mSocketRunnableObj.sendResponse("3aDone", "");
- }
- }
-
- private void doVibrate(JSONObject params) throws ItsException {
- try {
- if (mVibrator == null) {
- throw new ItsException("Unable to start vibrator");
- }
- JSONArray patternArray = params.getJSONArray(VIB_PATTERN_KEY);
- int len = patternArray.length();
- long pattern[] = new long[len];
- for (int i = 0; i < len; i++) {
- pattern[i] = patternArray.getLong(i);
- }
- Logt.i(TAG, String.format("Starting vibrator, pattern length %d",len));
- mVibrator.vibrate(pattern, -1);
- mSocketRunnableObj.sendResponse("vibrationStarted", "");
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error: ", e);
- }
- }
-
- private void doCapture(JSONObject params) throws ItsException {
- try {
- // Parse the JSON to get the list of capture requests.
- List<CaptureRequest.Builder> requests = ItsSerializer.deserializeRequestList(
- mCamera, params);
-
- // Set the output surface(s) and listeners.
- int widths[] = new int[MAX_NUM_OUTPUT_SURFACES];
- int heights[] = new int[MAX_NUM_OUTPUT_SURFACES];
- int formats[] = new int[MAX_NUM_OUTPUT_SURFACES];
- int numSurfaces = 0;
- try {
- mCountRawOrDng.set(0);
- mCountJpg.set(0);
- mCountYuv.set(0);
- mCountRaw10.set(0);
- mCountCapRes.set(0);
- mCaptureRawIsDng = false;
- mCaptureResults = new CaptureResult[requests.size()];
-
- JSONArray jsonOutputSpecs = ItsUtils.getOutputSpecs(params);
- if (jsonOutputSpecs != null) {
- numSurfaces = jsonOutputSpecs.length();
- if (numSurfaces > MAX_NUM_OUTPUT_SURFACES) {
- throw new ItsException("Too many output surfaces");
- }
- for (int i = 0; i < numSurfaces; i++) {
- // Get the specified surface.
- JSONObject surfaceObj = jsonOutputSpecs.getJSONObject(i);
- String sformat = surfaceObj.optString("format");
- Size sizes[];
- if ("yuv".equals(sformat) || "".equals(sformat)) {
- // Default to YUV if no format is specified.
- formats[i] = ImageFormat.YUV_420_888;
- sizes = ItsUtils.getYuvOutputSizes(mCameraCharacteristics);
- } else if ("jpg".equals(sformat) || "jpeg".equals(sformat)) {
- formats[i] = ImageFormat.JPEG;
- sizes = ItsUtils.getJpegOutputSizes(mCameraCharacteristics);
- } else if ("raw".equals(sformat)) {
- formats[i] = ImageFormat.RAW_SENSOR;
- sizes = ItsUtils.getRawOutputSizes(mCameraCharacteristics);
- } else if ("raw10".equals(sformat)) {
- formats[i] = ImageFormat.RAW10;
- sizes = ItsUtils.getRawOutputSizes(mCameraCharacteristics);
- } else if ("dng".equals(sformat)) {
- formats[i] = ImageFormat.RAW_SENSOR;
- sizes = ItsUtils.getRawOutputSizes(mCameraCharacteristics);
- mCaptureRawIsDng = true;
- } else {
- throw new ItsException("Unsupported format: " + sformat);
- }
- // If the size is omitted, then default to the largest allowed size for the
- // format.
- widths[i] = surfaceObj.optInt("width");
- heights[i] = surfaceObj.optInt("height");
- if (widths[i] <= 0) {
- if (sizes == null || sizes.length == 0) {
- throw new ItsException(String.format(
- "Zero stream configs available for requested format: %s",
- sformat));
- }
- widths[i] = sizes[0].getWidth();
- }
- if (heights[i] <= 0) {
- heights[i] = sizes[0].getHeight();
- }
- }
- } else {
- // No surface(s) specified at all.
- // Default: a single output surface which is full-res YUV.
- Size sizes[] =
- ItsUtils.getYuvOutputSizes(mCameraCharacteristics);
- numSurfaces = 1;
- widths[0] = sizes[0].getWidth();
- heights[0] = sizes[0].getHeight();
- formats[0] = ImageFormat.YUV_420_888;
- }
-
- prepareCaptureReader(widths, heights, formats, numSurfaces);
- List<Surface> outputSurfaces = new ArrayList<Surface>(numSurfaces);
- for (int i = 0; i < numSurfaces; i++) {
- outputSurfaces.add(mCaptureReaders[i].getSurface());
- }
- BlockingSessionCallback sessionListener = new BlockingSessionCallback();
- mCamera.createCaptureSession(outputSurfaces, sessionListener, mCameraHandler);
- mSession = sessionListener.waitAndGetSession(TIMEOUT_IDLE_MS);
-
- for (int i = 0; i < numSurfaces; i++) {
- ImageReader.OnImageAvailableListener readerListener =
- createAvailableListener(mCaptureCallback);
- mCaptureReaders[i].setOnImageAvailableListener(readerListener,mSaveHandlers[i]);
- }
-
- // Plan for how many callbacks need to be received throughout the duration of this
- // sequence of capture requests. There is one callback per image surface, and one
- // callback for the CaptureResult, for each capture.
- int numCaptures = requests.size();
- mCountCallbacksRemaining.set(numCaptures * (numSurfaces + 1));
-
- } catch (CameraAccessException e) {
- throw new ItsException("Error configuring outputs", e);
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error", e);
- }
-
- // Initiate the captures.
- for (int i = 0; i < requests.size(); i++) {
- // For DNG captures, need the LSC map to be available.
- if (mCaptureRawIsDng) {
- requests.get(i).set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE, 1);
- }
-
- CaptureRequest.Builder req = requests.get(i);
- for (int j = 0; j < numSurfaces; j++) {
- req.addTarget(mCaptureReaders[j].getSurface());
- }
- mSession.capture(req.build(), mCaptureResultListener, mResultHandler);
- }
-
- // Make sure all callbacks have been hit (wait until captures are done).
- // If no timeouts are received after a timeout, then fail.
- int currentCount = mCountCallbacksRemaining.get();
- while (currentCount > 0) {
- try {
- Thread.sleep(TIMEOUT_CALLBACK*1000);
- } catch (InterruptedException e) {
- throw new ItsException("Timeout failure", e);
- }
- int newCount = mCountCallbacksRemaining.get();
- if (newCount == currentCount) {
- throw new ItsException(
- "No callback received within timeout");
- }
- currentCount = newCount;
- }
- } catch (android.hardware.camera2.CameraAccessException e) {
- throw new ItsException("Access error: ", e);
- }
- }
-
- @Override
- public final void onSensorChanged(SensorEvent event) {
- synchronized(mEventLock) {
- if (mEventsEnabled) {
- MySensorEvent ev2 = new MySensorEvent();
- ev2.sensor = event.sensor;
- ev2.accuracy = event.accuracy;
- ev2.timestamp = event.timestamp;
- ev2.values = new float[event.values.length];
- System.arraycopy(event.values, 0, ev2.values, 0, event.values.length);
- mEvents.add(ev2);
- }
- }
- }
-
- @Override
- public final void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
-
- private final CaptureCallback mCaptureCallback = new CaptureCallback() {
- @Override
- public void onCaptureAvailable(Image capture) {
- try {
- int format = capture.getFormat();
- if (format == ImageFormat.JPEG) {
- Logt.i(TAG, "Received JPEG capture");
- byte[] img = ItsUtils.getDataFromImage(capture);
- ByteBuffer buf = ByteBuffer.wrap(img);
- int count = mCountJpg.getAndIncrement();
- mSocketRunnableObj.sendResponseCaptureBuffer("jpegImage", buf);
- } else if (format == ImageFormat.YUV_420_888) {
- Logt.i(TAG, "Received YUV capture");
- byte[] img = ItsUtils.getDataFromImage(capture);
- ByteBuffer buf = ByteBuffer.wrap(img);
- int count = mCountYuv.getAndIncrement();
- mSocketRunnableObj.sendResponseCaptureBuffer("yuvImage", buf);
- } else if (format == ImageFormat.RAW10) {
- Logt.i(TAG, "Received RAW10 capture");
- byte[] img = ItsUtils.getDataFromImage(capture);
- ByteBuffer buf = ByteBuffer.wrap(img);
- int count = mCountRaw10.getAndIncrement();
- mSocketRunnableObj.sendResponseCaptureBuffer("raw10Image", buf);
- } else if (format == ImageFormat.RAW_SENSOR) {
- Logt.i(TAG, "Received RAW16 capture");
- int count = mCountRawOrDng.getAndIncrement();
- if (! mCaptureRawIsDng) {
- byte[] img = ItsUtils.getDataFromImage(capture);
- ByteBuffer buf = ByteBuffer.wrap(img);
- mSocketRunnableObj.sendResponseCaptureBuffer("rawImage", buf);
- } else {
- // Wait until the corresponding capture result is ready, up to a timeout.
- long t0 = android.os.SystemClock.elapsedRealtime();
- while (! mThreadExitFlag
- && android.os.SystemClock.elapsedRealtime()-t0 < TIMEOUT_CAP_RES) {
- if (mCaptureResults[count] != null) {
- Logt.i(TAG, "Writing capture as DNG");
- DngCreator dngCreator = new DngCreator(
- mCameraCharacteristics, mCaptureResults[count]);
- ByteArrayOutputStream dngStream = new ByteArrayOutputStream();
- dngCreator.writeImage(dngStream, capture);
- byte[] dngArray = dngStream.toByteArray();
- ByteBuffer dngBuf = ByteBuffer.wrap(dngArray);
- mSocketRunnableObj.sendResponseCaptureBuffer("dngImage", dngBuf);
- break;
- } else {
- Thread.sleep(1);
- }
- }
- }
- } else {
- throw new ItsException("Unsupported image format: " + format);
- }
- mCountCallbacksRemaining.decrementAndGet();
- } catch (IOException e) {
- Logt.e(TAG, "Script error: ", e);
- } catch (InterruptedException e) {
- Logt.e(TAG, "Script error: ", e);
- } catch (ItsException e) {
- Logt.e(TAG, "Script error: ", e);
- }
- }
- };
-
- private static float r2f(Rational r) {
- return (float)r.getNumerator() / (float)r.getDenominator();
- }
-
- private final CaptureResultListener mCaptureResultListener = new CaptureResultListener() {
- @Override
- public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
- long timestamp, long frameNumber) {
- }
-
- @Override
- public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
- TotalCaptureResult result) {
- try {
- // Currently result has all 0 values.
- if (request == null || result == null) {
- throw new ItsException("Request/result is invalid");
- }
-
- StringBuilder logMsg = new StringBuilder();
- logMsg.append(String.format(
- "Capt result: AE=%d, AF=%d, AWB=%d, sens=%d, exp=%.1fms, dur=%.1fms, ",
- result.get(CaptureResult.CONTROL_AE_STATE),
- result.get(CaptureResult.CONTROL_AF_STATE),
- result.get(CaptureResult.CONTROL_AWB_STATE),
- result.get(CaptureResult.SENSOR_SENSITIVITY),
- result.get(CaptureResult.SENSOR_EXPOSURE_TIME).intValue() / 1000000.0f,
- result.get(CaptureResult.SENSOR_FRAME_DURATION).intValue() / 1000000.0f));
- if (result.get(CaptureResult.COLOR_CORRECTION_GAINS) != null) {
- logMsg.append(String.format(
- "gains=[%.1f, %.1f, %.1f, %.1f], ",
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getRed(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenEven(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenOdd(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getBlue()));
- } else {
- logMsg.append("gains=[], ");
- }
- if (result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) != null) {
- logMsg.append(String.format(
- "xform=[%.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f], ",
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,2)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,2)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,2))));
- } else {
- logMsg.append("xform=[], ");
- }
- logMsg.append(String.format(
- "foc=%.1f",
- result.get(CaptureResult.LENS_FOCUS_DISTANCE)));
- Logt.i(TAG, logMsg.toString());
-
- if (result.get(CaptureResult.CONTROL_AE_STATE) != null) {
- mConvergedAE = result.get(CaptureResult.CONTROL_AE_STATE) ==
- CaptureResult.CONTROL_AE_STATE_CONVERGED ||
- result.get(CaptureResult.CONTROL_AE_STATE) ==
- CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED ||
- result.get(CaptureResult.CONTROL_AE_STATE) ==
- CaptureResult.CONTROL_AE_STATE_LOCKED;
- mLockedAE = result.get(CaptureResult.CONTROL_AE_STATE) ==
- CaptureResult.CONTROL_AE_STATE_LOCKED;
- }
- if (result.get(CaptureResult.CONTROL_AF_STATE) != null) {
- mConvergedAF = result.get(CaptureResult.CONTROL_AF_STATE) ==
- CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED;
- }
- if (result.get(CaptureResult.CONTROL_AWB_STATE) != null) {
- mConvergedAWB = result.get(CaptureResult.CONTROL_AWB_STATE) ==
- CaptureResult.CONTROL_AWB_STATE_CONVERGED ||
- result.get(CaptureResult.CONTROL_AWB_STATE) ==
- CaptureResult.CONTROL_AWB_STATE_LOCKED;
- mLockedAWB = result.get(CaptureResult.CONTROL_AWB_STATE) ==
- CaptureResult.CONTROL_AWB_STATE_LOCKED;
- }
-
- if (mConvergedAE && (!mNeedsLockedAE || mLockedAE)) {
- if (result.get(CaptureResult.SENSOR_SENSITIVITY) != null
- && result.get(CaptureResult.SENSOR_EXPOSURE_TIME) != null) {
- mSocketRunnableObj.sendResponse("aeResult", String.format("%d %d",
- result.get(CaptureResult.SENSOR_SENSITIVITY).intValue(),
- result.get(CaptureResult.SENSOR_EXPOSURE_TIME).intValue()
- ));
- } else {
- Logt.i(TAG, String.format(
- "AE converged but NULL exposure values, sensitivity:%b, expTime:%b",
- result.get(CaptureResult.SENSOR_SENSITIVITY) == null,
- result.get(CaptureResult.SENSOR_EXPOSURE_TIME) == null));
- }
- }
-
- if (mConvergedAF) {
- if (result.get(CaptureResult.LENS_FOCUS_DISTANCE) != null) {
- mSocketRunnableObj.sendResponse("afResult", String.format("%f",
- result.get(CaptureResult.LENS_FOCUS_DISTANCE)
- ));
- } else {
- Logt.i(TAG, "AF converged but NULL focus distance values");
- }
- }
-
- if (mConvergedAWB && (!mNeedsLockedAWB || mLockedAWB)) {
- if (result.get(CaptureResult.COLOR_CORRECTION_GAINS) != null
- && result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) != null) {
- mSocketRunnableObj.sendResponse("awbResult", String.format(
- "%f %f %f %f %f %f %f %f %f %f %f %f %f",
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getRed(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenEven(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenOdd(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getBlue(),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,2)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,2)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,2))
- ));
- } else {
- Logt.i(TAG, String.format(
- "AWB converged but NULL color correction values, gains:%b, ccm:%b",
- result.get(CaptureResult.COLOR_CORRECTION_GAINS) == null,
- result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) == null));
- }
- }
-
- if (mIssuedRequest3A) {
- mIssuedRequest3A = false;
- mInterlock3A.open();
- } else {
- int count = mCountCapRes.getAndIncrement();
- mCaptureResults[count] = result;
- mSocketRunnableObj.sendResponseCaptureResult(mCameraCharacteristics,
- request, result, mCaptureReaders);
- mCountCallbacksRemaining.decrementAndGet();
- }
- } catch (ItsException e) {
- Logt.e(TAG, "Script error: ", e);
- } catch (Exception e) {
- Logt.e(TAG, "Script error: ", e);
- }
- }
-
- @Override
- public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
- CaptureFailure failure) {
- Logt.e(TAG, "Script error: capture failed");
- }
- };
-}
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java
deleted file mode 100644
index 8d330cf..0000000
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.camera2.its;
-
-import android.content.Context;
-import android.graphics.ImageFormat;
-import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.params.MeteringRectangle;
-import android.hardware.camera2.params.StreamConfigurationMap;
-import android.media.Image;
-import android.media.Image.Plane;
-import android.net.Uri;
-import android.os.Environment;
-import android.util.Log;
-import android.util.Size;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-
-public class ItsUtils {
- public static final String TAG = ItsUtils.class.getSimpleName();
-
- public static ByteBuffer jsonToByteBuffer(JSONObject jsonObj) {
- return ByteBuffer.wrap(jsonObj.toString().getBytes(Charset.defaultCharset()));
- }
-
- public static MeteringRectangle[] getJsonWeightedRectsFromArray(
- JSONArray a, boolean normalized, int width, int height)
- throws ItsException {
- try {
- // Returns [x0,y0,x1,y1,wgt, x0,y0,x1,y1,wgt, x0,y0,x1,y1,wgt, ...]
- assert(a.length() % 5 == 0);
- MeteringRectangle[] ma = new MeteringRectangle[a.length() / 5];
- for (int i = 0; i < a.length(); i += 5) {
- int x,y,w,h;
- if (normalized) {
- x = (int)Math.floor(a.getDouble(i+0) * width + 0.5f);
- y = (int)Math.floor(a.getDouble(i+1) * height + 0.5f);
- w = (int)Math.floor(a.getDouble(i+2) * width + 0.5f);
- h = (int)Math.floor(a.getDouble(i+3) * height + 0.5f);
- } else {
- x = a.getInt(i+0);
- y = a.getInt(i+1);
- w = a.getInt(i+2);
- h = a.getInt(i+3);
- }
- x = Math.max(x, 0);
- y = Math.max(y, 0);
- w = Math.min(w, width-x);
- h = Math.min(h, height-y);
- int wgt = a.getInt(i+4);
- ma[i/5] = new MeteringRectangle(x,y,w,h,wgt);
- }
- return ma;
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error: ", e);
- }
- }
-
- public static JSONArray getOutputSpecs(JSONObject jsonObjTop)
- throws ItsException {
- try {
- if (jsonObjTop.has("outputSurfaces")) {
- return jsonObjTop.getJSONArray("outputSurfaces");
- }
- return null;
- } catch (org.json.JSONException e) {
- throw new ItsException("JSON error: ", e);
- }
- }
-
- public static Size[] getRawOutputSizes(CameraCharacteristics ccs)
- throws ItsException {
- return getOutputSizes(ccs, ImageFormat.RAW_SENSOR);
- }
-
- public static Size[] getJpegOutputSizes(CameraCharacteristics ccs)
- throws ItsException {
- return getOutputSizes(ccs, ImageFormat.JPEG);
- }
-
- public static Size[] getYuvOutputSizes(CameraCharacteristics ccs)
- throws ItsException {
- return getOutputSizes(ccs, ImageFormat.YUV_420_888);
- }
-
- private static Size[] getOutputSizes(CameraCharacteristics ccs, int format)
- throws ItsException {
- StreamConfigurationMap configMap = ccs.get(
- CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- if (configMap == null) {
- throw new ItsException("Failed to get stream config");
- }
- return configMap.getOutputSizes(format);
- }
-
- public static byte[] getDataFromImage(Image image)
- throws ItsException {
- int format = image.getFormat();
- int width = image.getWidth();
- int height = image.getHeight();
- byte[] data = null;
-
- // Read image data
- Plane[] planes = image.getPlanes();
-
- // Check image validity
- if (!checkAndroidImageFormat(image)) {
- throw new ItsException(
- "Invalid image format passed to getDataFromImage: " + image.getFormat());
- }
-
- if (format == ImageFormat.JPEG) {
- // JPEG doesn't have pixelstride and rowstride, treat it as 1D buffer.
- ByteBuffer buffer = planes[0].getBuffer();
- data = new byte[buffer.capacity()];
- buffer.get(data);
- return data;
- } else if (format == ImageFormat.YUV_420_888 || format == ImageFormat.RAW_SENSOR
- || format == ImageFormat.RAW10) {
- int offset = 0;
- data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
- byte[] rowData = new byte[planes[0].getRowStride()];
- for (int i = 0; i < planes.length; i++) {
- ByteBuffer buffer = planes[i].getBuffer();
- int rowStride = planes[i].getRowStride();
- int pixelStride = planes[i].getPixelStride();
- int bytesPerPixel = ImageFormat.getBitsPerPixel(format) / 8;
- Logt.i(TAG, String.format(
- "Reading image: fmt %d, plane %d, w %d, h %d, rowStride %d, pixStride %d",
- format, i, width, height, rowStride, pixelStride));
- // For multi-planar yuv images, assuming yuv420 with 2x2 chroma subsampling.
- int w = (i == 0) ? width : width / 2;
- int h = (i == 0) ? height : height / 2;
- for (int row = 0; row < h; row++) {
- if (pixelStride == bytesPerPixel) {
- // Special case: optimized read of the entire row
- int length = w * bytesPerPixel;
- buffer.get(data, offset, length);
- // Advance buffer the remainder of the row stride
- buffer.position(buffer.position() + rowStride - length);
- offset += length;
- } else {
- // Generic case: should work for any pixelStride but slower.
- // Use intermediate buffer to avoid read byte-by-byte from
- // DirectByteBuffer, which is very bad for performance.
- // Also need avoid access out of bound by only reading the available
- // bytes in the bytebuffer.
- int readSize = rowStride;
- if (buffer.remaining() < readSize) {
- readSize = buffer.remaining();
- }
- buffer.get(rowData, 0, readSize);
- if (pixelStride >= 1) {
- for (int col = 0; col < w; col++) {
- data[offset++] = rowData[col * pixelStride];
- }
- } else {
- // PixelStride of 0 can mean pixel isn't a multiple of 8 bits, for
- // example with RAW10. Just copy the buffer, dropping any padding at
- // the end of the row.
- int length = (w * ImageFormat.getBitsPerPixel(format)) / 8;
- System.arraycopy(rowData,0,data,offset,length);
- offset += length;
- }
- }
- }
- }
- Logt.i(TAG, String.format("Done reading image, format %d", format));
- return data;
- } else {
- throw new ItsException("Unsupported image format: " + format);
- }
- }
-
- private static boolean checkAndroidImageFormat(Image image) {
- int format = image.getFormat();
- Plane[] planes = image.getPlanes();
- switch (format) {
- case ImageFormat.YUV_420_888:
- case ImageFormat.NV21:
- case ImageFormat.YV12:
- return 3 == planes.length;
- case ImageFormat.RAW_SENSOR:
- case ImageFormat.RAW10:
- case ImageFormat.JPEG:
- return 1 == planes.length;
- default:
- return false;
- }
- }
-}
-
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/Logt.java b/apps/CameraITS/service/src/com/android/camera2/its/Logt.java
deleted file mode 100644
index 2fc5399..0000000
--- a/apps/CameraITS/service/src/com/android/camera2/its/Logt.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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 com.android.camera2.its;
-
-import android.util.Log;
-
-public class Logt {
- public static void i(String tag, String msg) {
- long t = android.os.SystemClock.elapsedRealtime();
- Log.i(tag, String.format("[%d] %s", t, msg));
- }
- public static void e(String tag, String msg) {
- long t = android.os.SystemClock.elapsedRealtime();
- Log.e(tag, String.format("[%d] %s", t, msg));
- }
- public static void w(String tag, String msg) {
- long t = android.os.SystemClock.elapsedRealtime();
- Log.w(tag, String.format("[%d] %s", t, msg));
- }
- public static void e(String tag, String msg, Throwable tr) {
- long t = android.os.SystemClock.elapsedRealtime();
- Log.e(tag, String.format("[%d] %s", t, msg), tr);
- }
-}
-