summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camera/ICameraService.cpp28
-rw-r--r--include/camera/ICameraService.h2
-rw-r--r--services/camera/libcameraservice/CameraService.cpp83
-rw-r--r--services/camera/libcameraservice/CameraService.h34
4 files changed, 102 insertions, 45 deletions
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 51a775b..a02dbe2 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -20,6 +20,7 @@
#include <utils/Errors.h>
#include <utils/String16.h>
+#include <inttypes.h>
#include <stdint.h>
#include <sys/types.h>
@@ -303,10 +304,10 @@ public:
return res;
}
- virtual void notifySystemEvent(int eventId, int arg0) {
+ virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t len) {
Parcel data, reply;
data.writeInt32(eventId);
- data.writeInt32(arg0);
+ data.writeInt32Array(len, args);
remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply,
IBinder::FLAG_ONEWAY);
}
@@ -481,9 +482,26 @@ status_t BnCameraService::onTransact(
} break;
case NOTIFY_SYSTEM_EVENT: {
CHECK_INTERFACE(ICameraService, data, reply);
- int eventId = data.readInt32();
- int arg0 = data.readInt32();
- notifySystemEvent(eventId, arg0);
+ int32_t eventId = data.readInt32();
+ int32_t len = data.readInt32();
+ if (len < 0) {
+ ALOGE("%s: Received poorly formatted length in binder request: notifySystemEvent.",
+ __FUNCTION__);
+ return FAILED_TRANSACTION;
+ }
+ if (len > 512) {
+ ALOGE("%s: Length %" PRIi32 " too long in binder request: notifySystemEvent.",
+ __FUNCTION__, len);
+ return FAILED_TRANSACTION;
+ }
+ int32_t events[len] = {};
+ status_t status = data.read(events, sizeof(int32_t) * len);
+ if (status != NO_ERROR) {
+ ALOGE("%s: Received poorly formatted binder request: notifySystemEvent.",
+ __FUNCTION__);
+ return FAILED_TRANSACTION;
+ }
+ notifySystemEvent(eventId, events, len);
return NO_ERROR;
} break;
default:
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index cad275e..5f85635 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -164,7 +164,7 @@ public:
/**
* Notify the camera service of a system event. Should only be called from system_server.
*/
- virtual void notifySystemEvent(int eventId, int arg0) = 0;
+ virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 59e1c37..fc9a332 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -122,8 +122,8 @@ static void torch_mode_status_change(
// should be ok for now.
static CameraService *gCameraService;
-CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH),
- mLastUserId(DEFAULT_LAST_USER_ID), mSoundRef(0), mModule(0), mFlashlight(0) {
+CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH), mAllowedUsers(),
+ mSoundRef(0), mModule(0), mFlashlight(0) {
ALOGI("CameraService started (pid=%d)", getpid());
gCameraService = this;
@@ -676,6 +676,20 @@ status_t CameraService::makeClient(const sp<CameraService>& cameraService,
return NO_ERROR;
}
+String8 CameraService::toString(std::set<userid_t> intSet) {
+ String8 s("");
+ bool first = true;
+ for (userid_t i : intSet) {
+ if (first) {
+ s.appendFormat("%d", i);
+ first = false;
+ } else {
+ s.appendFormat(", %d", i);
+ }
+ }
+ return s;
+}
+
status_t CameraService::initializeShimMetadata(int cameraId) {
int uid = getCallingUid();
@@ -783,7 +797,7 @@ status_t CameraService::validateConnectLocked(const String8& cameraId, /*inout*/
// Check device policy for this camera
char value[PROPERTY_VALUE_MAX];
char key[PROPERTY_KEY_MAX];
- int clientUserId = multiuser_get_user_id(clientUid);
+ userid_t clientUserId = multiuser_get_user_id(clientUid);
snprintf(key, PROPERTY_KEY_MAX, "sys.secpolicy.camera.off_%d", clientUserId);
property_get(key, value, "0");
if (strcmp(value, "1") == 0) {
@@ -795,10 +809,10 @@ status_t CameraService::validateConnectLocked(const String8& cameraId, /*inout*/
// Only allow clients who are being used by the current foreground device user, unless calling
// from our own process.
- if (callingPid != getpid() &&
- (mLastUserId != clientUserId && mLastUserId != DEFAULT_LAST_USER_ID)) {
- ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from previous "
- "device user %d, current device user %d)", callingPid, clientUserId, mLastUserId);
+ if (callingPid != getpid() && (mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) {
+ ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from "
+ "device user %d, currently allowed device users: %s)", callingPid, clientUserId,
+ toString(mAllowedUsers).string());
return PERMISSION_DENIED;
}
@@ -1197,10 +1211,10 @@ status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
return OK;
}
-void CameraService::notifySystemEvent(int eventId, int arg0) {
+void CameraService::notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) {
switch(eventId) {
case ICameraService::USER_SWITCHED: {
- doUserSwitch(/*newUserId*/arg0);
+ doUserSwitch(/*newUserIds*/args, /*length*/length);
break;
}
case ICameraService::NO_EVENT:
@@ -1443,20 +1457,30 @@ sp<CameraService::BasicClient> CameraService::removeClientLocked(const String8&
return clientDescriptorPtr->getValue();
}
-void CameraService::doUserSwitch(int newUserId) {
+void CameraService::doUserSwitch(const int32_t* newUserId, size_t length) {
// 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;
+ std::set<userid_t> newAllowedUsers;
+ for (size_t i = 0; i < length; i++) {
+ if (newUserId[i] < 0) {
+ ALOGE("%s: Bad user ID %d given during user switch, ignoring.",
+ __FUNCTION__, newUserId[i]);
+ return;
+ }
+ newAllowedUsers.insert(static_cast<userid_t>(newUserId[i]));
+ }
+
+
+ if (newAllowedUsers == mAllowedUsers) {
+ ALOGW("%s: Received notification of user switch with no updated user IDs.", __FUNCTION__);
+ return;
}
- logUserSwitch(mLastUserId, newUserId);
+ logUserSwitch(mAllowedUsers, newAllowedUsers);
- mLastUserId = newUserId;
+ mAllowedUsers = std::move(newAllowedUsers);
// Current user has switched, evict all current clients.
std::vector<sp<BasicClient>> evicted;
@@ -1468,6 +1492,13 @@ void CameraService::doUserSwitch(int newUserId) {
continue;
}
+ // Don't evict clients that are still allowed.
+ uid_t clientUid = clientSp->getClientUid();
+ userid_t clientUserId = multiuser_get_user_id(clientUid);
+ if (mAllowedUsers.find(clientUserId) != mAllowedUsers.end()) {
+ continue;
+ }
+
evicted.push_back(clientSp);
String8 curTime = getFormattedCurrentTime();
@@ -1527,10 +1558,13 @@ void CameraService::logRejected(const char* cameraId, int clientPid,
cameraId, clientPackage, clientPid, reason));
}
-void CameraService::logUserSwitch(int oldUserId, int newUserId) {
+void CameraService::logUserSwitch(const std::set<userid_t>& oldUserIds,
+ const std::set<userid_t>& newUserIds) {
+ String8 newUsers = toString(newUserIds);
+ String8 oldUsers = toString(oldUserIds);
// Log the new and old users
- logEvent(String8::format("USER_SWITCH from old user: %d , to new user: %d", oldUserId,
- newUserId));
+ logEvent(String8::format("USER_SWITCH previous allowed users: %s , current allowed users: %s",
+ oldUsers.string(), newUsers.string()));
}
void CameraService::logDeviceRemoved(const char* cameraId, const char* reason) {
@@ -1735,6 +1769,10 @@ int CameraService::BasicClient::getClientPid() const {
return mClientPid;
}
+uid_t CameraService::BasicClient::getClientUid() const {
+ return mClientUid;
+}
+
bool CameraService::BasicClient::canCastToApiClient(apiLevel level) const {
// Defaults to API2.
return level == API_2;
@@ -1937,12 +1975,18 @@ String8 CameraService::CameraClientManager::toString() const {
auto conflicting = i->getConflicting();
auto clientSp = i->getValue();
String8 packageName;
+ userid_t clientUserId;
if (clientSp.get() != nullptr) {
packageName = String8{clientSp->getPackageName()};
+ uid_t clientUid = clientSp->getClientUid();
+ clientUserId = multiuser_get_user_id(clientUid);
}
ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Priority: %"
PRId32 ", ", key.string(), cost, pid, priority);
+ if (clientSp.get() != nullptr) {
+ ret.appendFormat("User Id: %d, ", clientUserId);
+ }
if (packageName.size() != 0) {
ret.appendFormat("Client Package Name: %s", packageName.string());
}
@@ -2025,6 +2069,7 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
result.appendFormat("Number of camera devices: %d\n", mNumberOfCameras);
String8 activeClientString = mActiveClientManager.toString();
result.appendFormat("Active Camera Clients:\n%s", activeClientString.string());
+ result.appendFormat("Allowed users:\n%s\n", toString(mAllowedUsers).string());
sp<VendorTagDescriptor> desc = VendorTagDescriptor::getGlobalVendorTagDescriptor();
if (desc == NULL) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 1041550..9b7163a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -83,11 +83,6 @@ public:
// Default number of messages to store in eviction log
static const size_t DEFAULT_EVENT_LOG_LENGTH = 100;
- enum {
- // Default last user id
- DEFAULT_LAST_USER_ID = 0,
- };
-
// Implementation of BinderService<T>
static char const* getServiceName() { return "media.camera"; }
@@ -141,7 +136,7 @@ public:
virtual status_t setTorchMode(const String16& cameraId, bool enabled,
const sp<IBinder>& clientBinder);
- virtual void notifySystemEvent(int eventId, int arg0);
+ virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t length);
// OK = supports api of that version, -EOPNOTSUPP = does not support
virtual status_t supportsCameraApi(
@@ -200,6 +195,9 @@ public:
virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
const CaptureResultExtras& resultExtras) = 0;
+ // Get the UID of the application client using this
+ virtual uid_t getClientUid() const;
+
// Get the PID of the application client using this
virtual int getClientPid() const;
@@ -469,7 +467,6 @@ private:
const String16& clientPackageName, int clientUid, apiLevel effectiveApiLevel,
bool legacyMode, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
-
// Lock guarding camera service state
Mutex mServiceLock;
@@ -492,8 +489,8 @@ private:
RingBuffer<String8> mEventLog;
Mutex mLogLock;
- // UID of last user.
- int mLastUserId;
+ // Currently allowed user IDs
+ std::set<userid_t> mAllowedUsers;
/**
* Get the camera state for a given camera id.
@@ -542,7 +539,7 @@ private:
/**
* Handle a notification that the current device user has changed.
*/
- void doUserSwitch(int newUserId);
+ void doUserSwitch(const int32_t* newUserId, size_t length);
/**
* Add an event log message.
@@ -568,7 +565,8 @@ private:
/**
* Add an event log message that the current device user has been switched.
*/
- void logUserSwitch(int oldUserId, int newUserId);
+ void logUserSwitch(const std::set<userid_t>& oldUserIds,
+ const std::set<userid_t>& newUserIds);
/**
* Add an event log message that a device has been removed by the HAL
@@ -699,6 +697,11 @@ 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);
+
+ static String8 toString(std::set<userid_t> intSet);
+
};
template<class Func>
@@ -775,15 +778,6 @@ status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String
if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) {
return ret;
}
- int userId = multiuser_get_user_id(clientUid);
-
- if (userId != mLastUserId && clientPid != getpid() ) {
- // If no previous user ID had been set, set to the user of the caller.
- logUserSwitch(mLastUserId, userId);
- LOG_ALWAYS_FATAL_IF(mLastUserId != DEFAULT_LAST_USER_ID,
- "Invalid state: Should never update user ID here unless was default");
- mLastUserId = userId;
- }
// Check the shim parameters after acquiring lock, if they have already been updated and
// we were doing a shim update, return immediately