CameraDeviceUserShim.java revision 3e4fed203fe7c945c53c6d6bb9f160932a1d15b3
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.hardware.camera2.legacy; 18 19import android.hardware.Camera; 20import android.hardware.camera2.CameraAccessException; 21import android.hardware.camera2.CaptureRequest; 22import android.hardware.camera2.ICameraDeviceCallbacks; 23import android.hardware.camera2.ICameraDeviceUser; 24import android.hardware.camera2.utils.LongParcelable; 25import android.hardware.camera2.impl.CameraMetadataNative; 26import android.hardware.camera2.utils.CameraBinderDecorator; 27import android.hardware.camera2.utils.CameraRuntimeException; 28import android.os.IBinder; 29import android.os.RemoteException; 30import android.util.Log; 31import android.util.SparseArray; 32import android.view.Surface; 33 34import java.util.ArrayList; 35import java.util.List; 36import java.util.concurrent.atomic.AtomicInteger; 37 38/** 39 * Compatibility implementation of the Camera2 API binder interface. 40 * 41 * <p> 42 * This is intended to be called from the same process as client 43 * {@link android.hardware.camera2.CameraDevice}, and wraps a 44 * {@link android.hardware.camera2.legacy.LegacyCameraDevice} that emulates Camera2 service using 45 * the Camera1 API. 46 * </p> 47 * 48 * <p> 49 * Keep up to date with ICameraDeviceUser.aidl. 50 * </p> 51 */ 52public class CameraDeviceUserShim implements ICameraDeviceUser { 53 private static final String TAG = "CameraDeviceUserShim"; 54 55 private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG); 56 57 private final LegacyCameraDevice mLegacyDevice; 58 59 private final Object mConfigureLock = new Object(); 60 private int mSurfaceIdCounter; 61 private boolean mConfiguring; 62 private final SparseArray<Surface> mSurfaces; 63 64 protected CameraDeviceUserShim(int cameraId, LegacyCameraDevice legacyCamera) { 65 mLegacyDevice = legacyCamera; 66 mConfiguring = false; 67 mSurfaces = new SparseArray<Surface>(); 68 69 mSurfaceIdCounter = 0; 70 } 71 72 public static CameraDeviceUserShim connectBinderShim(ICameraDeviceCallbacks callbacks, 73 int cameraId) { 74 if (DEBUG) { 75 Log.d(TAG, "Opening shim Camera device"); 76 } 77 // TODO: Move open/init into LegacyCameraDevice thread when API is switched to async. 78 Camera legacyCamera = Camera.openUninitialized(); 79 int initErrors = legacyCamera.cameraInit(cameraId); 80 // Check errors old HAL initialization 81 if (Camera.checkInitErrors(initErrors)) { 82 // TODO: Map over old camera error codes. This likely involves improving the error 83 // reporting in the HAL1 connect path. 84 throw new CameraRuntimeException(CameraAccessException.CAMERA_DISCONNECTED); 85 } 86 LegacyCameraDevice device = new LegacyCameraDevice(cameraId, legacyCamera, callbacks); 87 return new CameraDeviceUserShim(cameraId, device); 88 } 89 90 @Override 91 public void disconnect() { 92 if (DEBUG) { 93 Log.d(TAG, "disconnect called."); 94 } 95 mLegacyDevice.close(); 96 } 97 98 @Override 99 public int submitRequest(CaptureRequest request, boolean streaming, 100 /*out*/LongParcelable lastFrameNumber) { 101 if (DEBUG) { 102 Log.d(TAG, "submitRequest called."); 103 } 104 synchronized(mConfigureLock) { 105 if (mConfiguring) { 106 Log.e(TAG, "Cannot submit request, configuration change in progress."); 107 return CameraBinderDecorator.INVALID_OPERATION; 108 } 109 } 110 return mLegacyDevice.submitRequest(request, streaming, lastFrameNumber); 111 } 112 113 @Override 114 public int submitRequestList(List<CaptureRequest> request, boolean streaming, 115 /*out*/LongParcelable lastFrameNumber) { 116 if (DEBUG) { 117 Log.d(TAG, "submitRequestList called."); 118 } 119 synchronized(mConfigureLock) { 120 if (mConfiguring) { 121 Log.e(TAG, "Cannot submit request, configuration change in progress."); 122 return CameraBinderDecorator.INVALID_OPERATION; 123 } 124 } 125 return mLegacyDevice.submitRequestList(request, streaming, lastFrameNumber); 126 } 127 128 @Override 129 public int cancelRequest(int requestId, /*out*/LongParcelable lastFrameNumber) { 130 if (DEBUG) { 131 Log.d(TAG, "cancelRequest called."); 132 } 133 synchronized(mConfigureLock) { 134 if (mConfiguring) { 135 Log.e(TAG, "Cannot cancel request, configuration change in progress."); 136 return CameraBinderDecorator.INVALID_OPERATION; 137 } 138 } 139 long lastFrame = mLegacyDevice.cancelRequest(requestId); 140 lastFrameNumber.setNumber(lastFrame); 141 return CameraBinderDecorator.NO_ERROR; 142 } 143 144 @Override 145 public int beginConfigure() { 146 if (DEBUG) { 147 Log.d(TAG, "beginConfigure called."); 148 } 149 synchronized(mConfigureLock) { 150 if (mConfiguring) { 151 Log.e(TAG, "Cannot begin configure, configuration change already in progress."); 152 return CameraBinderDecorator.INVALID_OPERATION; 153 } 154 mConfiguring = true; 155 } 156 return CameraBinderDecorator.NO_ERROR; 157 } 158 159 @Override 160 public int endConfigure() { 161 if (DEBUG) { 162 Log.d(TAG, "endConfigure called."); 163 } 164 ArrayList<Surface> surfaces = null; 165 synchronized(mConfigureLock) { 166 if (!mConfiguring) { 167 Log.e(TAG, "Cannot end configure, no configuration change in progress."); 168 return CameraBinderDecorator.INVALID_OPERATION; 169 } 170 int numSurfaces = mSurfaces.size(); 171 if (numSurfaces > 0) { 172 for (int i = 0; i < numSurfaces; ++i) { 173 surfaces.add(mSurfaces.valueAt(i)); 174 } 175 } 176 mConfiguring = false; 177 } 178 return mLegacyDevice.configureOutputs(surfaces); 179 } 180 181 @Override 182 public int deleteStream(int streamId) { 183 if (DEBUG) { 184 Log.d(TAG, "deleteStream called."); 185 } 186 synchronized(mConfigureLock) { 187 if (!mConfiguring) { 188 Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet."); 189 return CameraBinderDecorator.INVALID_OPERATION; 190 } 191 int index = mSurfaces.indexOfKey(streamId); 192 if (index < 0) { 193 Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist."); 194 return CameraBinderDecorator.BAD_VALUE; 195 } 196 mSurfaces.removeAt(index); 197 } 198 return CameraBinderDecorator.NO_ERROR; 199 } 200 201 @Override 202 public int createStream(int width, int height, int format, Surface surface) { 203 if (DEBUG) { 204 Log.d(TAG, "createStream called."); 205 } 206 synchronized(mConfigureLock) { 207 if (!mConfiguring) { 208 Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet."); 209 return CameraBinderDecorator.INVALID_OPERATION; 210 } 211 int id = ++mSurfaceIdCounter; 212 mSurfaces.put(id, surface); 213 return id; 214 } 215 } 216 217 @Override 218 public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) { 219 if (DEBUG) { 220 Log.d(TAG, "createDefaultRequest called."); 221 } 222 // TODO: implement createDefaultRequest. 223 Log.e(TAG, "createDefaultRequest unimplemented."); 224 return CameraBinderDecorator.NO_ERROR; 225 } 226 227 @Override 228 public int getCameraInfo(/*out*/CameraMetadataNative info) { 229 if (DEBUG) { 230 Log.d(TAG, "getCameraInfo called."); 231 } 232 // TODO: implement getCameraInfo. 233 Log.e(TAG, "getCameraInfo unimplemented."); 234 return CameraBinderDecorator.NO_ERROR; 235 } 236 237 @Override 238 public int waitUntilIdle() throws RemoteException { 239 if (DEBUG) { 240 Log.d(TAG, "waitUntilIdle called."); 241 } 242 synchronized(mConfigureLock) { 243 if (mConfiguring) { 244 Log.e(TAG, "Cannot wait until idle, configuration change in progress."); 245 return CameraBinderDecorator.INVALID_OPERATION; 246 } 247 } 248 mLegacyDevice.waitUntilIdle(); 249 return CameraBinderDecorator.NO_ERROR; 250 } 251 252 @Override 253 public int flush(/*out*/LongParcelable lastFrameNumber) { 254 if (DEBUG) { 255 Log.d(TAG, "flush called."); 256 } 257 synchronized(mConfigureLock) { 258 if (mConfiguring) { 259 Log.e(TAG, "Cannot flush, configuration change in progress."); 260 return CameraBinderDecorator.INVALID_OPERATION; 261 } 262 } 263 // TODO: implement flush. 264 return CameraBinderDecorator.NO_ERROR; 265 } 266 267 @Override 268 public IBinder asBinder() { 269 // This is solely intended to be used for in-process binding. 270 return null; 271 } 272} 273