From 5d2d7788f1759b0f3d2c057af0b3ea61b0354fee Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Thu, 17 Dec 2015 16:50:50 -0800 Subject: [PATCH] Camera2: Switch to auto-gen C++ binder interfaces - Move camera AIDL files to frameworks/av - Update makefiles to point to new AIDL locations - Adjust camera2 implementation to match modifications to AIDL needed for native AIDL auto-generation - Move Surface.aidl to frameworks/native to allow use in native AIDL. Use android::view::Surface in Surface JNI to serialize Surface objects to ensure parceling compatibility. - Adjust service binder tests to new interface Bug: 25091611 Change-Id: I85b817374b34a4540fa145328dbe4bbf7f746baf --- Android.mk | 20 +- core/java/android/hardware/CameraInfo.aidl | 20 -- core/java/android/hardware/ICamera.aidl | 26 -- core/java/android/hardware/ICameraClient.aidl | 26 -- core/java/android/hardware/ICameraService.aidl | 89 ------ .../android/hardware/ICameraServiceListener.aidl | 28 -- .../java/android/hardware/ICameraServiceProxy.aidl | 37 --- .../hardware/camera2/CameraAccessException.java | 37 ++- .../android/hardware/camera2/CameraManager.java | 336 ++++++++++----------- .../android/hardware/camera2/CaptureRequest.aidl | 20 -- .../hardware/camera2/ICameraDeviceCallbacks.aidl | 35 --- .../hardware/camera2/ICameraDeviceUser.aidl | 107 ------- .../hardware/camera2/impl/CameraDeviceImpl.java | 209 ++++--------- .../camera2/impl/CameraMetadataNative.aidl | 20 -- .../camera2/impl/CameraMetadataNative.java | 22 +- .../hardware/camera2/impl/CaptureResultExtras.aidl | 20 -- .../camera2/impl/ICameraDeviceUserWrapper.java | 212 +++++++++++++ .../hardware/camera2/legacy/BurstHolder.java | 4 +- .../camera2/legacy/CameraDeviceUserShim.java | 208 +++++++------ .../camera2/legacy/LegacyCameraDevice.java | 63 ++-- .../camera2/legacy/LegacyExceptionUtils.java | 70 ++++- .../hardware/camera2/legacy/RequestQueue.java | 24 +- .../camera2/legacy/RequestThreadManager.java | 20 +- .../camera2/params/OutputConfiguration.aidl | 20 -- .../camera2/params/OutputConfiguration.java | 4 +- .../camera2/params/VendorTagDescriptor.java | 67 ++++ .../hardware/camera2/utils/BinderHolder.aidl | 20 -- .../hardware/camera2/utils/BinderHolder.java | 74 ----- .../camera2/utils/CameraBinderDecorator.java | 162 ---------- .../camera2/utils/CameraRuntimeException.java | 63 ---- .../utils/CameraServiceBinderDecorator.java | 70 ----- .../android/hardware/camera2/utils/Decorator.java | 92 ------ .../hardware/camera2/utils/LongParcelable.aidl | 20 -- .../android/hardware/camera2/utils/SubmitInfo.java | 106 +++++++ core/java/android/os/ServiceSpecificException.java | 11 +- core/java/android/view/Surface.aidl | 20 -- core/jni/Android.mk | 1 - .../android_hardware_camera2_CameraMetadata.cpp | 26 +- core/jni/android_view_Surface.cpp | 25 +- media/jni/Android.mk | 1 - media/jni/android_media_MediaRecorder.cpp | 1 - .../MediaFrameworkUnitTestRunner.java | 3 - .../integration/CameraBinderTest.java | 112 +++---- .../integration/CameraBinderTestUtils.java | 4 - .../integration/CameraDeviceBinderTest.java | 205 +++++++------ .../unit/CameraUtilsBinderDecoratorTest.java | 173 ----------- .../unit/CameraUtilsDecoratorTest.java | 171 ----------- .../unit/CameraUtilsRuntimeExceptionTest.java | 77 ----- .../com/android/server/camera/CameraService.java | 8 +- 49 files changed, 1110 insertions(+), 2079 deletions(-) delete mode 100644 core/java/android/hardware/CameraInfo.aidl delete mode 100644 core/java/android/hardware/ICamera.aidl delete mode 100644 core/java/android/hardware/ICameraClient.aidl delete mode 100644 core/java/android/hardware/ICameraService.aidl delete mode 100644 core/java/android/hardware/ICameraServiceListener.aidl delete mode 100644 core/java/android/hardware/ICameraServiceProxy.aidl delete mode 100644 core/java/android/hardware/camera2/CaptureRequest.aidl delete mode 100644 core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl delete mode 100644 core/java/android/hardware/camera2/ICameraDeviceUser.aidl delete mode 100644 core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl delete mode 100644 core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl create mode 100644 core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java delete mode 100644 core/java/android/hardware/camera2/params/OutputConfiguration.aidl create mode 100644 core/java/android/hardware/camera2/params/VendorTagDescriptor.java delete mode 100644 core/java/android/hardware/camera2/utils/BinderHolder.aidl delete mode 100644 core/java/android/hardware/camera2/utils/BinderHolder.java delete mode 100644 core/java/android/hardware/camera2/utils/CameraBinderDecorator.java delete mode 100644 core/java/android/hardware/camera2/utils/CameraRuntimeException.java delete mode 100644 core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java delete mode 100644 core/java/android/hardware/camera2/utils/Decorator.java delete mode 100644 core/java/android/hardware/camera2/utils/LongParcelable.aidl create mode 100644 core/java/android/hardware/camera2/utils/SubmitInfo.java delete mode 100644 core/java/android/view/Surface.aidl delete mode 100644 media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java delete mode 100644 media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java delete mode 100644 media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java diff --git a/Android.mk b/Android.mk index 2ee7600d3288..3ac5889f61c3 100644 --- a/Android.mk +++ b/Android.mk @@ -150,14 +150,14 @@ LOCAL_SRC_FILES += \ core/java/android/content/pm/IPackageStatsObserver.aidl \ core/java/android/content/pm/IOnPermissionsChangeListener.aidl \ core/java/android/database/IContentObserver.aidl \ - core/java/android/hardware/ICameraService.aidl \ - core/java/android/hardware/ICameraServiceListener.aidl \ - core/java/android/hardware/ICameraServiceProxy.aidl \ - core/java/android/hardware/ICamera.aidl \ - core/java/android/hardware/ICameraClient.aidl \ + ../av/camera/aidl/android/hardware/ICameraService.aidl \ + ../av/camera/aidl/android/hardware/ICameraServiceListener.aidl \ + ../av/camera/aidl/android/hardware/ICameraServiceProxy.aidl \ + ../av/camera/aidl/android/hardware/ICamera.aidl \ + ../av/camera/aidl/android/hardware/ICameraClient.aidl \ + ../av/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl \ + ../av/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl \ core/java/android/hardware/IConsumerIrService.aidl \ - core/java/android/hardware/camera2/ICameraDeviceUser.aidl \ - core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl \ core/java/android/hardware/ISerialManager.aidl \ core/java/android/hardware/display/IDisplayManager.aidl \ core/java/android/hardware/display/IDisplayManagerCallback.aidl \ @@ -455,6 +455,10 @@ LOCAL_AIDL_INCLUDES += \ $(FRAMEWORKS_BASE_JAVA_SRC_DIRS) \ frameworks/native/aidl/binder +LOCAL_AIDL_INCLUDES += \ + frameworks/av/camera/aidl \ + frameworks/native/aidl/gui + LOCAL_INTERMEDIATE_SOURCES := \ $(framework_res_source_path)/android/R.java \ $(framework_res_source_path)/android/Manifest.java \ @@ -577,7 +581,7 @@ aidl_files := \ frameworks/base/core/java/android/view/Display.aidl \ frameworks/base/core/java/android/view/InputDevice.aidl \ frameworks/base/core/java/android/view/InputEvent.aidl \ - frameworks/base/core/java/android/view/Surface.aidl \ + frameworks/native/aidl/gui/android/view/Surface.aidl \ frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \ frameworks/base/core/java/android/view/inputmethod/InputMethodSubtype.aidl \ frameworks/base/core/java/android/view/inputmethod/CursorAnchorInfo.aidl \ diff --git a/core/java/android/hardware/CameraInfo.aidl b/core/java/android/hardware/CameraInfo.aidl deleted file mode 100644 index e21e6941e976..000000000000 --- a/core/java/android/hardware/CameraInfo.aidl +++ /dev/null @@ -1,20 +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 android.hardware; - -/** @hide */ -parcelable CameraInfo; diff --git a/core/java/android/hardware/ICamera.aidl b/core/java/android/hardware/ICamera.aidl deleted file mode 100644 index d4f64f8468b3..000000000000 --- a/core/java/android/hardware/ICamera.aidl +++ /dev/null @@ -1,26 +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 android.hardware; - -/** @hide */ -interface ICamera -{ - /** - * Keep up-to-date with frameworks/av/include/camera/ICamera.h - */ - void disconnect(); -} diff --git a/core/java/android/hardware/ICameraClient.aidl b/core/java/android/hardware/ICameraClient.aidl deleted file mode 100644 index d7877b4be956..000000000000 --- a/core/java/android/hardware/ICameraClient.aidl +++ /dev/null @@ -1,26 +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 android.hardware; - -/** @hide */ -interface ICameraClient -{ - /** - * Keep up-to-date with frameworks/av/include/camera/ICameraClient.h - */ - // TODO: consider implementing this. -} diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl deleted file mode 100644 index 0b165cd78607..000000000000 --- a/core/java/android/hardware/ICameraService.aidl +++ /dev/null @@ -1,89 +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 android.hardware; - -import android.hardware.ICamera; -import android.hardware.ICameraClient; -import android.hardware.camera2.ICameraDeviceUser; -import android.hardware.camera2.ICameraDeviceCallbacks; -import android.hardware.camera2.impl.CameraMetadataNative; -import android.hardware.camera2.utils.BinderHolder; -import android.hardware.ICameraServiceListener; -import android.hardware.CameraInfo; - -/** - * Binder interface for the native camera service running in mediaserver. - * - * @hide - */ -interface ICameraService -{ - /** - * Keep up-to-date with frameworks/av/include/camera/ICameraService.h - */ - int getNumberOfCameras(int type); - - // rest of 'int' return values in this file are actually status_t - - int getCameraInfo(int cameraId, out CameraInfo info); - - int connect(ICameraClient client, int cameraId, - String opPackageName, - int clientUid, - // Container for an ICamera object - out BinderHolder device); - - int connectDevice(ICameraDeviceCallbacks callbacks, int cameraId, - String opPackageName, - int clientUid, - // Container for an ICameraDeviceUser object - out BinderHolder device); - - int addListener(ICameraServiceListener listener); - int removeListener(ICameraServiceListener listener); - - int getCameraCharacteristics(int cameraId, out CameraMetadataNative info); - - /** - * The java stubs for this method are not intended to be used. Please use - * the native stub in frameworks/av/include/camera/ICameraService.h instead. - * The BinderHolder output is being used as a placeholder, and will not be - * well-formatted in the generated java method. - */ - int getCameraVendorTagDescriptor(out BinderHolder desc); - - // Writes the camera1 parameters into a single-element array. - int getLegacyParameters(int cameraId, out String[] parameters); - // Determines if a particular API version is supported; see ICameraService.h for version defines - int supportsCameraApi(int cameraId, int apiVersion); - - int connectLegacy(ICameraClient client, int cameraId, - int halVersion, - String opPackageName, - int clientUid, - // Container for an ICamera object - out BinderHolder device); - - int setTorchMode(String CameraId, boolean enabled, IBinder clientBinder); - - /** - * Notify the camera service of a system event. Should only be called from system_server. - * - * Callers require the android.permission.CAMERA_SEND_SYSTEM_EVENTS permission. - */ - oneway void notifySystemEvent(int eventId, in int[] args); -} diff --git a/core/java/android/hardware/ICameraServiceListener.aidl b/core/java/android/hardware/ICameraServiceListener.aidl deleted file mode 100644 index 49278b622bef..000000000000 --- a/core/java/android/hardware/ICameraServiceListener.aidl +++ /dev/null @@ -1,28 +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 android.hardware; - -/** @hide */ -interface ICameraServiceListener -{ - /** - * Keep up-to-date with frameworks/av/include/camera/ICameraServiceListener.h - */ - void onStatusChanged(int status, int cameraId); - - void onTorchStatusChanged(int status, String cameraId); -} diff --git a/core/java/android/hardware/ICameraServiceProxy.aidl b/core/java/android/hardware/ICameraServiceProxy.aidl deleted file mode 100644 index 0e654d5083b6..000000000000 --- a/core/java/android/hardware/ICameraServiceProxy.aidl +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2015 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 android.hardware; - -/** - * Binder interface for the camera service proxy running in system_server. - * - * Keep in sync with frameworks/av/include/camera/ICameraServiceProxy.h - * - * @hide - */ -interface ICameraServiceProxy -{ - /** - * Ping the service proxy to update the valid users for the camera service. - */ - oneway void pingForUserUpdate(); - - /** - * Update the status of a camera device - */ - oneway void notifyCameraState(String cameraId, int newCameraState); -} diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java index 933ce0d73d85..f9b659c67e86 100644 --- a/core/java/android/hardware/camera2/CameraAccessException.java +++ b/core/java/android/hardware/camera2/CameraAccessException.java @@ -114,12 +114,12 @@ public class CameraAccessException extends AndroidException { } public CameraAccessException(@AccessError int problem, String message) { - super(message); + super(getCombinedMessage(problem, message)); mReason = problem; } public CameraAccessException(@AccessError int problem, String message, Throwable cause) { - super(message, cause); + super(getCombinedMessage(problem, message), cause); mReason = problem; } @@ -151,4 +151,37 @@ public class CameraAccessException extends AndroidException { } return null; } + + private static String getCombinedMessage(@AccessError int problem, String message) { + String problemString = getProblemString(problem); + return String.format("%s (%d): %s", problemString, problem, message); + } + + private static String getProblemString(int problem) { + String problemString; + switch (problem) { + case CAMERA_IN_USE: + problemString = "CAMERA_IN_USE"; + break; + case MAX_CAMERAS_IN_USE: + problemString = "MAX_CAMERAS_IN_USE"; + break; + case CAMERA_DISCONNECTED: + problemString = "CAMERA_DISCONNECTED"; + break; + case CAMERA_DISABLED: + problemString = "CAMERA_DISABLED"; + break; + case CAMERA_ERROR: + problemString = "CAMERA_ERROR"; + break; + case CAMERA_DEPRECATED_HAL: + problemString = "CAMERA_DEPRECATED_HAL"; + break; + default: + problemString = ""; + } + return problemString; + } + } diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 51796ebe463a..b3c8e3bb2efd 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -26,15 +26,14 @@ import android.hardware.CameraInfo; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.legacy.CameraDeviceUserShim; import android.hardware.camera2.legacy.LegacyMetadataMapper; -import android.hardware.camera2.utils.CameraServiceBinderDecorator; -import android.hardware.camera2.utils.CameraRuntimeException; -import android.hardware.camera2.utils.BinderHolder; import android.os.IBinder; import android.os.Binder; +import android.os.DeadObjectException; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.util.Log; import android.util.ArrayMap; @@ -240,25 +239,19 @@ public final class CameraManager { if (!supportsCamera2ApiLocked(cameraId)) { // Legacy backwards compatibility path; build static info from the camera // parameters - String[] outParameters = new String[1]; + String parameters = cameraService.getLegacyParameters(id); - cameraService.getLegacyParameters(id, /*out*/outParameters); - String parameters = outParameters[0]; - - CameraInfo info = new CameraInfo(); - cameraService.getCameraInfo(id, /*out*/info); + CameraInfo info = cameraService.getCameraInfo(id); characteristics = LegacyMetadataMapper.createCharacteristics(parameters, info); } else { // Normal path: Get the camera characteristics directly from the camera service - CameraMetadataNative info = new CameraMetadataNative(); - - cameraService.getCameraCharacteristics(id, info); + CameraMetadataNative info = cameraService.getCameraCharacteristics(id); characteristics = new CameraCharacteristics(info); } - } catch (CameraRuntimeException e) { - throw e.asChecked(); + } catch (ServiceSpecificException e) { + throwAsPublicException(e); } catch (RemoteException e) { // Camera service died - act as if the camera was disconnected throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, @@ -292,85 +285,83 @@ public final class CameraManager { throws CameraAccessException { CameraCharacteristics characteristics = getCameraCharacteristics(cameraId); CameraDevice device = null; - try { - synchronized (mLock) { + synchronized (mLock) { - ICameraDeviceUser cameraUser = null; + ICameraDeviceUser cameraUser = null; - android.hardware.camera2.impl.CameraDeviceImpl deviceImpl = - new android.hardware.camera2.impl.CameraDeviceImpl( - cameraId, - callback, - handler, - characteristics); + android.hardware.camera2.impl.CameraDeviceImpl deviceImpl = + new android.hardware.camera2.impl.CameraDeviceImpl( + cameraId, + callback, + handler, + characteristics); - BinderHolder holder = new BinderHolder(); + ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks(); - ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks(); - int id = Integer.parseInt(cameraId); - try { - if (supportsCamera2ApiLocked(cameraId)) { - // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices - ICameraService cameraService = CameraManagerGlobal.get().getCameraService(); - if (cameraService == null) { - throw new CameraRuntimeException( - CameraAccessException.CAMERA_DISCONNECTED, - "Camera service is currently unavailable"); - } - cameraService.connectDevice(callbacks, id, - mContext.getOpPackageName(), USE_CALLING_UID, holder); - cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder()); - } else { - // Use legacy camera implementation for HAL1 devices - Log.i(TAG, "Using legacy camera HAL."); - cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id); + int id; + try { + id = Integer.parseInt(cameraId); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: " + + cameraId); + } + + try { + if (supportsCamera2ApiLocked(cameraId)) { + // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices + ICameraService cameraService = CameraManagerGlobal.get().getCameraService(); + if (cameraService == null) { + throw new ServiceSpecificException( + ICameraService.ERROR_DISCONNECTED, + "Camera service is currently unavailable"); } - } catch (CameraRuntimeException e) { - if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) { - throw new AssertionError("Should've gone down the shim path"); - } else if (e.getReason() == CameraAccessException.CAMERA_IN_USE || - e.getReason() == CameraAccessException.MAX_CAMERAS_IN_USE || - e.getReason() == CameraAccessException.CAMERA_DISABLED || - e.getReason() == CameraAccessException.CAMERA_DISCONNECTED || - e.getReason() == CameraAccessException.CAMERA_ERROR) { - // Received one of the known connection errors - // The remote camera device cannot be connected to, so - // set the local camera to the startup error state - deviceImpl.setRemoteFailure(e); - - if (e.getReason() == CameraAccessException.CAMERA_DISABLED || - e.getReason() == CameraAccessException.CAMERA_DISCONNECTED || - e.getReason() == CameraAccessException.CAMERA_IN_USE) { - // Per API docs, these failures call onError and throw - throw e.asChecked(); - } - } else { - // Unexpected failure - rethrow - throw e; + cameraUser = cameraService.connectDevice(callbacks, id, + mContext.getOpPackageName(), USE_CALLING_UID); + } else { + // Use legacy camera implementation for HAL1 devices + Log.i(TAG, "Using legacy camera HAL."); + cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id); + } + } catch (ServiceSpecificException e) { + if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) { + throw new AssertionError("Should've gone down the shim path"); + } else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE || + e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE || + e.errorCode == ICameraService.ERROR_DISABLED || + e.errorCode == ICameraService.ERROR_DISCONNECTED || + e.errorCode == ICameraService.ERROR_INVALID_OPERATION) { + // Received one of the known connection errors + // The remote camera device cannot be connected to, so + // set the local camera to the startup error state + deviceImpl.setRemoteFailure(e); + + if (e.errorCode == ICameraService.ERROR_DISABLED || + e.errorCode == ICameraService.ERROR_DISCONNECTED || + e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) { + // Per API docs, these failures call onError and throw + throwAsPublicException(e); } - } catch (RemoteException e) { - // Camera service died - act as if it's a CAMERA_DISCONNECTED case - CameraRuntimeException ce = new CameraRuntimeException( - CameraAccessException.CAMERA_DISCONNECTED, - "Camera service is currently unavailable", e); - deviceImpl.setRemoteFailure(ce); - throw ce.asChecked(); + } else { + // Unexpected failure - rethrow + throwAsPublicException(e); } - - // TODO: factor out callback to be non-nested, then move setter to constructor - // For now, calling setRemoteDevice will fire initial - // onOpened/onUnconfigured callbacks. - deviceImpl.setRemoteDevice(cameraUser); - device = deviceImpl; + } catch (RemoteException e) { + // Camera service died - act as if it's a CAMERA_DISCONNECTED case + ServiceSpecificException sse = new ServiceSpecificException( + ICameraService.ERROR_DISCONNECTED, + "Camera service is currently unavailable"); + deviceImpl.setRemoteFailure(sse); + throwAsPublicException(sse); } - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: " - + cameraId); - } catch (CameraRuntimeException e) { - throw e.asChecked(); + // TODO: factor out callback to be non-nested, then move setter to constructor + // For now, calling setRemoteDevice will fire initial + // onOpened/onUnconfigured callbacks. + deviceImpl.setRemoteDevice(cameraUser); + device = deviceImpl; } + return device; } @@ -602,6 +593,56 @@ public final class CameraManager { } /** + * Convert ServiceSpecificExceptions and Binder RemoteExceptions from camera binder interfaces + * into the correct public exceptions. + * + * @hide + */ + public static void throwAsPublicException(Throwable t) throws CameraAccessException { + if (t instanceof ServiceSpecificException) { + ServiceSpecificException e = (ServiceSpecificException) t; + int reason = CameraAccessException.CAMERA_ERROR; + switch(e.errorCode) { + case ICameraService.ERROR_DISCONNECTED: + reason = CameraAccessException.CAMERA_DISCONNECTED; + break; + case ICameraService.ERROR_DISABLED: + reason = CameraAccessException.CAMERA_DISABLED; + break; + case ICameraService.ERROR_CAMERA_IN_USE: + reason = CameraAccessException.CAMERA_IN_USE; + break; + case ICameraService.ERROR_MAX_CAMERAS_IN_USE: + reason = CameraAccessException.MAX_CAMERAS_IN_USE; + break; + case ICameraService.ERROR_DEPRECATED_HAL: + reason = CameraAccessException.CAMERA_DEPRECATED_HAL; + break; + case ICameraService.ERROR_ILLEGAL_ARGUMENT: + case ICameraService.ERROR_ALREADY_EXISTS: + throw new IllegalArgumentException(e.getMessage(), e); + case ICameraService.ERROR_PERMISSION_DENIED: + throw new SecurityException(e.getMessage(), e); + case ICameraService.ERROR_TIMED_OUT: + case ICameraService.ERROR_INVALID_OPERATION: + default: + reason = CameraAccessException.CAMERA_ERROR; + } + throw new CameraAccessException(reason, e.getMessage(), e); + } else if (t instanceof DeadObjectException) { + throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, + "Camera service has died unexpectedly", + t); + } else if (t instanceof RemoteException) { + throw new UnsupportedOperationException("An unknown RemoteException was thrown" + + " which should never happen.", t); + } else if (t instanceof RuntimeException) { + RuntimeException e = (RuntimeException) t; + throw e; + } + } + + /** * Return or create the list of currently connected camera devices. * *

In case of errors connecting to the camera service, will return an empty list.

@@ -619,34 +660,32 @@ public final class CameraManager { try { numCameras = cameraService.getNumberOfCameras(CAMERA_TYPE_ALL); - } catch(CameraRuntimeException e) { - throw e.asChecked(); + } catch(ServiceSpecificException e) { + throwAsPublicException(e); } catch (RemoteException e) { // camera service just died - if no camera service, then no devices return deviceIdList; } - CameraMetadataNative info = new CameraMetadataNative(); for (int i = 0; i < numCameras; ++i) { // Non-removable cameras use integers starting at 0 for their // identifiers boolean isDeviceSupported = false; try { - cameraService.getCameraCharacteristics(i, info); + CameraMetadataNative info = cameraService.getCameraCharacteristics(i); if (!info.isEmpty()) { isDeviceSupported = true; } else { throw new AssertionError("Expected to get non-empty characteristics"); } - } catch(IllegalArgumentException e) { - // Got a BAD_VALUE from service, meaning that this - // device is not supported. - } catch(CameraRuntimeException e) { + } catch(ServiceSpecificException e) { // DISCONNECTED means that the HAL reported an low-level error getting the - // device info; skip listing the device. Other errors, + // device info; ILLEGAL_ARGUMENT means that this devices is not supported. + // Skip listing the device. Other errors, // propagate exception onward - if (e.getReason() != CameraAccessException.CAMERA_DISCONNECTED) { - throw e.asChecked(); + if (e.errorCode != ICameraService.ERROR_DISCONNECTED || + e.errorCode != ICameraService.ERROR_ILLEGAL_ARGUMENT) { + throwAsPublicException(e); } } catch(RemoteException e) { // Camera service died - no devices to list @@ -699,17 +738,7 @@ public final class CameraManager { // If no camera service, no support if (cameraService == null) return false; - int res = cameraService.supportsCameraApi(id, apiVersion); - - if (res != CameraServiceBinderDecorator.NO_ERROR) { - throw new AssertionError("Unexpected value " + res); - } - return true; - } catch (CameraRuntimeException e) { - if (e.getReason() != CameraAccessException.CAMERA_DEPRECATED_HAL) { - throw e; - } - // API level is not supported + return cameraService.supportsCameraApi(id, apiVersion); } catch (RemoteException e) { // Camera service is now down, no support for any API level } @@ -737,21 +766,6 @@ public final class CameraManager { */ private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera"; - // Keep up-to-date with ICameraServiceListener.h - - // Device physically unplugged - public static final int STATUS_NOT_PRESENT = 0; - // Device physically has been plugged in - // and the camera can be used exclusively - public static final int STATUS_PRESENT = 1; - // Device physically has been plugged in - // but it will not be connect-able until enumeration is complete - public static final int STATUS_ENUMERATING = 2; - // Camera is in use by another app and cannot be used exclusively - public static final int STATUS_NOT_AVAILABLE = 0x80000000; - - // End enums shared with ICameraServiceListener.h - // Camera ID -> Status map private final ArrayMap mDeviceStatus = new ArrayMap(); @@ -759,17 +773,6 @@ public final class CameraManager { private final ArrayMap mCallbackMap = new ArrayMap(); - // Keep up-to-date with ICameraServiceListener.h - - // torch mode has become not available to set via setTorchMode(). - public static final int TORCH_STATUS_NOT_AVAILABLE = 0; - // torch mode is off and available to be turned on via setTorchMode(). - public static final int TORCH_STATUS_AVAILABLE_OFF = 1; - // torch mode is on and available to be turned off via setTorchMode(). - public static final int TORCH_STATUS_AVAILABLE_ON = 2; - - // End enums shared with ICameraServiceListener.h - // torch client binder to set the torch mode with. private Binder mTorchClientBinder = new Binder(); @@ -839,29 +842,20 @@ public final class CameraManager { return; } - ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder); - - /** - * Wrap the camera service in a decorator which automatically translates return codes - * into exceptions. - */ - ICameraService cameraService = - CameraServiceBinderDecorator.newInstance(cameraServiceRaw); + ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder); try { - CameraServiceBinderDecorator.throwOnError( - CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor()); - } catch (CameraRuntimeException e) { - handleRecoverableSetupErrors(e, "Failed to set up vendor tags"); + CameraMetadataNative.setupGlobalVendorTagDescriptor(); + } catch (ServiceSpecificException e) { + handleRecoverableSetupErrors(e); } try { cameraService.addListener(this); mCameraService = cameraService; - } catch(CameraRuntimeException e) { + } catch(ServiceSpecificException e) { // Unexpected failure - throw new IllegalStateException("Failed to register a camera service listener", - e.asChecked()); + throw new IllegalStateException("Failed to register a camera service listener", e); } catch (RemoteException e) { // Camera service is now down, leave mCameraService as null } @@ -881,16 +875,9 @@ public final class CameraManager { } try { - int status = cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder); - } catch(CameraRuntimeException e) { - int problem = e.getReason(); - switch (problem) { - case CameraAccessException.CAMERA_ERROR: - throw new IllegalArgumentException( - "the camera device doesn't have a flash unit."); - default: - throw e.asChecked(); - } + cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder); + } catch(ServiceSpecificException e) { + throwAsPublicException(e); } catch (RemoteException e) { throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, "Camera service is currently unavailable"); @@ -898,21 +885,19 @@ public final class CameraManager { } } - private void handleRecoverableSetupErrors(CameraRuntimeException e, String msg) { - int problem = e.getReason(); - switch (problem) { - case CameraAccessException.CAMERA_DISCONNECTED: - String errorMsg = CameraAccessException.getDefaultMessage(problem); - Log.w(TAG, msg + ": " + errorMsg); + private void handleRecoverableSetupErrors(ServiceSpecificException e) { + switch (e.errorCode) { + case ICameraService.ERROR_DISCONNECTED: + Log.w(TAG, e.getMessage()); break; default: - throw new IllegalStateException(msg, e.asChecked()); + throw new IllegalStateException(e); } } private boolean isAvailable(int status) { switch (status) { - case STATUS_PRESENT: + case ICameraServiceListener.STATUS_PRESENT: return true; default: return false; @@ -921,10 +906,10 @@ public final class CameraManager { private boolean validStatus(int status) { switch (status) { - case STATUS_NOT_PRESENT: - case STATUS_PRESENT: - case STATUS_ENUMERATING: - case STATUS_NOT_AVAILABLE: + case ICameraServiceListener.STATUS_NOT_PRESENT: + case ICameraServiceListener.STATUS_PRESENT: + case ICameraServiceListener.STATUS_ENUMERATING: + case ICameraServiceListener.STATUS_NOT_AVAILABLE: return true; default: return false; @@ -933,9 +918,9 @@ public final class CameraManager { private boolean validTorchStatus(int status) { switch (status) { - case TORCH_STATUS_NOT_AVAILABLE: - case TORCH_STATUS_AVAILABLE_ON: - case TORCH_STATUS_AVAILABLE_OFF: + case ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE: + case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON: + case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF: return true; default: return false; @@ -966,14 +951,14 @@ public final class CameraManager { private void postSingleTorchUpdate(final TorchCallback callback, final Handler handler, final String id, final int status) { switch(status) { - case TORCH_STATUS_AVAILABLE_ON: - case TORCH_STATUS_AVAILABLE_OFF: + case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON: + case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF: handler.post( new Runnable() { @Override public void run() { callback.onTorchModeChanged(id, status == - TORCH_STATUS_AVAILABLE_ON); + ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON); } }); break; @@ -1220,11 +1205,12 @@ public final class CameraManager { // and torch statuses will be updated. for (int i = 0; i < mDeviceStatus.size(); i++) { String cameraId = mDeviceStatus.keyAt(i); - onStatusChangedLocked(STATUS_NOT_PRESENT, cameraId); + onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId); } for (int i = 0; i < mTorchStatus.size(); i++) { String cameraId = mTorchStatus.keyAt(i); - onTorchStatusChangedLocked(TORCH_STATUS_NOT_AVAILABLE, cameraId); + onTorchStatusChangedLocked(ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE, + cameraId); } scheduleCameraServiceReconnectionLocked(); diff --git a/core/java/android/hardware/camera2/CaptureRequest.aidl b/core/java/android/hardware/camera2/CaptureRequest.aidl deleted file mode 100644 index 0b7d5ba243ae..000000000000 --- a/core/java/android/hardware/camera2/CaptureRequest.aidl +++ /dev/null @@ -1,20 +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 android.hardware.camera2; - -/** @hide */ -parcelable CaptureRequest; diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl deleted file mode 100644 index 151c9183d731..000000000000 --- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl +++ /dev/null @@ -1,35 +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 android.hardware.camera2; - -import android.hardware.camera2.impl.CameraMetadataNative; -import android.hardware.camera2.impl.CaptureResultExtras; - -/** @hide */ -interface ICameraDeviceCallbacks -{ - /** - * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h - */ - - oneway void onDeviceError(int errorCode, in CaptureResultExtras resultExtras); - oneway void onDeviceIdle(); - oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp); - oneway void onResultReceived(in CameraMetadataNative result, - in CaptureResultExtras resultExtras); - oneway void onPrepared(int streamId); -} diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl deleted file mode 100644 index c9c9abc805f6..000000000000 --- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl +++ /dev/null @@ -1,107 +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 android.hardware.camera2; - -import android.hardware.camera2.CaptureRequest; -import android.hardware.camera2.impl.CameraMetadataNative; -import android.hardware.camera2.params.OutputConfiguration; -import android.hardware.camera2.utils.LongParcelable; -import android.view.Surface; - -/** @hide */ -interface ICameraDeviceUser -{ - /** - * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h and - * frameworks/base/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java - */ - void disconnect(); - - // ints here are status_t - - // non-negative value is the requestId. negative value is status_t - int submitRequest(in CaptureRequest request, boolean streaming, - out LongParcelable lastFrameNumber); - - int submitRequestList(in List requestList, boolean streaming, - out LongParcelable lastFrameNumber); - - int cancelRequest(int requestId, out LongParcelable lastFrameNumber); - - /** - * Begin the device configuration. - * - *

- * beginConfigure must be called before any call to deleteStream, createStream, - * or endConfigure. It is not valid to call this when the device is not idle. - *

- */ - int beginConfigure(); - - /** - * End the device configuration. - * - *

- * endConfigure must be called after stream configuration is complete (i.e. after - * a call to beginConfigure and subsequent createStream/deleteStream calls). This - * must be called before any requests can be submitted. - *

- */ - int endConfigure(boolean isConstrainedHighSpeed); - - int deleteStream(int streamId); - - // non-negative value is the stream ID. negative value is status_t - int createStream(in OutputConfiguration outputConfiguration); - - /** - * Create an input stream - * - *

Create an input stream of width, height, and format

- * - * @param width Width of the input buffers - * @param height Height of the input buffers - * @param format Format of the input buffers. One of HAL_PIXEL_FORMAT_*. - * - * @return stream ID if it's a non-negative value. status_t if it's a negative value. - */ - int createInputStream(int width, int height, int format); - - /** - * Get the surface of the input stream. - * - *

It's valid to call this method only after a stream configuration is completed - * successfully and the stream configuration includes a input stream.

- * - * @param surface An output argument for the surface of the input stream buffer queue. - */ - int getInputSurface(out Surface surface); - - int createDefaultRequest(int templateId, out CameraMetadataNative request); - - int getCameraInfo(out CameraMetadataNative info); - - int waitUntilIdle(); - - int flush(out LongParcelable lastFrameNumber); - - int prepare(int streamId); - - int tearDown(int streamId); - - int prepare2(int maxCount, int streamId); -} diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 3aba0d1bea96..00dd7802526a 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -33,14 +33,14 @@ import android.hardware.camera2.params.InputConfiguration; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.params.ReprocessFormatsMap; import android.hardware.camera2.params.StreamConfigurationMap; -import android.hardware.camera2.utils.CameraBinderDecorator; -import android.hardware.camera2.utils.CameraRuntimeException; -import android.hardware.camera2.utils.LongParcelable; +import android.hardware.camera2.utils.SubmitInfo; import android.hardware.camera2.utils.SurfaceUtils; +import android.hardware.ICameraService; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.util.Log; import android.util.Range; import android.util.Size; @@ -70,7 +70,7 @@ public class CameraDeviceImpl extends CameraDevice { private static final int REQUEST_ID_NONE = -1; // TODO: guard every function with if (!mRemoteDevice) check (if it was closed) - private ICameraDeviceUser mRemoteDevice; + private ICameraDeviceUserWrapper mRemoteDevice; // Lock to synchronize cross-thread access to device public interface final Object mInterfaceLock = new Object(); // access from this class and Session only! @@ -267,7 +267,7 @@ public class CameraDeviceImpl extends CameraDevice { // If setRemoteFailure already called, do nothing if (mInError) return; - mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice); + mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice); mDeviceHandler.post(mCallOnOpened); mDeviceHandler.post(mCallOnUnconfigured); @@ -280,28 +280,29 @@ public class CameraDeviceImpl extends CameraDevice { *

This places the camera device in the error state and informs the callback. * Use in place of setRemoteDevice() when startup fails.

*/ - public void setRemoteFailure(final CameraRuntimeException failure) { + public void setRemoteFailure(final ServiceSpecificException failure) { int failureCode = StateCallback.ERROR_CAMERA_DEVICE; boolean failureIsError = true; - switch (failure.getReason()) { - case CameraAccessException.CAMERA_IN_USE: + switch (failure.errorCode) { + case ICameraService.ERROR_CAMERA_IN_USE: failureCode = StateCallback.ERROR_CAMERA_IN_USE; break; - case CameraAccessException.MAX_CAMERAS_IN_USE: + case ICameraService.ERROR_MAX_CAMERAS_IN_USE: failureCode = StateCallback.ERROR_MAX_CAMERAS_IN_USE; break; - case CameraAccessException.CAMERA_DISABLED: + case ICameraService.ERROR_DISABLED: failureCode = StateCallback.ERROR_CAMERA_DISABLED; break; - case CameraAccessException.CAMERA_DISCONNECTED: + case ICameraService.ERROR_DISCONNECTED: failureIsError = false; break; - case CameraAccessException.CAMERA_ERROR: + case ICameraService.ERROR_INVALID_OPERATION: failureCode = StateCallback.ERROR_CAMERA_DEVICE; break; default: - Log.wtf(TAG, "Unknown failure in opening camera device: " + failure.getReason()); + Log.e(TAG, "Unexpected failure in opening camera device: " + failure.errorCode + + failure.getMessage()); break; } final int code = failureCode; @@ -430,27 +431,20 @@ public class CameraDeviceImpl extends CameraDevice { } } - try { - mRemoteDevice.endConfigure(isConstrainedHighSpeed); - } - catch (IllegalArgumentException e) { - // OK. camera service can reject stream config if it's not supported by HAL - // This is only the result of a programmer misusing the camera2 api. - Log.w(TAG, "Stream configuration failed"); - return false; - } + mRemoteDevice.endConfigure(isConstrainedHighSpeed); success = true; - } catch (CameraRuntimeException e) { - if (e.getReason() == CAMERA_IN_USE) { + } catch (IllegalArgumentException e) { + // OK. camera service can reject stream config if it's not supported by HAL + // This is only the result of a programmer misusing the camera2 api. + Log.w(TAG, "Stream configuration failed due to: " + e.getMessage()); + return false; + } catch (CameraAccessException e) { + if (e.getReason() == CameraAccessException.CAMERA_IN_USE) { throw new IllegalStateException("The camera is currently busy." + - " You must wait until the previous operation completes."); + " You must wait until the previous operation completes.", e); } - - throw e.asChecked(); - } catch (RemoteException e) { - // impossible - return false; + throw e; } finally { if (success && outputs.size() > 0) { mDeviceHandler.post(mCallOnIdle); @@ -594,12 +588,7 @@ public class CameraDeviceImpl extends CameraDevice { configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations, isConstrainedHighSpeed); if (configureSuccess == true && inputConfig != null) { - input = new Surface(); - try { - mRemoteDevice.getInputSurface(/*out*/input); - } catch (CameraRuntimeException e) { - e.asChecked(); - } + input = mRemoteDevice.getInputSurface(); } } catch (CameraAccessException e) { configureSuccess = false; @@ -608,9 +597,6 @@ public class CameraDeviceImpl extends CameraDevice { if (DEBUG) { Log.v(TAG, "createCaptureSession - failed with exception ", e); } - } catch (RemoteException e) { - // impossible - return; } List outSurfaces = new ArrayList<>(outputConfigurations.size()); @@ -655,16 +641,9 @@ public class CameraDeviceImpl extends CameraDevice { synchronized(mInterfaceLock) { checkIfCameraClosedOrInError(); - CameraMetadataNative templatedRequest = new CameraMetadataNative(); + CameraMetadataNative templatedRequest = null; - try { - mRemoteDevice.createDefaultRequest(templateType, /*out*/templatedRequest); - } catch (CameraRuntimeException e) { - throw e.asChecked(); - } catch (RemoteException e) { - // impossible - return null; - } + templatedRequest = mRemoteDevice.createDefaultRequest(templateType); CaptureRequest.Builder builder = new CaptureRequest.Builder( templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE); @@ -701,14 +680,8 @@ public class CameraDeviceImpl extends CameraDevice { if (streamId == -1) { throw new IllegalArgumentException("Surface is not part of this session"); } - try { - mRemoteDevice.prepare(streamId); - } catch (CameraRuntimeException e) { - throw e.asChecked(); - } catch (RemoteException e) { - // impossible - return; - } + + mRemoteDevice.prepare(streamId); } } @@ -728,14 +701,8 @@ public class CameraDeviceImpl extends CameraDevice { if (streamId == -1) { throw new IllegalArgumentException("Surface is not part of this session"); } - try { - mRemoteDevice.prepare2(maxCount, streamId); - } catch (CameraRuntimeException e) { - throw e.asChecked(); - } catch (RemoteException e) { - // impossible - return; - } + + mRemoteDevice.prepare2(maxCount, streamId); } } @@ -753,14 +720,8 @@ public class CameraDeviceImpl extends CameraDevice { if (streamId == -1) { throw new IllegalArgumentException("Surface is not part of this session"); } - try { - mRemoteDevice.tearDown(streamId); - } catch (CameraRuntimeException e) { - throw e.asChecked(); - } catch (RemoteException e) { - // impossible - return; - } + + mRemoteDevice.tearDown(streamId); } } @@ -875,45 +836,37 @@ public class CameraDeviceImpl extends CameraDevice { synchronized(mInterfaceLock) { checkIfCameraClosedOrInError(); - int requestId; - if (repeating) { stopRepeating(); } - LongParcelable lastFrameNumberRef = new LongParcelable(); - try { - requestId = mRemoteDevice.submitRequestList(requestList, repeating, - /*out*/lastFrameNumberRef); - if (DEBUG) { - Log.v(TAG, "last frame number " + lastFrameNumberRef.getNumber()); - } - } catch (CameraRuntimeException e) { - throw e.asChecked(); - } catch (RemoteException e) { - // impossible - return -1; + SubmitInfo requestInfo; + + CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]); + requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating); + if (DEBUG) { + Log.v(TAG, "last frame number " + requestInfo.getLastFrameNumber()); } if (callback != null) { - mCaptureCallbackMap.put(requestId, new CaptureCallbackHolder(callback, - requestList, handler, repeating, mNextSessionId - 1)); + mCaptureCallbackMap.put(requestInfo.getRequestId(), + new CaptureCallbackHolder( + callback, requestList, handler, repeating, mNextSessionId - 1)); } else { if (DEBUG) { - Log.d(TAG, "Listen for request " + requestId + " is null"); + Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null"); } } - long lastFrameNumber = lastFrameNumberRef.getNumber(); - if (repeating) { if (mRepeatingRequestId != REQUEST_ID_NONE) { - checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber); + checkEarlyTriggerSequenceComplete(mRepeatingRequestId, + requestInfo.getLastFrameNumber()); } - mRepeatingRequestId = requestId; + mRepeatingRequestId = requestInfo.getRequestId(); } else { - mRequestLastFrameNumbersList.add(new RequestLastFrameNumbersHolder(requestList, - requestId, lastFrameNumber)); + mRequestLastFrameNumbersList.add( + new RequestLastFrameNumbersHolder(requestList, requestInfo)); } if (mIdle) { @@ -921,7 +874,7 @@ public class CameraDeviceImpl extends CameraDevice { } mIdle = false; - return requestId; + return requestInfo.getRequestId(); } } @@ -949,19 +902,9 @@ public class CameraDeviceImpl extends CameraDevice { int requestId = mRepeatingRequestId; mRepeatingRequestId = REQUEST_ID_NONE; - try { - LongParcelable lastFrameNumberRef = new LongParcelable(); - mRemoteDevice.cancelRequest(requestId, /*out*/lastFrameNumberRef); - long lastFrameNumber = lastFrameNumberRef.getNumber(); - - checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber); + long lastFrameNumber = mRemoteDevice.cancelRequest(requestId); - } catch (CameraRuntimeException e) { - throw e.asChecked(); - } catch (RemoteException e) { - // impossible - return; - } + checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber); } } } @@ -974,14 +917,8 @@ public class CameraDeviceImpl extends CameraDevice { if (mRepeatingRequestId != REQUEST_ID_NONE) { throw new IllegalStateException("Active repeating request ongoing"); } - try { - mRemoteDevice.waitUntilIdle(); - } catch (CameraRuntimeException e) { - throw e.asChecked(); - } catch (RemoteException e) { - // impossible - return; - } + + mRemoteDevice.waitUntilIdle(); } } @@ -997,19 +934,11 @@ public class CameraDeviceImpl extends CameraDevice { mDeviceHandler.post(mCallOnIdle); return; } - try { - LongParcelable lastFrameNumberRef = new LongParcelable(); - mRemoteDevice.flush(/*out*/lastFrameNumberRef); - if (mRepeatingRequestId != REQUEST_ID_NONE) { - long lastFrameNumber = lastFrameNumberRef.getNumber(); - checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber); - mRepeatingRequestId = REQUEST_ID_NONE; - } - } catch (CameraRuntimeException e) { - throw e.asChecked(); - } catch (RemoteException e) { - // impossible - return; + + long lastFrameNumber = mRemoteDevice.flush(); + if (mRepeatingRequestId != REQUEST_ID_NONE) { + checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber); + mRepeatingRequestId = REQUEST_ID_NONE; } } } @@ -1021,14 +950,8 @@ public class CameraDeviceImpl extends CameraDevice { return; } - try { - if (mRemoteDevice != null) { - mRemoteDevice.disconnect(); - } - } catch (CameraRuntimeException e) { - Log.e(TAG, "Exception while closing: ", e.asChecked()); - } catch (RemoteException e) { - // impossible + if (mRemoteDevice != null) { + mRemoteDevice.disconnect(); } // Only want to fire the onClosed callback once; @@ -1297,14 +1220,14 @@ public class CameraDeviceImpl extends CameraDevice { * Create a request-last-frame-numbers holder with a list of requests, request ID, and * the last frame number returned by camera service. */ - public RequestLastFrameNumbersHolder(List requestList, int requestId, - long lastFrameNumber) { + public RequestLastFrameNumbersHolder(List requestList, SubmitInfo requestInfo) { long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED; long lastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED; - long frameNumber = lastFrameNumber; + long frameNumber = requestInfo.getLastFrameNumber(); - if (lastFrameNumber < requestList.size() - 1) { - throw new IllegalArgumentException("lastFrameNumber: " + lastFrameNumber + + if (requestInfo.getLastFrameNumber() < requestList.size() - 1) { + throw new IllegalArgumentException( + "lastFrameNumber: " + requestInfo.getLastFrameNumber() + " should be at least " + (requestList.size() - 1) + " for the number of " + " requests in the list: " + requestList.size()); } @@ -1330,7 +1253,7 @@ public class CameraDeviceImpl extends CameraDevice { mLastRegularFrameNumber = lastRegularFrameNumber; mLastReprocessFrameNumber = lastReprocessFrameNumber; - mRequestId = requestId; + mRequestId = requestInfo.getRequestId(); } /** diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl b/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl deleted file mode 100644 index 4a89129b0c9b..000000000000 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl +++ /dev/null @@ -1,20 +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 android.hardware.camera2.impl; - -/** @hide */ -parcelable CameraMetadataNative; diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 12a2910b2055..79eac262050b 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -58,6 +58,7 @@ import android.location.Location; import android.location.LocationManager; import android.os.Parcelable; import android.os.Parcel; +import android.os.ServiceSpecificException; import android.util.Log; import android.util.Size; @@ -363,13 +364,24 @@ public class CameraMetadataNative implements Parcelable { * Set the global client-side vendor tag descriptor to allow use of vendor * tags in camera applications. * - * @return int A native status_t value corresponding to one of the - * {@link CameraBinderDecorator} integer constants. - * @see CameraBinderDecorator#throwOnError - * + * @throws ServiceSpecificException * @hide */ - public static native int nativeSetupGlobalVendorTagDescriptor(); + public static void setupGlobalVendorTagDescriptor() throws ServiceSpecificException { + int err = nativeSetupGlobalVendorTagDescriptor(); + if (err != 0) { + throw new ServiceSpecificException(err, "Failure to set up global vendor tags"); + } + } + + /** + * Set the global client-side vendor tag descriptor to allow use of vendor + * tags in camera applications. + * + * @return int An error code corresponding to one of the + * {@link ICameraService} error constants, or 0 on success. + */ + private static native int nativeSetupGlobalVendorTagDescriptor(); /** * Set a camera metadata field to a value. The field definitions can be diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl b/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl deleted file mode 100644 index ebc812a65d4b..000000000000 --- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl +++ /dev/null @@ -1,20 +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 android.hardware.camera2.impl; - -/** @hide */ -parcelable CaptureResultExtras; diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java new file mode 100644 index 000000000000..ddc3fd12b70d --- /dev/null +++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2016 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 android.hardware.camera2.impl; + +import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED; +import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED; +import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE; +import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR; +import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE; +import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL; + +import android.hardware.ICameraService; +import android.hardware.camera2.CameraManager; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.ICameraDeviceUser; +import android.hardware.camera2.impl.CameraMetadataNative; +import android.hardware.camera2.params.OutputConfiguration; +import android.hardware.camera2.utils.SubmitInfo; +import android.os.RemoteException; +import android.view.Surface; + +/** + * A wrapper around ICameraDeviceUser. + * + * Mainly used to convert ServiceSpecificExceptions to the correct + * checked / unchecked exception. + * + * @hide + */ +public class ICameraDeviceUserWrapper { + + private final ICameraDeviceUser mRemoteDevice; + + public ICameraDeviceUserWrapper(ICameraDeviceUser remoteDevice) { + if (remoteDevice == null) { + throw new NullPointerException("Remote device may not be null"); + } + mRemoteDevice = remoteDevice; + } + + public void disconnect() { + try { + mRemoteDevice.disconnect(); + } catch (RemoteException t) { + // ignore binder errors for disconnect + } + } + + public SubmitInfo submitRequest(CaptureRequest request, boolean streaming) + throws CameraAccessException { + try { + return mRemoteDevice.submitRequest(request, streaming); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean streaming) + throws CameraAccessException { + try { + return mRemoteDevice.submitRequestList(requestList, streaming); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public long cancelRequest(int requestId) throws CameraAccessException { + try { + return mRemoteDevice.cancelRequest(requestId); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public void beginConfigure() throws CameraAccessException { + try { + mRemoteDevice.beginConfigure(); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public void endConfigure(boolean isConstrainedHighSpeed) throws CameraAccessException { + try { + mRemoteDevice.endConfigure(isConstrainedHighSpeed); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public void deleteStream(int streamId) throws CameraAccessException { + try { + mRemoteDevice.deleteStream(streamId); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public int createStream(OutputConfiguration outputConfiguration) + throws CameraAccessException { + try { + return mRemoteDevice.createStream(outputConfiguration); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public int createInputStream(int width, int height, int format) throws CameraAccessException { + try { + return mRemoteDevice.createInputStream(width, height, format); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public Surface getInputSurface() throws CameraAccessException { + try { + return mRemoteDevice.getInputSurface(); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public CameraMetadataNative createDefaultRequest(int templateId) throws CameraAccessException { + try { + return mRemoteDevice.createDefaultRequest(templateId); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public CameraMetadataNative getCameraInfo() throws CameraAccessException { + try { + return mRemoteDevice.getCameraInfo(); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public void waitUntilIdle() throws CameraAccessException { + try { + mRemoteDevice.waitUntilIdle(); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public long flush() throws CameraAccessException { + try { + return mRemoteDevice.flush(); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public void prepare(int streamId) throws CameraAccessException { + try { + mRemoteDevice.prepare(streamId); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public void tearDown(int streamId) throws CameraAccessException { + try { + mRemoteDevice.tearDown(streamId); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + public void prepare2(int maxCount, int streamId) throws CameraAccessException { + try { + mRemoteDevice.prepare2(maxCount, streamId); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } + + +} diff --git a/core/java/android/hardware/camera2/legacy/BurstHolder.java b/core/java/android/hardware/camera2/legacy/BurstHolder.java index e7b3682382fe..23efe15fc03b 100644 --- a/core/java/android/hardware/camera2/legacy/BurstHolder.java +++ b/core/java/android/hardware/camera2/legacy/BurstHolder.java @@ -35,10 +35,10 @@ public class BurstHolder { * * @param requestId id of the burst request. * @param repeating true if this burst is repeating. - * @param requests a {@link List} of {@link CaptureRequest}s in this burst. + * @param requests the array of {@link CaptureRequest}s for this burst. * @param jpegSurfaceIds a {@link Collection} of IDs for the surfaces that have jpeg outputs. */ - public BurstHolder(int requestId, boolean repeating, List requests, + public BurstHolder(int requestId, boolean repeating, CaptureRequest[] requests, Collection jpegSurfaceIds) { mRequestBuilders = new ArrayList<>(); int i = 0; diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java index 798c94126073..d01c275e74dc 100644 --- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java +++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java @@ -16,6 +16,7 @@ package android.hardware.camera2.legacy; +import android.hardware.ICameraService; import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.hardware.camera2.CameraAccessException; @@ -23,12 +24,10 @@ import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.ICameraDeviceCallbacks; import android.hardware.camera2.ICameraDeviceUser; -import android.hardware.camera2.utils.LongParcelable; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.impl.CaptureResultExtras; import android.hardware.camera2.params.OutputConfiguration; -import android.hardware.camera2.utils.CameraBinderDecorator; -import android.hardware.camera2.utils.CameraRuntimeException; +import android.hardware.camera2.utils.SubmitInfo; import android.os.ConditionVariable; import android.os.IBinder; import android.os.Looper; @@ -36,6 +35,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.util.Log; import android.util.SparseArray; import android.view.Surface; @@ -93,7 +93,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { private static int translateErrorsFromCamera1(int errorCode) { if (errorCode == -EACCES) { - return CameraBinderDecorator.PERMISSION_DENIED; + return ICameraService.ERROR_PERMISSION_DENIED; } return errorCode; @@ -173,7 +173,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { * * @return int error code * - * @throws CameraRuntimeException if the camera open times out with ({@code CAMERA_ERROR}) + * @throws ServiceSpecificException if the camera open times out with ({@code CAMERA_ERROR}) */ public int waitForOpen(int timeoutMs) { // Block until the camera is open asynchronously @@ -186,7 +186,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e); } - throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION); } return mInitErrors; @@ -344,7 +344,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { Camera legacyCamera = init.getCamera(); // Check errors old HAL initialization - CameraBinderDecorator.throwOnError(initErrors); + LegacyExceptionUtils.throwOnServiceError(initErrors); // Disable shutter sounds (this will work unconditionally) for api2 clients legacyCamera.disableShutterSound(); @@ -356,8 +356,8 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { try { legacyParameters = legacyCamera.getParameters(); } catch (RuntimeException e) { - throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR, - "Unable to get initial parameters", e); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, + "Unable to get initial parameters: " + e.getMessage()); } CameraCharacteristics characteristics = @@ -386,101 +386,106 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { } @Override - public int submitRequest(CaptureRequest request, boolean streaming, - /*out*/LongParcelable lastFrameNumber) { + public SubmitInfo submitRequest(CaptureRequest request, boolean streaming) { if (DEBUG) { Log.d(TAG, "submitRequest called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot submit request, device has been closed."); - return -ENODEV; + String err = "Cannot submit request, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } synchronized(mConfigureLock) { if (mConfiguring) { - Log.e(TAG, "Cannot submit request, configuration change in progress."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot submit request, configuration change in progress."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } } - return mLegacyDevice.submitRequest(request, streaming, lastFrameNumber); + return mLegacyDevice.submitRequest(request, streaming); } @Override - public int submitRequestList(List request, boolean streaming, - /*out*/LongParcelable lastFrameNumber) { + public SubmitInfo submitRequestList(CaptureRequest[] request, boolean streaming) { if (DEBUG) { Log.d(TAG, "submitRequestList called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot submit request list, device has been closed."); - return -ENODEV; + String err = "Cannot submit request list, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } synchronized(mConfigureLock) { if (mConfiguring) { - Log.e(TAG, "Cannot submit request, configuration change in progress."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot submit request, configuration change in progress."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } } - return mLegacyDevice.submitRequestList(request, streaming, lastFrameNumber); + return mLegacyDevice.submitRequestList(request, streaming); } @Override - public int cancelRequest(int requestId, /*out*/LongParcelable lastFrameNumber) { + public long cancelRequest(int requestId) { if (DEBUG) { Log.d(TAG, "cancelRequest called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot cancel request, device has been closed."); - return -ENODEV; + String err = "Cannot cancel request, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } synchronized(mConfigureLock) { if (mConfiguring) { - Log.e(TAG, "Cannot cancel request, configuration change in progress."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot cancel request, configuration change in progress."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } } - long lastFrame = mLegacyDevice.cancelRequest(requestId); - lastFrameNumber.setNumber(lastFrame); - return CameraBinderDecorator.NO_ERROR; + return mLegacyDevice.cancelRequest(requestId); } @Override - public int beginConfigure() { + public void beginConfigure() { if (DEBUG) { Log.d(TAG, "beginConfigure called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot begin configure, device has been closed."); - return -ENODEV; + String err = "Cannot begin configure, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } synchronized(mConfigureLock) { if (mConfiguring) { - Log.e(TAG, "Cannot begin configure, configuration change already in progress."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot begin configure, configuration change already in progress."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } mConfiguring = true; } - return CameraBinderDecorator.NO_ERROR; } @Override - public int endConfigure(boolean isConstrainedHighSpeed) { + public void endConfigure(boolean isConstrainedHighSpeed) { if (DEBUG) { Log.d(TAG, "endConfigure called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot end configure, device has been closed."); - return -ENODEV; + String err = "Cannot end configure, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } ArrayList surfaces = null; synchronized(mConfigureLock) { if (!mConfiguring) { - Log.e(TAG, "Cannot end configure, no configuration change in progress."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot end configure, no configuration change in progress."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } int numSurfaces = mSurfaces.size(); if (numSurfaces > 0) { @@ -491,32 +496,34 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { } mConfiguring = false; } - return mLegacyDevice.configureOutputs(surfaces); + mLegacyDevice.configureOutputs(surfaces); } @Override - public int deleteStream(int streamId) { + public void deleteStream(int streamId) { if (DEBUG) { Log.d(TAG, "deleteStream called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot delete stream, device has been closed."); - return -ENODEV; + String err = "Cannot delete stream, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } synchronized(mConfigureLock) { if (!mConfiguring) { - Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot delete stream, no configuration change in progress."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } int index = mSurfaces.indexOfKey(streamId); if (index < 0) { - Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist."); - return CameraBinderDecorator.BAD_VALUE; + String err = "Cannot delete stream, stream id " + streamId + " doesn't exist."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err); } mSurfaces.removeAt(index); } - return CameraBinderDecorator.NO_ERROR; } @Override @@ -525,18 +532,21 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { Log.d(TAG, "createStream called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot create stream, device has been closed."); - return -ENODEV; + String err = "Cannot create stream, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } synchronized(mConfigureLock) { if (!mConfiguring) { - Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot create stream, beginConfigure hasn't been called yet."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) { - Log.e(TAG, "Cannot create stream, stream rotation is not supported."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot create stream, stream rotation is not supported."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err); } int id = ++mSurfaceIdCounter; mSurfaces.put(id, outputConfiguration.getSurface()); @@ -546,24 +556,27 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { @Override public int createInputStream(int width, int height, int format) { - Log.e(TAG, "creating input stream is not supported on legacy devices"); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Creating input stream is not supported on legacy devices"; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } @Override - public int getInputSurface(/*out*/ Surface surface) { - Log.e(TAG, "getting input surface is not supported on legacy devices"); - return CameraBinderDecorator.INVALID_OPERATION; + public Surface getInputSurface() { + String err = "Getting input surface is not supported on legacy devices"; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } @Override - public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) { + public CameraMetadataNative createDefaultRequest(int templateId) { if (DEBUG) { Log.d(TAG, "createDefaultRequest called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot create default request, device has been closed."); - return -ENODEV; + String err = "Cannot create default request, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } CameraMetadataNative template; @@ -571,99 +584,96 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { template = LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId); } catch (IllegalArgumentException e) { - Log.e(TAG, "createDefaultRequest - invalid templateId specified"); - return CameraBinderDecorator.BAD_VALUE; + String err = "createDefaultRequest - invalid templateId specified"; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err); } - request.swap(template); - return CameraBinderDecorator.NO_ERROR; + return template; } @Override - public int getCameraInfo(/*out*/CameraMetadataNative info) { + public CameraMetadataNative getCameraInfo() { if (DEBUG) { Log.d(TAG, "getCameraInfo called."); } // TODO: implement getCameraInfo. Log.e(TAG, "getCameraInfo unimplemented."); - return CameraBinderDecorator.NO_ERROR; + return null; } @Override - public int waitUntilIdle() throws RemoteException { + public void waitUntilIdle() throws RemoteException { if (DEBUG) { Log.d(TAG, "waitUntilIdle called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot wait until idle, device has been closed."); - return -ENODEV; + String err = "Cannot wait until idle, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } synchronized(mConfigureLock) { if (mConfiguring) { - Log.e(TAG, "Cannot wait until idle, configuration change in progress."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot wait until idle, configuration change in progress."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } } mLegacyDevice.waitUntilIdle(); - return CameraBinderDecorator.NO_ERROR; } @Override - public int flush(/*out*/LongParcelable lastFrameNumber) { + public long flush() { if (DEBUG) { Log.d(TAG, "flush called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot flush, device has been closed."); - return -ENODEV; + String err = "Cannot flush, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } synchronized(mConfigureLock) { if (mConfiguring) { - Log.e(TAG, "Cannot flush, configuration change in progress."); - return CameraBinderDecorator.INVALID_OPERATION; + String err = "Cannot flush, configuration change in progress."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); } } - long lastFrame = mLegacyDevice.flush(); - if (lastFrameNumber != null) { - lastFrameNumber.setNumber(lastFrame); - } - return CameraBinderDecorator.NO_ERROR; + return mLegacyDevice.flush(); } - public int prepare(int streamId) { + public void prepare(int streamId) { if (DEBUG) { Log.d(TAG, "prepare called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot prepare stream, device has been closed."); - return -ENODEV; + String err = "Cannot prepare stream, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } // LEGACY doesn't support actual prepare, just signal success right away mCameraCallbacks.onPrepared(streamId); - - return CameraBinderDecorator.NO_ERROR; } - public int prepare2(int maxCount, int streamId) { + public void prepare2(int maxCount, int streamId) { // We don't support this in LEGACY mode. - return prepare(streamId); + prepare(streamId); } - public int tearDown(int streamId) { + public void tearDown(int streamId) { if (DEBUG) { Log.d(TAG, "tearDown called."); } if (mLegacyDevice.isClosed()) { - Log.e(TAG, "Cannot tear down stream, device has been closed."); - return -ENODEV; + String err = "Cannot tear down stream, device has been closed."; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err); } // LEGACY doesn't support actual teardown, so just a no-op - - return CameraBinderDecorator.NO_ERROR; } @Override diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java index fddfbde9844e..e62df3c8c495 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java +++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java @@ -26,14 +26,13 @@ import android.hardware.camera2.impl.CaptureResultExtras; import android.hardware.camera2.ICameraDeviceCallbacks; import android.hardware.camera2.params.StreamConfigurationMap; import android.hardware.camera2.utils.ArrayUtils; -import android.hardware.camera2.utils.CameraBinderDecorator; -import android.hardware.camera2.utils.LongParcelable; +import android.hardware.camera2.utils.SubmitInfo; import android.hardware.camera2.impl.CameraMetadataNative; -import android.hardware.camera2.utils.CameraRuntimeException; import android.os.ConditionVariable; import android.os.Handler; import android.os.HandlerThread; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.util.Log; import android.util.Pair; import android.util.Size; @@ -45,7 +44,6 @@ import java.util.Collection; import java.util.List; import static android.hardware.camera2.legacy.LegacyExceptionUtils.*; -import static android.hardware.camera2.utils.CameraBinderDecorator.*; import static com.android.internal.util.Preconditions.*; /** @@ -357,9 +355,9 @@ public class LegacyCameraDevice implements AutoCloseable { if (success) { mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null; } else { - return CameraBinderDecorator.INVALID_OPERATION; + return LegacyExceptionUtils.INVALID_OPERATION; } - return CameraBinderDecorator.NO_ERROR; + return LegacyExceptionUtils.NO_ERROR; } /** @@ -367,17 +365,16 @@ public class LegacyCameraDevice implements AutoCloseable { * * @param requestList a list of capture requests to execute. * @param repeating {@code true} if this burst is repeating. - * @param frameNumber an output argument that contains either the frame number of the last frame - * that will be returned for this request, or the frame number of the last - * frame that will be returned for the current repeating request if this - * burst is set to be repeating. - * @return the request id. + * @return the submission info, including the new request id, and the last frame number, which + * contains either the frame number of the last frame that will be returned for this request, + * or the frame number of the last frame that will be returned for the current repeating + * request if this burst is set to be repeating. */ - public int submitRequestList(List requestList, boolean repeating, - /*out*/LongParcelable frameNumber) { - if (requestList == null || requestList.isEmpty()) { + public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean repeating) { + if (requestList == null || requestList.length == 0) { Log.e(TAG, "submitRequestList - Empty/null requests are not allowed"); - return BAD_VALUE; + throw new ServiceSpecificException(BAD_VALUE, + "submitRequestList - Empty/null requests are not allowed"); } List surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList() : @@ -388,28 +385,33 @@ public class LegacyCameraDevice implements AutoCloseable { if (request.getTargets().isEmpty()) { Log.e(TAG, "submitRequestList - " + "Each request must have at least one Surface target"); - return BAD_VALUE; + throw new ServiceSpecificException(BAD_VALUE, + "submitRequestList - " + + "Each request must have at least one Surface target"); } for (Surface surface : request.getTargets()) { if (surface == null) { Log.e(TAG, "submitRequestList - Null Surface targets are not allowed"); - return BAD_VALUE; + throw new ServiceSpecificException(BAD_VALUE, + "submitRequestList - Null Surface targets are not allowed"); } else if (mConfiguredSurfaces == null) { Log.e(TAG, "submitRequestList - must configure " + " device with valid surfaces before submitting requests"); - return INVALID_OPERATION; + throw new ServiceSpecificException(INVALID_OPERATION, + "submitRequestList - must configure " + + " device with valid surfaces before submitting requests"); } else if (!containsSurfaceId(surface, surfaceIds)) { Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured"); - return BAD_VALUE; + throw new ServiceSpecificException(BAD_VALUE, + "submitRequestList - cannot use a surface that wasn't configured"); } } } // TODO: further validation of request here mIdle.close(); - return mRequestThreadManager.submitCaptureRequests(requestList, repeating, - frameNumber); + return mRequestThreadManager.submitCaptureRequests(requestList, repeating); } /** @@ -417,17 +419,14 @@ public class LegacyCameraDevice implements AutoCloseable { * * @param request the capture request to execute. * @param repeating {@code true} if this request is repeating. - * @param frameNumber an output argument that contains either the frame number of the last frame - * that will be returned for this request, or the frame number of the last - * frame that will be returned for the current repeating request if this - * request is set to be repeating. - * @return the request id. + * @return the submission info, including the new request id, and the last frame number, which + * contains either the frame number of the last frame that will be returned for this request, + * or the frame number of the last frame that will be returned for the current repeating + * request if this burst is set to be repeating. */ - public int submitRequest(CaptureRequest request, boolean repeating, - /*out*/LongParcelable frameNumber) { - ArrayList requestList = new ArrayList(); - requestList.add(request); - return submitRequestList(requestList, repeating, frameNumber); + public SubmitInfo submitRequest(CaptureRequest request, boolean repeating) { + CaptureRequest[] requestList = { request }; + return submitRequestList(requestList, repeating); } /** @@ -493,7 +492,7 @@ public class LegacyCameraDevice implements AutoCloseable { protected void finalize() throws Throwable { try { close(); - } catch (CameraRuntimeException e) { + } catch (ServiceSpecificException e) { Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage()); } finally { super.finalize(); diff --git a/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java b/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java index 4501e81a1ef2..93d6001c08da 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java +++ b/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java @@ -16,10 +16,11 @@ package android.hardware.camera2.legacy; -import android.hardware.camera2.utils.CameraBinderDecorator; +import android.hardware.ICameraService; +import android.os.ServiceSpecificException; import android.util.AndroidException; -import static android.system.OsConstants.ENODEV; +import static android.system.OsConstants.*; /** * Utility class containing exception handling used solely by the compatibility mode shim. @@ -27,6 +28,14 @@ import static android.system.OsConstants.ENODEV; public class LegacyExceptionUtils { private static final String TAG = "LegacyExceptionUtils"; + public static final int NO_ERROR = 0; + public static final int PERMISSION_DENIED = -EPERM; + public static final int ALREADY_EXISTS = -EEXIST; + public static final int BAD_VALUE = -EINVAL; + public static final int DEAD_OBJECT = -ENOSYS; + public static final int INVALID_OPERATION = -EPIPE; + public static final int TIMED_OUT = -ETIMEDOUT; + /** * Checked exception thrown when a BufferQueue has been abandoned by its consumer. */ @@ -58,8 +67,8 @@ public class LegacyExceptionUtils { * @return {@code errorFlag} if the value was non-negative, throws otherwise. */ public static int throwOnError(int errorFlag) throws BufferQueueAbandonedException { - if (errorFlag == CameraBinderDecorator.NO_ERROR) { - return CameraBinderDecorator.NO_ERROR; + if (errorFlag == NO_ERROR) { + return NO_ERROR; } else if (errorFlag == -ENODEV) { throw new BufferQueueAbandonedException(); } @@ -70,6 +79,59 @@ public class LegacyExceptionUtils { return errorFlag; } + /** + * Throw error codes returned by the camera service as exceptions. + * + * @param errorFlag error to throw as an exception. + */ + public static void throwOnServiceError(int errorFlag) { + int errorCode = ICameraService.ERROR_INVALID_OPERATION; + String errorMsg; + + if (errorFlag >= NO_ERROR) { + return; + } else if (errorFlag == PERMISSION_DENIED) { + errorCode = ICameraService.ERROR_PERMISSION_DENIED; + errorMsg = "Lacking privileges to access camera service"; + } else if (errorFlag == ALREADY_EXISTS) { + // This should be handled at the call site. Typically this isn't bad, + // just means we tried to do an operation that already completed. + return; + } else if (errorFlag == BAD_VALUE) { + errorCode = ICameraService.ERROR_ILLEGAL_ARGUMENT; + errorMsg = "Bad argument passed to camera service"; + } else if (errorFlag == DEAD_OBJECT) { + errorCode = ICameraService.ERROR_DISCONNECTED; + errorMsg = "Camera service not available"; + } else if (errorFlag == TIMED_OUT) { + errorCode = ICameraService.ERROR_INVALID_OPERATION; + errorMsg = "Operation timed out in camera service"; + } else if (errorFlag == -EACCES) { + errorCode = ICameraService.ERROR_DISABLED; + errorMsg = "Camera disabled by policy"; + } else if (errorFlag == -EBUSY) { + errorCode = ICameraService.ERROR_CAMERA_IN_USE; + errorMsg = "Camera already in use"; + } else if (errorFlag == -EUSERS) { + errorCode = ICameraService.ERROR_MAX_CAMERAS_IN_USE; + errorMsg = "Maximum number of cameras in use"; + } else if (errorFlag == -ENODEV) { + errorCode = ICameraService.ERROR_DISCONNECTED; + errorMsg = "Camera device not available"; + } else if (errorFlag == -EOPNOTSUPP) { + errorCode = ICameraService.ERROR_DEPRECATED_HAL; + errorMsg = "Deprecated camera HAL does not support this"; + } else if (errorFlag == INVALID_OPERATION) { + errorCode = ICameraService.ERROR_INVALID_OPERATION; + errorMsg = "Illegal state encountered in camera service."; + } else { + errorCode = ICameraService.ERROR_INVALID_OPERATION; + errorMsg = "Unknown camera device error " + errorFlag; + } + + throw new ServiceSpecificException(errorCode, errorMsg); + } + private LegacyExceptionUtils() { throw new AssertionError(); } diff --git a/core/java/android/hardware/camera2/legacy/RequestQueue.java b/core/java/android/hardware/camera2/legacy/RequestQueue.java index c995029c3416..8f252a19b48c 100644 --- a/core/java/android/hardware/camera2/legacy/RequestQueue.java +++ b/core/java/android/hardware/camera2/legacy/RequestQueue.java @@ -16,7 +16,7 @@ package android.hardware.camera2.legacy; import android.hardware.camera2.CaptureRequest; -import android.hardware.camera2.utils.LongParcelable; +import android.hardware.camera2.utils.SubmitInfo; import android.util.Log; import android.util.Pair; @@ -111,31 +111,29 @@ public class RequestQueue { * * @param requests the burst of requests to add to the queue. * @param repeating true if the burst is repeating. - * @param frameNumber an output argument that contains either the frame number of the last frame - * that will be returned for this request, or the frame number of the last - * frame that will be returned for the current repeating request if this - * burst is set to be repeating. - * @return the request id. + * @return the submission info, including the new request id, and the last frame number, which + * contains either the frame number of the last frame that will be returned for this request, + * or the frame number of the last frame that will be returned for the current repeating + * request if this burst is set to be repeating. */ - public synchronized int submit(List requests, boolean repeating, - /*out*/LongParcelable frameNumber) { + public synchronized SubmitInfo submit(CaptureRequest[] requests, boolean repeating) { int requestId = mCurrentRequestId++; BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds); - long ret = INVALID_FRAME; + long lastFrame = INVALID_FRAME; if (burst.isRepeating()) { Log.i(TAG, "Repeating capture request set."); if (mRepeatingRequest != null) { - ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME : + lastFrame = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME : mCurrentRepeatingFrameNumber - 1; } mCurrentRepeatingFrameNumber = INVALID_FRAME; mRepeatingRequest = burst; } else { mRequestQueue.offer(burst); - ret = calculateLastFrame(burst.getRequestId()); + lastFrame = calculateLastFrame(burst.getRequestId()); } - frameNumber.setNumber(ret); - return requestId; + SubmitInfo info = new SubmitInfo(requestId, lastFrame); + return info; } private long calculateLastFrame(int requestId) { diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index 48665980e9cd..1ca7ddfc6563 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -21,7 +21,7 @@ import android.hardware.Camera; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.impl.CameraDeviceImpl; -import android.hardware.camera2.utils.LongParcelable; +import android.hardware.camera2.utils.SubmitInfo; import android.hardware.camera2.utils.SizeAreaComparator; import android.hardware.camera2.impl.CameraMetadataNative; import android.os.ConditionVariable; @@ -1008,21 +1008,19 @@ public class RequestThreadManager { * * @param requests the burst of requests to add to the queue. * @param repeating true if the burst is repeating. - * @param frameNumber an output argument that contains either the frame number of the last frame - * that will be returned for this request, or the frame number of the last - * frame that will be returned for the current repeating request if this - * burst is set to be repeating. - * @return the request id. + * @return the submission info, including the new request id, and the last frame number, which + * contains either the frame number of the last frame that will be returned for this request, + * or the frame number of the last frame that will be returned for the current repeating + * request if this burst is set to be repeating. */ - public int submitCaptureRequests(List requests, boolean repeating, - /*out*/LongParcelable frameNumber) { + public SubmitInfo submitCaptureRequests(CaptureRequest[] requests, boolean repeating) { Handler handler = mRequestThread.waitAndGetHandler(); - int ret; + SubmitInfo info; synchronized (mIdleLock) { - ret = mRequestQueue.submit(requests, repeating, frameNumber); + info = mRequestQueue.submit(requests, repeating); handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST); } - return ret; + return info; } /** diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.aidl b/core/java/android/hardware/camera2/params/OutputConfiguration.aidl deleted file mode 100644 index 0921cd8e77b5..000000000000 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 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 android.hardware.camera2.params; - -/** @hide */ -parcelable OutputConfiguration; diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index 4407e552bdac..cd0c4742d2cc 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -21,11 +21,11 @@ import android.annotation.SystemApi; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.utils.HashCodeHelpers; import android.hardware.camera2.utils.SurfaceUtils; +import android.os.Parcel; +import android.os.Parcelable; import android.util.Log; import android.util.Size; import android.view.Surface; -import android.os.Parcel; -import android.os.Parcelable; import static com.android.internal.util.Preconditions.*; diff --git a/core/java/android/hardware/camera2/params/VendorTagDescriptor.java b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java new file mode 100644 index 000000000000..ea424e594081 --- /dev/null +++ b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 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 android.hardware.camera2.params; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +/** + * A class for describing the vendor tags declared by a camera HAL module. + * Generally only used by the native side of + * android.hardware.camera2.impl.CameraMetadataNative + * + * @hide + */ +public final class VendorTagDescriptor implements Parcelable { + + private VendorTagDescriptor(Parcel source) { + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public VendorTagDescriptor createFromParcel(Parcel source) { + try { + VendorTagDescriptor vendorDescriptor = new VendorTagDescriptor(source); + return vendorDescriptor; + } catch (Exception e) { + Log.e(TAG, "Exception creating VendorTagDescriptor from parcel", e); + return null; + } + } + + @Override + public VendorTagDescriptor[] newArray(int size) { + return new VendorTagDescriptor[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + if (dest == null) { + throw new IllegalArgumentException("dest must not be null"); + } + } + + private static final String TAG = "VendorTagDescriptor"; +} diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.aidl b/core/java/android/hardware/camera2/utils/BinderHolder.aidl deleted file mode 100644 index f39d645a8857..000000000000 --- a/core/java/android/hardware/camera2/utils/BinderHolder.aidl +++ /dev/null @@ -1,20 +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 android.hardware.camera2.utils; - -/** @hide */ -parcelable BinderHolder; diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.java b/core/java/android/hardware/camera2/utils/BinderHolder.java deleted file mode 100644 index 9eea390427c6..000000000000 --- a/core/java/android/hardware/camera2/utils/BinderHolder.java +++ /dev/null @@ -1,74 +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 android.hardware.camera2.utils; - -import android.os.Parcel; -import android.os.Parcelable; -import android.os.IBinder; - -/** - * @hide - */ -public class BinderHolder implements Parcelable { - private IBinder mBinder = null; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeStrongBinder(mBinder); - } - - public void readFromParcel(Parcel src) { - mBinder = src.readStrongBinder(); - } - - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public BinderHolder createFromParcel(Parcel in) { - return new BinderHolder(in); - } - - @Override - public BinderHolder[] newArray(int size) { - return new BinderHolder[size]; - } - }; - - public IBinder getBinder() { - return mBinder; - } - - public void setBinder(IBinder binder) { - mBinder = binder; - } - - public BinderHolder() {} - - public BinderHolder(IBinder binder) { - mBinder = binder; - } - - private BinderHolder(Parcel in) { - mBinder = in.readStrongBinder(); - } -} - diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java deleted file mode 100644 index 162edc9ab469..000000000000 --- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java +++ /dev/null @@ -1,162 +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 android.hardware.camera2.utils; - -import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED; -import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED; -import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE; -import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR; -import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE; -import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL; -import static android.system.OsConstants.*; - -import android.os.DeadObjectException; -import android.os.RemoteException; - -import java.lang.reflect.Method; - -/** - * Translate camera device status_t return values into exceptions. - * - * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance - * @hide - */ -public class CameraBinderDecorator { - - public static final int NO_ERROR = 0; - public static final int PERMISSION_DENIED = -EPERM; - public static final int ALREADY_EXISTS = -EEXIST; - public static final int BAD_VALUE = -EINVAL; - public static final int DEAD_OBJECT = -ENOSYS; - public static final int INVALID_OPERATION = -EPIPE; - public static final int TIMED_OUT = -ETIMEDOUT; - - /** - * TODO: add as error codes in Errors.h - * - POLICY_PROHIBITS - * - RESOURCE_BUSY - * - NO_SUCH_DEVICE - * - NOT_SUPPORTED - * - TOO_MANY_USERS - */ - - static class CameraBinderDecoratorListener implements Decorator.DecoratorListener { - - @Override - public void onBeforeInvocation(Method m, Object[] args) { - } - - @Override - public void onAfterInvocation(Method m, Object[] args, Object result) { - // int return type => status_t => convert to exception - if (m.getReturnType() == Integer.TYPE) { - int returnValue = (Integer) result; - throwOnError(returnValue); - } - } - - @Override - public boolean onCatchException(Method m, Object[] args, Throwable t) { - - if (t instanceof DeadObjectException) { - throw new CameraRuntimeException(CAMERA_DISCONNECTED, - "Process hosting the camera service has died unexpectedly", - t); - } else if (t instanceof RemoteException) { - throw new UnsupportedOperationException("An unknown RemoteException was thrown" + - " which should never happen.", t); - } - - return false; - } - - @Override - public void onFinally(Method m, Object[] args) { - } - - } - - /** - * Throw error codes returned by the camera service as exceptions. - * - * @param errorFlag error to throw as an exception. - */ - public static void throwOnError(int errorFlag) { - if (errorFlag == NO_ERROR) { - return; - } else if (errorFlag == PERMISSION_DENIED) { - throw new SecurityException("Lacking privileges to access camera service"); - } else if (errorFlag == ALREADY_EXISTS) { - // This should be handled at the call site. Typically this isn't bad, - // just means we tried to do an operation that already completed. - return; - } else if (errorFlag == BAD_VALUE) { - throw new IllegalArgumentException("Bad argument passed to camera service"); - } else if (errorFlag == DEAD_OBJECT) { - throw new CameraRuntimeException(CAMERA_DISCONNECTED); - } else if (errorFlag == TIMED_OUT) { - throw new CameraRuntimeException(CAMERA_ERROR, - "Operation timed out in camera service"); - } else if (errorFlag == -EACCES) { - throw new CameraRuntimeException(CAMERA_DISABLED); - } else if (errorFlag == -EBUSY) { - throw new CameraRuntimeException(CAMERA_IN_USE); - } else if (errorFlag == -EUSERS) { - throw new CameraRuntimeException(MAX_CAMERAS_IN_USE); - } else if (errorFlag == -ENODEV) { - throw new CameraRuntimeException(CAMERA_DISCONNECTED); - } else if (errorFlag == -EOPNOTSUPP) { - throw new CameraRuntimeException(CAMERA_DEPRECATED_HAL); - } else if (errorFlag == INVALID_OPERATION) { - throw new CameraRuntimeException(CAMERA_ERROR, - "Illegal state encountered in camera service."); - } - - /** - * Trap the rest of the negative return values. If we have known - * error codes i.e. ALREADY_EXISTS that aren't really runtime - * errors, then add them to the top switch statement - */ - if (errorFlag < 0) { - throw new CameraRuntimeException(CAMERA_ERROR, - String.format("Unknown camera device error %d", errorFlag)); - } - } - - /** - *

- * Wraps the type T with a proxy that will check 'status_t' return codes - * from the native side of the camera service, and throw Java exceptions - * automatically based on the code. - *

- *

- * In addition it also rewrites binder's RemoteException into either a - * CameraAccessException or an UnsupportedOperationException. - *

- *

- * As a result of calling any method on the proxy, RemoteException is - * guaranteed never to be thrown. - *

- * - * @param obj object that will serve as the target for all method calls - * @param the type of the element you want to wrap. This must be an interface. - * @return a proxy that will intercept all invocations to obj - */ - public static T newInstance(T obj) { - return Decorator. newInstance(obj, new CameraBinderDecoratorListener()); - } -} diff --git a/core/java/android/hardware/camera2/utils/CameraRuntimeException.java b/core/java/android/hardware/camera2/utils/CameraRuntimeException.java deleted file mode 100644 index 9ed88a9e1c55..000000000000 --- a/core/java/android/hardware/camera2/utils/CameraRuntimeException.java +++ /dev/null @@ -1,63 +0,0 @@ -package android.hardware.camera2.utils; - -import android.hardware.camera2.CameraAccessException; - -/** - * @hide - */ -public class CameraRuntimeException extends RuntimeException { - - private final int mReason; - private String mMessage; - private Throwable mCause; - - public final int getReason() { - return mReason; - } - - public CameraRuntimeException(int problem) { - super(); - mReason = problem; - } - - public CameraRuntimeException(int problem, String message) { - super(message); - mReason = problem; - mMessage = message; - } - - public CameraRuntimeException(int problem, String message, Throwable cause) { - super(message, cause); - mReason = problem; - mMessage = message; - mCause = cause; - } - - public CameraRuntimeException(int problem, Throwable cause) { - super(cause); - mReason = problem; - mCause = cause; - } - - /** - * Recreate this exception as the CameraAccessException equivalent. - * @return CameraAccessException - */ - public CameraAccessException asChecked() { - CameraAccessException e; - - if (mMessage != null && mCause != null) { - e = new CameraAccessException(mReason, mMessage, mCause); - } else if (mMessage != null) { - e = new CameraAccessException(mReason, mMessage); - } else if (mCause != null) { - e = new CameraAccessException(mReason, mCause); - } else { - e = new CameraAccessException(mReason); - } - // throw and catch, so java has a chance to fill out the stack trace - e.setStackTrace(this.getStackTrace()); - - return e; - } -} diff --git a/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java deleted file mode 100644 index c1fb6b10eb8e..000000000000 --- a/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java +++ /dev/null @@ -1,70 +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 android.hardware.camera2.utils; - -import android.os.DeadObjectException; -import android.os.RemoteException; -import android.util.Log; - -import java.lang.reflect.Method; - -/** - * Translate camera service status_t return values into exceptions. - * - * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance - * @hide - */ -public class CameraServiceBinderDecorator extends CameraBinderDecorator { - - private static final String TAG = "CameraServiceBinderDecorator"; - - static class CameraServiceBinderDecoratorListener - extends CameraBinderDecorator.CameraBinderDecoratorListener { - - // Pass through remote exceptions, unlike CameraBinderDecorator - @Override - public boolean onCatchException(Method m, Object[] args, Throwable t) { - - if (t instanceof DeadObjectException) { - // Can sometimes happen (camera service died) - // Pass on silently - } else if (t instanceof RemoteException) { - // Some other kind of remote exception - this is not normal, so let's at least - // note it before moving on - Log.e(TAG, "Unexpected RemoteException from camera service call.", t); - } - // All other exceptions also get sent onward - return false; - } - - } - - /** - *

- * Wraps the type T with a proxy that will check 'status_t' return codes - * from the native side of the camera service, and throw Java exceptions - * automatically based on the code. - *

- * - * @param obj object that will serve as the target for all method calls - * @param the type of the element you want to wrap. This must be an interface. - * @return a proxy that will intercept all invocations to obj - */ - public static T newInstance(T obj) { - return Decorator. newInstance(obj, new CameraServiceBinderDecoratorListener()); - } -} diff --git a/core/java/android/hardware/camera2/utils/Decorator.java b/core/java/android/hardware/camera2/utils/Decorator.java deleted file mode 100644 index 582649712f91..000000000000 --- a/core/java/android/hardware/camera2/utils/Decorator.java +++ /dev/null @@ -1,92 +0,0 @@ - -package android.hardware.camera2.utils; - -import java.lang.reflect.*; - -/** - * This is an implementation of the 'decorator' design pattern using Java's proxy mechanism. - * - * @see android.hardware.camera2.utils.Decorator#newInstance - * - * @hide - */ -public class Decorator implements InvocationHandler { - - public interface DecoratorListener { - /** - * This method is called before the target method is invoked - * @param args arguments to target method - * @param m Method being called - */ - void onBeforeInvocation(Method m, Object[] args); - /** - * This function is called after the target method is invoked - * if there were no uncaught exceptions - * @param args arguments to target method - * @param m Method being called - * @param result return value of target method - */ - void onAfterInvocation(Method m, Object[] args, Object result); - /** - * This method is called only if there was an exception thrown by the target method - * during its invocation. - * - * @param args arguments to target method - * @param m Method being called - * @param t Throwable that was thrown - * @return false to rethrow exception, true if the exception was handled - */ - boolean onCatchException(Method m, Object[] args, Throwable t); - /** - * This is called after the target method is invoked, regardless of whether or not - * there were any exceptions. - * @param args arguments to target method - * @param m Method being called - */ - void onFinally(Method m, Object[] args); - } - - private final T mObject; - private final DecoratorListener mListener; - - /** - * Create a decorator wrapping the specified object's method calls. - * - * @param obj the object whose method calls you want to intercept - * @param listener the decorator handler for intercepted method calls - * @param the type of the element you want to wrap. This must be an interface. - * @return a wrapped interface-compatible T - */ - @SuppressWarnings("unchecked") - public static T newInstance(T obj, DecoratorListener listener) { - return (T)java.lang.reflect.Proxy.newProxyInstance( - obj.getClass().getClassLoader(), - obj.getClass().getInterfaces(), - new Decorator(obj, listener)); - } - - private Decorator(T obj, DecoratorListener listener) { - this.mObject = obj; - this.mListener = listener; - } - - @Override - public Object invoke(Object proxy, Method m, Object[] args) - throws Throwable - { - Object result = null; - try { - mListener.onBeforeInvocation(m, args); - result = m.invoke(mObject, args); - mListener.onAfterInvocation(m, args, result); - } catch (InvocationTargetException e) { - Throwable t = e.getTargetException(); - if (!mListener.onCatchException(m, args, t)) { - throw t; - } - } finally { - mListener.onFinally(m, args); - } - return result; - } -} diff --git a/core/java/android/hardware/camera2/utils/LongParcelable.aidl b/core/java/android/hardware/camera2/utils/LongParcelable.aidl deleted file mode 100644 index 98ad1b2c1537..000000000000 --- a/core/java/android/hardware/camera2/utils/LongParcelable.aidl +++ /dev/null @@ -1,20 +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 android.hardware.camera2.utils; - -/** @hide */ -parcelable LongParcelable; diff --git a/core/java/android/hardware/camera2/utils/SubmitInfo.java b/core/java/android/hardware/camera2/utils/SubmitInfo.java new file mode 100644 index 000000000000..d1692b599f28 --- /dev/null +++ b/core/java/android/hardware/camera2/utils/SubmitInfo.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2015 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 android.hardware.camera2.utils; + +import android.os.Parcel; +import android.os.Parcelable; +import android.hardware.camera2.ICameraDeviceUser; + +/** + * The status information returned for a successful capture request submission. + * + * Includes the request ID for the newly submitted capture request, and the + * last frame number of either the previous repeating request (for repeating + * requests), or of the request(s) just submitted (for single-shot capture). + * + * @hide + */ +public class SubmitInfo implements Parcelable { + + private int mRequestId; + private long mLastFrameNumber; + + public SubmitInfo() { + mRequestId = -1; + mLastFrameNumber = ICameraDeviceUser.NO_IN_FLIGHT_REPEATING_FRAMES; + } + + public SubmitInfo(int requestId, long lastFrameNumber) { + mRequestId = requestId; + mLastFrameNumber = lastFrameNumber; + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public SubmitInfo createFromParcel(Parcel in) { + return new SubmitInfo(in); + } + + @Override + public SubmitInfo[] newArray(int size) { + return new SubmitInfo[size]; + } + }; + + private SubmitInfo(Parcel in) { + readFromParcel(in); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mRequestId); + dest.writeLong(mLastFrameNumber); + } + + public void readFromParcel(Parcel in) { + mRequestId = in.readInt(); + mLastFrameNumber = in.readLong(); + } + + /** + * Return the request ID for the submitted capture request/burst. + * + * This is used to track the completion status of the requested captures, + * and to cancel repeating requests. + */ + public int getRequestId() { + return mRequestId; + } + + /** + * Return the last frame number for the submitted capture request/burst. + * + * For a repeating request, this is the last frame number of the _prior_ + * repeating request, to indicate when to fire the sequence completion callback + * for the prior repeating request. + * + * For a single-shot capture, this is the last frame number of _this_ + * burst, to indicate when to fire the sequence completion callback for the request itself. + * + * For a repeating request, may be NO_IN_FLIGHT_REPEATING_FRAMES, if no + * instances of a prior repeating request were actually issued to the camera device. + */ + public long getLastFrameNumber() { + return mLastFrameNumber; + } + +} diff --git a/core/java/android/os/ServiceSpecificException.java b/core/java/android/os/ServiceSpecificException.java index 20f237a58ae1..04fca195356b 100644 --- a/core/java/android/os/ServiceSpecificException.java +++ b/core/java/android/os/ServiceSpecificException.java @@ -20,20 +20,23 @@ package android.os; * *

This exception includes an error code specific to the throwing * service. This is mostly used by system services to indicate - * domain specific error conditions. + * domain specific error conditions.

+ * + *

Since these exceptions are designed to be passed through Binder + * interfaces, and to be generated by native-code Binder services, + * they do not support exception chaining.

* * @hide */ public class ServiceSpecificException extends RuntimeException { public final int errorCode; - ServiceSpecificException(int errorCode, String message) { + public ServiceSpecificException(int errorCode, String message) { super(message); this.errorCode = errorCode; } - ServiceSpecificException(int errorCode) { + public ServiceSpecificException(int errorCode) { this.errorCode = errorCode; } } - diff --git a/core/java/android/view/Surface.aidl b/core/java/android/view/Surface.aidl deleted file mode 100644 index 90bf37a205d7..000000000000 --- a/core/java/android/view/Surface.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/Surface.aidl -** -** Copyright 2007, 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 android.view; - -parcelable Surface; diff --git a/core/jni/Android.mk b/core/jni/Android.mk index ed3fe428b5a3..816a2c49a2d9 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -190,7 +190,6 @@ LOCAL_C_INCLUDES += \ $(call include-path-for, bluedroid) \ $(call include-path-for, libhardware)/hardware \ $(call include-path-for, libhardware_legacy)/hardware_legacy \ - $(TOP)/frameworks/av/include \ $(TOP)/frameworks/base/media/jni \ $(TOP)/system/core/base/include \ $(TOP)/system/core/include \ diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp index 793002734111..afccfcfe5cef 100644 --- a/core/jni/android_hardware_camera2_CameraMetadata.cpp +++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp @@ -33,9 +33,9 @@ #include "core_jni_helpers.h" #include "android_runtime/android_hardware_camera2_CameraMetadata.h" +#include #include #include -#include #include #include #include @@ -906,32 +906,36 @@ static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag) { static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) { const String16 NAME("media.camera"); - sp cameraService; + sp cameraService; status_t err = getService(NAME, /*out*/&cameraService); if (err != OK) { ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__, strerror(-err), err); - return err; + return hardware::ICameraService::ERROR_DISCONNECTED; } - sp desc; - err = cameraService->getCameraVendorTagDescriptor(/*out*/desc); + sp desc = new VendorTagDescriptor(); + binder::Status res = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get()); - if (err == -EOPNOTSUPP) { + if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DEPRECATED_HAL) { ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__); VendorTagDescriptor::clearGlobalVendorTagDescriptor(); return OK; - } else if (err != OK) { - ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)", - __FUNCTION__, strerror(-err), err); - return err; + } else if (!res.isOk()) { + ALOGE("%s: Failed to setup vendor tag descriptors: %s: %s", + __FUNCTION__, res.serviceSpecificErrorCode(), + res.toString8().string()); + return res.serviceSpecificErrorCode(); } err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc); - return err; + if (err != OK) { + return hardware::ICameraService::ERROR_INVALID_OPERATION; + } + return OK; } } // extern "C" diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index cf68449096a6..b7701d6d7531 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -411,22 +411,27 @@ static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz, return 0; } + android::view::Surface surfaceShim; + + // Calling code in Surface.java has already read the name of the Surface + // from the Parcel + surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true); + sp self(reinterpret_cast(nativeObject)); - sp binder(parcel->readStrongBinder()); // update the Surface only if the underlying IGraphicBufferProducer // has changed. - if (self != NULL - && (IInterface::asBinder(self->getIGraphicBufferProducer()) == binder)) { + if (self != nullptr + && (IInterface::asBinder(self->getIGraphicBufferProducer()) == + IInterface::asBinder(surfaceShim.graphicBufferProducer))) { // same IGraphicBufferProducer, return ourselves return jlong(self.get()); } sp sur; - sp gbp(interface_cast(binder)); - if (gbp != NULL) { + if (surfaceShim.graphicBufferProducer != nullptr) { // we have a new IGraphicBufferProducer, create a new Surface for it - sur = new Surface(gbp, true); + sur = new Surface(surfaceShim.graphicBufferProducer, true); // and keep a reference before passing to java sur->incStrong(&sRefBaseOwner); } @@ -447,7 +452,13 @@ static void nativeWriteToParcel(JNIEnv* env, jclass clazz, return; } sp self(reinterpret_cast(nativeObject)); - parcel->writeStrongBinder( self != 0 ? IInterface::asBinder(self->getIGraphicBufferProducer()) : NULL); + android::view::Surface surfaceShim; + if (self != nullptr) { + surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer(); + } + // Calling code in Surface.java has already written the name of the Surface + // to the Parcel + surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true); } static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) { diff --git a/media/jni/Android.mk b/media/jni/Android.mk index fa9c48c59af0..29739caa8b74 100644 --- a/media/jni/Android.mk +++ b/media/jni/Android.mk @@ -64,7 +64,6 @@ LOCAL_C_INCLUDES += \ frameworks/av/media/mtp \ frameworks/native/include/media/openmax \ $(call include-path-for, libhardware)/hardware \ - system/media/camera/include \ $(PV_INCLUDES) \ $(JNI_H_INCLUDE) diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 701f7ac8d5bf..922ad79e3d28 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java index 61dede34bb5c..9be7004c5701 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java @@ -60,10 +60,7 @@ public class MediaFrameworkUnitTestRunner extends InstrumentationTestRunner { } private void addCameraUnitTests(TestSuite suite) { - suite.addTestSuite(CameraUtilsDecoratorTest.class); - suite.addTestSuite(CameraUtilsRuntimeExceptionTest.class); suite.addTestSuite(CameraUtilsUncheckedThrowTest.class); - suite.addTestSuite(CameraUtilsBinderDecoratorTest.class); suite.addTestSuite(CameraUtilsTypeReferenceTest.class); suite.addTestSuite(CameraMetadataTest.class); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java index 6f742037dbe4..9a0946ea981b 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java @@ -19,16 +19,16 @@ package com.android.mediaframeworktest.integration; import android.hardware.CameraInfo; import android.hardware.ICamera; import android.hardware.ICameraClient; +import android.hardware.ICameraService; import android.hardware.ICameraServiceListener; import android.hardware.camera2.ICameraDeviceCallbacks; import android.hardware.camera2.ICameraDeviceUser; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.impl.CaptureResultExtras; -import android.hardware.camera2.utils.BinderHolder; -import android.hardware.camera2.utils.CameraBinderDecorator; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; @@ -84,14 +84,7 @@ public class CameraBinderTest extends AndroidTestCase { public void testCameraInfo() throws Exception { for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { - CameraInfo info = new CameraInfo(); - info.info.facing = -1; - info.info.orientation = -1; - - assertTrue( - "Camera service returned info for camera " + cameraId, - mUtils.getCameraService().getCameraInfo(cameraId, info) == - CameraBinderTestUtils.NO_ERROR); + CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId); assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1); assertTrue("Orientation was not set for camera " + cameraId, info.info.orientation != -1); @@ -105,20 +98,17 @@ public class CameraBinderTest extends AndroidTestCase { public void testGetLegacyParameters() throws Exception { for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { - String[] parameters = new String[1]; - assertEquals("Camera service returned parameters for camera " + cameraId, - CameraBinderTestUtils.NO_ERROR, - mUtils.getCameraService().getLegacyParameters(cameraId, /*out*/parameters)); - assertNotNull(parameters[0]); + String parameters = mUtils.getCameraService().getLegacyParameters(cameraId); + assertNotNull(parameters); assertTrue("Parameters should have at least one character in it", - parameters[0].length() > 0); + parameters.length() > 0); - int end = parameters[0].length(); + int end = parameters.length(); if (end > MAX_PARAMETERS_LENGTH) { end = MAX_PARAMETERS_LENGTH; } - Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters[0].substring(0, end)); + Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters.substring(0, end)); } } @@ -127,14 +117,8 @@ public class CameraBinderTest extends AndroidTestCase { public void testSupportsCamera2Api() throws Exception { for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { - int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2); + boolean supports = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2); - if (res != CameraBinderTestUtils.NO_ERROR && res != -android.system.OsConstants.EOPNOTSUPP) { - fail("Camera service returned bad value when queried if it supports camera2 api: " - + res + " for camera ID " + cameraId); - } - - boolean supports = res == CameraBinderTestUtils.NO_ERROR; Log.v(TAG, "Camera " + cameraId + " supports api2: " + supports); } } @@ -144,10 +128,10 @@ public class CameraBinderTest extends AndroidTestCase { public void testSupportsCamera1Api() throws Exception { for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { - int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_1); - assertEquals( - "Camera service returned bad value when queried if it supports camera1 api: " - + res + " for camera ID " + cameraId, CameraBinderTestUtils.NO_ERROR, res); + boolean supports = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_1); + assertTrue( + "Camera service returned false when queried if it supports camera1 api " + + " for camera ID " + cameraId, supports); } } @@ -169,11 +153,10 @@ public class CameraBinderTest extends AndroidTestCase { String clientPackageName = getContext().getPackageName(); - BinderHolder holder = new BinderHolder(); - CameraBinderDecorator.newInstance(mUtils.getCameraService()) + ICamera cameraUser = mUtils.getCameraService() .connect(dummyCallbacks, cameraId, clientPackageName, - CameraBinderTestUtils.USE_CALLING_UID, holder); - ICamera cameraUser = ICamera.Stub.asInterface(holder.getBinder()); + ICameraService.USE_CALLING_UID, + ICameraService.USE_CALLING_PID); assertNotNull(String.format("Camera %s was null", cameraId), cameraUser); Log.v(TAG, String.format("Camera %s connected", cameraId)); @@ -191,14 +174,11 @@ public class CameraBinderTest extends AndroidTestCase { String clientPackageName = getContext().getPackageName(); - BinderHolder holder = new BinderHolder(); - try { - CameraBinderDecorator.newInstance(mUtils.getCameraService()) + cameraUser = mUtils.getCameraService() .connectLegacy(dummyCallbacks, cameraId, CAMERA_HAL_API_VERSION_1_0, - clientPackageName, - CameraBinderTestUtils.USE_CALLING_UID, holder); - cameraUser = ICamera.Stub.asInterface(holder.getBinder()); + clientPackageName, + ICameraService.USE_CALLING_UID); assertNotNull(String.format("Camera %s was null", cameraId), cameraUser); Log.v(TAG, String.format("Camera %s connected as HAL1 legacy device", cameraId)); @@ -284,11 +264,11 @@ public class CameraBinderTest extends AndroidTestCase { String clientPackageName = getContext().getPackageName(); - BinderHolder holder = new BinderHolder(); - CameraBinderDecorator.newInstance(mUtils.getCameraService()) - .connectDevice(dummyCallbacks, cameraId, - clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder); - ICameraDeviceUser cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder()); + ICameraDeviceUser cameraUser = + mUtils.getCameraService().connectDevice( + dummyCallbacks, cameraId, + clientPackageName, + ICameraService.USE_CALLING_UID); assertNotNull(String.format("Camera %s was null", cameraId), cameraUser); Log.v(TAG, String.format("Camera %s connected", cameraId)); @@ -323,27 +303,33 @@ public class CameraBinderTest extends AndroidTestCase { ICameraServiceListener listener = new DummyCameraServiceListener(); - assertTrue( - "Listener was removed before added", - mUtils.getCameraService().removeListener(listener) == - CameraBinderTestUtils.BAD_VALUE); + try { + mUtils.getCameraService().removeListener(listener); + fail("Listener was removed before added"); + } catch (ServiceSpecificException e) { + assertEquals("Listener was removed before added", + e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT); + } - assertTrue("Listener was not added", - mUtils.getCameraService().addListener(listener) == - CameraBinderTestUtils.NO_ERROR); - assertTrue( - "Listener was wrongly added again", - mUtils.getCameraService().addListener(listener) == - CameraBinderTestUtils.ALREADY_EXISTS); + mUtils.getCameraService().addListener(listener); - assertTrue( - "Listener was not removed", - mUtils.getCameraService().removeListener(listener) == - CameraBinderTestUtils.NO_ERROR); - assertTrue( - "Listener was wrongly removed again", - mUtils.getCameraService().removeListener(listener) == - CameraBinderTestUtils.BAD_VALUE); + try { + mUtils.getCameraService().addListener(listener); + fail("Listener was wrongly added again"); + } catch (ServiceSpecificException e) { + assertEquals("Listener was wrongly added again", + e.errorCode, ICameraService.ERROR_ALREADY_EXISTS); + } + + mUtils.getCameraService().removeListener(listener); + + try { + mUtils.getCameraService().removeListener(listener); + fail("Listener was wrongly removed twice"); + } catch (ServiceSpecificException e) { + assertEquals("Listener was wrongly removed twice", + e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT); + } } } } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java index 5c4b23bb7b33..38fc49fcc902 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java @@ -18,10 +18,6 @@ public class CameraBinderTestUtils { static final String CAMERA_SERVICE_BINDER_NAME = "media.camera"; - protected static final int USE_CALLING_UID = -1; - protected static final int BAD_VALUE = -EINVAL; - protected static final int INVALID_OPERATION = -ENOSYS; - protected static final int ALREADY_EXISTS = -EEXIST; public static final int NO_ERROR = 0; private final Context mContext; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java index d71b44bf549a..5c1d8a7e143b 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java @@ -18,6 +18,7 @@ package com.android.mediaframeworktest.integration; import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; +import android.hardware.ICameraService; import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; @@ -27,12 +28,13 @@ import android.hardware.camera2.ICameraDeviceUser; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.impl.CaptureResultExtras; import android.hardware.camera2.params.OutputConfiguration; -import android.hardware.camera2.utils.BinderHolder; +import android.hardware.camera2.utils.SubmitInfo; import android.media.Image; import android.media.ImageReader; import android.os.Handler; import android.os.HandlerThread; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.os.SystemClock; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; @@ -164,11 +166,10 @@ public class CameraDeviceBinderTest extends AndroidTestCase { } private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception { - CameraMetadataNative metadata = new CameraMetadataNative(); + CameraMetadataNative metadata = null; assertTrue(metadata.isEmpty()); - int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); + metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW); assertFalse(metadata.isEmpty()); CaptureRequest.Builder request = new CaptureRequest.Builder(metadata, /*reprocess*/false, @@ -183,12 +184,13 @@ public class CameraDeviceBinderTest extends AndroidTestCase { return request; } - private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception { - int requestId = mCameraUser.submitRequest(request, streaming, null); + private SubmitInfo submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception { + SubmitInfo requestInfo = mCameraUser.submitRequest(request, streaming); assertTrue( - "Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")", - requestId >= 0); - return requestId; + "Request IDs should be non-negative (expected: >= 0, actual: " + + requestInfo.getRequestId() + ")", + requestInfo.getRequestId() >= 0); + return requestInfo; } @Override @@ -214,10 +216,8 @@ public class CameraDeviceBinderTest extends AndroidTestCase { mMockCb = spy(dummyCallbacks); - BinderHolder holder = new BinderHolder(); - mUtils.getCameraService().connectDevice(mMockCb, mCameraId, - clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder); - mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder()); + mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId, + clientPackageName, ICameraService.USE_CALLING_UID); assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser); mHandlerThread = new HandlerThread(TAG); mHandlerThread.start(); @@ -238,11 +238,10 @@ public class CameraDeviceBinderTest extends AndroidTestCase { @SmallTest public void testCreateDefaultRequest() throws Exception { - CameraMetadataNative metadata = new CameraMetadataNative(); + CameraMetadataNative metadata = null; assertTrue(metadata.isEmpty()); - int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); + metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW); assertFalse(metadata.isEmpty()); } @@ -252,18 +251,28 @@ public class CameraDeviceBinderTest extends AndroidTestCase { int streamId = mCameraUser.createStream(mOutputConfiguration); assertEquals(0, streamId); - assertEquals(CameraBinderTestUtils.ALREADY_EXISTS, - mCameraUser.createStream(mOutputConfiguration)); + try { + mCameraUser.createStream(mOutputConfiguration); + fail("Creating same stream twice"); + } catch (ServiceSpecificException e) { + assertEquals("Creating same stream twice", + e.errorCode, ICameraService.ERROR_ALREADY_EXISTS); + } - assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId)); + mCameraUser.deleteStream(streamId); } @SmallTest public void testDeleteInvalidStream() throws Exception { - assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(-1)); - assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0)); - assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(1)); - assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0xC0FFEE)); + int[] badStreams = { -1, 0, 1, 0xC0FFEE }; + for (int badStream : badStreams) { + try { + mCameraUser.deleteStream(badStream); + fail("Allowed bad stream delete"); + } catch (ServiceSpecificException e) { + assertEquals(e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT); + } + } } @SmallTest @@ -273,8 +282,13 @@ public class CameraDeviceBinderTest extends AndroidTestCase { int streamId = mCameraUser.createStream(mOutputConfiguration); assertEquals(0, streamId); - assertEquals(CameraBinderTestUtils.ALREADY_EXISTS, - mCameraUser.createStream(mOutputConfiguration)); + try { + mCameraUser.createStream(mOutputConfiguration); + fail("Created same stream twice"); + } catch (ServiceSpecificException e) { + assertEquals("Created same stream twice", + ICameraService.ERROR_ALREADY_EXISTS, e.errorCode); + } // Create second stream with a different surface. SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0); @@ -286,8 +300,8 @@ public class CameraDeviceBinderTest extends AndroidTestCase { assertEquals(1, streamId2); // Clean up streams - assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId)); - assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId2)); + mCameraUser.deleteStream(streamId); + mCameraUser.deleteStream(streamId2); } @SmallTest @@ -295,16 +309,25 @@ public class CameraDeviceBinderTest extends AndroidTestCase { CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false); CaptureRequest request1 = builder.build(); - int status = mCameraUser.submitRequest(request1, /* streaming */false, null); - assertEquals("Expected submitRequest to return BAD_VALUE " + - "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status); + try { + SubmitInfo requestInfo = mCameraUser.submitRequest(request1, /* streaming */false); + fail("Exception expected"); + } catch(ServiceSpecificException e) { + assertEquals("Expected submitRequest to throw ServiceSpecificException with BAD_VALUE " + + "since we had 0 surface targets set.", ICameraService.ERROR_ILLEGAL_ARGUMENT, + e.errorCode); + } builder.addTarget(mSurface); CaptureRequest request2 = builder.build(); - status = mCameraUser.submitRequest(request2, /* streaming */false, null); - assertEquals("Expected submitRequest to return BAD_VALUE since " + - "the target surface wasn't registered with createStream.", - CameraBinderTestUtils.BAD_VALUE, status); + try { + SubmitInfo requestInfo = mCameraUser.submitRequest(request2, /* streaming */false); + fail("Exception expected"); + } catch(ServiceSpecificException e) { + assertEquals("Expected submitRequest to throw ILLEGAL_ARGUMENT " + + "ServiceSpecificException since the target wasn't registered with createStream.", + ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode); + } } @SmallTest @@ -314,9 +337,10 @@ public class CameraDeviceBinderTest extends AndroidTestCase { CaptureRequest request = builder.build(); // Submit valid request twice. - int requestId1 = submitCameraRequest(request, /* streaming */false); - int requestId2 = submitCameraRequest(request, /* streaming */false); - assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2); + SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false); + assertNotSame("Request IDs should be unique for multiple requests", + requestInfo1.getRequestId(), requestInfo2.getRequestId()); } @@ -329,32 +353,35 @@ public class CameraDeviceBinderTest extends AndroidTestCase { // Submit valid request once (non-streaming), and another time // (streaming) - int requestId1 = submitCameraRequest(request, /* streaming */false); - - int requestIdStreaming = submitCameraRequest(request, /* streaming */true); - assertNotSame("Request IDs should be unique for multiple requests", requestId1, - requestIdStreaming); - - int status = mCameraUser.cancelRequest(-1, null); - assertEquals("Invalid request IDs should not be cancellable", - CameraBinderTestUtils.BAD_VALUE, status); - - status = mCameraUser.cancelRequest(requestId1, null); - assertEquals("Non-streaming request IDs should not be cancellable", - CameraBinderTestUtils.BAD_VALUE, status); + SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false); + + SubmitInfo requestInfoStreaming = submitCameraRequest(request, /* streaming */true); + assertNotSame("Request IDs should be unique for multiple requests", + requestInfo1.getRequestId(), + requestInfoStreaming.getRequestId()); + + try { + long lastFrameNumber = mCameraUser.cancelRequest(-1); + fail("Expected exception"); + } catch (ServiceSpecificException e) { + assertEquals("Invalid request IDs should not be cancellable", + ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode); + } - status = mCameraUser.cancelRequest(requestIdStreaming, null); - assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR, - status); + try { + long lastFrameNumber = mCameraUser.cancelRequest(requestInfo1.getRequestId()); + fail("Expected exception"); + } catch (ServiceSpecificException e) { + assertEquals("Non-streaming request IDs should not be cancellable", + ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode); + } + long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId()); } @SmallTest public void testCameraInfo() throws RemoteException { - CameraMetadataNative info = new CameraMetadataNative(); - - int status = mCameraUser.getCameraInfo(/*out*/info); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); + CameraMetadataNative info = mCameraUser.getCameraInfo(); assertFalse(info.isEmpty()); assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS)); @@ -362,10 +389,7 @@ public class CameraDeviceBinderTest extends AndroidTestCase { @SmallTest public void testCameraCharacteristics() throws RemoteException { - CameraMetadataNative info = new CameraMetadataNative(); - - int status = mUtils.getCameraService().getCameraCharacteristics(mCameraId, /*out*/info); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); + CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId); assertFalse(info.isEmpty()); assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS)); @@ -374,18 +398,19 @@ public class CameraDeviceBinderTest extends AndroidTestCase { @SmallTest public void testWaitUntilIdle() throws Exception { CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); - int requestIdStreaming = submitCameraRequest(builder.build(), /* streaming */true); + SubmitInfo requestInfoStreaming = submitCameraRequest(builder.build(), /* streaming */true); // Test Bad case first: waitUntilIdle when there is active repeating request - int status = mCameraUser.waitUntilIdle(); - assertEquals("waitUntilIdle is invalid operation when there is active repeating request", - CameraBinderTestUtils.INVALID_OPERATION, status); + try { + mCameraUser.waitUntilIdle(); + } catch (ServiceSpecificException e) { + assertEquals("waitUntilIdle is invalid operation when there is active repeating request", + ICameraService.ERROR_INVALID_OPERATION, e.errorCode); + } // Test good case, waitUntilIdle when there is no active repeating request - status = mCameraUser.cancelRequest(requestIdStreaming, null); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); - status = mCameraUser.waitUntilIdle(); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); + long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId()); + mCameraUser.waitUntilIdle(); } @SmallTest @@ -411,12 +436,12 @@ public class CameraDeviceBinderTest extends AndroidTestCase { ArgumentCaptor timestamps = ArgumentCaptor.forClass(Long.class); // Test both single request and streaming request. - int requestId1 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false); verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted( any(CaptureResultExtras.class), anyLong()); - int streamingId = submitCameraRequest(request, /* streaming */true); + SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true); verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED)) .onCaptureStarted( any(CaptureResultExtras.class), @@ -436,22 +461,22 @@ public class CameraDeviceBinderTest extends AndroidTestCase { CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); // Try streaming - int streamingId = submitCameraRequest(request, /* streaming */true); + SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true); // Wait a bit to fill up the queue SystemClock.sleep(WAIT_FOR_WORK_MS); // Cancel and make sure we eventually quiesce - status = mCameraUser.cancelRequest(streamingId, null); + long lastFrameNumber = mCameraUser.cancelRequest(streamingInfo.getRequestId()); verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onDeviceIdle(); // Submit a few capture requests - int requestId1 = submitCameraRequest(request, /* streaming */false); - int requestId2 = submitCameraRequest(request, /* streaming */false); - int requestId3 = submitCameraRequest(request, /* streaming */false); - int requestId4 = submitCameraRequest(request, /* streaming */false); - int requestId5 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false); // And wait for more idle verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onDeviceIdle(); @@ -463,38 +488,34 @@ public class CameraDeviceBinderTest extends AndroidTestCase { int status; // Initial flush should work - status = mCameraUser.flush(null); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); + long lastFrameNumber = mCameraUser.flush(); // Then set up a stream CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); // Flush should still be a no-op, really - status = mCameraUser.flush(null); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); + lastFrameNumber = mCameraUser.flush(); // Submit a few capture requests - int requestId1 = submitCameraRequest(request, /* streaming */false); - int requestId2 = submitCameraRequest(request, /* streaming */false); - int requestId3 = submitCameraRequest(request, /* streaming */false); - int requestId4 = submitCameraRequest(request, /* streaming */false); - int requestId5 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false); + SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false); // Then flush and wait for idle - status = mCameraUser.flush(null); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); + lastFrameNumber = mCameraUser.flush(); verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onDeviceIdle(); // Now a streaming request - int streamingId = submitCameraRequest(request, /* streaming */true); + SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true); // Wait a bit to fill up the queue SystemClock.sleep(WAIT_FOR_WORK_MS); // Then flush and wait for the idle callback - status = mCameraUser.flush(null); - assertEquals(CameraBinderTestUtils.NO_ERROR, status); + lastFrameNumber = mCameraUser.flush(); verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onDeviceIdle(); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java deleted file mode 100644 index 33c638801c4b..000000000000 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java +++ /dev/null @@ -1,173 +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.mediaframeworktest.unit; - -import android.hardware.camera2.CameraAccessException; -import android.hardware.camera2.utils.CameraBinderDecorator; -import android.hardware.camera2.utils.CameraRuntimeException; -import android.os.DeadObjectException; -import android.os.RemoteException; -import android.os.TransactionTooLargeException; -import android.test.suitebuilder.annotation.SmallTest; - -import static org.mockito.Mockito.*; -import static android.hardware.camera2.utils.CameraBinderDecorator.*; -import static android.hardware.camera2.CameraAccessException.*; -import static android.system.OsConstants.*; - -import junit.framework.Assert; - -public class CameraUtilsBinderDecoratorTest extends junit.framework.TestCase { - - private interface ICameraBinderStereotype { - - double doNothing(); - - // int is a 'status_t' - int doSomethingPositive(); - - int doSomethingNoError(); - - int doSomethingPermissionDenied(); - - int doSomethingAlreadyExists(); - - int doSomethingBadValue(); - - int doSomethingDeadObject() throws CameraRuntimeException; - - int doSomethingBadPolicy() throws CameraRuntimeException; - - int doSomethingDeviceBusy() throws CameraRuntimeException; - - int doSomethingNoSuchDevice() throws CameraRuntimeException; - - int doSomethingUnknownErrorCode(); - - int doSomethingThrowDeadObjectException() throws RemoteException; - - int doSomethingThrowTransactionTooLargeException() throws RemoteException; - } - - private static final double SOME_ARBITRARY_DOUBLE = 1.0; - private static final int SOME_ARBITRARY_POSITIVE_INT = 5; - private static final int SOME_ARBITRARY_NEGATIVE_INT = -0xC0FFEE; - - @SmallTest - public void testStereotypes() { - - ICameraBinderStereotype mock = mock(ICameraBinderStereotype.class); - try { - when(mock.doNothing()).thenReturn(SOME_ARBITRARY_DOUBLE); - when(mock.doSomethingPositive()).thenReturn(SOME_ARBITRARY_POSITIVE_INT); - when(mock.doSomethingNoError()).thenReturn(NO_ERROR); - when(mock.doSomethingPermissionDenied()).thenReturn(PERMISSION_DENIED); - when(mock.doSomethingAlreadyExists()).thenReturn(ALREADY_EXISTS); - when(mock.doSomethingBadValue()).thenReturn(BAD_VALUE); - when(mock.doSomethingDeadObject()).thenReturn(DEAD_OBJECT); - when(mock.doSomethingBadPolicy()).thenReturn(-EACCES); - when(mock.doSomethingDeviceBusy()).thenReturn(-EBUSY); - when(mock.doSomethingNoSuchDevice()).thenReturn(-ENODEV); - when(mock.doSomethingUnknownErrorCode()).thenReturn(SOME_ARBITRARY_NEGATIVE_INT); - when(mock.doSomethingThrowDeadObjectException()).thenThrow(new DeadObjectException()); - when(mock.doSomethingThrowTransactionTooLargeException()).thenThrow( - new TransactionTooLargeException()); - } catch (RemoteException e) { - Assert.fail("Unreachable"); - } - - ICameraBinderStereotype decoratedMock = CameraBinderDecorator.newInstance(mock); - - // ignored by decorator because return type is double, not int - assertEquals(SOME_ARBITRARY_DOUBLE, decoratedMock.doNothing()); - - // pass through for positive values - assertEquals(SOME_ARBITRARY_POSITIVE_INT, decoratedMock.doSomethingPositive()); - - // pass through NO_ERROR - assertEquals(NO_ERROR, decoratedMock.doSomethingNoError()); - - try { - decoratedMock.doSomethingPermissionDenied(); - Assert.fail("Should've thrown SecurityException"); - } catch (SecurityException e) { - } - - assertEquals(ALREADY_EXISTS, decoratedMock.doSomethingAlreadyExists()); - - try { - decoratedMock.doSomethingBadValue(); - Assert.fail("Should've thrown IllegalArgumentException"); - } catch (IllegalArgumentException e) { - } - - try { - decoratedMock.doSomethingDeadObject(); - Assert.fail("Should've thrown CameraRuntimeException"); - } catch (CameraRuntimeException e) { - assertEquals(CAMERA_DISCONNECTED, e.getReason()); - } - - try { - decoratedMock.doSomethingBadPolicy(); - Assert.fail("Should've thrown CameraRuntimeException"); - } catch (CameraRuntimeException e) { - assertEquals(CAMERA_DISABLED, e.getReason()); - } - - try { - decoratedMock.doSomethingDeviceBusy(); - Assert.fail("Should've thrown CameraRuntimeException"); - } catch (CameraRuntimeException e) { - assertEquals(CAMERA_IN_USE, e.getReason()); - } - - try { - decoratedMock.doSomethingNoSuchDevice(); - Assert.fail("Should've thrown CameraRuntimeException"); - } catch (CameraRuntimeException e) { - assertEquals(CAMERA_DISCONNECTED, e.getReason()); - } - - try { - decoratedMock.doSomethingUnknownErrorCode(); - Assert.fail("Should've thrown UnsupportedOperationException"); - } catch (UnsupportedOperationException e) { - assertEquals(String.format("Unknown error %d", - SOME_ARBITRARY_NEGATIVE_INT), e.getMessage()); - } - - try { - decoratedMock.doSomethingThrowDeadObjectException(); - Assert.fail("Should've thrown CameraRuntimeException"); - } catch (CameraRuntimeException e) { - assertEquals(CAMERA_DISCONNECTED, e.getReason()); - } catch (RemoteException e) { - Assert.fail("Should not throw a DeadObjectException directly, but rethrow"); - } - - try { - decoratedMock.doSomethingThrowTransactionTooLargeException(); - Assert.fail("Should've thrown UnsupportedOperationException"); - } catch (UnsupportedOperationException e) { - assertTrue(e.getCause() instanceof TransactionTooLargeException); - } catch (RemoteException e) { - Assert.fail("Should not throw a TransactionTooLargeException directly, but rethrow"); - } - } - -} diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java deleted file mode 100644 index c3b60065916c..000000000000 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java +++ /dev/null @@ -1,171 +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.mediaframeworktest.unit; - -import android.test.suitebuilder.annotation.SmallTest; -import android.hardware.camera2.utils.*; -import android.hardware.camera2.utils.Decorator.DecoratorListener; - -import junit.framework.Assert; - -import java.lang.reflect.Method; - -/** - * adb shell am instrument -e class 'com.android.mediaframeworktest.unit.CameraUtilsDecoratorTest' \ - * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner - */ -public class CameraUtilsDecoratorTest extends junit.framework.TestCase { - private DummyListener mDummyListener; - private DummyInterface mIface; - - @Override - public void setUp() { - mDummyListener = new DummyListener(); - mIface = Decorator.newInstance(new DummyImpl(), mDummyListener); - } - - interface DummyInterface { - int addValues(int x, int y, int z); - - void raiseException() throws Exception; - - void raiseUnsupportedOperationException() throws UnsupportedOperationException; - } - - class DummyImpl implements DummyInterface { - @Override - public int addValues(int x, int y, int z) { - return x + y + z; - } - - @Override - public void raiseException() throws Exception { - throw new Exception("Test exception"); - } - - @Override - public void raiseUnsupportedOperationException() throws UnsupportedOperationException { - throw new UnsupportedOperationException("Test exception"); - } - } - - class DummyListener implements DecoratorListener { - - public boolean beforeCalled = false; - public boolean afterCalled = false; - public boolean catchCalled = false; - public boolean finallyCalled = false; - public Object resultValue = null; - - public boolean raiseException = false; - - @Override - public void onBeforeInvocation(Method m, Object[] args) { - beforeCalled = true; - } - - @Override - public void onAfterInvocation(Method m, Object[] args, Object result) { - afterCalled = true; - resultValue = result; - - if (raiseException) { - throw new UnsupportedOperationException("Test exception"); - } - } - - @Override - public boolean onCatchException(Method m, Object[] args, Throwable t) { - catchCalled = true; - return false; - } - - @Override - public void onFinally(Method m, Object[] args) { - finallyCalled = true; - } - - }; - - @SmallTest - public void testDecorator() { - - // TODO rewrite this using mocks - - assertTrue(mIface.addValues(1, 2, 3) == 6); - assertTrue(mDummyListener.beforeCalled); - assertTrue(mDummyListener.afterCalled); - - int resultValue = (Integer)mDummyListener.resultValue; - assertTrue(resultValue == 6); - assertTrue(mDummyListener.finallyCalled); - assertFalse(mDummyListener.catchCalled); - } - - @SmallTest - public void testDecoratorExceptions() { - - boolean gotExceptions = false; - try { - mIface.raiseException(); - } catch (Exception e) { - gotExceptions = true; - assertTrue(e.getMessage() == "Test exception"); - } - assertTrue(gotExceptions); - assertTrue(mDummyListener.beforeCalled); - assertFalse(mDummyListener.afterCalled); - assertTrue(mDummyListener.catchCalled); - assertTrue(mDummyListener.finallyCalled); - } - - @SmallTest - public void testDecoratorUnsupportedOperationException() { - - boolean gotExceptions = false; - try { - mIface.raiseUnsupportedOperationException(); - } catch (UnsupportedOperationException e) { - gotExceptions = true; - assertTrue(e.getMessage() == "Test exception"); - } - assertTrue(gotExceptions); - assertTrue(mDummyListener.beforeCalled); - assertFalse(mDummyListener.afterCalled); - assertTrue(mDummyListener.catchCalled); - assertTrue(mDummyListener.finallyCalled); - } - - @SmallTest - public void testDecoratorRaisesException() { - - boolean gotExceptions = false; - try { - mDummyListener.raiseException = true; - mIface.addValues(1, 2, 3); - Assert.fail("unreachable"); - } catch (UnsupportedOperationException e) { - gotExceptions = true; - assertTrue(e.getMessage() == "Test exception"); - } - assertTrue(gotExceptions); - assertTrue(mDummyListener.beforeCalled); - assertTrue(mDummyListener.afterCalled); - assertFalse(mDummyListener.catchCalled); - assertTrue(mDummyListener.finallyCalled); - } -} diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java deleted file mode 100644 index 02c9f2af11ad..000000000000 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java +++ /dev/null @@ -1,77 +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.mediaframeworktest.unit; - -import android.hardware.camera2.CameraAccessException; -import android.hardware.camera2.utils.CameraRuntimeException; -import android.hardware.camera2.utils.UncheckedThrow; -import android.test.suitebuilder.annotation.SmallTest; - -import junit.framework.Assert; - -public class CameraUtilsRuntimeExceptionTest extends junit.framework.TestCase { - - @SmallTest - public void testCameraRuntimeException1() { - try { - CameraRuntimeException runtimeExc = new CameraRuntimeException(12345); - throw runtimeExc.asChecked(); - } catch (CameraAccessException e) { - assertEquals(12345, e.getReason()); - assertNull(e.getMessage()); - assertNull(e.getCause()); - } - } - - @SmallTest - public void testCameraRuntimeException2() { - try { - CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello"); - throw runtimeExc.asChecked(); - } catch (CameraAccessException e) { - assertEquals(12345, e.getReason()); - assertEquals("Hello", e.getMessage()); - assertNull(e.getCause()); - } - } - - @SmallTest - public void testCameraRuntimeException3() { - Throwable cause = new IllegalStateException("For great justice"); - try { - CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, cause); - throw runtimeExc.asChecked(); - } catch (CameraAccessException e) { - assertEquals(12345, e.getReason()); - assertNull(e.getMessage()); - assertEquals(cause, e.getCause()); - } - } - - @SmallTest - public void testCameraRuntimeException4() { - Throwable cause = new IllegalStateException("For great justice"); - try { - CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello", cause); - throw runtimeExc.asChecked(); - } catch (CameraAccessException e) { - assertEquals(12345, e.getReason()); - assertEquals("Hello", e.getMessage()); - assertEquals(cause, e.getCause()); - } - } -} diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java index f82454a1d9f8..cd8eb4e3bb3c 100644 --- a/services/core/java/com/android/server/camera/CameraService.java +++ b/services/core/java/com/android/server/camera/CameraService.java @@ -60,10 +60,6 @@ public class CameraService extends SystemService public static final String CAMERA_SERVICE_PROXY_BINDER_NAME = "media.camera.proxy"; - // Event arguments to use with the camera service notifySystemEvent call: - public static final int NO_EVENT = 0; // NOOP - public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle - // State arguments to use with the notifyCameraState call from camera service: public static final int CAMERA_STATE_OPEN = 0; public static final int CAMERA_STATE_ACTIVE = 1; @@ -224,7 +220,7 @@ public class CameraService extends SystemService if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) { // Some user handles have been added or removed, update mediaserver. mEnabledCameraUsers = currentUserHandles; - notifyMediaserverLocked(USER_SWITCHED, currentUserHandles); + notifyMediaserverLocked(ICameraService.EVENT_USER_SWITCHED, currentUserHandles); } } @@ -244,7 +240,7 @@ public class CameraService extends SystemService if (mEnabledCameraUsers == null) { return; } - if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) { + if (notifyMediaserverLocked(ICameraService.EVENT_USER_SWITCHED, mEnabledCameraUsers)) { retries = 0; } } -- 2.11.0