1 /* 2 * Copyright (C) 2023 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 package com.google.android.car.kitchensink.camera2; 17 18 import android.content.Intent; 19 import android.hardware.camera2.CameraAccessException; 20 import android.hardware.camera2.CameraCaptureSession; 21 import android.hardware.camera2.CameraDevice; 22 import android.hardware.camera2.CameraManager; 23 import android.hardware.camera2.CaptureRequest; 24 import android.hardware.camera2.params.OutputConfiguration; 25 import android.hardware.camera2.params.SessionConfiguration; 26 import android.os.Bundle; 27 import android.os.Handler; 28 import android.os.HandlerThread; 29 import android.os.UserHandle; 30 import android.util.Log; 31 import android.view.SurfaceHolder; 32 import android.view.SurfaceView; 33 import android.view.View; 34 import android.widget.Button; 35 36 import androidx.fragment.app.FragmentActivity; 37 38 import com.google.android.car.kitchensink.R; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 import java.util.concurrent.Executor; 43 44 public class CameraSystemActivity extends FragmentActivity { 45 private static final String TAG = "Camera2.SystemUser.KS"; 46 private CameraManager mCameraManager; 47 private SurfaceView mSurfaceView; 48 private SurfacePreviewListener mSurfacePreviewListener; 49 private HandlerThread mHandlerThread; 50 private Handler mHandler; 51 private CameraDevice mCameraDevice; 52 private String mCameraId; 53 private CaptureRequest.Builder mCaptureRequestBuilder; 54 private CameraCaptureSession mCaptureSession; 55 private CameraSessionListener mCameraSessionListener; 56 private CameraStateListener mCameraStateListener; 57 58 @Override onCreate(Bundle savedInstanceState)59 protected void onCreate(Bundle savedInstanceState) { 60 super.onCreate(savedInstanceState); 61 int myUserId = UserHandle.myUserId(); 62 Log.i(TAG, "onCreate userid " + myUserId); 63 if (myUserId != UserHandle.USER_SYSTEM) { 64 Log.i(TAG, "onCreate re-starting self as user 0"); 65 Intent selfIntent = 66 new Intent(CameraSystemActivity.this, CameraSystemActivity.class); 67 startActivityAsUser(selfIntent, UserHandle.SYSTEM); 68 finish(); 69 } 70 71 setContentView(R.layout.camera_system_activity); 72 mCameraManager = getSystemService(CameraManager.class); 73 mSurfaceView = findViewById(R.id.surface_view_1); 74 mSurfacePreviewListener = new SurfacePreviewListener(); 75 mSurfaceView.getHolder().addCallback(mSurfacePreviewListener); 76 mHandlerThread = new HandlerThread("CameraPreviewThread"); 77 mHandlerThread.start(); 78 mHandler = new Handler(mHandlerThread.getLooper()); 79 mCameraStateListener = new CameraStateListener(); 80 mCameraSessionListener = new CameraSessionListener(); 81 Button finishButton = (Button) findViewById(R.id.finish); 82 finishButton.setOnClickListener( 83 new View.OnClickListener() { 84 @Override 85 public void onClick(View view) { 86 finish(); 87 } 88 }); 89 } 90 openCamera()91 public void openCamera() { 92 try { 93 String[] cameraIds = mCameraManager.getCameraIdListNoLazy(); 94 if (cameraIds.length > 0) { 95 mCameraId = cameraIds[0]; 96 Log.i(TAG, "Opening camera " + mCameraId); 97 mCameraManager.openCamera(mCameraId, mCameraStateListener, mHandler); 98 } else { 99 Log.w(TAG, "Camera service reported no cameras connected to device."); 100 } 101 } catch (CameraAccessException e) { 102 Log.e(TAG, "Failed to open camera. Got CameraAccessException."); 103 } catch (IllegalStateException e) { 104 Log.e(TAG, "Failed to open camera. Got IllegalStateException."); 105 } 106 } 107 108 public class SurfacePreviewListener implements SurfaceHolder.Callback { 109 110 @Override surfaceCreated(SurfaceHolder holder)111 public void surfaceCreated(SurfaceHolder holder) { 112 Log.i(TAG, "Surface created"); 113 openCamera(); 114 } 115 116 @Override surfaceChanged(SurfaceHolder holder, int format, int width, int height)117 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 118 Log.i(TAG, "Surface Changed to: " + width + "x" + height); 119 } 120 121 @Override surfaceDestroyed(SurfaceHolder holder)122 public void surfaceDestroyed(SurfaceHolder holder) { 123 Log.i(TAG, "Surface destroyed"); 124 } 125 } 126 127 public static class HandlerExecutor implements Executor { 128 private final Handler mHandler; 129 HandlerExecutor(Handler handler)130 public HandlerExecutor(Handler handler) { 131 mHandler = handler; 132 } 133 134 @Override execute(Runnable runCmd)135 public void execute(Runnable runCmd) { 136 mHandler.post(runCmd); 137 } 138 } 139 140 class CameraStateListener extends CameraDevice.StateCallback { 141 142 @Override onOpened(CameraDevice camera)143 public void onOpened(CameraDevice camera) { 144 Log.i(TAG, "Camera Opened"); 145 mCameraDevice = camera; 146 try { 147 mCaptureRequestBuilder = mCameraDevice.createCaptureRequest( 148 CameraDevice.TEMPLATE_PREVIEW); 149 mCaptureRequestBuilder.addTarget(mSurfaceView.getHolder().getSurface()); 150 List<OutputConfiguration> outputs = new ArrayList<>(); 151 outputs.add(new OutputConfiguration(mSurfaceView.getHolder().getSurface())); 152 SessionConfiguration sessionConfig = new SessionConfiguration( 153 SessionConfiguration.SESSION_REGULAR, outputs, 154 new HandlerExecutor(mHandler), mCameraSessionListener); 155 CaptureRequest request = mCaptureRequestBuilder.build(); 156 sessionConfig.setSessionParameters(request); 157 mCameraDevice.createCaptureSession(sessionConfig); 158 } catch (CameraAccessException e) { 159 Log.e(TAG, "Failed to start capture session. Got CameraAccessException."); 160 } catch (IllegalStateException e) { 161 Log.e(TAG, "Failed to start capture session. Got IllegalStateException."); 162 } 163 } 164 165 @Override onDisconnected(CameraDevice camera)166 public void onDisconnected(CameraDevice camera) {} 167 168 @Override onError(CameraDevice camera, int error)169 public void onError(CameraDevice camera, int error) {} 170 } 171 172 class CameraSessionListener extends CameraCaptureSession.StateCallback { 173 174 @Override onConfigured(CameraCaptureSession session)175 public void onConfigured(CameraCaptureSession session) { 176 mCaptureSession = session; 177 try { 178 mCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(), null, mHandler); 179 } catch (CameraAccessException e) { 180 Log.e(TAG, "Failed to start camera preview. Got CameraAccessException."); 181 } catch (IllegalStateException e) { 182 Log.e(TAG, "Failed to start camera preview. Got IllegalStateException."); 183 } 184 } 185 186 @Override onConfigureFailed(CameraCaptureSession session)187 public void onConfigureFailed(CameraCaptureSession session) {} 188 } 189 190 @Override onDestroy()191 protected void onDestroy() { 192 try { 193 194 if (mCaptureSession != null) { 195 mCaptureSession.stopRepeating(); 196 mCaptureSession.close(); 197 } 198 199 if (mHandlerThread != null) { 200 mHandlerThread.quitSafely(); 201 mHandlerThread.join(); 202 } 203 204 mHandler = null; 205 mCameraSessionListener = null; 206 207 if (mCameraDevice != null) { 208 mCameraDevice.close(); 209 mCameraDevice = null; 210 } 211 212 super.onDestroy(); 213 } catch (Exception e) { } 214 } 215 } 216