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