diff options
| author | 2021-09-07 20:12:01 +0000 | |
|---|---|---|
| committer | 2021-09-07 20:12:01 +0000 | |
| commit | bb56e9f505080a8b8c5f33c84648c6d8c00f4ae7 (patch) | |
| tree | 9499a8133a6a7c45a8ebdd04568ca4648a43d84b | |
| parent | 440771d13a1dbeb77d98ee8c320b24478558f596 (diff) | |
| parent | 5383387933e6e6b6412d1da589464b4ec465f771 (diff) | |
Merge "Camera: Propogate onCameraOpened flag at listener registration"
| -rw-r--r-- | core/java/android/hardware/CameraStatus.java | 3 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/CameraManager.java | 89 |
2 files changed, 78 insertions, 14 deletions
diff --git a/core/java/android/hardware/CameraStatus.java b/core/java/android/hardware/CameraStatus.java index 29802cb33c38..874af297683e 100644 --- a/core/java/android/hardware/CameraStatus.java +++ b/core/java/android/hardware/CameraStatus.java @@ -31,6 +31,7 @@ public class CameraStatus implements Parcelable { public String cameraId; public int status; public String[] unavailablePhysicalCameras; + public String clientPackage; @Override public int describeContents() { @@ -42,12 +43,14 @@ public class CameraStatus implements Parcelable { out.writeString(cameraId); out.writeInt(status); out.writeStringArray(unavailablePhysicalCameras); + out.writeString(clientPackage); } public void readFromParcel(Parcel in) { cameraId = in.readString(); status = in.readInt(); unavailablePhysicalCameras = in.readStringArray(); + clientPackage = in.readString(); } public static final @android.annotation.NonNull Parcelable.Creator<CameraStatus> CREATOR = diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 5833b3dbef86..f5306b8e864c 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -24,6 +24,7 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; +import android.content.pm.PackageManager; import android.hardware.CameraStatus; import android.hardware.ICameraService; import android.hardware.ICameraServiceListener; @@ -90,12 +91,19 @@ public final class CameraManager { private final Context mContext; private final Object mLock = new Object(); + private static final String CAMERA_OPEN_CLOSE_LISTENER_PERMISSION = + "android.permission.CAMERA_OPEN_CLOSE_LISTENER"; + private final boolean mHasOpenCloseListenerPermission; + /** * @hide */ public CameraManager(Context context) { synchronized(mLock) { mContext = context; + mHasOpenCloseListenerPermission = + mContext.checkSelfPermission(CAMERA_OPEN_CLOSE_LISTENER_PERMISSION) == + PackageManager.PERMISSION_GRANTED; } } @@ -253,7 +261,7 @@ public final class CameraManager { public void registerAvailabilityCallback(@NonNull AvailabilityCallback callback, @Nullable Handler handler) { CameraManagerGlobal.get().registerAvailabilityCallback(callback, - CameraDeviceImpl.checkAndWrapHandler(handler)); + CameraDeviceImpl.checkAndWrapHandler(handler), mHasOpenCloseListenerPermission); } /** @@ -274,7 +282,8 @@ public final class CameraManager { if (executor == null) { throw new IllegalArgumentException("executor was null"); } - CameraManagerGlobal.get().registerAvailabilityCallback(callback, executor); + CameraManagerGlobal.get().registerAvailabilityCallback(callback, executor, + mHasOpenCloseListenerPermission); } /** @@ -1303,6 +1312,8 @@ public final class CameraManager { // Camera ID -> (physical camera ID -> Status map) private final ArrayMap<String, ArrayList<String>> mUnavailablePhysicalDevices = new ArrayMap<String, ArrayList<String>>(); + // Opened Camera ID -> apk name map + private final ArrayMap<String, String> mOpenedDevices = new ArrayMap<String, String>(); private final Set<Set<String>> mConcurrentCameraIdCombinations = new ArraySet<Set<String>>(); @@ -1325,6 +1336,7 @@ public final class CameraManager { // Access only through getCameraService to deal with binder death private ICameraService mCameraService; + private boolean mHasOpenCloseListenerPermission = false; // Singleton, don't allow construction private CameraManagerGlobal() { @@ -1403,6 +1415,12 @@ public final class CameraManager { c.cameraId, unavailPhysicalCamera); } } + + if (mHasOpenCloseListenerPermission && + c.status == ICameraServiceListener.STATUS_NOT_AVAILABLE && + !c.clientPackage.isEmpty()) { + onCameraOpenedLocked(c.cameraId, c.clientPackage); + } } mCameraService = cameraService; } catch(ServiceSpecificException e) { @@ -1893,6 +1911,12 @@ public final class CameraManager { ICameraServiceListener.STATUS_NOT_PRESENT); } } + + } + for (int i = 0; i < mOpenedDevices.size(); i++) { + String id = mOpenedDevices.keyAt(i); + String clientPackageId = mOpenedDevices.valueAt(i); + postSingleCameraOpenedUpdate(callback, executor, id, clientPackageId); } } @@ -2058,9 +2082,15 @@ public final class CameraManager { * * @param callback the new callback to send camera availability notices to * @param executor The executor which should invoke the callback. May not be null. + * @param hasOpenCloseListenerPermission whether the client has permission for + * onCameraOpened/onCameraClosed callback */ - public void registerAvailabilityCallback(AvailabilityCallback callback, Executor executor) { + public void registerAvailabilityCallback(AvailabilityCallback callback, Executor executor, + boolean hasOpenCloseListenerPermission) { synchronized (mLock) { + // In practice, this permission doesn't change. So we don't need one flag for each + // callback object. + mHasOpenCloseListenerPermission = hasOpenCloseListenerPermission; connectCameraServiceLocked(); Executor oldExecutor = mCallbackMap.put(callback, executor); @@ -2152,26 +2182,53 @@ public final class CameraManager { @Override public void onCameraOpened(String cameraId, String clientPackageId) { synchronized (mLock) { - final int callbackCount = mCallbackMap.size(); - for (int i = 0; i < callbackCount; i++) { - Executor executor = mCallbackMap.valueAt(i); - final AvailabilityCallback callback = mCallbackMap.keyAt(i); + onCameraOpenedLocked(cameraId, clientPackageId); + } + } - postSingleCameraOpenedUpdate(callback, executor, cameraId, clientPackageId); + private void onCameraOpenedLocked(String cameraId, String clientPackageId) { + String oldApk = mOpenedDevices.put(cameraId, clientPackageId); + + if (oldApk != null) { + if (oldApk.equals(clientPackageId)) { + Log.w(TAG, + "onCameraOpened was previously called for " + oldApk + + " and is now again called for the same package name, " + + "so no new client visible update will be sent"); + return; + } else { + Log.w(TAG, + "onCameraOpened was previously called for " + oldApk + + " and is now called for " + clientPackageId + + " without onCameraClosed being called first"); } } + + final int callbackCount = mCallbackMap.size(); + for (int i = 0; i < callbackCount; i++) { + Executor executor = mCallbackMap.valueAt(i); + final AvailabilityCallback callback = mCallbackMap.keyAt(i); + + postSingleCameraOpenedUpdate(callback, executor, cameraId, clientPackageId); + } } @Override public void onCameraClosed(String cameraId) { synchronized (mLock) { - final int callbackCount = mCallbackMap.size(); - for (int i = 0; i < callbackCount; i++) { - Executor executor = mCallbackMap.valueAt(i); - final AvailabilityCallback callback = mCallbackMap.keyAt(i); + onCameraClosedLocked(cameraId); + } + } - postSingleCameraClosedUpdate(callback, executor, cameraId); - } + private void onCameraClosedLocked(String cameraId) { + mOpenedDevices.remove(cameraId); + + final int callbackCount = mCallbackMap.size(); + for (int i = 0; i < callbackCount; i++) { + Executor executor = mCallbackMap.valueAt(i); + final AvailabilityCallback callback = mCallbackMap.keyAt(i); + + postSingleCameraClosedUpdate(callback, executor, cameraId); } } @@ -2229,6 +2286,10 @@ public final class CameraManager { for (int i = mDeviceStatus.size() - 1; i >= 0; i--) { String cameraId = mDeviceStatus.keyAt(i); onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId); + + if (mHasOpenCloseListenerPermission) { + onCameraClosedLocked(cameraId); + } } for (int i = 0; i < mTorchStatus.size(); i++) { String cameraId = mTorchStatus.keyAt(i); |