Camera: implement camera audio restriction API
Test: new CTS test
Bug: 135676184
Change-Id: I5f26e343a4ee92b66fabfaa6bda94224ae311c40
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index c6c35ef..19849f8 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -347,6 +347,13 @@
return c->setPreviewCallbackTarget(callbackProducer);
}
+int32_t Camera::setAudioRestriction(int32_t mode)
+{
+ sp <::android::hardware::ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->setAudioRestriction(mode);
+}
+
// callback from camera service
void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
{
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index f0945c7..060e8e0 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -56,6 +56,7 @@
SET_VIDEO_BUFFER_TARGET,
RELEASE_RECORDING_FRAME_HANDLE,
RELEASE_RECORDING_FRAME_HANDLE_BATCH,
+ SET_AUDIO_RESTRICTION,
};
class BpCamera: public BpInterface<ICamera>
@@ -191,6 +192,14 @@
}
}
+ int32_t setAudioRestriction(int32_t mode) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeInt32(mode);
+ remote()->transact(SET_AUDIO_RESTRICTION, data, &reply);
+ return reply.readInt32();
+ }
+
status_t setVideoBufferMode(int32_t videoBufferMode)
{
ALOGV("setVideoBufferMode: %d", videoBufferMode);
@@ -494,6 +503,12 @@
reply->writeInt32(setVideoTarget(st));
return NO_ERROR;
} break;
+ case SET_AUDIO_RESTRICTION: {
+ CHECK_INTERFACE(ICamera, data, reply);
+ int32_t mode = data.readInt32();
+ reply->writeInt32(setAudioRestriction(mode));
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 49dfde8..5987b42 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -155,4 +155,20 @@
void updateOutputConfiguration(int streamId, in OutputConfiguration outputConfiguration);
void finalizeOutputConfigurations(int streamId, in OutputConfiguration outputConfiguration);
+
+
+ // Keep in sync with public API in
+ // frameworks/base/core/java/android/hardware/camera2/CameraDevice.java
+ const int AUDIO_RESTRICTION_NONE = 0;
+ const int AUDIO_RESTRICTION_VIBRATION = 1;
+ const int AUDIO_RESTRICTION_VIBRATION_SOUND = 3;
+
+ /**
+ * Set audio restriction mode for this camera device.
+ *
+ * @param mode the audio restriction mode ID as above
+ *
+ * @return the resulting system-wide audio restriction mode
+ */
+ int setCameraAudioRestriction(int mode);
}
diff --git a/camera/include/camera/Camera.h b/camera/include/camera/Camera.h
index 430aa1c..9800bb7 100644
--- a/camera/include/camera/Camera.h
+++ b/camera/include/camera/Camera.h
@@ -167,6 +167,8 @@
sp<ICameraRecordingProxy> getRecordingProxy();
+ int32_t setAudioRestriction(int32_t mode);
+
// ICameraClient interface
virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
diff --git a/camera/include/camera/android/hardware/ICamera.h b/camera/include/camera/android/hardware/ICamera.h
index 80823d6..eba9efe 100644
--- a/camera/include/camera/android/hardware/ICamera.h
+++ b/camera/include/camera/android/hardware/ICamera.h
@@ -140,6 +140,9 @@
// Set the video buffer producer for camera to use in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
virtual status_t setVideoTarget(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
+
+ // Set the audio restriction mode
+ virtual int32_t setAudioRestriction(int32_t mode) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 9a91ea0..9ba6553 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -135,7 +135,8 @@
CameraService::CameraService() :
mEventLog(DEFAULT_EVENT_LOG_LENGTH),
mNumberOfCameras(0),
- mSoundRef(0), mInitialized(false) {
+ mSoundRef(0), mInitialized(false),
+ mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) {
ALOGI("CameraService started (pid=%d)", getpid());
mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
}
@@ -164,6 +165,7 @@
mUidPolicy->registerSelf();
mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
mSensorPrivacyPolicy->registerSelf();
+ mAppOps.setCameraAudioRestriction(mAudioRestriction);
sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
if (hcs->registerAsService() != android::OK) {
ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0",
@@ -2027,6 +2029,7 @@
mActiveClientManager.remove(i);
}
}
+ updateAudioRestrictionLocked();
}
bool CameraService::evictClientIdByRemote(const wp<IBinder>& remote) {
@@ -2400,6 +2403,7 @@
mClientPackageName(clientPackageName), mClientPid(clientPid), mClientUid(clientUid),
mServicePid(servicePid),
mDisconnected(false),
+ mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
mRemoteBinder(remoteCallback)
{
if (sCameraService == nullptr) {
@@ -2503,6 +2507,30 @@
return level == API_2;
}
+int32_t CameraService::BasicClient::setAudioRestriction(int32_t mode) {
+ {
+ Mutex::Autolock l(mAudioRestrictionLock);
+ mAudioRestriction = mode;
+ }
+ return sCameraService->updateAudioRestriction();
+}
+
+int32_t CameraService::BasicClient::getAudioRestriction() const {
+ Mutex::Autolock l(mAudioRestrictionLock);
+ return mAudioRestriction;
+}
+
+bool CameraService::BasicClient::isValidAudioRestriction(int32_t mode) {
+ switch (mode) {
+ case hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE:
+ case hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_VIBRATION:
+ case hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_VIBRATION_SOUND:
+ return true;
+ default:
+ return false;
+ }
+}
+
status_t CameraService::BasicClient::startCameraOps() {
ATRACE_CALL();
@@ -3532,4 +3560,25 @@
" help print this message\n");
}
+int32_t CameraService::updateAudioRestriction() {
+ Mutex::Autolock lock(mServiceLock);
+ return updateAudioRestrictionLocked();
+}
+
+int32_t CameraService::updateAudioRestrictionLocked() {
+ int32_t mode = 0;
+ // iterate through all active client
+ for (const auto& i : mActiveClientManager.getAll()) {
+ const auto clientSp = i->getValue();
+ mode |= clientSp->getAudioRestriction();
+ }
+
+ bool modeChanged = (mAudioRestriction != mode);
+ mAudioRestriction = mode;
+ if (modeChanged) {
+ mAppOps.setCameraAudioRestriction(mode);
+ }
+ return mode;
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 67829dd..df8c17c 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -258,6 +258,14 @@
// Block the client form using the camera
virtual void block();
+
+ // set audio restriction from client
+ // Will call into camera service and hold mServiceLock
+ virtual int32_t setAudioRestriction(int32_t mode);
+
+ virtual int32_t getAudioRestriction() const;
+
+ static bool isValidAudioRestriction(int32_t mode);
protected:
BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
@@ -286,6 +294,9 @@
const pid_t mServicePid;
bool mDisconnected;
+ mutable Mutex mAudioRestrictionLock;
+ int32_t mAudioRestriction;
+
// - The app-side Binder interface to receive callbacks from us
sp<IBinder> mRemoteBinder; // immutable after constructor
@@ -439,6 +450,9 @@
}; // class CameraClientManager
+ int32_t updateAudioRestriction();
+ int32_t updateAudioRestrictionLocked();
+
private:
typedef hardware::camera::common::V1_0::CameraDeviceStatus CameraDeviceStatus;
@@ -966,6 +980,13 @@
void broadcastTorchModeStatus(const String8& cameraId,
hardware::camera::common::V1_0::TorchModeStatus status);
+
+ // TODO: right now each BasicClient holds one AppOpsManager instance.
+ // We can refactor the code so all of clients share this instance
+ AppOpsManager mAppOps;
+
+ // Aggreated audio restriction mode for all camera clients
+ int32_t mAudioRestriction;
};
} // namespace android
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 162b50f..eb599e0 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -2253,6 +2253,12 @@
return OK;
}
+int32_t Camera2Client::setAudioRestriction(int /*mode*/) {
+ // Empty implementation. setAudioRestriction is hidden interface and not
+ // supported by android.hardware.Camera API
+ return INVALID_OPERATION;
+}
+
const char* Camera2Client::kAutofocusLabel = "autofocus";
const char* Camera2Client::kTakepictureLabel = "take_picture";
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index a9ea271..8df8d2b 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -83,6 +83,7 @@
virtual void notifyError(int32_t errorCode,
const CaptureResultExtras& resultExtras);
virtual status_t setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer);
+ virtual int32_t setAudioRestriction(int mode);
/**
* Interface used by CameraService
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index d65ac7b..089f6cf 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -1171,4 +1171,18 @@
return INVALID_OPERATION;
}
+int32_t CameraClient::setAudioRestriction(int mode) {
+ if (!isValidAudioRestriction(mode)) {
+ ALOGE("%s: invalid audio restriction mode %d", __FUNCTION__, mode);
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+ return BasicClient::setAudioRestriction(mode);
+}
+
+
}; // namespace android
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 9530b6c..fefa8c9 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -59,6 +59,7 @@
virtual String8 getParameters() const;
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
virtual status_t setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer);
+ virtual int32_t setAudioRestriction(int mode);
// Interface used by CameraService
CameraClient(const sp<CameraService>& cameraService,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index c7a4f2b..be188bc 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1870,6 +1870,26 @@
return res;
}
+binder::Status CameraDeviceClient::setCameraAudioRestriction(int32_t mode,
+ /*out*/ int32_t* outMode) {
+ ATRACE_CALL();
+ binder::Status res;
+ if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+ if (!isValidAudioRestriction(mode)) {
+ String8 msg = String8::format("Camera %s: invalid audio restriction mode %d",
+ mCameraIdStr.string(), mode);
+ ALOGW("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
+
+ Mutex::Autolock icl(mBinderSerializationLock);
+ if (outMode != nullptr) {
+ *outMode = BasicClient::setAudioRestriction(mode);
+ }
+ return binder::Status::ok();
+}
+
status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
return BasicClient::dump(fd, args);
}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 1c5abb0..a9aa190 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -152,6 +152,10 @@
virtual binder::Status finalizeOutputConfigurations(int32_t streamId,
const hardware::camera2::params::OutputConfiguration &outputConfiguration) override;
+ virtual binder::Status setCameraAudioRestriction(int32_t mode,
+ /*out*/
+ int32_t* outMode = NULL) override;
+
/**
* Interface used by CameraService
*/