Merge "CameraSource: Remove CHECK if set preview target fails with CameraSource" into tm-dev
diff --git a/camera/aidl/android/hardware/ICameraServiceProxy.aidl b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
index f5d0120..88783fb 100644
--- a/camera/aidl/android/hardware/ICameraServiceProxy.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
@@ -44,4 +44,9 @@
* {@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_270}).
*/
int getRotateAndCropOverride(String packageName, int lensFacing, int userId);
+
+ /**
+ * Checks if the camera has been disabled via device policy.
+ */
+ boolean isCameraDisabled();
}
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 9a7b9c1..02e7114 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -70,6 +70,7 @@
dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL;
record_config_callback AudioSystem::gRecordConfigCallback = NULL;
routing_callback AudioSystem::gRoutingCallback = NULL;
+vol_range_init_req_callback AudioSystem::gVolRangeInitReqCallback = NULL;
// Required to be held while calling into gSoundTriggerCaptureStateListener.
class CaptureStateListenerImpl;
@@ -781,6 +782,11 @@
gRoutingCallback = cb;
}
+/*static*/ void AudioSystem::setVolInitReqCallback(vol_range_init_req_callback cb) {
+ Mutex::Autolock _l(gLock);
+ gVolRangeInitReqCallback = cb;
+}
+
// client singleton for AudioPolicyService binder interface
// protected by gLockAPS
sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
@@ -2574,6 +2580,19 @@
return Status::ok();
}
+Status AudioSystem::AudioPolicyServiceClient::onVolumeRangeInitRequest() {
+ vol_range_init_req_callback cb = NULL;
+ {
+ Mutex::Autolock _l(AudioSystem::gLock);
+ cb = gVolRangeInitReqCallback;
+ }
+
+ if (cb != NULL) {
+ cb();
+ }
+ return Status::ok();
+}
+
void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused) {
{
Mutex::Autolock _l(mLock);
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
index d93a59d..c0cdd96 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
@@ -46,4 +46,7 @@
AudioSource source);
/** Notifies a change of audio routing */
void onRoutingUpdated();
+ /** Notifies a request for volume index ranges to be reset after they were observed as invalid
+ */
+ void onVolumeRangeInitRequest();
}
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 1cc22a0..b5b9277 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -77,6 +77,7 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
typedef void (*routing_callback)();
+typedef void (*vol_range_init_req_callback)();
class IAudioFlinger;
class String8;
@@ -154,6 +155,7 @@
static void setDynPolicyCallback(dynamic_policy_callback cb);
static void setRecordConfigCallback(record_config_callback);
static void setRoutingCallback(routing_callback cb);
+ static void setVolInitReqCallback(vol_range_init_req_callback cb);
// Sets the binder to use for accessing the AudioFlinger service. This enables the system server
// to grant specific isolated processes access to the audio system. Currently used only for the
@@ -736,6 +738,7 @@
int32_t patchHandle,
media::audio::common::AudioSource source) override;
binder::Status onRoutingUpdated();
+ binder::Status onVolumeRangeInitRequest();
private:
Mutex mLock;
@@ -763,6 +766,7 @@
static dynamic_policy_callback gDynPolicyCallback;
static record_config_callback gRecordConfigCallback;
static routing_callback gRoutingCallback;
+ static vol_range_init_req_callback gVolRangeInitReqCallback;
static size_t gInBuffSize;
// previous parameters for recording buffer size queries
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 20d0523..496591a 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -533,6 +533,10 @@
virtual void onRoutingUpdated() = 0;
+ // Used to notify AudioService that an error was encountering when reading
+ // the volume ranges, and that they should be re-initialized
+ virtual void onVolumeRangeInitRequest() = 0;
+
// Used to notify the sound trigger module that an audio capture is about to
// take place. This should typically result in any active recognition
// sessions to be preempted on modules that do not support sound trigger
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 49a0dde..ddc72f6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2118,11 +2118,15 @@
// apply volume rules for current stream and device if necessary
auto &curves = getVolumeCurves(client->attributes());
- checkAndSetVolume(curves, client->volumeSource(),
+ if (NO_ERROR != checkAndSetVolume(curves, client->volumeSource(),
curves.getVolumeIndex(outputDesc->devices().types()),
outputDesc,
outputDesc->devices().types(), 0 /*delay*/,
- outputDesc->useHwGain() /*force*/);
+ outputDesc->useHwGain() /*force*/)) {
+ // request AudioService to reinitialize the volume curves asynchronously
+ ALOGE("checkAndSetVolume failed, requesting volume range init");
+ mpClientInterface->onVolumeRangeInitRequest();
+ };
// update the outputs if starting an output with a stream that can affect notification
// routing
@@ -7290,6 +7294,11 @@
deviceTypes = outputDesc->devices().types();
}
+ if (curves.getVolumeIndexMin() < 0 || curves.getVolumeIndexMax() < 0) {
+ ALOGE("invalid volume index range");
+ return BAD_VALUE;
+ }
+
float volumeDb = computeVolume(curves, volumeSource, index, deviceTypes);
if (outputDesc->isFixedVolume(deviceTypes) ||
// Force VoIP volume to max for bluetooth SCO device except if muted
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 63a1e71..c766a15 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -277,6 +277,11 @@
mAudioPolicyService->onRoutingUpdated();
}
+void AudioPolicyService::AudioPolicyClient::onVolumeRangeInitRequest()
+{
+ mAudioPolicyService->onVolumeRangeInitRequest();
+}
+
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use)
{
return AudioSystem::newAudioUniqueId(use);
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 18339b0..e7d945f 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -488,6 +488,19 @@
}
}
+void AudioPolicyService::onVolumeRangeInitRequest()
+{
+ mOutputCommandThread->volRangeInitReqCommand();
+}
+
+void AudioPolicyService::doOnVolumeRangeInitRequest()
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onVolumeRangeInitRequest();
+ }
+}
+
void AudioPolicyService::onCheckSpatializer()
{
Mutex::Autolock _l(mLock);
@@ -721,6 +734,13 @@
}
}
+void AudioPolicyService::NotificationClient::onVolumeRangeInitRequest()
+{
+ if (mAudioPolicyServiceClient != 0 && isServiceUid(mUid)) {
+ mAudioPolicyServiceClient->onVolumeRangeInitRequest();
+ }
+}
+
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
IPCThreadState::self()->getCallingPid());
@@ -2161,6 +2181,17 @@
mLock.lock();
} break;
+ case VOL_RANGE_INIT_REQUEST: {
+ ALOGV("AudioCommandThread() processing volume range init request");
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnVolumeRangeInitRequest();
+ mLock.lock();
+ } break;
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -2485,6 +2516,14 @@
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::volRangeInitReqCommand()
+{
+ sp<AudioCommand>command = new AudioCommand();
+ command->mCommand = VOL_RANGE_INIT_REQUEST;
+ ALOGV("AudioCommandThread() adding volume range init request");
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
@@ -2652,6 +2691,10 @@
} break;
+ case VOL_RANGE_INIT_REQUEST: {
+ // command may come from different requests, do not filter
+ } break;
+
default:
break;
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index d863ff1..3a08cf8 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -343,6 +343,9 @@
void onRoutingUpdated();
void doOnRoutingUpdated();
+ void onVolumeRangeInitRequest();
+ void doOnVolumeRangeInitRequest();
+
/**
* Spatializer SpatializerPolicyCallback implementation.
* onCheckSpatializer() sends an event on mOutputCommandThread which executes
@@ -530,7 +533,8 @@
ROUTING_UPDATED,
UPDATE_UID_STATES,
CHECK_SPATIALIZER_OUTPUT, // verify if spatializer effect should be created or moved
- UPDATE_ACTIVE_SPATIALIZER_TRACKS // Update active track counts on spalializer output
+ UPDATE_ACTIVE_SPATIALIZER_TRACKS, // Update active track counts on spalializer output
+ VOL_RANGE_INIT_REQUEST, // request to reset the volume range indices
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -581,6 +585,7 @@
void updateUidStatesCommand();
void checkSpatializerCommand();
void updateActiveSpatializerTracksCommand();
+ void volRangeInitReqCommand();
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
@@ -803,6 +808,8 @@
virtual void onRoutingUpdated();
+ virtual void onVolumeRangeInitRequest();
+
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
void setSoundTriggerCaptureState(bool active) override;
@@ -842,6 +849,7 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
void onRoutingUpdated();
+ void onVolumeRangeInitRequest();
void setAudioPortCallbacksEnabled(bool enabled);
void setAudioVolumeGroupCallbacksEnabled(bool enabled);
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index adef8f1..057fa58 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -138,7 +138,12 @@
}
size_t getRoutingUpdatedCounter() const {
- return mRoutingUpdatedUpdateCount; }
+ return mRoutingUpdatedUpdateCount;
+ }
+
+ void onVolumeRangeInitRequest() override {
+
+ }
status_t updateSecondaryOutputs(
const TrackSecondaryOutputsMap& trackSecondaryOutputs __unused) override {
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index da85658..8a85fee 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -85,6 +85,7 @@
audio_patch_handle_t patchHandle __unused,
audio_source_t source __unused) override { }
void onRoutingUpdated() override { }
+ void onVolumeRangeInitRequest() override { }
void setEffectSuspended(int effectId __unused,
audio_session_t sessionId __unused,
bool suspended __unused) {}
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 47594c3..9bacaf4 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -42,6 +42,7 @@
srcs: [
"CameraService.cpp",
+ "CameraServiceWatchdog.cpp",
"CameraFlashlight.cpp",
"common/Camera2ClientBase.cpp",
"common/CameraDeviceBase.cpp",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a965080..741138e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1688,6 +1688,13 @@
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
}
+ if (CameraServiceProxyWrapper::isCameraDisabled()) {
+ String8 msg =
+ String8::format("Camera disabled by device policy");
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(ERROR_DISABLED, msg.string());
+ }
+
// enforce system camera permissions
if (oomScoreOffset > 0 &&
!hasPermissionsForSystemCamera(callingPid, CameraThreadState::getCallingUid())) {
@@ -3717,21 +3724,10 @@
void CameraService::UidPolicy::onUidStateChanged(uid_t uid, int32_t procState,
int64_t procStateSeq __unused, int32_t capability __unused) {
- bool procStateChange = false;
- {
- Mutex::Autolock _l(mUidLock);
- if (mMonitoredUids.find(uid) != mMonitoredUids.end() &&
- mMonitoredUids[uid].procState != procState) {
- mMonitoredUids[uid].procState = procState;
- procStateChange = true;
- }
- }
-
- if (procStateChange) {
- sp<CameraService> service = mService.promote();
- if (service != nullptr) {
- service->notifyMonitoredUids();
- }
+ Mutex::Autolock _l(mUidLock);
+ if (mMonitoredUids.find(uid) != mMonitoredUids.end() &&
+ mMonitoredUids[uid].procState != procState) {
+ mMonitoredUids[uid].procState = procState;
}
}
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.cpp b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
new file mode 100644
index 0000000..fcd6ebe
--- /dev/null
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CameraServiceWatchdog"
+
+#include "CameraServiceWatchdog.h"
+
+namespace android {
+
+bool CameraServiceWatchdog::threadLoop()
+{
+ {
+ AutoMutex _l(mWatchdogLock);
+
+ while (mPause) {
+ mWatchdogCondition.wait(mWatchdogLock);
+ }
+ }
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(mCycleLengthMs));
+
+ {
+ AutoMutex _l(mWatchdogLock);
+
+ for (auto it = tidToCycleCounterMap.begin(); it != tidToCycleCounterMap.end(); it++) {
+ uint32_t currentThreadId = it->first;
+
+ tidToCycleCounterMap[currentThreadId]++;
+
+ if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) {
+ ALOGW("CameraServiceWatchdog triggering kill for pid: %d", getpid());
+ kill(getpid(), SIGKILL);
+ }
+ }
+ }
+
+ return true;
+}
+
+void CameraServiceWatchdog::requestExit()
+{
+ Thread::requestExit();
+
+ AutoMutex _l(mWatchdogLock);
+
+ tidToCycleCounterMap.clear();
+
+ if (mPause) {
+ mPause = false;
+ mWatchdogCondition.signal();
+ }
+}
+
+void CameraServiceWatchdog::stop(uint32_t tid)
+{
+ AutoMutex _l(mWatchdogLock);
+
+ tidToCycleCounterMap.erase(tid);
+
+ if (tidToCycleCounterMap.empty()) {
+ mPause = true;
+ }
+}
+
+void CameraServiceWatchdog::start(uint32_t tid)
+{
+ AutoMutex _l(mWatchdogLock);
+
+ tidToCycleCounterMap[tid] = 0;
+
+ if (mPause) {
+ mPause = false;
+ mWatchdogCondition.signal();
+ }
+}
+
+} // namespace android
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
new file mode 100644
index 0000000..f4955e2
--- /dev/null
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The CameraService watchdog is used to help detect bad states in the
+ * Camera HAL. The threadloop uses cycle counters, assigned to each calling
+ * thread, to monitor the elapsing time and kills the process when the
+ * expected duration has exceeded.
+ * Notes on multi-threaded behaviors:
+ * - The threadloop is blocked/paused when there are no calls being
+ * monitored.
+ * - The start and stop functions handle simultaneous call monitoring
+ * and single call monitoring differently. See function documentation for
+ * more details.
+ */
+
+#include <chrono>
+#include <thread>
+#include <time.h>
+#include <utils/Thread.h>
+#include <utils/Log.h>
+#include <unordered_map>
+
+// Used to wrap the call of interest in start and stop calls
+#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid())
+#define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
+ watchThread([&]() { return toMonitor;}, gettid(), cycles, cycleLength);
+
+// Default cycles and cycle length values used to calculate permitted elapsed time
+const static size_t kMaxCycles = 100;
+const static uint32_t kCycleLengthMs = 100;
+
+namespace android {
+
+class CameraServiceWatchdog : public Thread {
+
+public:
+ explicit CameraServiceWatchdog() : mPause(true), mMaxCycles(kMaxCycles),
+ mCycleLengthMs(kCycleLengthMs) {};
+
+ explicit CameraServiceWatchdog (size_t maxCycles, uint32_t cycleLengthMs) :
+ mPause(true), mMaxCycles(maxCycles), mCycleLengthMs(cycleLengthMs) {};
+
+ virtual ~CameraServiceWatchdog() {};
+
+ virtual void requestExit();
+
+ /** Used to wrap monitored calls in start and stop functions using custom timer values */
+ template<typename T>
+ auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) {
+ auto res = NULL;
+
+ if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
+ // Create another instance of the watchdog to prevent disruption
+ // of timer for current monitored calls
+ sp<CameraServiceWatchdog> tempWatchdog =
+ new CameraServiceWatchdog(cycles, cycleLength);
+ tempWatchdog->run("CameraServiceWatchdog");
+ res = tempWatchdog->watchThread(func, tid);
+ tempWatchdog->requestExit();
+ tempWatchdog.clear();
+ } else {
+ // If custom timer values are equivalent to set class timer values, use
+ // current thread
+ res = watchThread(func, tid);
+ }
+
+ return res;
+ }
+
+ /** Used to wrap monitored calls in start and stop functions using class timer values */
+ template<typename T>
+ auto watchThread(T func, uint32_t tid) {
+ auto res = NULL;
+
+ start(tid);
+ res = func();
+ stop(tid);
+
+ return res;
+ }
+
+private:
+
+ /**
+ * Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
+ * start() unblocks and starts the watchdog
+ */
+ void start(uint32_t tid);
+
+ /**
+ * If there are no calls left to be monitored, stop blocks/pauses threadloop
+ * otherwise stop() erases the cycle counter to end watchdog for the calling thread
+ */
+ void stop(uint32_t tid);
+
+ virtual bool threadLoop();
+
+ Mutex mWatchdogLock; // Lock for condition variable
+ Condition mWatchdogCondition; // Condition variable for stop/start
+ bool mPause; // True if thread is currently paused
+ uint32_t mMaxCycles; // Max cycles
+ uint32_t mCycleLengthMs; // Length of time elapsed per cycle
+
+ std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
+};
+
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 04e65d4..ddbc8ba 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -115,6 +115,10 @@
status_t Camera3Device::initializeCommonLocked() {
+ /** Start watchdog thread */
+ mCameraServiceWatchdog = new CameraServiceWatchdog();
+ mCameraServiceWatchdog->run("CameraServiceWatchdog");
+
/** Start up status tracker thread */
mStatusTracker = new StatusTracker(this);
status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
@@ -316,7 +320,7 @@
// Call close without internal mutex held, as the HAL close may need to
// wait on assorted callbacks,etc, to complete before it can return.
- interface->close();
+ mCameraServiceWatchdog->WATCH(interface->close());
flushInflightRequests();
@@ -339,6 +343,12 @@
}
}
ALOGI("%s: X", __FUNCTION__);
+
+ if (mCameraServiceWatchdog != NULL) {
+ mCameraServiceWatchdog->requestExit();
+ mCameraServiceWatchdog.clear();
+ }
+
return res;
}
@@ -1719,7 +1729,12 @@
mSessionStatsBuilder.stopCounter();
}
- return mRequestThread->flush();
+ // Calculate expected duration for flush with additional buffer time in ms for watchdog
+ uint64_t maxExpectedDuration = (getExpectedInFlightDuration() + kBaseGetBufferWait) / 1e6;
+ status_t res = mCameraServiceWatchdog->WATCH_CUSTOM_TIMER(mRequestThread->flush(),
+ maxExpectedDuration / kCycleLengthMs, kCycleLengthMs);
+
+ return res;
}
status_t Camera3Device::prepare(int streamId) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 749b342..748d063 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -32,6 +32,7 @@
#include <camera/CaptureResult.h>
#include "android/hardware/camera/metadata/3.8/types.h"
+#include "CameraServiceWatchdog.h"
#include "common/CameraDeviceBase.h"
#include "device3/BufferUtils.h"
#include "device3/StatusTracker.h"
@@ -98,6 +99,9 @@
metadata_vendor_id_t getVendorTagId() const override { return mVendorTagId; }
+ // Watchdog thread
+ sp<CameraServiceWatchdog> mCameraServiceWatchdog;
+
// Transitions to idle state on success.
virtual status_t initialize(sp<CameraProviderManager> /*manager*/,
const String8& /*monitorTags*/) = 0;
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
index a00b221..f7cede8 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
@@ -260,4 +260,16 @@
sessionStats->onClose(latencyMs);
}
+bool CameraServiceProxyWrapper::isCameraDisabled() {
+ sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
+ if (proxyBinder == nullptr) return true;
+ bool ret = false;
+ auto status = proxyBinder->isCameraDisabled(&ret);
+ if (!status.isOk()) {
+ ALOGE("%s: Failed during camera disabled query: %s", __FUNCTION__,
+ status.exceptionMessage().c_str());
+ }
+ return ret;
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
index 6604aa1..61fc915 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
@@ -95,6 +95,9 @@
// Return the current top activity rotate and crop override.
static int getRotateAndCropOverride(String16 packageName, int lensFacing, int userId);
+
+ // Detect if the camera is disabled by device policy.
+ static bool isCameraDisabled();
};
} // android
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 4090dae..a46266e 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -322,6 +322,10 @@
streamUseCase == ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
return true;
}
+ // Allow vendor stream use case unconditionally.
+ if (streamUseCase >= ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) {
+ return true;
+ }
for (size_t i = 0; i < availableStreamUseCases.count; i++) {
if (availableStreamUseCases.data.i64[i] == streamUseCase) {