diff options
Diffstat (limited to 'java/com/android/dialer/simulator/impl/SimulatorPreviewCamera.java')
-rw-r--r-- | java/com/android/dialer/simulator/impl/SimulatorPreviewCamera.java | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/java/com/android/dialer/simulator/impl/SimulatorPreviewCamera.java b/java/com/android/dialer/simulator/impl/SimulatorPreviewCamera.java new file mode 100644 index 000000000..e089f75ff --- /dev/null +++ b/java/com/android/dialer/simulator/impl/SimulatorPreviewCamera.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2017 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.dialer.simulator.impl; + +import android.content.Context; +import android.graphics.SurfaceTexture; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCaptureSession; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraDevice; +import android.hardware.camera2.CameraManager; +import android.hardware.camera2.CameraMetadata; +import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.params.StreamConfigurationMap; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.telecom.VideoProfile.CameraCapabilities; +import android.util.Size; +import android.view.Surface; +import com.android.dialer.common.Assert; +import com.android.dialer.common.LogUtil; +import java.util.Arrays; + +/** + * Used by the video provider to draw the local camera. The in-call UI is responsible for setting + * the camera (front or back) and the view to draw to. The video provider then uses this class to + * capture frames from the given camera and draw to the given view. + */ +final class SimulatorPreviewCamera { + @NonNull private final Context context; + @NonNull private final String cameraId; + @NonNull private final Surface surface; + @Nullable private CameraDevice camera; + private boolean isStopped; + + SimulatorPreviewCamera( + @NonNull Context context, @NonNull String cameraId, @NonNull Surface surface) { + this.context = Assert.isNotNull(context); + this.cameraId = Assert.isNotNull(cameraId); + this.surface = Assert.isNotNull(surface); + } + + void startCamera() { + LogUtil.enterBlock("SimulatorPreviewCamera.startCamera"); + Assert.checkState(!isStopped); + try { + context + .getSystemService(CameraManager.class) + .openCamera(cameraId, new CameraListener(), null /* handler */); + } catch (CameraAccessException | SecurityException e) { + throw Assert.createIllegalStateFailException("camera error: " + e); + } + } + + void stopCamera() { + LogUtil.enterBlock("SimulatorPreviewCamera.stopCamera"); + isStopped = true; + if (camera != null) { + camera.close(); + camera = null; + } + } + + @Nullable + static CameraCapabilities getCameraCapabilities( + @NonNull Context context, @Nullable String cameraId) { + if (cameraId == null) { + LogUtil.e("SimulatorPreviewCamera.getCameraCapabilities", "null camera ID"); + return null; + } + + CameraManager cameraManager = context.getSystemService(CameraManager.class); + CameraCharacteristics characteristics; + try { + characteristics = cameraManager.getCameraCharacteristics(cameraId); + } catch (CameraAccessException e) { + throw Assert.createIllegalStateFailException("camera error: " + e); + } + + StreamConfigurationMap map = + characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + Size previewSize = map.getOutputSizes(SurfaceTexture.class)[0]; + LogUtil.i("SimulatorPreviewCamera.getCameraCapabilities", "preview size: " + previewSize); + return new CameraCapabilities(previewSize.getWidth(), previewSize.getHeight()); + } + + private final class CameraListener extends CameraDevice.StateCallback { + @Override + public void onOpened(CameraDevice camera) { + LogUtil.enterBlock("SimulatorPreviewCamera.CameraListener.onOpened"); + SimulatorPreviewCamera.this.camera = camera; + if (isStopped) { + LogUtil.i("SimulatorPreviewCamera.CameraListener.onOpened", "stopped"); + stopCamera(); + return; + } + + try { + camera.createCaptureSession( + Arrays.asList(Assert.isNotNull(surface)), + new CaptureSessionCallback(), + null /* handler */); + } catch (CameraAccessException e) { + throw Assert.createIllegalStateFailException("camera error: " + e); + } + } + + @Override + public void onError(CameraDevice camera, int error) { + LogUtil.i("SimulatorPreviewCamera.CameraListener.onError", "error: " + error); + stopCamera(); + } + + @Override + public void onDisconnected(CameraDevice camera) { + LogUtil.enterBlock("SimulatorPreviewCamera.CameraListener.onDisconnected"); + stopCamera(); + } + + @Override + public void onClosed(CameraDevice camera) { + LogUtil.enterBlock("SimulatorPreviewCamera.CameraListener.onCLosed"); + } + } + + private final class CaptureSessionCallback extends CameraCaptureSession.StateCallback { + @Override + public void onConfigured(@NonNull CameraCaptureSession session) { + LogUtil.enterBlock("SimulatorPreviewCamera.CaptureSessionCallback.onConfigured"); + + if (isStopped) { + LogUtil.i("SimulatorPreviewCamera.CaptureSessionCallback.onConfigured", "stopped"); + stopCamera(); + return; + } + try { + CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); + builder.addTarget(surface); + builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); + session.setRepeatingRequest( + builder.build(), null /* captureCallback */, null /* handler */); + } catch (CameraAccessException e) { + throw Assert.createIllegalStateFailException("camera error: " + e); + } + } + + @Override + public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { + LogUtil.enterBlock("SimulatorPreviewCamera.CaptureSessionCallback.onConfigureFailed"); + } + } +} |