CameraDeviceUserShim.java revision 5776aafc7e70c0b79c4bee2bc50f44121b37c962
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 surfaces = new ArrayList<>(); 173 for (int i = 0; i < numSurfaces; ++i) { 174 surfaces.add(mSurfaces.valueAt(i)); 175 } 176 } 177 mConfiguring = false; 178 } 179 return mLegacyDevice.configureOutputs(surfaces); 180 } 181 182 @Override 183 public int deleteStream(int streamId) { 184 if (DEBUG) { 185 Log.d(TAG, "deleteStream called."); 186 } 187 synchronized(mConfigureLock) { 188 if (!mConfiguring) { 189 Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet."); 190 return CameraBinderDecorator.INVALID_OPERATION; 191 } 192 int index = mSurfaces.indexOfKey(streamId); 193 if (index < 0) { 194 Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist."); 195 return CameraBinderDecorator.BAD_VALUE; 196 } 197 mSurfaces.removeAt(index); 198 } 199 return CameraBinderDecorator.NO_ERROR; 200 } 201 202 @Override 203 public int createStream(int width, int height, int format, Surface surface) { 204 if (DEBUG) { 205 Log.d(TAG, "createStream called."); 206 } 207 synchronized(mConfigureLock) { 208 if (!mConfiguring) { 209 Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet."); 210 return CameraBinderDecorator.INVALID_OPERATION; 211 } 212 int id = ++mSurfaceIdCounter; 213 mSurfaces.put(id, surface); 214 return id; 215 } 216 } 217 218 @Override 219 public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) { 220 if (DEBUG) { 221 Log.d(TAG, "createDefaultRequest called."); 222 } 223 // TODO: implement createDefaultRequest. 224 Log.e(TAG, "createDefaultRequest unimplemented."); 225 return CameraBinderDecorator.NO_ERROR; 226 } 227 228 @Override 229 public int getCameraInfo(/*out*/CameraMetadataNative info) { 230 if (DEBUG) { 231 Log.d(TAG, "getCameraInfo called."); 232 } 233 // TODO: implement getCameraInfo. 234 Log.e(TAG, "getCameraInfo unimplemented."); 235 return CameraBinderDecorator.NO_ERROR; 236 } 237 238 @Override 239 public int waitUntilIdle() throws RemoteException { 240 if (DEBUG) { 241 Log.d(TAG, "waitUntilIdle called."); 242 } 243 synchronized(mConfigureLock) { 244 if (mConfiguring) { 245 Log.e(TAG, "Cannot wait until idle, configuration change in progress."); 246 return CameraBinderDecorator.INVALID_OPERATION; 247 } 248 } 249 mLegacyDevice.waitUntilIdle(); 250 return CameraBinderDecorator.NO_ERROR; 251 } 252 253 @Override 254 public int flush(/*out*/LongParcelable lastFrameNumber) { 255 if (DEBUG) { 256 Log.d(TAG, "flush called."); 257 } 258 synchronized(mConfigureLock) { 259 if (mConfiguring) { 260 Log.e(TAG, "Cannot flush, configuration change in progress."); 261 return CameraBinderDecorator.INVALID_OPERATION; 262 } 263 } 264 // TODO: implement flush. 265 return CameraBinderDecorator.NO_ERROR; 266 } 267 268 @Override 269 public IBinder asBinder() { 270 // This is solely intended to be used for in-process binding. 271 return null; 272 } 273} 274