diff --git a/camera/Camera.cpp b/camera/Camera.cpp index c6c35efcff..19849f8d68 100644 --- a/camera/Camera.cpp +++ b/camera/Camera.cpp @@ -347,6 +347,13 @@ status_t Camera::setPreviewCallbackTarget( 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 f0945c7cf4..060e8e06a8 100644 --- a/camera/ICamera.cpp +++ b/camera/ICamera.cpp @@ -56,6 +56,7 @@ enum { SET_VIDEO_BUFFER_TARGET, RELEASE_RECORDING_FRAME_HANDLE, RELEASE_RECORDING_FRAME_HANDLE_BATCH, + SET_AUDIO_RESTRICTION, }; class BpCamera: public BpInterface @@ -191,6 +192,14 @@ public: } } + 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 @@ status_t BnCamera::onTransact( 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 49dfde8ac5..5987b4231c 100644 --- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl +++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl @@ -155,4 +155,20 @@ interface ICameraDeviceUser 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 430aa1c959..9800bb747f 100644 --- a/camera/include/camera/Camera.h +++ b/camera/include/camera/Camera.h @@ -167,6 +167,8 @@ public: sp 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& dataPtr, diff --git a/camera/include/camera/android/hardware/ICamera.h b/camera/include/camera/android/hardware/ICamera.h index 80823d6ccd..eba9efec52 100644 --- a/camera/include/camera/android/hardware/ICamera.h +++ b/camera/include/camera/android/hardware/ICamera.h @@ -140,6 +140,9 @@ public: // Set the video buffer producer for camera to use in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode. virtual status_t setVideoTarget( const sp& 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 9a91ea0689..9ba6553acb 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -135,7 +135,8 @@ sp CameraService::sCameraServiceProxy; 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(&mServiceLock); } @@ -164,6 +165,7 @@ void CameraService::onFirstRef() mUidPolicy->registerSelf(); mSensorPrivacyPolicy = new SensorPrivacyPolicy(this); mSensorPrivacyPolicy->registerSelf(); + mAppOps.setCameraAudioRestriction(mAudioRestriction); sp 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 @@ void CameraService::removeByClient(const BasicClient* client) { mActiveClientManager.remove(i); } } + updateAudioRestrictionLocked(); } bool CameraService::evictClientIdByRemote(const wp& remote) { @@ -2400,6 +2403,7 @@ CameraService::BasicClient::BasicClient(const sp& cameraService, 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 @@ bool CameraService::BasicClient::canCastToApiClient(apiLevel level) const { 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 @@ status_t CameraService::printHelp(int out) { " 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 67829dd5fc..df8c17c88b 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -258,6 +258,14 @@ public: // 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, const sp& remoteCallback, @@ -286,6 +294,9 @@ public: const pid_t mServicePid; bool mDisconnected; + mutable Mutex mAudioRestrictionLock; + int32_t mAudioRestriction; + // - The app-side Binder interface to receive callbacks from us sp mRemoteBinder; // immutable after constructor @@ -439,6 +450,9 @@ public: }; // class CameraClientManager + int32_t updateAudioRestriction(); + int32_t updateAudioRestrictionLocked(); + private: typedef hardware::camera::common::V1_0::CameraDeviceStatus CameraDeviceStatus; @@ -966,6 +980,13 @@ private: 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 162b50f5ce..eb599e06c4 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -2253,6 +2253,12 @@ status_t Camera2Client::setVideoTarget(const sp& bufferP 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 a9ea271dd1..8df8d2b5cc 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.h +++ b/services/camera/libcameraservice/api1/Camera2Client.h @@ -83,6 +83,7 @@ public: virtual void notifyError(int32_t errorCode, const CaptureResultExtras& resultExtras); virtual status_t setVideoTarget(const sp& 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 d65ac7b339..089f6cfc7f 100644 --- a/services/camera/libcameraservice/api1/CameraClient.cpp +++ b/services/camera/libcameraservice/api1/CameraClient.cpp @@ -1171,4 +1171,18 @@ status_t CameraClient::setVideoTarget(const sp& bufferPr 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 9530b6c4a9..fefa8c900c 100644 --- a/services/camera/libcameraservice/api1/CameraClient.h +++ b/services/camera/libcameraservice/api1/CameraClient.h @@ -59,6 +59,7 @@ public: virtual String8 getParameters() const; virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2); virtual status_t setVideoTarget(const sp& bufferProducer); + virtual int32_t setAudioRestriction(int mode); // Interface used by CameraService CameraClient(const sp& cameraService, diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp index c7a4f2bfad..be188bcee9 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp @@ -1870,6 +1870,26 @@ binder::Status CameraDeviceClient::finalizeOutputConfigurations(int32_t streamId 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& args) { return BasicClient::dump(fd, args); } diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h index 1c5abb034d..a9aa190cf1 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.h +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h @@ -152,6 +152,10 @@ public: 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 */