diff options
| author | 2019-09-24 20:05:18 +0000 | |
|---|---|---|
| committer | 2019-09-24 20:05:18 +0000 | |
| commit | 7f9a4c9e8cc8d32a6128c9c55d576793a2f0ecf8 (patch) | |
| tree | 696e8acc02ec213e117758d168d44668051cac81 | |
| parent | c022a8d13a811419e9efdd9d9c5748bbace9e9f2 (diff) | |
| parent | 4feeee88911503cc365b223a712437abcd91c94f (diff) | |
Merge changes from topic "system-camera-cts"
* changes:
Allow com.android.shell to get RECORD_AUDIO permissions.
CameraManager: Add @TestApi method getCameraIdListNoLazy().
| -rw-r--r-- | api/test-current.txt | 4 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/CameraManager.java | 146 | ||||
| -rw-r--r-- | packages/Shell/AndroidManifest.xml | 2 |
3 files changed, 125 insertions, 27 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index 51b569f029d0..0e93738b28f4 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -925,6 +925,10 @@ package android.hardware.camera2 { field public static final int SESSION_OPERATION_MODE_VENDOR_START = 32768; // 0x8000 } + public final class CameraManager { + method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException; + } + } package android.hardware.display { diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index c8276b25c52d..fc90096e5add 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemService; +import android.annotation.TestApi; import android.content.Context; import android.hardware.CameraInfo; import android.hardware.CameraStatus; @@ -47,6 +48,7 @@ import android.view.WindowManager; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; @@ -109,6 +111,21 @@ public final class CameraManager { } /** + * Similar to getCameraIdList(). However, getCamerIdListNoLazy() necessarily communicates with + * cameraserver in order to get the list of camera ids. This is to faciliate testing since some + * camera ids may go 'offline' without callbacks from cameraserver because of changes in + * SYSTEM_CAMERA permissions (though this is not a changeable permission, tests may call + * adopt(drop)ShellPermissionIdentity() and effectively change their permissions). This call + * affects the camera ids returned by getCameraIdList() as well. Tests which do adopt shell + * permission identity should not mix getCameraIdList() and getCameraListNoLazyCalls(). + */ + /** @hide */ + @TestApi + public String[] getCameraIdListNoLazy() throws CameraAccessException { + return CameraManagerGlobal.get().getCameraIdListNoLazy(); + } + + /** * Register a callback to be notified about camera device availability. * * <p>Registering the same callback again will replace the handler with the @@ -995,35 +1012,27 @@ public final class CameraManager { // Camera service is now down, leave mCameraService as null } } - - /** - * Get a list of all camera IDs that are at least PRESENT; ignore devices that are - * NOT_PRESENT or ENUMERATING, since they cannot be used by anyone. - */ - public String[] getCameraIdList() { + private String[] extractCameraIdListLocked() { String[] cameraIds = null; - synchronized(mLock) { - // Try to make sure we have an up-to-date list of camera devices. - connectCameraServiceLocked(); - - int idCount = 0; - for (int i = 0; i < mDeviceStatus.size(); i++) { - int status = mDeviceStatus.valueAt(i); - if (status == ICameraServiceListener.STATUS_NOT_PRESENT || - status == ICameraServiceListener.STATUS_ENUMERATING) continue; - idCount++; - } - cameraIds = new String[idCount]; - idCount = 0; - for (int i = 0; i < mDeviceStatus.size(); i++) { - int status = mDeviceStatus.valueAt(i); - if (status == ICameraServiceListener.STATUS_NOT_PRESENT || - status == ICameraServiceListener.STATUS_ENUMERATING) continue; - cameraIds[idCount] = mDeviceStatus.keyAt(i); - idCount++; - } + int idCount = 0; + for (int i = 0; i < mDeviceStatus.size(); i++) { + int status = mDeviceStatus.valueAt(i); + if (status == ICameraServiceListener.STATUS_NOT_PRESENT + || status == ICameraServiceListener.STATUS_ENUMERATING) continue; + idCount++; } - + cameraIds = new String[idCount]; + idCount = 0; + for (int i = 0; i < mDeviceStatus.size(); i++) { + int status = mDeviceStatus.valueAt(i); + if (status == ICameraServiceListener.STATUS_NOT_PRESENT + || status == ICameraServiceListener.STATUS_ENUMERATING) continue; + cameraIds[idCount] = mDeviceStatus.keyAt(i); + idCount++; + } + return cameraIds; + } + private static void sortCameraIds(String[] cameraIds) { // The sort logic must match the logic in // libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds Arrays.sort(cameraIds, new Comparator<String>() { @@ -1054,6 +1063,89 @@ public final class CameraManager { return s1.compareTo(s2); } }}); + + } + + public static boolean cameraStatusesContains(CameraStatus[] cameraStatuses, String id) { + for (CameraStatus c : cameraStatuses) { + if (c.cameraId.equals(id)) { + return true; + } + } + return false; + } + + public String[] getCameraIdListNoLazy() { + CameraStatus[] cameraStatuses; + ICameraServiceListener.Stub testListener = new ICameraServiceListener.Stub() { + @Override + public void onStatusChanged(int status, String id) throws RemoteException { + } + @Override + public void onTorchStatusChanged(int status, String id) throws RemoteException { + } + @Override + public void onCameraAccessPrioritiesChanged() { + }}; + + String[] cameraIds = null; + synchronized (mLock) { + connectCameraServiceLocked(); + try { + // The purpose of the addListener, removeListener pair here is to get a fresh + // list of camera ids from cameraserver. We do this since for in test processes, + // changes can happen w.r.t non-changeable permissions (eg: SYSTEM_CAMERA + // permissions can be effectively changed by calling + // adopt(drop)ShellPermissionIdentity()). + // Camera devices, which have their discovery affected by these permission + // changes, will not have clients get callbacks informing them about these + // devices going offline (in real world scenarios, these permissions aren't + // changeable). Future calls to getCameraIdList() will reflect the changes in + // the camera id list after getCameraIdListNoLazy() is called. + cameraStatuses = mCameraService.addListener(testListener); + mCameraService.removeListener(testListener); + for (CameraStatus c : cameraStatuses) { + onStatusChangedLocked(c.status, c.cameraId); + } + Set<String> deviceCameraIds = mDeviceStatus.keySet(); + ArrayList<String> deviceIdsToRemove = new ArrayList<String>(); + for (String deviceCameraId : deviceCameraIds) { + // Its possible that a device id was removed without a callback notifying + // us. This may happen in case a process 'drops' system camera permissions + // (even though the permission isn't a changeable one, tests may call + // adoptShellPermissionIdentity() and then dropShellPermissionIdentity(). + if (!cameraStatusesContains(cameraStatuses, deviceCameraId)) { + deviceIdsToRemove.add(deviceCameraId); + } + } + for (String id : deviceIdsToRemove) { + onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, id); + } + } catch (ServiceSpecificException e) { + // Unexpected failure + throw new IllegalStateException("Failed to register a camera service listener", + e); + } catch (RemoteException e) { + // Camera service is now down, leave mCameraService as null + } + cameraIds = extractCameraIdListLocked(); + } + sortCameraIds(cameraIds); + return cameraIds; + } + + /** + * Get a list of all camera IDs that are at least PRESENT; ignore devices that are + * NOT_PRESENT or ENUMERATING, since they cannot be used by anyone. + */ + public String[] getCameraIdList() { + String[] cameraIds = null; + synchronized (mLock) { + // Try to make sure we have an up-to-date list of camera devices. + connectCameraServiceLocked(); + cameraIds = extractCameraIdListLocked(); + } + sortCameraIds(cameraIds); return cameraIds; } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index b2ff4b3268b2..e767bccc7b4a 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -172,6 +172,8 @@ <!-- Permissions needed to test system only camera devices --> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.SYSTEM_CAMERA" /> + <!-- Permissions needed for CTS camera test: RecordingTest.java when assuming shell id --> + <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- Permission needed to enable/disable Bluetooth/Wifi --> <uses-permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED" /> <uses-permission android:name="android.permission.MANAGE_WIFI_WHEN_WIRELESS_CONSENT_REQUIRED" /> |