Loading camera/ICameraService.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -302,6 +302,15 @@ public: status_t res = data.readInt32(); return res; } virtual void notifySystemEvent(int eventId, int arg0) { Parcel data, reply; data.writeInt32(eventId); data.writeInt32(arg0); remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply, IBinder::FLAG_ONEWAY); } }; IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService"); Loading Loading @@ -470,6 +479,13 @@ status_t BnCameraService::onTransact( reply->writeInt32(status); return NO_ERROR; } break; case NOTIFY_SYSTEM_EVENT: { CHECK_INTERFACE(ICameraService, data, reply); int eventId = data.readInt32(); int arg0 = data.readInt32(); notifySystemEvent(eventId, arg0); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } Loading include/camera/ICameraService.h +18 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ public: SUPPORTS_CAMERA_API, CONNECT_LEGACY, SET_TORCH_MODE, NOTIFY_SYSTEM_EVENT, }; enum { Loading @@ -66,6 +67,17 @@ public: CAMERA_HAL_API_VERSION_UNSPECIFIED = -1 }; /** * Keep up-to-date with declarations in * frameworks/base/services/core/java/com/android/server/camera/CameraService.java * * These event codes are intended to be used with the notifySystemEvent call. */ enum { NO_EVENT = 0, USER_SWITCHED, }; public: DECLARE_META_INTERFACE(CameraService); Loading Loading @@ -148,6 +160,11 @@ public: */ virtual status_t setTorchMode(const String16& cameraId, bool enabled, const sp<IBinder>& clientBinder) = 0; /** * Notify the camera service of a system event. Should only be called from system_server. */ virtual void notifySystemEvent(int eventId, int arg0) = 0; }; // ---------------------------------------------------------------------------- Loading services/camera/libcameraservice/CameraService.cpp +110 −12 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ #include <binder/ProcessInfoService.h> #include <cutils/atomic.h> #include <cutils/properties.h> #include <cutils/multiuser.h> #include <gui/Surface.h> #include <hardware/hardware.h> #include <media/AudioSystem.h> Loading Loading @@ -123,9 +122,8 @@ static void torch_mode_status_change( // should be ok for now. static CameraService *gCameraService; CameraService::CameraService() : mEventLog(DEFAULT_EVICTION_LOG_LENGTH), mSoundRef(0), mModule(0), mFlashlight(0) { CameraService::CameraService() : mEventLog(DEFAULT_EVICTION_LOG_LENGTH), mLastUserId(DEFAULT_LAST_USER_ID), mSoundRef(0), mModule(0), mFlashlight(0) { ALOGI("CameraService started (pid=%d)", getpid()); gCameraService = this; Loading Loading @@ -757,7 +755,8 @@ status_t CameraService::getLegacyParametersLazy(int cameraId, return INVALID_OPERATION; } status_t CameraService::validateConnect(const String8& cameraId, /*inout*/int& clientUid) const { status_t CameraService::validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid) const { int callingPid = getCallingPid(); Loading Loading @@ -797,6 +796,13 @@ status_t CameraService::validateConnect(const String8& cameraId, /*inout*/int& c return -EACCES; } // Only allow clients who are being used by the current foreground device user. if (mLastUserId != clientUserId && mLastUserId != DEFAULT_LAST_USER_ID) { ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from non-foreground " "device user)", callingPid); return PERMISSION_DENIED; } return checkIfDeviceIsUsable(cameraId); } Loading Loading @@ -1163,6 +1169,21 @@ status_t CameraService::setTorchMode(const String16& cameraId, bool enabled, return OK; } void CameraService::notifySystemEvent(int eventId, int arg0) { switch(eventId) { case ICameraService::USER_SWITCHED: { doUserSwitch(/*newUserId*/arg0); break; } case ICameraService::NO_EVENT: default: { ALOGW("%s: Received invalid system event from system_server: %d", __FUNCTION__, eventId); break; } } } status_t CameraService::addListener( const sp<ICameraServiceListener>& listener) { ALOGV("%s: Add listener %p", __FUNCTION__, listener.get()); Loading Loading @@ -1351,6 +1372,8 @@ bool CameraService::evictClientIdByRemote(const wp<IBinder>& remote) { // other clients from connecting in mServiceLockWrapper if held mServiceLock.unlock(); // Do not clear caller identity, remote caller should be client proccess for (auto& i : evicted) { if (i.get() != nullptr) { i->disconnect(); Loading Loading @@ -1392,6 +1415,60 @@ sp<CameraService::BasicClient> CameraService::removeClientLocked(const String8& return clientDescriptorPtr->getValue(); } void CameraService::doUserSwitch(int newUserId) { // Acquire mServiceLock and prevent other clients from connecting std::unique_ptr<AutoConditionLock> lock = AutoConditionLock::waitAndAcquire(mServiceLockWrapper); if (newUserId <= 0) { ALOGW("%s: Bad user ID %d given during user switch, resetting to default.", __FUNCTION__, newUserId); newUserId = DEFAULT_LAST_USER_ID; } mLastUserId = newUserId; // Current user has switched, evict all current clients. std::vector<sp<BasicClient>> evicted; for (auto& i : mActiveClientManager.getAll()) { auto clientSp = i->getValue(); if (clientSp.get() == nullptr) { ALOGE("%s: Dead client still in mActiveClientManager.", __FUNCTION__); continue; } evicted.push_back(clientSp); String8 curTime = getFormattedCurrentTime(); ALOGE("Evicting conflicting client for camera ID %s due to user change", i->getKey().string()); // Log the clients evicted mEventLog.add(String8::format("%s : EVICT device %s client for package %s (PID %" PRId32 ", priority %" PRId32 ")\n - Evicted due to user switch.", curTime.string(), i->getKey().string(), String8{clientSp->getPackageName()}.string(), i->getOwnerId(), i->getPriority())); } // Do not hold mServiceLock while disconnecting clients, but retain the condition // blocking other clients from connecting in mServiceLockWrapper if held. mServiceLock.unlock(); // Clear caller identity temporarily so client disconnect PID checks work correctly int64_t token = IPCThreadState::self()->clearCallingIdentity(); for (auto& i : evicted) { i->disconnect(); } IPCThreadState::self()->restoreCallingIdentity(token); // Reacquire mServiceLock mServiceLock.lock(); } void CameraService::logDisconnected(const String8& cameraId, int clientPid, const String8& clientPackage) { Loading @@ -1411,16 +1488,18 @@ void CameraService::logConnected(const String8& cameraId, int clientPid, curTime.string(), cameraId.string(), clientPackage.string(), clientPid)); } status_t CameraService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { const int pid = getCallingPid(); const int selfPid = getpid(); // Permission checks switch (code) { case BnCameraService::CONNECT: case BnCameraService::CONNECT_DEVICE: case BnCameraService::CONNECT_LEGACY: const int pid = getCallingPid(); const int self_pid = getpid(); if (pid != self_pid) { case BnCameraService::CONNECT_LEGACY: { if (pid != selfPid) { // we're called from a different process, do the real check if (!checkCallingPermission( String16("android.permission.CAMERA"))) { Loading @@ -1432,6 +1511,21 @@ status_t CameraService::onTransact( } break; } case BnCameraService::NOTIFY_SYSTEM_EVENT: { if (pid != selfPid) { // Ensure we're being called by system_server, or similar process with // permissions to notify the camera service about system events if (!checkCallingPermission( String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) { const int uid = getCallingUid(); ALOGE("Permission Denial: cannot send updates to camera service about system" " events from pid=%d, uid=%d", pid, uid); return PERMISSION_DENIED; } } break; } } return BnCameraService::onTransact(code, data, reply, flags); } Loading Loading @@ -1544,7 +1638,11 @@ CameraService::BasicClient::~BasicClient() { } void CameraService::BasicClient::disconnect() { if (mDisconnected) return; if (mDisconnected) { ALOGE("%s: Disconnect called on already disconnected client for device %d", __FUNCTION__, mCameraId); return; } mDisconnected = true;; mCameraService->removeByClient(this); Loading services/camera/libcameraservice/CameraService.h +24 −6 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H #include <cutils/multiuser.h> #include <utils/Vector.h> #include <utils/KeyedVector.h> #include <binder/AppOpsManager.h> Loading Loading @@ -92,6 +93,11 @@ public: // Default number of messages to store in eviction log static const size_t DEFAULT_EVICTION_LOG_LENGTH = 50; enum { // Default last user id DEFAULT_LAST_USER_ID = 0, }; // Implementation of BinderService<T> static char const* getServiceName() { return "media.camera"; } Loading Loading @@ -145,6 +151,8 @@ public: virtual status_t setTorchMode(const String16& cameraId, bool enabled, const sp<IBinder>& clientBinder); virtual void notifySystemEvent(int eventId, int arg0); // OK = supports api of that version, -EOPNOTSUPP = does not support virtual status_t supportsCameraApi( int cameraId, int apiVersion); Loading Loading @@ -447,7 +455,7 @@ private: virtual void onFirstRef(); // Check if we can connect, before we acquire the service lock. status_t validateConnect(const String8& cameraId, /*inout*/int& clientUid) const; status_t validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid) const; // Handle active client evictions, and update service state. // Only call with with mServiceLock held. Loading Loading @@ -485,6 +493,9 @@ private: // Circular buffer for storing event logging for dumps RingBuffer<String8> mEventLog; // UID of last user. int mLastUserId; /** * Get the camera state for a given camera id. * Loading Loading @@ -529,6 +540,11 @@ private: */ sp<CameraService::BasicClient> removeClientLocked(const String8& cameraId); /** * Handle a notification that the current device user has changed. */ void doUserSwitch(int newUserId); /** * Add a event log message that a client has been disconnected. */ Loading Loading @@ -702,22 +718,24 @@ status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String "Camera API version %d", clientPid, clientName8.string(), cameraId.string(), halVersion, static_cast<int>(effectiveApiLevel)); // Enforce client permissions and do basic sanity checks if((ret = validateConnect(cameraId, /*inout*/clientUid)) != NO_ERROR) { return ret; } sp<CLIENT> client = nullptr; { // Acquire mServiceLock and prevent other clients from connecting std::unique_ptr<AutoConditionLock> lock = AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS); if (lock == nullptr) { ALOGE("CameraService::connect X (PID %d) rejected (too many other clients connecting)." , clientPid); return -EBUSY; } // Enforce client permissions and do basic sanity checks if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) { return ret; } mLastUserId = multiuser_get_user_id(clientUid); // Check the shim parameters after acquiring lock, if they have already been updated and // we were doing a shim update, return immediately if (shimUpdateOnly) { Loading Loading
camera/ICameraService.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -302,6 +302,15 @@ public: status_t res = data.readInt32(); return res; } virtual void notifySystemEvent(int eventId, int arg0) { Parcel data, reply; data.writeInt32(eventId); data.writeInt32(arg0); remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply, IBinder::FLAG_ONEWAY); } }; IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService"); Loading Loading @@ -470,6 +479,13 @@ status_t BnCameraService::onTransact( reply->writeInt32(status); return NO_ERROR; } break; case NOTIFY_SYSTEM_EVENT: { CHECK_INTERFACE(ICameraService, data, reply); int eventId = data.readInt32(); int arg0 = data.readInt32(); notifySystemEvent(eventId, arg0); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } Loading
include/camera/ICameraService.h +18 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ public: SUPPORTS_CAMERA_API, CONNECT_LEGACY, SET_TORCH_MODE, NOTIFY_SYSTEM_EVENT, }; enum { Loading @@ -66,6 +67,17 @@ public: CAMERA_HAL_API_VERSION_UNSPECIFIED = -1 }; /** * Keep up-to-date with declarations in * frameworks/base/services/core/java/com/android/server/camera/CameraService.java * * These event codes are intended to be used with the notifySystemEvent call. */ enum { NO_EVENT = 0, USER_SWITCHED, }; public: DECLARE_META_INTERFACE(CameraService); Loading Loading @@ -148,6 +160,11 @@ public: */ virtual status_t setTorchMode(const String16& cameraId, bool enabled, const sp<IBinder>& clientBinder) = 0; /** * Notify the camera service of a system event. Should only be called from system_server. */ virtual void notifySystemEvent(int eventId, int arg0) = 0; }; // ---------------------------------------------------------------------------- Loading
services/camera/libcameraservice/CameraService.cpp +110 −12 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ #include <binder/ProcessInfoService.h> #include <cutils/atomic.h> #include <cutils/properties.h> #include <cutils/multiuser.h> #include <gui/Surface.h> #include <hardware/hardware.h> #include <media/AudioSystem.h> Loading Loading @@ -123,9 +122,8 @@ static void torch_mode_status_change( // should be ok for now. static CameraService *gCameraService; CameraService::CameraService() : mEventLog(DEFAULT_EVICTION_LOG_LENGTH), mSoundRef(0), mModule(0), mFlashlight(0) { CameraService::CameraService() : mEventLog(DEFAULT_EVICTION_LOG_LENGTH), mLastUserId(DEFAULT_LAST_USER_ID), mSoundRef(0), mModule(0), mFlashlight(0) { ALOGI("CameraService started (pid=%d)", getpid()); gCameraService = this; Loading Loading @@ -757,7 +755,8 @@ status_t CameraService::getLegacyParametersLazy(int cameraId, return INVALID_OPERATION; } status_t CameraService::validateConnect(const String8& cameraId, /*inout*/int& clientUid) const { status_t CameraService::validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid) const { int callingPid = getCallingPid(); Loading Loading @@ -797,6 +796,13 @@ status_t CameraService::validateConnect(const String8& cameraId, /*inout*/int& c return -EACCES; } // Only allow clients who are being used by the current foreground device user. if (mLastUserId != clientUserId && mLastUserId != DEFAULT_LAST_USER_ID) { ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from non-foreground " "device user)", callingPid); return PERMISSION_DENIED; } return checkIfDeviceIsUsable(cameraId); } Loading Loading @@ -1163,6 +1169,21 @@ status_t CameraService::setTorchMode(const String16& cameraId, bool enabled, return OK; } void CameraService::notifySystemEvent(int eventId, int arg0) { switch(eventId) { case ICameraService::USER_SWITCHED: { doUserSwitch(/*newUserId*/arg0); break; } case ICameraService::NO_EVENT: default: { ALOGW("%s: Received invalid system event from system_server: %d", __FUNCTION__, eventId); break; } } } status_t CameraService::addListener( const sp<ICameraServiceListener>& listener) { ALOGV("%s: Add listener %p", __FUNCTION__, listener.get()); Loading Loading @@ -1351,6 +1372,8 @@ bool CameraService::evictClientIdByRemote(const wp<IBinder>& remote) { // other clients from connecting in mServiceLockWrapper if held mServiceLock.unlock(); // Do not clear caller identity, remote caller should be client proccess for (auto& i : evicted) { if (i.get() != nullptr) { i->disconnect(); Loading Loading @@ -1392,6 +1415,60 @@ sp<CameraService::BasicClient> CameraService::removeClientLocked(const String8& return clientDescriptorPtr->getValue(); } void CameraService::doUserSwitch(int newUserId) { // Acquire mServiceLock and prevent other clients from connecting std::unique_ptr<AutoConditionLock> lock = AutoConditionLock::waitAndAcquire(mServiceLockWrapper); if (newUserId <= 0) { ALOGW("%s: Bad user ID %d given during user switch, resetting to default.", __FUNCTION__, newUserId); newUserId = DEFAULT_LAST_USER_ID; } mLastUserId = newUserId; // Current user has switched, evict all current clients. std::vector<sp<BasicClient>> evicted; for (auto& i : mActiveClientManager.getAll()) { auto clientSp = i->getValue(); if (clientSp.get() == nullptr) { ALOGE("%s: Dead client still in mActiveClientManager.", __FUNCTION__); continue; } evicted.push_back(clientSp); String8 curTime = getFormattedCurrentTime(); ALOGE("Evicting conflicting client for camera ID %s due to user change", i->getKey().string()); // Log the clients evicted mEventLog.add(String8::format("%s : EVICT device %s client for package %s (PID %" PRId32 ", priority %" PRId32 ")\n - Evicted due to user switch.", curTime.string(), i->getKey().string(), String8{clientSp->getPackageName()}.string(), i->getOwnerId(), i->getPriority())); } // Do not hold mServiceLock while disconnecting clients, but retain the condition // blocking other clients from connecting in mServiceLockWrapper if held. mServiceLock.unlock(); // Clear caller identity temporarily so client disconnect PID checks work correctly int64_t token = IPCThreadState::self()->clearCallingIdentity(); for (auto& i : evicted) { i->disconnect(); } IPCThreadState::self()->restoreCallingIdentity(token); // Reacquire mServiceLock mServiceLock.lock(); } void CameraService::logDisconnected(const String8& cameraId, int clientPid, const String8& clientPackage) { Loading @@ -1411,16 +1488,18 @@ void CameraService::logConnected(const String8& cameraId, int clientPid, curTime.string(), cameraId.string(), clientPackage.string(), clientPid)); } status_t CameraService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { const int pid = getCallingPid(); const int selfPid = getpid(); // Permission checks switch (code) { case BnCameraService::CONNECT: case BnCameraService::CONNECT_DEVICE: case BnCameraService::CONNECT_LEGACY: const int pid = getCallingPid(); const int self_pid = getpid(); if (pid != self_pid) { case BnCameraService::CONNECT_LEGACY: { if (pid != selfPid) { // we're called from a different process, do the real check if (!checkCallingPermission( String16("android.permission.CAMERA"))) { Loading @@ -1432,6 +1511,21 @@ status_t CameraService::onTransact( } break; } case BnCameraService::NOTIFY_SYSTEM_EVENT: { if (pid != selfPid) { // Ensure we're being called by system_server, or similar process with // permissions to notify the camera service about system events if (!checkCallingPermission( String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) { const int uid = getCallingUid(); ALOGE("Permission Denial: cannot send updates to camera service about system" " events from pid=%d, uid=%d", pid, uid); return PERMISSION_DENIED; } } break; } } return BnCameraService::onTransact(code, data, reply, flags); } Loading Loading @@ -1544,7 +1638,11 @@ CameraService::BasicClient::~BasicClient() { } void CameraService::BasicClient::disconnect() { if (mDisconnected) return; if (mDisconnected) { ALOGE("%s: Disconnect called on already disconnected client for device %d", __FUNCTION__, mCameraId); return; } mDisconnected = true;; mCameraService->removeByClient(this); Loading
services/camera/libcameraservice/CameraService.h +24 −6 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H #include <cutils/multiuser.h> #include <utils/Vector.h> #include <utils/KeyedVector.h> #include <binder/AppOpsManager.h> Loading Loading @@ -92,6 +93,11 @@ public: // Default number of messages to store in eviction log static const size_t DEFAULT_EVICTION_LOG_LENGTH = 50; enum { // Default last user id DEFAULT_LAST_USER_ID = 0, }; // Implementation of BinderService<T> static char const* getServiceName() { return "media.camera"; } Loading Loading @@ -145,6 +151,8 @@ public: virtual status_t setTorchMode(const String16& cameraId, bool enabled, const sp<IBinder>& clientBinder); virtual void notifySystemEvent(int eventId, int arg0); // OK = supports api of that version, -EOPNOTSUPP = does not support virtual status_t supportsCameraApi( int cameraId, int apiVersion); Loading Loading @@ -447,7 +455,7 @@ private: virtual void onFirstRef(); // Check if we can connect, before we acquire the service lock. status_t validateConnect(const String8& cameraId, /*inout*/int& clientUid) const; status_t validateConnectLocked(const String8& cameraId, /*inout*/int& clientUid) const; // Handle active client evictions, and update service state. // Only call with with mServiceLock held. Loading Loading @@ -485,6 +493,9 @@ private: // Circular buffer for storing event logging for dumps RingBuffer<String8> mEventLog; // UID of last user. int mLastUserId; /** * Get the camera state for a given camera id. * Loading Loading @@ -529,6 +540,11 @@ private: */ sp<CameraService::BasicClient> removeClientLocked(const String8& cameraId); /** * Handle a notification that the current device user has changed. */ void doUserSwitch(int newUserId); /** * Add a event log message that a client has been disconnected. */ Loading Loading @@ -702,22 +718,24 @@ status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String "Camera API version %d", clientPid, clientName8.string(), cameraId.string(), halVersion, static_cast<int>(effectiveApiLevel)); // Enforce client permissions and do basic sanity checks if((ret = validateConnect(cameraId, /*inout*/clientUid)) != NO_ERROR) { return ret; } sp<CLIENT> client = nullptr; { // Acquire mServiceLock and prevent other clients from connecting std::unique_ptr<AutoConditionLock> lock = AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS); if (lock == nullptr) { ALOGE("CameraService::connect X (PID %d) rejected (too many other clients connecting)." , clientPid); return -EBUSY; } // Enforce client permissions and do basic sanity checks if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) { return ret; } mLastUserId = multiuser_get_user_id(clientUid); // Check the shim parameters after acquiring lock, if they have already been updated and // we were doing a shim update, return immediately if (shimUpdateOnly) { Loading