diff options
author | Sol Boucher <solb@google.com> | 2014-08-16 00:23:31 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-08-15 18:45:09 +0000 |
commit | b2df32dd892ae8076714b7ebd33c715378c4c730 (patch) | |
tree | 5274854790d76d0bfe57f2265051099da127d950 /camera2 | |
parent | fa88947e17223d1e52eb8bfbac2f1cab7f2e56ba (diff) | |
parent | 50f5b019ba3f333a09a1beb9667fd7290082dc31 (diff) | |
download | android_frameworks_ex-b2df32dd892ae8076714b7ebd33c715378c4c730.tar.gz android_frameworks_ex-b2df32dd892ae8076714b7ebd33c715378c4c730.tar.bz2 android_frameworks_ex-b2df32dd892ae8076714b7ebd33c715378c4c730.zip |
Merge "camera2-portability: Make factory offer choice of backing API" into lmp-dev
Diffstat (limited to 'camera2')
4 files changed, 179 insertions, 14 deletions
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java index 65047f1..fc19aed 100644 --- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java +++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java @@ -215,6 +215,8 @@ class AndroidCamera2AgentImpl extends CameraAgent { mOpenCallback = openCallback; mCameraIndex = cameraIndex; mCameraId = mCameraDevices.get(mCameraIndex); + Log.i(TAG, String.format("Opening camera index %d (id %s) with camera2 API", + cameraIndex, mCameraId)); if (mCameraId == null) { mOpenCallback.onCameraDisabled(msg.arg1); @@ -858,6 +860,9 @@ class AndroidCamera2AgentImpl extends CameraAgent { public void setPreviewDataCallbackWithBuffer(Handler handler, CameraPreviewDataCallback cb) {} + // TODO: Implement + public void addCallbackBuffer(final byte[] callbackBuffer) {} + @Override public void autoFocus(final Handler handler, final CameraAFCallback cb) { mDispatchThread.runJob(new Runnable() { diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraAgentImpl.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraAgentImpl.java index 95f0320..6885cee 100644 --- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraAgentImpl.java +++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraAgentImpl.java @@ -304,6 +304,7 @@ class AndroidCameraAgentImpl extends CameraAgent { break; } + Log.i(TAG, "Opening camera " + cameraId + " with camera1 API"); mCamera = android.hardware.Camera.open(cameraId); if (mCamera != null) { mCameraId = cameraId; diff --git a/camera2/portability/src/com/android/ex/camera2/portability/CameraAgentFactory.java b/camera2/portability/src/com/android/ex/camera2/portability/CameraAgentFactory.java index 00dc280..77ad0c3 100644 --- a/camera2/portability/src/com/android/ex/camera2/portability/CameraAgentFactory.java +++ b/camera2/portability/src/com/android/ex/camera2/portability/CameraAgentFactory.java @@ -17,42 +17,150 @@ package com.android.ex.camera2.portability; import android.content.Context; +import android.os.Build; + +import com.android.ex.camera2.portability.debug.Log; +import com.android.ex.camera2.portability.util.SystemProperties; /** * A factory class for {@link CameraAgent}. + * + * <p>The choice of framework API to use can be made automatically based on the + * system API level, explicitly forced by the client app, or overridden entirely + * by setting the system property com.camera2.portability.fwk_api to 1 or 2.</p> */ public class CameraAgentFactory { + private static final Log.Tag TAG = new Log.Tag("CamAgntFact"); + + /** Android release replacing the Camera class with the camera2 package. */ + private static final int FIRST_SDK_WITH_API_2 = 21; + + // The debugging override, which overrides *all* API level selections if set + // to API_LEVEL_OVERRIDE_API{1,2}; otherwise, this has no effect. Note that + // we check this once when the library is first loaded so that #recycle() + // doesn't try to clean up the wrong type of CameraAgent. + private static final String API_LEVEL_OVERRIDE_KEY = "camera2.portability.force_api"; + private static final String API_LEVEL_OVERRIDE_DEFAULT = "0"; + private static final String API_LEVEL_OVERRIDE_API1 = "1"; + private static final String API_LEVEL_OVERRIDE_API2 = "2"; + private static final String API_LEVEL_OVERRIDE_VALUE = + SystemProperties.get(API_LEVEL_OVERRIDE_KEY, API_LEVEL_OVERRIDE_DEFAULT); private static CameraAgent sAndroidCameraAgent; + private static CameraAgent sAndroidCamera2Agent; private static int sAndroidCameraAgentClientCount; + private static int sAndroidCamera2AgentClientCount; /** - * Returns the android camera implementation of {@link com.android.camera.cameradevice.CameraAgent}. + * Used to indicate which camera framework should be used. + */ + public static enum CameraApi { + /** Automatically select based on the device's SDK level. */ + AUTO, + + /** Use the {@link android.hardware.Camera} class. */ + API_1, + + /** Use the {@link android.hardware.camera2} package. */ + API_2 + }; + + private static CameraApi highestSupportedApi() { + // TODO: Check SDK_INT instead of RELEASE before L launch + if (Build.VERSION.SDK_INT >= FIRST_SDK_WITH_API_2 || Build.VERSION.CODENAME.equals("L")) { + return CameraApi.API_2; + } else { + return CameraApi.API_1; + } + } + + private static CameraApi validateApiChoice(CameraApi choice) { + if (API_LEVEL_OVERRIDE_VALUE.equals(API_LEVEL_OVERRIDE_API1)) { + Log.d(TAG, "API level overridden by system property: forced to 1"); + return CameraApi.API_1; + } else if (API_LEVEL_OVERRIDE_VALUE.equals(API_LEVEL_OVERRIDE_API2)) { + Log.d(TAG, "API level overridden by system property: forced to 2"); + return CameraApi.API_2; + } + + if (choice == null) { + Log.w(TAG, "null API level request, so assuming AUTO"); + choice = CameraApi.AUTO; + } + if (choice == CameraApi.AUTO) { + choice = highestSupportedApi(); + } + + return choice; + } + + /** + * Returns the android camera implementation of + * {@link com.android.camera.cameradevice.CameraAgent}. + * + * <p>To clean up the resources allocated by this call, be sure to invoke + * {@link #recycle(boolean)} with the same {@code api} value provided + * here.</p> * + * @param context The application context. + * @param api Which camera framework to use. * @return The {@link CameraAgent} to control the camera device. + * + * @throws UnsupportedOperationException If {@code CameraApi.API_2} was + * requested on an unsupported device. */ - public static synchronized CameraAgent getAndroidCameraAgent(Context context) { - if (sAndroidCameraAgent == null) { - if (false) { - sAndroidCameraAgent = new AndroidCamera2AgentImpl(context); - } else { + public static synchronized CameraAgent getAndroidCameraAgent(Context context, CameraApi api) { + api = validateApiChoice(api); + + if (api == CameraApi.API_1) { + if (sAndroidCameraAgent == null) { sAndroidCameraAgent = new AndroidCameraAgentImpl(); + sAndroidCameraAgentClientCount = 1; + } else { + ++sAndroidCameraAgentClientCount; } - sAndroidCameraAgentClientCount = 1; - } else { - ++sAndroidCameraAgentClientCount; + return sAndroidCameraAgent; + } else { // API_2 + if (highestSupportedApi() == CameraApi.API_1) { + throw new UnsupportedOperationException("Camera API_2 unavailable on this device"); + } + + if (sAndroidCamera2Agent == null) { + sAndroidCamera2Agent = new AndroidCamera2AgentImpl(context); + sAndroidCamera2AgentClientCount = 1; + } else { + ++sAndroidCamera2AgentClientCount; + } + return sAndroidCamera2Agent; } - return sAndroidCameraAgent; } /** * Recycles the resources. Always call this method when the activity is * stopped. + * + * @param api Which camera framework handle to recycle. + * + * @throws UnsupportedOperationException If {@code CameraApi.API_2} was + * requested on an unsupported device. */ - public static synchronized void recycle() { - if (--sAndroidCameraAgentClientCount == 0 && sAndroidCameraAgent != null) { - sAndroidCameraAgent.recycle(); - sAndroidCameraAgent = null; + public static synchronized void recycle(CameraApi api) { + api = validateApiChoice(api); + + if (api == CameraApi.API_1) { + if (--sAndroidCameraAgentClientCount == 0 && sAndroidCameraAgent != null) { + sAndroidCameraAgent.recycle(); + sAndroidCameraAgent = null; + } + } else { // API_2 + if (highestSupportedApi() == CameraApi.API_1) { + throw new UnsupportedOperationException("Camera API_2 unavailable on this device"); + } + + if (--sAndroidCamera2AgentClientCount == 0 && sAndroidCamera2Agent != null) { + sAndroidCamera2Agent.recycle(); + sAndroidCamera2Agent = null; + } } } } diff --git a/camera2/portability/src/com/android/ex/camera2/portability/util/SystemProperties.java b/camera2/portability/src/com/android/ex/camera2/portability/util/SystemProperties.java new file mode 100644 index 0000000..81493f3 --- /dev/null +++ b/camera2/portability/src/com/android/ex/camera2/portability/util/SystemProperties.java @@ -0,0 +1,51 @@ +/* + * 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.ex.camera2.portability.util; + +import com.android.ex.camera2.portability.debug.Log; + +import java.lang.reflect.Method; + +/** + * Mirrors hidden class {@link android.os.SystemProperties} (available since API Level 1). + */ +public final class SystemProperties { + private static final Log.Tag TAG = new Log.Tag("SysProps"); + + /** + * Gets system properties set by <code>adb shell setprop <em>key</em> <em>value</em></code> + * + * @param key the property key. + * @param defaultValue the value to return if the property is undefined or empty (this parameter + * may be {@code null}). + * @return the system property value or the default value. + */ + public static String get(String key, String defaultValue) { + try { + final Class<?> systemProperties = Class.forName("android.os.SystemProperties"); + final Method get = systemProperties.getMethod("get", String.class, String.class); + return (String) get.invoke(null, key, defaultValue); + } catch (Exception e) { + // This should never happen + Log.e(TAG, "Exception while getting system property: ", e); + return defaultValue; + } + } + + private SystemProperties() { + } +} |