CameraDeviceUserShim.java revision a1d662716b3da384dfe3a758f079e0cbd089784a
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.cameraInitUnspecified(cameraId); 80 81 // Check errors old HAL initialization 82 CameraBinderDecorator.throwOnError(initErrors); 83 84 LegacyCameraDevice device = new LegacyCameraDevice(cameraId, legacyCamera, callbacks); 85 return new CameraDeviceUserShim(cameraId, device); 86 } 87 88 @Override 89 public void disconnect() { 90 if (DEBUG) { 91 Log.d(TAG, "disconnect called."); 92 } 93 mLegacyDevice.close(); 94 } 95 96 @Override 97 public int submitRequest(CaptureRequest request, boolean streaming, 98 /*out*/LongParcelable lastFrameNumber) { 99 if (DEBUG) { 100 Log.d(TAG, "submitRequest called."); 101 } 102 synchronized(mConfigureLock) { 103 if (mConfiguring) { 104 Log.e(TAG, "Cannot submit request, configuration change in progress."); 105 return CameraBinderDecorator.INVALID_OPERATION; 106 } 107 } 108 return mLegacyDevice.submitRequest(request, streaming, lastFrameNumber); 109 } 110 111 @Override 112 public int submitRequestList(List<CaptureRequest> request, boolean streaming, 113 /*out*/LongParcelable lastFrameNumber) { 114 if (DEBUG) { 115 Log.d(TAG, "submitRequestList called."); 116 } 117 synchronized(mConfigureLock) { 118 if (mConfiguring) { 119 Log.e(TAG, "Cannot submit request, configuration change in progress."); 120 return CameraBinderDecorator.INVALID_OPERATION; 121 } 122 } 123 return mLegacyDevice.submitRequestList(request, streaming, lastFrameNumber); 124 } 125 126 @Override 127 public int cancelRequest(int requestId, /*out*/LongParcelable lastFrameNumber) { 128 if (DEBUG) { 129 Log.d(TAG, "cancelRequest called."); 130 } 131 synchronized(mConfigureLock) { 132 if (mConfiguring) { 133 Log.e(TAG, "Cannot cancel request, configuration change in progress."); 134 return CameraBinderDecorator.INVALID_OPERATION; 135 } 136 } 137 long lastFrame = mLegacyDevice.cancelRequest(requestId); 138 lastFrameNumber.setNumber(lastFrame); 139 return CameraBinderDecorator.NO_ERROR; 140 } 141 142 @Override 143 public int beginConfigure() { 144 if (DEBUG) { 145 Log.d(TAG, "beginConfigure called."); 146 } 147 synchronized(mConfigureLock) { 148 if (mConfiguring) { 149 Log.e(TAG, "Cannot begin configure, configuration change already in progress."); 150 return CameraBinderDecorator.INVALID_OPERATION; 151 } 152 mConfiguring = true; 153 } 154 return CameraBinderDecorator.NO_ERROR; 155 } 156 157 @Override 158 public int endConfigure() { 159 if (DEBUG) { 160 Log.d(TAG, "endConfigure called."); 161 } 162 ArrayList<Surface> surfaces = null; 163 synchronized(mConfigureLock) { 164 if (!mConfiguring) { 165 Log.e(TAG, "Cannot end configure, no configuration change in progress."); 166 return CameraBinderDecorator.INVALID_OPERATION; 167 } 168 int numSurfaces = mSurfaces.size(); 169 if (numSurfaces > 0) { 170 for (int i = 0; i < numSurfaces; ++i) { 171 surfaces.add(mSurfaces.valueAt(i)); 172 } 173 } 174 mConfiguring = false; 175 } 176 return mLegacyDevice.configureOutputs(surfaces); 177 } 178 179 @Override 180 public int deleteStream(int streamId) { 181 if (DEBUG) { 182 Log.d(TAG, "deleteStream called."); 183 } 184 synchronized(mConfigureLock) { 185 if (!mConfiguring) { 186 Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet."); 187 return CameraBinderDecorator.INVALID_OPERATION; 188 } 189 int index = mSurfaces.indexOfKey(streamId); 190 if (index < 0) { 191 Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist."); 192 return CameraBinderDecorator.BAD_VALUE; 193 } 194 mSurfaces.removeAt(index); 195 } 196 return CameraBinderDecorator.NO_ERROR; 197 } 198 199 @Override 200 public int createStream(int width, int height, int format, Surface surface) { 201 if (DEBUG) { 202 Log.d(TAG, "createStream called."); 203 } 204 synchronized(mConfigureLock) { 205 if (!mConfiguring) { 206 Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet."); 207 return CameraBinderDecorator.INVALID_OPERATION; 208 } 209 int id = ++mSurfaceIdCounter; 210 mSurfaces.put(id, surface); 211 return id; 212 } 213 } 214 215 @Override 216 public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) { 217 if (DEBUG) { 218 Log.d(TAG, "createDefaultRequest called."); 219 } 220 // TODO: implement createDefaultRequest. 221 Log.e(TAG, "createDefaultRequest unimplemented."); 222 return CameraBinderDecorator.NO_ERROR; 223 } 224 225 @Override 226 public int getCameraInfo(/*out*/CameraMetadataNative info) { 227 if (DEBUG) { 228 Log.d(TAG, "getCameraInfo called."); 229 } 230 // TODO: implement getCameraInfo. 231 Log.e(TAG, "getCameraInfo unimplemented."); 232 return CameraBinderDecorator.NO_ERROR; 233 } 234 235 @Override 236 public int waitUntilIdle() throws RemoteException { 237 if (DEBUG) { 238 Log.d(TAG, "waitUntilIdle called."); 239 } 240 synchronized(mConfigureLock) { 241 if (mConfiguring) { 242 Log.e(TAG, "Cannot wait until idle, configuration change in progress."); 243 return CameraBinderDecorator.INVALID_OPERATION; 244 } 245 } 246 mLegacyDevice.waitUntilIdle(); 247 return CameraBinderDecorator.NO_ERROR; 248 } 249 250 @Override 251 public int flush(/*out*/LongParcelable lastFrameNumber) { 252 if (DEBUG) { 253 Log.d(TAG, "flush called."); 254 } 255 synchronized(mConfigureLock) { 256 if (mConfiguring) { 257 Log.e(TAG, "Cannot flush, configuration change in progress."); 258 return CameraBinderDecorator.INVALID_OPERATION; 259 } 260 } 261 // TODO: implement flush. 262 return CameraBinderDecorator.NO_ERROR; 263 } 264 265 @Override 266 public IBinder asBinder() { 267 // This is solely intended to be used for in-process binding. 268 return null; 269 } 270} 271