summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/AudioFlinger.cpp25
-rw-r--r--services/audioflinger/AudioFlinger.h3
-rw-r--r--services/audioflinger/Threads.cpp89
-rw-r--r--services/audioflinger/Threads.h28
-rw-r--r--services/camera/libcameraservice/CameraService.cpp136
-rw-r--r--services/camera/libcameraservice/CameraService.h31
-rw-r--r--services/camera/libcameraservice/common/Camera2ClientBase.cpp2
7 files changed, 185 insertions, 129 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3c14e1f..485e320 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1268,11 +1268,11 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
// the config change is always sent from playback or record threads to avoid deadlock
// with AudioSystem::gLock
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AudioSystem::OUTPUT_OPENED);
+ mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_OPENED);
}
for (size_t i = 0; i < mRecordThreads.size(); i++) {
- mRecordThreads.valueAt(i)->sendIoConfigEvent(AudioSystem::INPUT_OPENED);
+ mRecordThreads.valueAt(i)->sendIoConfigEvent(AUDIO_INPUT_OPENED);
}
}
}
@@ -1306,14 +1306,13 @@ void AudioFlinger::removeNotificationClient(pid_t pid)
}
}
-void AudioFlinger::audioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2)
+void AudioFlinger::ioConfigChanged(audio_io_config_event event,
+ const sp<AudioIoDescriptor>& ioDesc)
{
Mutex::Autolock _l(mClientLock);
size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
- mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event,
- ioHandle,
- param2);
+ mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioDesc);
}
}
@@ -1832,7 +1831,7 @@ status_t AudioFlinger::openOutput(audio_module_handle_t module,
*latencyMs = thread->latency();
// notify client processes of the new output creation
- thread->audioConfigChanged(AudioSystem::OUTPUT_OPENED);
+ thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
// the first primary output opened designates the primary hw device
if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
@@ -1870,7 +1869,7 @@ audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
// notify client processes of the new output creation
- thread->audioConfigChanged(AudioSystem::OUTPUT_OPENED);
+ thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
return id;
}
@@ -1920,7 +1919,9 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
}
}
}
- audioConfigChanged(AudioSystem::OUTPUT_CLOSED, output, NULL);
+ const sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
+ ioDesc->mIoHandle = output;
+ ioConfigChanged(AUDIO_OUTPUT_CLOSED, ioDesc);
}
thread->exit();
// The thread entity (active unit of execution) is no longer running here,
@@ -1998,7 +1999,7 @@ status_t AudioFlinger::openInput(audio_module_handle_t module,
if (thread != 0) {
// notify client processes of the new input creation
- thread->audioConfigChanged(AudioSystem::INPUT_OPENED);
+ thread->ioConfigChanged(AUDIO_INPUT_OPENED);
return NO_ERROR;
}
return NO_INIT;
@@ -2181,7 +2182,9 @@ status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input)
putOrphanEffectChain_l(chain);
}
}
- audioConfigChanged(AudioSystem::INPUT_CLOSED, input, NULL);
+ const sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
+ ioDesc->mIoHandle = input;
+ ioConfigChanged(AUDIO_INPUT_CLOSED, ioDesc);
mRecordThreads.removeItem(input);
}
// FIXME: calling thread->exit() without mLock held should not be needed anymore now that
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 72db62b..51b2610 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -546,7 +546,8 @@ private:
// no range check, doesn't check per-thread stream volume, AudioFlinger::mLock held
float streamVolume_l(audio_stream_type_t stream) const
{ return mStreamTypes[stream].volume; }
- void audioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2);
+ void ioConfigChanged(audio_io_config_event event,
+ const sp<AudioIoDescriptor>& ioDesc);
// Allocate an audio_io_handle_t, session ID, effect ID, or audio_module_handle_t.
// They all share the same ID space, but the namespaces are actually independent
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 234e45f..8b8dd78 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -584,16 +584,16 @@ status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
return status;
}
-void AudioFlinger::ThreadBase::sendIoConfigEvent(int event, int param)
+void AudioFlinger::ThreadBase::sendIoConfigEvent(audio_io_config_event event)
{
Mutex::Autolock _l(mLock);
- sendIoConfigEvent_l(event, param);
+ sendIoConfigEvent_l(event);
}
// sendIoConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendIoConfigEvent_l(int event, int param)
+void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event)
{
- sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, param);
+ sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event);
sendConfigEvent_l(configEvent);
}
@@ -657,7 +657,7 @@ void AudioFlinger::ThreadBase::processConfigEvents_l()
} break;
case CFG_EVENT_IO: {
IoConfigEventData *data = (IoConfigEventData *)event->mData.get();
- audioConfigChanged(data->mEvent, data->mParam);
+ ioConfigChanged(data->mEvent);
} break;
case CFG_EVENT_SET_PARAMETER: {
SetParameterConfigEventData *data = (SetParameterConfigEventData *)event->mData.get();
@@ -1921,32 +1921,28 @@ String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
return out_s8;
}
-void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
- AudioSystem::OutputDescriptor desc;
- void *param2 = NULL;
+void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event event) {
+ sp<AudioIoDescriptor> desc = new AudioIoDescriptor();
+ ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event);
- ALOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event,
- param);
+ desc->mIoHandle = mId;
switch (event) {
- case AudioSystem::OUTPUT_OPENED:
- case AudioSystem::OUTPUT_CONFIG_CHANGED:
- desc.channelMask = mChannelMask;
- desc.samplingRate = mSampleRate;
- desc.format = mFormat;
- desc.frameCount = mNormalFrameCount; // FIXME see
+ case AUDIO_OUTPUT_OPENED:
+ case AUDIO_OUTPUT_CONFIG_CHANGED:
+ desc->mChannelMask = mChannelMask;
+ desc->mSamplingRate = mSampleRate;
+ desc->mFormat = mFormat;
+ desc->mFrameCount = mNormalFrameCount; // FIXME see
// AudioFlinger::frameCount(audio_io_handle_t)
- desc.latency = latency_l();
- param2 = &desc;
+ desc->mLatency = latency_l();
break;
- case AudioSystem::STREAM_CONFIG_CHANGED:
- param2 = &param;
- case AudioSystem::OUTPUT_CLOSED:
+ case AUDIO_OUTPUT_CLOSED:
default:
break;
}
- mAudioFlinger->audioConfigChanged(event, mId, param2);
+ mAudioFlinger->ioConfigChanged(event, desc);
}
void AudioFlinger::PlaybackThread::writeCallback()
@@ -2055,6 +2051,9 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l()
ALOGW("direct output implements resume but not pause");
}
}
+ if (!mHwSupportsPause && mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) {
+ LOG_ALWAYS_FATAL("HW_AV_SYNC requested but HAL does not implement pause and resume");
+ }
if (mType == DUPLICATING && mMixerBufferEnabled && mEffectBufferEnabled) {
// For best precision, we use float instead of the associated output
@@ -4203,7 +4202,7 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa
}
mTracks[i]->mName = name;
}
- sendIoConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+ sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
}
@@ -4375,9 +4374,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
sp<Track> l = mLatestActiveTrack.promote();
bool last = l.get() == track;
- if (mHwSupportsPause && track->isPausing()) {
+ if (track->isPausing()) {
track->setPaused();
- if (last && !mHwPaused) {
+ if (mHwSupportsPause && last && !mHwPaused) {
doHwPause = true;
mHwPaused = true;
}
@@ -4387,13 +4386,11 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
if (last) {
flushPending = true;
}
- } else if (mHwSupportsPause && track->isResumePending()){
+ } else if (track->isResumePending()) {
track->resumeAck();
- if (last) {
- if (mHwPaused) {
- doHwResume = true;
- mHwPaused = false;
- }
+ if (last && mHwPaused) {
+ doHwResume = true;
+ mHwPaused = false;
}
}
@@ -4655,7 +4652,7 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& key
}
if (status == NO_ERROR && reconfig) {
readOutputParameters_l();
- sendIoConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+ sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
}
@@ -6701,7 +6698,7 @@ bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValueP
}
if (status == NO_ERROR) {
readInputParameters_l();
- sendIoConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
+ sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
}
}
}
@@ -6722,26 +6719,26 @@ String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
return out_s8;
}
-void AudioFlinger::RecordThread::audioConfigChanged(int event, int param __unused) {
- AudioSystem::OutputDescriptor desc;
- const void *param2 = NULL;
+void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event event) {
+ sp<AudioIoDescriptor> desc = new AudioIoDescriptor();
+
+ desc->mIoHandle = mId;
switch (event) {
- case AudioSystem::INPUT_OPENED:
- case AudioSystem::INPUT_CONFIG_CHANGED:
- desc.channelMask = mChannelMask;
- desc.samplingRate = mSampleRate;
- desc.format = mFormat;
- desc.frameCount = mFrameCount;
- desc.latency = 0;
- param2 = &desc;
+ case AUDIO_INPUT_OPENED:
+ case AUDIO_INPUT_CONFIG_CHANGED:
+ desc->mChannelMask = mChannelMask;
+ desc->mSamplingRate = mSampleRate;
+ desc->mFormat = mFormat;
+ desc->mFrameCount = mFrameCount;
+ desc->mLatency = 0;
break;
- case AudioSystem::INPUT_CLOSED:
+ case AUDIO_INPUT_CLOSED:
default:
break;
}
- mAudioFlinger->audioConfigChanged(event, mId, param2);
+ mAudioFlinger->ioConfigChanged(event, desc);
}
void AudioFlinger::RecordThread::readInputParameters_l()
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 2c514f8..8167bd1 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -100,22 +100,21 @@ public:
class IoConfigEventData : public ConfigEventData {
public:
- IoConfigEventData(int event, int param) :
- mEvent(event), mParam(param) {}
+ IoConfigEventData(audio_io_config_event event) :
+ mEvent(event) {}
virtual void dump(char *buffer, size_t size) {
- snprintf(buffer, size, "IO event: event %d, param %d\n", mEvent, mParam);
+ snprintf(buffer, size, "IO event: event %d\n", mEvent);
}
- const int mEvent;
- const int mParam;
+ const audio_io_config_event mEvent;
};
class IoConfigEvent : public ConfigEvent {
public:
- IoConfigEvent(int event, int param) :
+ IoConfigEvent(audio_io_config_event event) :
ConfigEvent(CFG_EVENT_IO) {
- mData = new IoConfigEventData(event, param);
+ mData = new IoConfigEventData(event);
}
virtual ~IoConfigEvent() {}
};
@@ -250,13 +249,13 @@ public:
status_t& status) = 0;
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys) = 0;
- virtual void audioConfigChanged(int event, int param = 0) = 0;
+ virtual void ioConfigChanged(audio_io_config_event event) = 0;
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from
// processConfigEvents_l().
status_t sendConfigEvent_l(sp<ConfigEvent>& event);
- void sendIoConfigEvent(int event, int param = 0);
- void sendIoConfigEvent_l(int event, int param = 0);
+ void sendIoConfigEvent(audio_io_config_event event);
+ void sendIoConfigEvent_l(audio_io_config_event event);
void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio);
status_t sendSetParameterConfigEvent_l(const String8& keyValuePair);
status_t sendCreateAudioPatchConfigEvent(const struct audio_patch *patch,
@@ -560,7 +559,7 @@ public:
{ return android_atomic_acquire_load(&mSuspended) > 0; }
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged(int event, int param = 0);
+ virtual void ioConfigChanged(audio_io_config_event event);
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
// FIXME rename mixBuffer() to sinkBuffer() and remove int16_t* dependency.
// Consider also removing and passing an explicit mMainBuffer initialization
@@ -713,8 +712,9 @@ protected:
audio_patch_handle_t *handle);
virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
- bool usesHwAvSync() const { return (mType == DIRECT) && (mOutput != NULL) &&
- (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }
+ bool usesHwAvSync() const { return (mType == DIRECT) && (mOutput != NULL)
+ && mHwSupportsPause
+ && (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }
private:
@@ -1230,7 +1230,7 @@ public:
status_t& status);
virtual void cacheParameters_l() {}
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged(int event, int param = 0);
+ virtual void ioConfigChanged(audio_io_config_event event);
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle);
virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8c5c43a..3f80faf 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -890,9 +890,12 @@ status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clien
if (current != nullptr) {
auto clientSp = current->getValue();
if (clientSp.get() != nullptr) { // should never be needed
- if (clientSp->getRemote() == remoteCallback) {
+ if (!clientSp->canCastToApiClient(effectiveApiLevel)) {
+ ALOGW("CameraService connect called from same client, but with a different"
+ " API level, evicting prior client...");
+ } else if (clientSp->getRemote() == remoteCallback) {
ALOGI("CameraService::connect X (PID %d) (second call from same"
- "app binder, returning the same client)", clientPid);
+ " app binder, returning the same client)", clientPid);
*client = clientSp;
return NO_ERROR;
}
@@ -1054,19 +1057,24 @@ status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clien
status_t CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
- const String16& clientPackageName,
+ const String16& opPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) {
+ const status_t result = checkCameraAccess(opPackageName);
+ if (result != NO_ERROR) {
+ return result;
+ }
+
status_t ret = NO_ERROR;
String8 id = String8::format("%d", cameraId);
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, CAMERA_HAL_API_VERSION_UNSPECIFIED,
- clientPackageName, clientUid, API_1, false, false, /*out*/client);
+ opPackageName, clientUid, API_1, false, false, /*out*/client);
if(ret != NO_ERROR) {
- logRejected(id, getCallingPid(), String8(clientPackageName),
+ logRejected(id, getCallingPid(), String8(opPackageName),
String8::format("%s (%d)", strerror(-ret), ret));
return ret;
}
@@ -1078,11 +1086,16 @@ status_t CameraService::connect(
status_t CameraService::connectLegacy(
const sp<ICameraClient>& cameraClient,
int cameraId, int halVersion,
- const String16& clientPackageName,
+ const String16& opPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) {
+ const status_t result = checkCameraAccess(opPackageName);
+ if (result != NO_ERROR) {
+ return result;
+ }
+
String8 id = String8::format("%d", cameraId);
int apiVersion = mModule->getModuleApiVersion();
if (halVersion != CAMERA_HAL_API_VERSION_UNSPECIFIED &&
@@ -1095,18 +1108,18 @@ status_t CameraService::connectLegacy(
*/
ALOGE("%s: camera HAL module version %x doesn't support connecting to legacy HAL devices!",
__FUNCTION__, apiVersion);
- logRejected(id, getCallingPid(), String8(clientPackageName),
+ logRejected(id, getCallingPid(), String8(opPackageName),
String8("HAL module version doesn't support legacy HAL connections"));
return INVALID_OPERATION;
}
status_t ret = NO_ERROR;
sp<Client> client = nullptr;
- ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion, clientPackageName,
+ ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion, opPackageName,
clientUid, API_1, true, false, /*out*/client);
if(ret != NO_ERROR) {
- logRejected(id, getCallingPid(), String8(clientPackageName),
+ logRejected(id, getCallingPid(), String8(opPackageName),
String8::format("%s (%d)", strerror(-ret), ret));
return ret;
}
@@ -1118,20 +1131,25 @@ status_t CameraService::connectLegacy(
status_t CameraService::connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
- const String16& clientPackageName,
+ const String16& opPackageName,
int clientUid,
/*out*/
sp<ICameraDeviceUser>& device) {
+ const status_t result = checkCameraAccess(opPackageName);
+ if (result != NO_ERROR) {
+ return result;
+ }
+
status_t ret = NO_ERROR;
String8 id = String8::format("%d", cameraId);
sp<CameraDeviceClient> client = nullptr;
ret = connectHelper<ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
- CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, API_2, false, false,
+ CAMERA_HAL_API_VERSION_UNSPECIFIED, opPackageName, clientUid, API_2, false, false,
/*out*/client);
if(ret != NO_ERROR) {
- logRejected(id, getCallingPid(), String8(clientPackageName),
+ logRejected(id, getCallingPid(), String8(opPackageName),
String8::format("%s (%d)", strerror(-ret), ret));
return ret;
}
@@ -1526,24 +1544,24 @@ void CameraService::logEvent(const char* event) {
}
void CameraService::logDisconnected(const char* cameraId, int clientPid,
- const char* clientPackage) {
+ const char* opPackageName) {
// Log the clients evicted
logEvent(String8::format("DISCONNECT device %s client for package %s (PID %d)", cameraId,
- clientPackage, clientPid));
+ opPackageName, clientPid));
}
void CameraService::logConnected(const char* cameraId, int clientPid,
- const char* clientPackage) {
+ const char* opPackageName) {
// Log the clients evicted
logEvent(String8::format("CONNECT device %s client for package %s (PID %d)", cameraId,
- clientPackage, clientPid));
+ opPackageName, clientPid));
}
void CameraService::logRejected(const char* cameraId, int clientPid,
- const char* clientPackage, const char* reason) {
+ const char* opPackageName, const char* reason) {
// Log the client rejected
logEvent(String8::format("REJECT device %s client for package %s (PID %d), reason: (%s)",
- cameraId, clientPackage, clientPid, reason));
+ cameraId, opPackageName, clientPid, reason));
}
void CameraService::logUserSwitch(int oldUserId, int newUserId) {
@@ -1580,21 +1598,6 @@ status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* re
// Permission checks
switch (code) {
- case BnCameraService::CONNECT:
- case BnCameraService::CONNECT_DEVICE:
- case BnCameraService::CONNECT_LEGACY: {
- if (pid != selfPid) {
- // we're called from a different process, do the real check
- if (!checkCallingPermission(
- String16("android.permission.CAMERA"))) {
- const int uid = getCallingUid();
- ALOGE("Permission Denial: "
- "can't use the camera pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- }
- break;
- }
case BnCameraService::NOTIFY_SYSTEM_EVENT: {
if (pid != selfPid) {
// Ensure we're being called by system_server, or similar process with
@@ -1614,6 +1617,38 @@ status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* re
return BnCameraService::onTransact(code, data, reply, flags);
}
+status_t CameraService::checkCameraAccess(const String16& opPackageName) {
+ const int pid = getCallingPid();
+
+ if (pid == getpid()) {
+ return NO_ERROR;
+ }
+
+ const int uid = getCallingUid();
+
+ if (!checkCallingPermission(String16("android.permission.CAMERA"))) {
+ ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+
+ AppOpsManager appOps;
+ const int32_t result = appOps.noteOp(AppOpsManager::OP_CAMERA, uid, opPackageName);
+
+ switch (result) {
+ case AppOpsManager::MODE_ERRORED: {
+ ALOGE("App op OP_CAMERA errored: can't use the camera pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ } break;
+
+ case AppOpsManager::MODE_IGNORED: {
+ ALOGE("App op OP_CAMERA ignored: can't use the camera pid=%d, uid=%d", pid, uid);
+ return INVALID_OPERATION;
+ } break;
+ }
+
+ return NO_ERROR;
+}
+
// We share the media players for shutter and recording sound for all clients.
// A reference count is kept to determine when we will actually release the
// media players.
@@ -1666,13 +1701,13 @@ void CameraService::playSound(sound_kind kind) {
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
- const String16& clientPackageName,
+ const String16& opPackageName,
int cameraId, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid) :
CameraService::BasicClient(cameraService,
IInterface::asBinder(cameraClient),
- clientPackageName,
+ opPackageName,
cameraId, cameraFacing,
clientPid, clientUid,
servicePid)
@@ -1699,11 +1734,11 @@ CameraService::Client::~Client() {
CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
- const String16& clientPackageName,
+ const String16& opPackageName,
int cameraId, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid):
- mClientPackageName(clientPackageName), mDisconnected(false)
+ mOpPackageName(opPackageName), mDisconnected(false)
{
mCameraService = cameraService;
mRemoteBinder = remoteCallback;
@@ -1731,7 +1766,7 @@ void CameraService::BasicClient::disconnect() {
mCameraService->removeByClient(this);
mCameraService->logDisconnected(String8::format("%d", mCameraId), mClientPid,
- String8(mClientPackageName));
+ String8(mOpPackageName));
sp<IBinder> remote = getRemote();
if (remote != nullptr) {
@@ -1746,7 +1781,7 @@ void CameraService::BasicClient::disconnect() {
}
String16 CameraService::BasicClient::getPackageName() const {
- return mClientPackageName;
+ return mOpPackageName;
}
@@ -1754,6 +1789,11 @@ int CameraService::BasicClient::getClientPid() const {
return mClientPid;
}
+bool CameraService::BasicClient::canCastToApiClient(apiLevel level) const {
+ // Defaults to API2.
+ return level == API_2;
+}
+
status_t CameraService::BasicClient::startCameraOps() {
int32_t res;
// Notify app ops that the camera is not available
@@ -1761,17 +1801,17 @@ status_t CameraService::BasicClient::startCameraOps() {
{
ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
- __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
+ __FUNCTION__, String8(mOpPackageName).string(), mClientUid);
}
mAppOpsManager.startWatchingMode(AppOpsManager::OP_CAMERA,
- mClientPackageName, mOpsCallback);
+ mOpPackageName, mOpsCallback);
res = mAppOpsManager.startOp(AppOpsManager::OP_CAMERA,
- mClientUid, mClientPackageName);
+ mClientUid, mOpPackageName);
if (res != AppOpsManager::MODE_ALLOWED) {
ALOGI("Camera %d: Access for \"%s\" has been revoked",
- mCameraId, String8(mClientPackageName).string());
+ mCameraId, String8(mOpPackageName).string());
return PERMISSION_DENIED;
}
@@ -1789,7 +1829,7 @@ status_t CameraService::BasicClient::finishCameraOps() {
if (mOpsActive) {
// Notify app ops that the camera is available again
mAppOpsManager.finishOp(AppOpsManager::OP_CAMERA, mClientUid,
- mClientPackageName);
+ mOpPackageName);
mOpsActive = false;
auto rejected = {ICameraServiceListener::STATUS_NOT_PRESENT,
@@ -1814,7 +1854,7 @@ status_t CameraService::BasicClient::finishCameraOps() {
void CameraService::BasicClient::opChanged(int32_t op, const String16& packageName) {
String8 name(packageName);
- String8 myName(mClientPackageName);
+ String8 myName(mOpPackageName);
if (op != AppOpsManager::OP_CAMERA) {
ALOGW("Unexpected app ops notification received: %d", op);
@@ -1823,7 +1863,7 @@ void CameraService::BasicClient::opChanged(int32_t op, const String16& packageNa
int32_t res;
res = mAppOpsManager.checkOp(AppOpsManager::OP_CAMERA,
- mClientUid, mClientPackageName);
+ mClientUid, mOpPackageName);
ALOGV("checkOp returns: %d, %s ", res,
res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" :
res == AppOpsManager::MODE_IGNORED ? "IGNORED" :
@@ -1866,6 +1906,10 @@ void CameraService::Client::disconnect() {
BasicClient::disconnect();
}
+bool CameraService::Client::canCastToApiClient(apiLevel level) const {
+ return level == API_1;
+}
+
CameraService::Client::OpsCallback::OpsCallback(wp<BasicClient> client):
mClient(client) {
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 84e61c5..502fcfa 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -65,6 +65,7 @@ public:
class Client;
class BasicClient;
+ // The effective API level. The Camera2 API running in LEGACY mode counts as API_1.
enum apiLevel {
API_1 = 1,
API_2 = 2
@@ -125,19 +126,19 @@ public:
virtual status_t getCameraVendorTagDescriptor(/*out*/ sp<VendorTagDescriptor>& desc);
virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
- const String16& clientPackageName, int clientUid,
+ const String16& opPackageName, int clientUid,
/*out*/
sp<ICamera>& device);
virtual status_t connectLegacy(const sp<ICameraClient>& cameraClient, int cameraId,
- int halVersion, const String16& clientPackageName, int clientUid,
+ int halVersion, const String16& opPackageName, int clientUid,
/*out*/
sp<ICamera>& device);
virtual status_t connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
- const String16& clientPackageName,
+ const String16& opPackageName,
int clientUid,
/*out*/
sp<ICameraDeviceUser>& device);
@@ -215,10 +216,14 @@ public:
// Get the PID of the application client using this
virtual int getClientPid() const;
+
+ // Check what API level is used for this client. This is used to determine which
+ // superclass this can be cast to.
+ virtual bool canCastToApiClient(apiLevel level) const;
protected:
BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
- const String16& clientPackageName,
+ const String16& opPackageName,
int cameraId,
int cameraFacing,
int clientPid,
@@ -237,7 +242,7 @@ public:
sp<CameraService> mCameraService; // immutable after constructor
int mCameraId; // immutable after constructor
int mCameraFacing; // immutable after constructor
- const String16 mClientPackageName;
+ const String16 mOpPackageName;
pid_t mClientPid;
uid_t mClientUid; // immutable after constructor
pid_t mServicePid; // immutable after constructor
@@ -304,7 +309,7 @@ public:
// Interface used by CameraService
Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
- const String16& clientPackageName,
+ const String16& opPackageName,
int cameraId,
int cameraFacing,
int clientPid,
@@ -323,6 +328,10 @@ public:
virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
const CaptureResultExtras& resultExtras);
+
+ // Check what API level is used for this client. This is used to determine which
+ // superclass this can be cast to.
+ virtual bool canCastToApiClient(apiLevel level) const;
protected:
// Convert client from cookie.
static sp<CameraService::Client> getClientFromCookie(void* user);
@@ -471,7 +480,7 @@ private:
// Single implementation shared between the various connect calls
template<class CALLBACK, class CLIENT>
status_t connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId, int halVersion,
- const String16& clientPackageName, int clientUid, apiLevel effectiveApiLevel,
+ const String16& opPackageName, int clientUid, apiLevel effectiveApiLevel,
bool legacyMode, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
@@ -704,6 +713,8 @@ private:
int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client);
+
+ status_t checkCameraAccess(const String16& opPackageName);
};
template<class Func>
@@ -752,11 +763,11 @@ void CameraService::CameraState::updateStatus(ICameraServiceListener::Status sta
template<class CALLBACK, class CLIENT>
status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
- int halVersion, const String16& clientPackageName, int clientUid,
+ int halVersion, const String16& opPackageName, int clientUid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
status_t ret = NO_ERROR;
- String8 clientName8(clientPackageName);
+ String8 clientName8(opPackageName);
int clientPid = getCallingPid();
ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
@@ -827,7 +838,7 @@ status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String
int facing = -1;
int deviceVersion = getDeviceVersion(id, /*out*/&facing);
sp<BasicClient> tmp = nullptr;
- if((ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
+ if((ret = makeClient(this, cameraCb, opPackageName, cameraId, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)) != NO_ERROR) {
return ret;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index ba0b264..9b2e143 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -118,7 +118,7 @@ Camera2ClientBase<TClientBase>::~Camera2ClientBase() {
ALOGI("Closed Camera %d. Client was: %s (PID %d, UID %u)",
TClientBase::mCameraId,
- String8(TClientBase::mClientPackageName).string(),
+ String8(TClientBase::mOpPackageName).string(),
mInitialClientPid, TClientBase::mClientUid);
}