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