xref: /aosp_15_r20/cts/tests/camera/src/android/hardware/multiprocess/camera/cts/Camera2Activity.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2015 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 
17 package android.hardware.multiprocess.camera.cts;
18 
19 import android.app.Activity;
20 import android.content.Intent;
21 import android.graphics.Rect;
22 import android.hardware.camera2.CameraAccessException;
23 import android.hardware.camera2.CameraDevice;
24 import android.hardware.camera2.CameraManager;
25 import android.os.Bundle;
26 import android.os.Handler;
27 import android.os.HandlerThread;
28 import android.os.Process;
29 import android.util.Log;
30 import android.view.WindowMetrics;
31 
32 /**
33  * Activity implementing basic access of the Camera2 API.
34  *
35  * <p />
36  * This will log all errors to {@link android.hardware.multiprocess.camera.cts.ErrorLoggingService}.
37  */
38 public class Camera2Activity extends Activity {
39     private static final String TAG = "Camera2Activity";
40 
41     ErrorLoggingService.ErrorServiceConnection mErrorServiceConnection;
42     CameraManager mCameraManager;
43     AvailabilityCallback mAvailabilityCallback;
44     StateCallback mStateCallback;
45     Handler mCameraHandler;
46     HandlerThread mCameraHandlerThread;
47     boolean mIgnoreCameraAccess = false;
48     boolean mIgnoreTopActivityResumed = false;
49     boolean mIgnoreActivityPaused = false;
50 
51     @Override
onCreate(Bundle savedInstanceState)52     protected void onCreate(Bundle savedInstanceState) {
53         Log.i(TAG, "onCreate called: uid " + Process.myUid() + ".");
54         super.onCreate(savedInstanceState);
55 
56         Intent intent = getIntent();
57         mIgnoreCameraAccess = intent.getBooleanExtra(
58                 TestConstants.EXTRA_IGNORE_CAMERA_ACCESS, false);
59         mIgnoreTopActivityResumed = intent.getBooleanExtra(
60                 TestConstants.EXTRA_IGNORE_TOP_ACTIVITY_RESUMED, false);
61         mIgnoreActivityPaused = intent.getBooleanExtra(
62                 TestConstants.EXTRA_IGNORE_ACTIVITY_PAUSED, false);
63 
64         mCameraHandlerThread = new HandlerThread("CameraHandlerThread");
65         mCameraHandlerThread.start();
66         mCameraHandler = new Handler(mCameraHandlerThread.getLooper());
67         mErrorServiceConnection = new ErrorLoggingService.ErrorServiceConnection(this);
68         mErrorServiceConnection.start();
69     }
70 
71     @Override
onPause()72     protected void onPause() {
73         Log.i(TAG, "onPause called.");
74         super.onPause();
75 
76         if (!mIgnoreActivityPaused) {
77             mErrorServiceConnection.logAsync(TestConstants.EVENT_ACTIVITY_PAUSED, "");
78         }
79     }
80 
81     @Override
onResume()82     protected void onResume() {
83         Log.i(TAG, "onResume called.");
84         super.onResume();
85 
86         WindowMetrics metrics = getWindowManager().getCurrentWindowMetrics();
87         Rect windowRect = metrics.getBounds();
88         mErrorServiceConnection.logAsync(TestConstants.EVENT_ACTIVITY_RESUMED,
89                 windowRect.left + ":" + windowRect.top + ":"
90                 + windowRect.right + ":" + windowRect.bottom);
91 
92         try {
93             mCameraManager = getSystemService(CameraManager.class);
94 
95             if (mCameraManager == null) {
96                 mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, TAG +
97                         " could not connect camera service");
98                 return;
99             }
100             // TODO: http://b/145308043 move this back to getCameraIdListNoLazy()
101             String[] cameraIds = mCameraManager.getCameraIdList();
102 
103             if (cameraIds == null || cameraIds.length == 0) {
104                 mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, TAG +
105                         " device reported having no cameras");
106                 return;
107             }
108 
109             if (mAvailabilityCallback == null) {
110                 mAvailabilityCallback = new AvailabilityCallback();
111                 mCameraManager.registerAvailabilityCallback(mAvailabilityCallback, mCameraHandler);
112             }
113 
114             final String chosen = cameraIds[0];
115             if (mStateCallback == null || mStateCallback.mChosen != chosen) {
116                 mStateCallback = new StateCallback(chosen);
117                 mCameraManager.openCamera(chosen, mStateCallback, mCameraHandler);
118             }
119         } catch (CameraAccessException e) {
120             mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, TAG +
121                     " camera exception during connection: " + e);
122             Log.e(TAG, "Access exception: " + e);
123         }
124 
125         Log.i(TAG, "onResume finished.");
126     }
127 
128     @Override
onTopResumedActivityChanged(boolean topResumed)129     public void onTopResumedActivityChanged(boolean topResumed) {
130         /**
131          * Log here for easier debugging in split screen mode. We will receive this instead of
132          * onResume because in split screen both activities are always in the resumed state.
133          */
134         Log.i(TAG, "onTopResumedActivityChanged(" + topResumed + ")");
135         super.onTopResumedActivityChanged(topResumed);
136 
137         if (!mIgnoreTopActivityResumed) {
138             if (topResumed) {
139                 mErrorServiceConnection.logAsync(
140                         TestConstants.EVENT_ACTIVITY_TOP_RESUMED_TRUE, "");
141             } else {
142                 mErrorServiceConnection.logAsync(
143                         TestConstants.EVENT_ACTIVITY_TOP_RESUMED_FALSE, "");
144             }
145         }
146     }
147 
148     @Override
onDestroy()149     protected void onDestroy() {
150         Log.i(TAG, "onDestroy called.");
151         super.onDestroy();
152 
153         if (mAvailabilityCallback != null) {
154             mCameraManager.unregisterAvailabilityCallback(mAvailabilityCallback);
155             mAvailabilityCallback = null;
156         }
157 
158         mCameraHandlerThread.quitSafely();
159 
160         if (mErrorServiceConnection != null) {
161             mErrorServiceConnection.stop();
162             mErrorServiceConnection = null;
163         }
164     }
165 
166     private class AvailabilityCallback extends CameraManager.AvailabilityCallback {
167         @Override
onCameraAvailable(String cameraId)168         public void onCameraAvailable(String cameraId) {
169             super.onCameraAvailable(cameraId);
170             mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_AVAILABLE,
171                     cameraId);
172             Log.i(TAG, "Camera " + cameraId + " is available");
173         }
174 
175         @Override
onCameraUnavailable(String cameraId)176         public void onCameraUnavailable(String cameraId) {
177             super.onCameraUnavailable(cameraId);
178             mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_UNAVAILABLE,
179                     cameraId);
180             Log.i(TAG, "Camera " + cameraId + " is unavailable");
181         }
182 
183         @Override
onCameraAccessPrioritiesChanged()184         public void onCameraAccessPrioritiesChanged() {
185             super.onCameraAccessPrioritiesChanged();
186             if (!mIgnoreCameraAccess) {
187                 mErrorServiceConnection.logAsync(
188                         TestConstants.EVENT_CAMERA_ACCESS_PRIORITIES_CHANGED, "");
189             }
190             Log.i(TAG, "Camera access priorities changed");
191         }
192 
193         @Override
onPhysicalCameraAvailable(String cameraId, String physicalCameraId)194         public void onPhysicalCameraAvailable(String cameraId, String physicalCameraId) {
195             super.onPhysicalCameraAvailable(cameraId, physicalCameraId);
196             mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_AVAILABLE,
197                     cameraId + " : " + physicalCameraId);
198             Log.i(TAG, "Camera " + cameraId + " : " + physicalCameraId + " is available");
199         }
200 
201         @Override
onPhysicalCameraUnavailable(String cameraId, String physicalCameraId)202         public void onPhysicalCameraUnavailable(String cameraId, String physicalCameraId) {
203             super.onPhysicalCameraUnavailable(cameraId, physicalCameraId);
204             mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_UNAVAILABLE,
205                     cameraId + " : " + physicalCameraId);
206             Log.i(TAG, "Camera " + cameraId + " : " + physicalCameraId + " is unavailable");
207         }
208     }
209 
210     private class StateCallback extends CameraDevice.StateCallback {
211         String mChosen;
212 
StateCallback(String chosen)213         StateCallback(String chosen) {
214             mChosen = chosen;
215         }
216 
217         @Override
onOpened(CameraDevice cameraDevice)218         public void onOpened(CameraDevice cameraDevice) {
219             mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_CONNECT,
220                     mChosen);
221             Log.i(TAG, "Camera " + mChosen + " is opened");
222         }
223 
224         @Override
onDisconnected(CameraDevice cameraDevice)225         public void onDisconnected(CameraDevice cameraDevice) {
226             mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_EVICTED,
227                     mChosen);
228             Log.i(TAG, "Camera " + mChosen + " is disconnected");
229         }
230 
231         @Override
onError(CameraDevice cameraDevice, int i)232         public void onError(CameraDevice cameraDevice, int i) {
233             mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, TAG
234                     + " Camera " + mChosen + " experienced error " + i);
235             Log.e(TAG, "Camera " + mChosen + " onError called with error " + i);
236         }
237     }
238 }
239