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