Camera: Support new provider callback version in camera service
The new provider callback version enables availability callback for
physical camera.
Test: Camera CTS
Bug: 119325027
Change-Id: I22e0b669c3d9891a431e1befc7f1c9f40b826a08
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index c53e6c3..aecb70a 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -60,6 +60,13 @@
if (res != OK) return res;
res = parcel->writeInt32(status);
+ if (res != OK) return res;
+
+ std::vector<String16> unavailablePhysicalIds16;
+ for (auto& id8 : unavailablePhysicalIds) {
+ unavailablePhysicalIds16.push_back(String16(id8));
+ }
+ res = parcel->writeString16Vector(unavailablePhysicalIds16);
return res;
}
@@ -70,6 +77,14 @@
cameraId = String8(tempCameraId);
res = parcel->readInt32(&status);
+ if (res != OK) return res;
+
+ std::vector<String16> unavailablePhysicalIds16;
+ res = parcel->readString16Vector(&unavailablePhysicalIds16);
+ if (res != OK) return res;
+ for (auto& id16 : unavailablePhysicalIds16) {
+ unavailablePhysicalIds.push_back(String8(id16));
+ }
return res;
}
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
index e9dcbdb..81657fd 100644
--- a/camera/aidl/android/hardware/ICameraServiceListener.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -54,6 +54,12 @@
oneway void onStatusChanged(int status, String cameraId);
/**
+ * Notify registered client about status changes for a physical camera backing
+ * a logical camera.
+ */
+ oneway void onPhysicalCameraStatusChanged(int status, String cameraId, String physicalCameraId);
+
+ /**
* The torch mode status of a camera.
*
* Initial status will be transmitted with onTorchStatusChanged immediately
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 320c499..22e9578 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -32,6 +32,7 @@
"android.hardware.camera.common@1.0",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
+ "android.hardware.camera.provider@2.6",
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.4",
diff --git a/camera/include/camera/CameraBase.h b/camera/include/camera/CameraBase.h
index 74a2dce..499b0e6 100644
--- a/camera/include/camera/CameraBase.h
+++ b/camera/include/camera/CameraBase.h
@@ -80,10 +80,16 @@
*/
int32_t status;
+ /**
+ * Unavailable physical camera names for a multi-camera device
+ */
+ std::vector<String8> unavailablePhysicalIds;
+
virtual status_t writeToParcel(android::Parcel* parcel) const;
virtual status_t readFromParcel(const android::Parcel* parcel);
- CameraStatus(String8 id, int32_t s) : cameraId(id), status(s) {}
+ CameraStatus(String8 id, int32_t s, const std::vector<String8>& unavailSubIds) :
+ cameraId(id), status(s), unavailablePhysicalIds(unavailSubIds) {}
CameraStatus() : status(ICameraServiceListener::STATUS_PRESENT) {}
};
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 7a0f63b..4870265 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -32,6 +32,7 @@
namespace acam {
// Static member definitions
const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
+const char* CameraManagerGlobal::kPhysicalCameraIdKey = "PhysicalCameraId";
const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
const char* CameraManagerGlobal::kContextKey = "CallbackContext";
Mutex CameraManagerGlobal::sLock;
@@ -220,7 +221,7 @@
if (pair.second) {
for (auto& pair : mDeviceStatusMap) {
const String8& cameraId = pair.first;
- int32_t status = pair.second.status;
+ int32_t status = pair.second.getStatus();
// Don't send initial callbacks for camera ids which don't support
// camera2
if (!pair.second.supportsHAL3) {
@@ -264,9 +265,9 @@
// Needed to make sure we're connected to cameraservice
getCameraServiceLocked();
for(auto& deviceStatus : mDeviceStatusMap) {
- if (deviceStatus.second.status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
- deviceStatus.second.status ==
- hardware::ICameraServiceListener::STATUS_ENUMERATING) {
+ int32_t status = deviceStatus.second.getStatus();
+ if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
+ status == hardware::ICameraServiceListener::STATUS_ENUMERATING) {
continue;
}
if (!deviceStatus.second.supportsHAL3) {
@@ -341,6 +342,39 @@
(*cb)(context);
break;
}
+ case kWhatSendSinglePhysicalCameraCallback:
+ {
+ ACameraManager_PhysicalCameraAvailabilityCallback cb;
+ void* context;
+ AString cameraId;
+ AString physicalCameraId;
+ bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
+ if (!found) {
+ ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
+ return;
+ }
+ if (cb == nullptr) {
+ // Physical camera callback is null
+ return;
+ }
+ found = msg->findPointer(kContextKey, &context);
+ if (!found) {
+ ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+ return;
+ }
+ found = msg->findString(kCameraIdKey, &cameraId);
+ if (!found) {
+ ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
+ return;
+ }
+ found = msg->findString(kPhysicalCameraIdKey, &physicalCameraId);
+ if (!found) {
+ ALOGE("%s: Cannot find physical camera ID!", __FUNCTION__);
+ return;
+ }
+ (*cb)(context, cameraId.c_str(), physicalCameraId.c_str());
+ break;
+ }
default:
ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
break;
@@ -368,6 +402,17 @@
return binder::Status::ok();
}
+binder::Status CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
+ int32_t status, const String16& cameraId, const String16& physicalCameraId) {
+ sp<CameraManagerGlobal> cm = mCameraManager.promote();
+ if (cm != nullptr) {
+ cm->onStatusChanged(status, String8(cameraId), String8(physicalCameraId));
+ } else {
+ ALOGE("Cannot deliver physical camera status change. Global camera manager died");
+ }
+ return binder::Status::ok();
+}
+
void CameraManagerGlobal::onCameraAccessPrioritiesChanged() {
Mutex::Autolock _l(mLock);
for (auto cb : mCallbacks) {
@@ -397,7 +442,7 @@
bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
int32_t oldStatus = firstStatus ?
status : // first status
- mDeviceStatusMap[cameraId].status;
+ mDeviceStatusMap[cameraId].getStatus();
if (!firstStatus &&
isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
@@ -406,8 +451,14 @@
}
bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
+ if (firstStatus) {
+ mDeviceStatusMap.emplace(std::piecewise_construct,
+ std::forward_as_tuple(cameraId),
+ std::forward_as_tuple(status, supportsHAL3));
+ } else {
+ mDeviceStatusMap[cameraId].updateStatus(status);
+ }
// Iterate through all registered callbacks
- mDeviceStatusMap[cameraId] = StatusAndHAL3Support(status, supportsHAL3);
if (supportsHAL3) {
for (auto cb : mCallbacks) {
sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
@@ -424,6 +475,81 @@
}
}
+void CameraManagerGlobal::onStatusChanged(
+ int32_t status, const String8& cameraId, const String8& physicalCameraId) {
+ Mutex::Autolock _l(mLock);
+ onStatusChangedLocked(status, cameraId, physicalCameraId);
+}
+
+void CameraManagerGlobal::onStatusChangedLocked(
+ int32_t status, const String8& cameraId, const String8& physicalCameraId) {
+ if (!validStatus(status)) {
+ ALOGE("%s: Invalid status %d", __FUNCTION__, status);
+ return;
+ }
+
+ auto logicalStatus = mDeviceStatusMap.find(cameraId);
+ if (logicalStatus == mDeviceStatusMap.end()) {
+ ALOGE("%s: Physical camera id %s status change on a non-present id %s",
+ __FUNCTION__, physicalCameraId.c_str(), cameraId.c_str());
+ return;
+ }
+ int32_t logicalCamStatus = mDeviceStatusMap[cameraId].getStatus();
+ if (logicalCamStatus != hardware::ICameraServiceListener::STATUS_PRESENT &&
+ logicalCamStatus != hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE) {
+ ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
+ __FUNCTION__, physicalCameraId.string(), status, logicalCamStatus);
+ return;
+ }
+
+ bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
+
+ bool updated = false;
+ if (status == hardware::ICameraServiceListener::STATUS_PRESENT) {
+ updated = mDeviceStatusMap[cameraId].removeUnavailablePhysicalId(physicalCameraId);
+ } else {
+ updated = mDeviceStatusMap[cameraId].addUnavailablePhysicalId(physicalCameraId);
+ }
+
+ // Iterate through all registered callbacks
+ if (supportsHAL3 && updated) {
+ for (auto cb : mCallbacks) {
+ sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+ ACameraManager_PhysicalCameraAvailabilityCallback cbFp = isStatusAvailable(status) ?
+ cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable;
+ msg->setPointer(kCallbackFpKey, (void *) cbFp);
+ msg->setPointer(kContextKey, cb.mContext);
+ msg->setString(kCameraIdKey, AString(cameraId));
+ msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId));
+ msg->post();
+ }
+ }
+}
+
+int32_t CameraManagerGlobal::StatusAndHAL3Support::getStatus() {
+ std::lock_guard<std::mutex> lock(mLock);
+ return status;
+}
+
+void CameraManagerGlobal::StatusAndHAL3Support::updateStatus(int32_t newStatus) {
+ std::lock_guard<std::mutex> lock(mLock);
+ status = newStatus;
+}
+
+bool CameraManagerGlobal::StatusAndHAL3Support::addUnavailablePhysicalId(
+ const String8& physicalCameraId) {
+ std::lock_guard<std::mutex> lock(mLock);
+ auto result = unavailablePhysicalIds.insert(physicalCameraId);
+ return result.second;
+}
+
+bool CameraManagerGlobal::StatusAndHAL3Support::removeUnavailablePhysicalId(
+ const String8& physicalCameraId) {
+ std::lock_guard<std::mutex> lock(mLock);
+ auto count = unavailablePhysicalIds.erase(physicalCameraId);
+ return count > 0;
+}
+
} // namespace acam
} // namespace android
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index e945ba0..98cd934 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -85,6 +85,8 @@
public:
explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
virtual binder::Status onStatusChanged(int32_t status, const String16& cameraId);
+ virtual binder::Status onPhysicalCameraStatusChanged(int32_t status,
+ const String16& cameraId, const String16& physicalCameraId);
// Torch API not implemented yet
virtual binder::Status onTorchStatusChanged(int32_t, const String16&) {
@@ -104,18 +106,24 @@
mAvailable(callback->onCameraAvailable),
mUnavailable(callback->onCameraUnavailable),
mAccessPriorityChanged(nullptr),
+ mPhysicalCamAvailable(nullptr),
+ mPhysicalCamUnavailable(nullptr),
mContext(callback->context) {}
explicit Callback(const ACameraManager_ExtendedAvailabilityCallbacks *callback) :
mAvailable(callback->availabilityCallbacks.onCameraAvailable),
mUnavailable(callback->availabilityCallbacks.onCameraUnavailable),
mAccessPriorityChanged(callback->onCameraAccessPrioritiesChanged),
+ mPhysicalCamAvailable(callback->onPhysicalCameraAvailable),
+ mPhysicalCamUnavailable(callback->onPhysicalCameraUnavailable),
mContext(callback->availabilityCallbacks.context) {}
bool operator == (const Callback& other) const {
return (mAvailable == other.mAvailable &&
mUnavailable == other.mUnavailable &&
mAccessPriorityChanged == other.mAccessPriorityChanged &&
+ mPhysicalCamAvailable == other.mPhysicalCamAvailable &&
+ mPhysicalCamUnavailable == other.mPhysicalCamUnavailable &&
mContext == other.mContext);
}
bool operator != (const Callback& other) const {
@@ -124,6 +132,12 @@
bool operator < (const Callback& other) const {
if (*this == other) return false;
if (mContext != other.mContext) return mContext < other.mContext;
+ if (mPhysicalCamAvailable != other.mPhysicalCamAvailable) {
+ return mPhysicalCamAvailable < other.mPhysicalCamAvailable;
+ }
+ if (mPhysicalCamUnavailable != other.mPhysicalCamUnavailable) {
+ return mPhysicalCamUnavailable < other.mPhysicalCamUnavailable;
+ }
if (mAccessPriorityChanged != other.mAccessPriorityChanged) {
return mAccessPriorityChanged < other.mAccessPriorityChanged;
}
@@ -136,6 +150,8 @@
ACameraManager_AvailabilityCallback mAvailable;
ACameraManager_AvailabilityCallback mUnavailable;
ACameraManager_AccessPrioritiesChangedCallback mAccessPriorityChanged;
+ ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamAvailable;
+ ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable;
void* mContext;
};
std::set<Callback> mCallbacks;
@@ -144,8 +160,10 @@
enum {
kWhatSendSingleCallback,
kWhatSendSingleAccessCallback,
+ kWhatSendSinglePhysicalCameraCallback,
};
static const char* kCameraIdKey;
+ static const char* kPhysicalCameraIdKey;
static const char* kCallbackFpKey;
static const char* kContextKey;
class CallbackHandler : public AHandler {
@@ -160,6 +178,9 @@
void onCameraAccessPrioritiesChanged();
void onStatusChanged(int32_t status, const String8& cameraId);
void onStatusChangedLocked(int32_t status, const String8& cameraId);
+ void onStatusChanged(int32_t status, const String8& cameraId, const String8& physicalCameraId);
+ void onStatusChangedLocked(int32_t status, const String8& cameraId,
+ const String8& physicalCameraId);
// Utils for status
static bool validStatus(int32_t status);
static bool isStatusAvailable(int32_t status);
@@ -187,11 +208,20 @@
};
struct StatusAndHAL3Support {
+ private:
int32_t status = hardware::ICameraServiceListener::STATUS_NOT_PRESENT;
- bool supportsHAL3 = false;
+ mutable std::mutex mLock;
+ std::set<String8> unavailablePhysicalIds;
+ public:
+ const bool supportsHAL3 = false;
StatusAndHAL3Support(int32_t st, bool HAL3support):
status(st), supportsHAL3(HAL3support) { };
StatusAndHAL3Support() = default;
+
+ bool addUnavailablePhysicalId(const String8& physicalCameraId);
+ bool removeUnavailablePhysicalId(const String8& physicalCameraId);
+ int32_t getStatus();
+ void updateStatus(int32_t newStatus);
};
// Map camera_id -> status
diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h
index 2cc8a97..e2b71bf 100644
--- a/camera/ndk/include/camera/NdkCameraManager.h
+++ b/camera/ndk/include/camera/NdkCameraManager.h
@@ -123,6 +123,21 @@
const char* cameraId);
/**
+ * Definition of physical camera availability callbacks.
+ *
+ * @param context The optional application context provided by user in
+ * {@link ACameraManager_AvailabilityCallbacks}.
+ * @param cameraId The ID of the logical multi-camera device whose physical camera status is
+ * changing. The memory of this argument is owned by camera framework and will
+ * become invalid immediately after this callback returns.
+ * @param physicalCameraId The ID of the physical camera device whose status is changing. The
+ * memory of this argument is owned by camera framework and will become invalid
+ * immediately after this callback returns.
+ */
+typedef void (*ACameraManager_PhysicalCameraAvailabilityCallback)(void* context,
+ const char* cameraId, const char* physicalCameraId);
+
+/**
* A listener for camera devices becoming available or unavailable to open.
*
* <p>Cameras become available when they are no longer in use, or when a new
@@ -320,8 +335,15 @@
/// Called when there is camera access permission change
ACameraManager_AccessPrioritiesChangedCallback onCameraAccessPrioritiesChanged;
+ /// Called when a physical camera becomes available
+ ACameraManager_PhysicalCameraAvailabilityCallback onPhysicalCameraAvailable __INTRODUCED_IN(30);
+
+ /// Called when a physical camera becomes unavailable
+ ACameraManager_PhysicalCameraAvailabilityCallback onPhysicalCameraUnavailable
+ __INTRODUCED_IN(30);
+
/// Reserved for future use, please ensure that all entries are set to NULL
- void *reserved[6];
+ void *reserved[4];
} ACameraManager_ExtendedAvailabilityCallbacks;
/**
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 3ac3ded..8b371db 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -7941,14 +7941,20 @@
* <p>The camera device is a logical camera backed by two or more physical cameras.</p>
* <p>In API level 28, the physical cameras must also be exposed to the application via
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraIdList">CameraManager#getCameraIdList</a>.</p>
- * <p>Starting from API level 29, some or all physical cameras may not be independently
- * exposed to the application, in which case the physical camera IDs will not be
- * available in <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraIdList">CameraManager#getCameraIdList</a>. But the
+ * <p>Starting from API level 29:</p>
+ * <ul>
+ * <li>Some or all physical cameras may not be independently exposed to the application,
+ * in which case the physical camera IDs will not be available in
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraIdList">CameraManager#getCameraIdList</a>. But the
* application can still query the physical cameras' characteristics by calling
- * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraCharacteristics">CameraManager#getCameraCharacteristics</a>. Additionally,
- * if a physical camera is hidden from camera ID list, the mandatory stream combinations
- * for that physical camera must be supported through the logical camera using physical
- * streams.</p>
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraCharacteristics">CameraManager#getCameraCharacteristics</a>.</li>
+ * <li>If a physical camera is hidden from camera ID list, the mandatory stream
+ * combinations for that physical camera must be supported through the logical camera
+ * using physical streams. One exception is that in API level 30, a physical camera
+ * may become unavailable via
+ * {@link ACameraManager_PhysicalCameraAvailabilityCallback }
+ * callback.</li>
+ * </ul>
* <p>Combinations of logical and physical streams, or physical streams from different
* physical cameras are not guaranteed. However, if the camera device supports
* {@link ACameraDevice_isSessionConfigurationSupported },
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index cd5bdd1..571cf59 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -83,6 +83,12 @@
return binder::Status::ok();
};
+ virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
+ const String16& /*cameraId*/, const String16& /*physicalCameraId*/) {
+ // No op
+ return binder::Status::ok();
+ };
+
virtual binder::Status onTorchStatusChanged(int32_t status, const String16& cameraId) {
Mutex::Autolock l(mLock);
mCameraTorchStatuses[cameraId] = status;
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 496a21b..87cb0b5 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -117,6 +117,7 @@
"android.hardware.camera.common@1.0",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
+ "android.hardware.camera.provider@2.6",
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 2fe7179..8666b7b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -420,7 +420,52 @@
}
updateStatus(newStatus, id);
}
+}
+void CameraService::onDeviceStatusChanged(const String8& id,
+ const String8& physicalId,
+ CameraDeviceStatus newHalStatus) {
+ ALOGI("%s: Status changed for cameraId=%s, physicalCameraId=%s, newStatus=%d",
+ __FUNCTION__, id.string(), physicalId.string(), newHalStatus);
+
+ StatusInternal newStatus = mapToInternal(newHalStatus);
+
+ std::shared_ptr<CameraState> state = getCameraState(id);
+
+ if (state == nullptr) {
+ ALOGE("%s: Physical camera id %s status change on a non-present ID %s",
+ __FUNCTION__, id.string(), physicalId.string());
+ return;
+ }
+
+ StatusInternal logicalCameraStatus = state->getStatus();
+ if (logicalCameraStatus != StatusInternal::PRESENT &&
+ logicalCameraStatus != StatusInternal::NOT_AVAILABLE) {
+ ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
+ __FUNCTION__, physicalId.string(), newHalStatus, logicalCameraStatus);
+ return;
+ }
+
+ bool updated = false;
+ if (newStatus == StatusInternal::PRESENT) {
+ updated = state->removeUnavailablePhysicalId(physicalId);
+ } else {
+ updated = state->addUnavailablePhysicalId(physicalId);
+ }
+
+ if (updated) {
+ logDeviceRemoved(id, String8::format("Device %s-%s availability changed from %d to %d",
+ id.string(), physicalId.string(),
+ newStatus != StatusInternal::PRESENT,
+ newStatus == StatusInternal::PRESENT));
+
+ String16 id16(id), physicalId16(physicalId);
+ Mutex::Autolock lock(mStatusListenerLock);
+ for (auto& listener : mListenerList) {
+ listener->getListener()->onPhysicalCameraStatusChanged(mapToInterface(newStatus),
+ id16, physicalId16);
+ }
+ }
}
void CameraService::disconnectClient(const String8& id, sp<BasicClient> clientToDisconnect) {
@@ -2045,7 +2090,8 @@
{
Mutex::Autolock lock(mCameraStatesLock);
for (auto& i : mCameraStates) {
- cameraStatuses->emplace_back(i.first, mapToInterface(i.second->getStatus()));
+ cameraStatuses->emplace_back(i.first,
+ mapToInterface(i.second->getStatus()), i.second->getUnavailablePhysicalIds());
}
}
// Remove the camera statuses that should be hidden from the client, we do
@@ -3188,6 +3234,12 @@
return mStatus;
}
+std::vector<String8> CameraService::CameraState::getUnavailablePhysicalIds() const {
+ Mutex::Autolock lock(mStatusLock);
+ std::vector<String8> res(mUnavailablePhysicalIds.begin(), mUnavailablePhysicalIds.end());
+ return res;
+}
+
CameraParameters CameraService::CameraState::getShimParams() const {
return mShimParams;
}
@@ -3212,6 +3264,18 @@
return mSystemCameraKind;
}
+bool CameraService::CameraState::addUnavailablePhysicalId(const String8& physicalId) {
+ Mutex::Autolock lock(mStatusLock);
+ auto result = mUnavailablePhysicalIds.insert(physicalId);
+ return result.second;
+}
+
+bool CameraService::CameraState::removeUnavailablePhysicalId(const String8& physicalId) {
+ Mutex::Autolock lock(mStatusLock);
+ auto count = mUnavailablePhysicalIds.erase(physicalId);
+ return count > 0;
+}
+
// ----------------------------------------------------------------------------
// ClientEventListener
// ----------------------------------------------------------------------------
@@ -3569,7 +3633,7 @@
return;
}
// Update the status for this camera state, then send the onStatusChangedCallbacks to each
- // of the listeners with both the mStatusStatus and mStatusListenerLock held
+ // of the listeners with both the mStatusLock and mStatusListenerLock held
state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind, &supportsHAL3]
(const String8& cameraId, StatusInternal status) {
@@ -3591,6 +3655,8 @@
Mutex::Autolock lock(mStatusListenerLock);
+ notifyPhysicalCameraStatusLocked(mapToInterface(status), cameraId);
+
for (auto& listener : mListenerList) {
bool isVendorListener = listener->isVendorListener();
if (shouldSkipStatusUpdates(deviceKind, isVendorListener,
@@ -3684,6 +3750,28 @@
return OK;
}
+void CameraService::notifyPhysicalCameraStatusLocked(int32_t status, const String8& cameraId) {
+ Mutex::Autolock lock(mCameraStatesLock);
+ for (const auto& state : mCameraStates) {
+ std::vector<std::string> physicalCameraIds;
+ if (!mCameraProviderManager->isLogicalCamera(state.first.c_str(), &physicalCameraIds)) {
+ // This is not a logical multi-camera.
+ continue;
+ }
+ if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(), cameraId.c_str())
+ == physicalCameraIds.end()) {
+ // cameraId is not a physical camera of this logical multi-camera.
+ continue;
+ }
+
+ String16 id16(state.first), physicalId16(cameraId);
+ for (auto& listener : mListenerList) {
+ listener->getListener()->onPhysicalCameraStatusChanged(status,
+ id16, physicalId16);
+ }
+ }
+}
+
void CameraService::blockClientsForUid(uid_t uid) {
const auto clients = mActiveClientManager.getAll();
for (auto& current : clients) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 726cb0f..34b970d 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -103,6 +103,9 @@
virtual void onDeviceStatusChanged(const String8 &cameraId,
hardware::camera::common::V1_0::CameraDeviceStatus newHalStatus) override;
+ virtual void onDeviceStatusChanged(const String8 &cameraId,
+ const String8 &physicalCameraId,
+ hardware::camera::common::V1_0::CameraDeviceStatus newHalStatus) override;
virtual void onTorchStatusChanged(const String8& cameraId,
hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
virtual void onNewProviderRegistered() override;
@@ -556,11 +559,24 @@
*/
SystemCameraKind getSystemCameraKind() const;
+ /**
+ * Add/Remove the unavailable physical camera ID.
+ */
+ bool addUnavailablePhysicalId(const String8& physicalId);
+ bool removeUnavailablePhysicalId(const String8& physicalId);
+
+ /**
+ * Return the unavailable physical ids for this device.
+ *
+ * This method acquires mStatusLock.
+ */
+ std::vector<String8> getUnavailablePhysicalIds() const;
private:
const String8 mId;
StatusInternal mStatus; // protected by mStatusLock
const int mCost;
std::set<String8> mConflicting;
+ std::set<String8> mUnavailablePhysicalIds;
mutable Mutex mStatusLock;
CameraParameters mShimParams;
const SystemCameraKind mSystemCameraKind;
@@ -962,6 +978,9 @@
status_t setTorchStatusLocked(const String8 &cameraId,
hardware::camera::common::V1_0::TorchModeStatus status);
+ // notify physical camera status when the physical camera is public.
+ void notifyPhysicalCameraStatusLocked(int32_t status, const String8& cameraId);
+
// IBinder::DeathRecipient implementation
virtual void binderDied(const wp<IBinder> &who);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 0f74a48..57f812f 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1255,20 +1255,6 @@
mMinorVersion = 4;
}
- // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
- // before setCallback returns
- hardware::Return<Status> status = interface->setCallback(this);
- if (!status.isOk()) {
- ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
- __FUNCTION__, mProviderName.c_str(), status.description().c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to register callbacks with camera provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return mapToStatusT(status);
- }
-
hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
if (!linked.isOk()) {
ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
@@ -1297,6 +1283,7 @@
return res;
}
+ Status status;
// Get initial list of camera devices, if any
std::vector<std::string> devices;
hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
@@ -1353,6 +1340,22 @@
}
}
+ // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
+ // before setCallback returns. setCallback must be called after addDevice so that
+ // the physical camera status callback can look up available regular
+ // cameras.
+ hardware::Return<Status> st = interface->setCallback(this);
+ if (!st.isOk()) {
+ ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), st.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (st != Status::OK) {
+ ALOGE("%s: Unable to register callbacks with camera provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(st);
+ }
+
ALOGI("Camera provider %s ready with %zu camera devices",
mProviderName.c_str(), mDevices.size());
@@ -1604,6 +1607,61 @@
return hardware::Void();
}
+hardware::Return<void> CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ const hardware::hidl_string& physicalCameraDeviceName,
+ CameraDeviceStatus newStatus) {
+ sp<StatusListener> listener;
+ std::string id;
+ bool initialized = false;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ bool known = false;
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ id = deviceInfo->mId;
+
+ if (!deviceInfo->mIsLogicalCamera) {
+ ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+ __FUNCTION__, id.c_str(), physicalCameraDeviceName.c_str());
+ return hardware::Void();
+ }
+ if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
+ physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
+ ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+ __FUNCTION__, id.c_str(), physicalCameraDeviceName.c_str());
+ return hardware::Void();
+ }
+ ALOGI("Camera device %s physical device %s status is now %s, was %s",
+ cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
+ deviceStatusToString(newStatus), deviceStatusToString(
+ deviceInfo->mPhysicalStatus[physicalCameraDeviceName]));
+ known = true;
+ break;
+ }
+ }
+ // Previously unseen device; status must not be NOT_PRESENT
+ if (!known) {
+ ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str(),
+ physicalCameraDeviceName.c_str());
+ return hardware::Void();
+ }
+ listener = mManager->getStatusListener();
+ initialized = mInitialized;
+ }
+ // Call without lock held to allow reentrancy into provider manager
+ // Don't send the callback if providerInfo hasn't been initialized.
+ // CameraService will initialize device status after provider is
+ // initialized
+ if (listener != nullptr && initialized) {
+ String8 physicalId(physicalCameraDeviceName.c_str());
+ listener->onDeviceStatusChanged(String8(id.c_str()),
+ physicalId, newStatus);
+ }
+ return hardware::Void();
+}
+
hardware::Return<void> CameraProviderManager::ProviderInfo::torchModeStatusChange(
const hardware::hidl_string& cameraDeviceName,
TorchModeStatus newStatus) {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 58df0e8..3eba162 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -29,6 +29,7 @@
#include <utils/Errors.h>
#include <android/hardware/camera/common/1.0/types.h>
#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
+#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
#include <android/hidl/manager/1.0/IServiceNotification.h>
#include <camera/VendorTagDescriptor.h>
@@ -136,6 +137,9 @@
virtual void onDeviceStatusChanged(const String8 &cameraId,
hardware::camera::common::V1_0::CameraDeviceStatus newStatus) = 0;
+ virtual void onDeviceStatusChanged(const String8 &cameraId,
+ const String8 &physicalCameraId,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) = 0;
virtual void onTorchStatusChanged(const String8 &cameraId,
hardware::camera::common::V1_0::TorchModeStatus newStatus) = 0;
virtual void onNewProviderRegistered() = 0;
@@ -342,7 +346,7 @@
std::mutex mProviderInterfaceMapLock;
struct ProviderInfo :
- virtual public hardware::camera::provider::V2_4::ICameraProviderCallback,
+ virtual public hardware::camera::provider::V2_6::ICameraProviderCallback,
virtual public hardware::hidl_death_recipient
{
const std::string mProviderName;
@@ -380,12 +384,16 @@
status_t dump(int fd, const Vector<String16>& args) const;
// ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
- virtual hardware::Return<void> cameraDeviceStatusChange(
+ hardware::Return<void> cameraDeviceStatusChange(
const hardware::hidl_string& cameraDeviceName,
hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
- virtual hardware::Return<void> torchModeStatusChange(
+ hardware::Return<void> torchModeStatusChange(
const hardware::hidl_string& cameraDeviceName,
hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
+ hardware::Return<void> physicalCameraDeviceStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ const hardware::hidl_string& physicalCameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
// hidl_death_recipient interface - this locks the parent mInterfaceMutex
virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
@@ -417,6 +425,8 @@
const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
+ std::map<std::string, hardware::camera::common::V1_0::CameraDeviceStatus>
+ mPhysicalStatus;
sp<ProviderInfo> mParentProvider;
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
index 0f6be79..175eb8e 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
@@ -46,12 +46,18 @@
~H2BCameraServiceListener() { }
virtual ::android::binder::Status onStatusChanged(int32_t status,
- const ::android::String16& cameraId) override;
+ const ::android::String16& cameraId) override;
+ virtual ::android::binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
+ const ::android::String16& /*cameraId*/,
+ const ::android::String16& /*physicalCameraId*/) override {
+ // no implementation yet.
+ return binder::Status::ok();
+ }
virtual ::android::binder::Status onTorchStatusChanged(
- int32_t status, const ::android::String16& cameraId) override;
+ int32_t status, const ::android::String16& cameraId) override;
virtual binder::Status onCameraAccessPrioritiesChanged() {
- // TODO: no implementation yet.
+ // TODO: no implementation yet. b/148146086
return binder::Status::ok();
}
};
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index ec5e876..ea4eb3b 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -31,6 +31,7 @@
android.hardware.camera.common@1.0 \
android.hardware.camera.provider@2.4 \
android.hardware.camera.provider@2.5 \
+ android.hardware.camera.provider@2.6 \
android.hardware.camera.device@1.0 \
android.hardware.camera.device@3.2 \
android.hardware.camera.device@3.4
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index 084dc62..a8f6889 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -236,6 +236,8 @@
void onDeviceStatusChanged(const String8 &,
hardware::camera::common::V1_0::CameraDeviceStatus) override {}
+ void onDeviceStatusChanged(const String8 &, const String8 &,
+ hardware::camera::common::V1_0::CameraDeviceStatus) override {}
void onTorchStatusChanged(const String8 &,
hardware::camera::common::V1_0::TorchModeStatus) override {}
void onNewProviderRegistered() override {}