From 99f8b24930f5fa70fbb93921d67e0db48eb81b20 Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Wed, 29 Apr 2015 17:36:58 -0700 Subject: Camera: API1 shim: Don't tightly apply crop region Due to older HAL compatibility, we have been setting a tight crop region that just bounds the current output streams. However, this did not take into account any possible ZSL output stream, so correct application of our stream cropping rules to ZSL results in double-crop scenarios, if the ZSL stream aspect ratio does not match the aspect ratio of the other output streams. Since all current HALs follow the correct stream cropping rules (or at least sufficiently ignore them for ZSL), simplify the cropping substantially - now either calculate the crop region based purely off the active array dimensions and zoom factor, or purely off the preview stream and zoom factor. The former is used for setting the request crop, and the latter is used for converting coordinates for metering regions. Bug: 20316691 Change-Id: I5a0bc2e7c09cf60fbae4220566540ca9e674d652 --- .../libcameraservice/api1/client2/Parameters.cpp | 117 ++++++--------------- .../libcameraservice/api1/client2/Parameters.h | 13 +-- 2 files changed, 37 insertions(+), 93 deletions(-) diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp index 6b0f8b5..c3a6842 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp @@ -2100,12 +2100,7 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { delete[] reqMeteringAreas; - /* don't include jpeg thumbnail size - it's valid for - it to be set to (0,0), meaning 'no thumbnail' */ - CropRegion crop = calculateCropRegion( (CropRegion::Outputs)( - CropRegion::OUTPUT_PREVIEW | - CropRegion::OUTPUT_VIDEO | - CropRegion::OUTPUT_PICTURE )); + CropRegion crop = calculateCropRegion(/*previewOnly*/ false); int32_t reqCropRegion[4] = { static_cast(crop.left), static_cast(crop.top), @@ -2603,7 +2598,7 @@ int Parameters::cropXToArray(int x) const { ALOG_ASSERT(x >= 0, "Crop-relative X coordinate = '%d' is out of bounds" "(lower = 0)", x); - CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW); + CropRegion previewCrop = calculateCropRegion(/*previewOnly*/ true); ALOG_ASSERT(x < previewCrop.width, "Crop-relative X coordinate = '%d' " "is out of bounds (upper = %f)", x, previewCrop.width); @@ -2619,7 +2614,7 @@ int Parameters::cropYToArray(int y) const { ALOG_ASSERT(y >= 0, "Crop-relative Y coordinate = '%d' is out of bounds " "(lower = 0)", y); - CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW); + CropRegion previewCrop = calculateCropRegion(/*previewOnly*/ true); ALOG_ASSERT(y < previewCrop.height, "Crop-relative Y coordinate = '%d' is " "out of bounds (upper = %f)", y, previewCrop.height); @@ -2634,12 +2629,12 @@ int Parameters::cropYToArray(int y) const { } int Parameters::normalizedXToCrop(int x) const { - CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW); + CropRegion previewCrop = calculateCropRegion(/*previewOnly*/ true); return (x + 1000) * (previewCrop.width - 1) / 2000; } int Parameters::normalizedYToCrop(int y) const { - CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW); + CropRegion previewCrop = calculateCropRegion(/*previewOnly*/ true); return (y + 1000) * (previewCrop.height - 1) / 2000; } @@ -2855,8 +2850,7 @@ Vector Parameters::getAvailableJpegSizes() { return jpegSizes; } -Parameters::CropRegion Parameters::calculateCropRegion( - Parameters::CropRegion::Outputs outputs) const { +Parameters::CropRegion Parameters::calculateCropRegion(bool previewOnly) const { float zoomLeft, zoomTop, zoomWidth, zoomHeight; @@ -2880,90 +2874,45 @@ Parameters::CropRegion Parameters::calculateCropRegion( maxDigitalZoom.data.f[0], zoomIncrement, zoomRatio, previewWidth, previewHeight, fastInfo.arrayWidth, fastInfo.arrayHeight); - /* - * Assumption: On the HAL side each stream buffer calculates its crop - * rectangle as follows: - * cropRect = (zoomLeft, zoomRight, - * zoomWidth, zoomHeight * zoomWidth / outputWidth); - * - * Note that if zoomWidth > bufferWidth, the new cropHeight > zoomHeight - * (we can then get into trouble if the cropHeight > arrayHeight). - * By selecting the zoomRatio based on the smallest outputRatio, we - * guarantee this will never happen. - */ + if (previewOnly) { + // Calculate a tight crop region for the preview stream only + float previewRatio = static_cast(previewWidth) / previewHeight; - // Enumerate all possible output sizes, select the one with the smallest - // aspect ratio - float minOutputWidth, minOutputHeight, minOutputRatio; - { - float outputSizes[][2] = { - { static_cast(previewWidth), - static_cast(previewHeight) }, - { static_cast(videoWidth), - static_cast(videoHeight) }, - { static_cast(jpegThumbSize[0]), - static_cast(jpegThumbSize[1]) }, - { static_cast(pictureWidth), - static_cast(pictureHeight) }, - }; - - minOutputWidth = outputSizes[0][0]; - minOutputHeight = outputSizes[0][1]; - minOutputRatio = minOutputWidth / minOutputHeight; - for (unsigned int i = 0; - i < sizeof(outputSizes) / sizeof(outputSizes[0]); - ++i) { - - // skip over outputs we don't want to consider for the crop region - if ( !((1 << i) & outputs) ) { - continue; - } - - float outputWidth = outputSizes[i][0]; - float outputHeight = outputSizes[i][1]; - float outputRatio = outputWidth / outputHeight; - - if (minOutputRatio > outputRatio) { - minOutputRatio = outputRatio; - minOutputWidth = outputWidth; - minOutputHeight = outputHeight; - } + /* Ensure that the width/height never go out of bounds + * by scaling across a diffent dimension if an out-of-bounds + * possibility exists. + * + * e.g. if the previewratio < arrayratio and e.g. zoomratio = 1.0, then by + * calculating the zoomWidth from zoomHeight we'll actually get a + * zoomheight > arrayheight + */ + float arrayRatio = 1.f * fastInfo.arrayWidth / fastInfo.arrayHeight; + if (previewRatio >= arrayRatio) { + // Adjust the height based on the width + zoomWidth = fastInfo.arrayWidth / zoomRatio; + zoomHeight = zoomWidth * + previewHeight / previewWidth; - // and then use this output ratio instead of preview output ratio - ALOGV("Enumerating output ratio %f = %f / %f, min is %f", - outputRatio, outputWidth, outputHeight, minOutputRatio); + } else { + // Adjust the width based on the height + zoomHeight = fastInfo.arrayHeight / zoomRatio; + zoomWidth = zoomHeight * + previewWidth / previewHeight; } - } - - /* Ensure that the width/height never go out of bounds - * by scaling across a diffent dimension if an out-of-bounds - * possibility exists. - * - * e.g. if the previewratio < arrayratio and e.g. zoomratio = 1.0, then by - * calculating the zoomWidth from zoomHeight we'll actually get a - * zoomheight > arrayheight - */ - float arrayRatio = 1.f * fastInfo.arrayWidth / fastInfo.arrayHeight; - if (minOutputRatio >= arrayRatio) { - // Adjust the height based on the width - zoomWidth = fastInfo.arrayWidth / zoomRatio; - zoomHeight = zoomWidth * - minOutputHeight / minOutputWidth; - } else { - // Adjust the width based on the height + // Calculate the global crop region with a shape matching the active + // array. + zoomWidth = fastInfo.arrayWidth / zoomRatio; zoomHeight = fastInfo.arrayHeight / zoomRatio; - zoomWidth = zoomHeight * - minOutputWidth / minOutputHeight; } - // centering the zoom area within the active area + + // center the zoom area within the active area zoomLeft = (fastInfo.arrayWidth - zoomWidth) / 2; zoomTop = (fastInfo.arrayHeight - zoomHeight) / 2; ALOGV("Crop region calculated (x=%d,y=%d,w=%f,h=%f) for zoom=%d", (int32_t)zoomLeft, (int32_t)zoomTop, zoomWidth, zoomHeight, this->zoom); - CropRegion crop = { zoomLeft, zoomTop, zoomWidth, zoomHeight }; return crop; } diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h index e628a7e..46d48bc 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.h +++ b/services/camera/libcameraservice/api1/client2/Parameters.h @@ -271,21 +271,16 @@ struct Parameters { // if video snapshot size is currently overridden bool isJpegSizeOverridden(); - // Calculate the crop region rectangle based on current stream sizes + // Calculate the crop region rectangle, either tightly about the preview + // resolution, or a region just based on the active array; both take + // into account the current zoom level. struct CropRegion { float left; float top; float width; float height; - - enum Outputs { - OUTPUT_PREVIEW = 0x01, - OUTPUT_VIDEO = 0x02, - OUTPUT_JPEG_THUMBNAIL = 0x04, - OUTPUT_PICTURE = 0x08, - }; }; - CropRegion calculateCropRegion(CropRegion::Outputs outputs) const; + CropRegion calculateCropRegion(bool previewOnly) const; // Calculate the field of view of the high-resolution JPEG capture status_t calculatePictureFovs(float *horizFov, float *vertFov) const; -- cgit v1.1 From 781f40ad2eacd5e6944b9c17d04a800360d97768 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Wed, 6 May 2015 11:52:24 -0700 Subject: stagefright: fix pushBlankBuffersToNW for non-meta decoders Bug: 20709429 Change-Id: Ifaee74083dedecb755e5c8ba3369cf90dfd74035 --- media/libstagefright/ACodec.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index b7798d2..22395cc 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -4156,6 +4156,9 @@ status_t ACodec::pushBlankBuffersToNativeWindow() { goto error; } + static_cast(mNativeWindow.get()) + ->getIGraphicBufferProducer()->allowAllocation(true); + err = mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); if (err != NO_ERROR) { -- cgit v1.1 From f34885409f15aea16a1d8a2258eb8ca434a96bb5 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 7 May 2015 15:35:42 -0700 Subject: Revert "Enable full floating point path in AudioMixer" This reverts commit 5b8fde71e08f57478ef25d040fc5f66294011ac6. temporary revert while we investigate. Bug: 20912450. --- services/audioflinger/AudioMixer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index 7040af4..193fd64 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -66,9 +66,9 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) #endif -// Set kUseNewMixer to true to use the new mixer engine always. Otherwise the -// original code will be used for stereo sinks, the new mixer for multichannel. -static const bool kUseNewMixer = true; +// Set kUseNewMixer to true to use the new mixer engine. Otherwise the +// original code will be used. This is false for now. +static const bool kUseNewMixer = false; // Set kUseFloat to true to allow floating input into the mixer engine. // If kUseNewMixer is false, this is ignored or may be overridden internally -- cgit v1.1 From 97ebb1beb6b5d1dc36166352c445c0b81cbacccb Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Thu, 14 May 2015 13:50:57 -0700 Subject: camera2: Fix empty set handling for eviction. Bug: 20304829 Change-Id: I120ed6e41ca592c3770797a5fb1e5ce556543949 --- .../camera/libcameraservice/utils/ClientManager.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h index aa40a2d..5afb7a3 100644 --- a/services/camera/libcameraservice/utils/ClientManager.h +++ b/services/camera/libcameraservice/utils/ClientManager.h @@ -432,15 +432,17 @@ std::vector>> ClientManager>& curClientPtr) { - if (curClientPtr->getKey() == (*iter)->getKey()) { - iter++; - return true; - } - return false; - }), mClients.end()); + if (iter != evicted.cend()) { + // Remove evicted clients from list + mClients.erase(std::remove_if(mClients.begin(), mClients.end(), + [&iter] (std::shared_ptr>& curClientPtr) { + if (curClientPtr->getKey() == (*iter)->getKey()) { + iter++; + return true; + } + return false; + }), mClients.end()); + } mClients.push_back(client); mRemovedCondition.broadcast(); -- cgit v1.1 From 053119cdf5f115097cf3f69784b6d78e623eb60c Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Thu, 30 Apr 2015 17:44:07 -0700 Subject: camera2: Fix work-profile eviction handling. Bug: 20124384 Change-Id: I6fb82dbfd5f98746ed4befed81a583e3709bfee8 --- camera/ICameraService.cpp | 28 ++++++-- include/camera/ICameraService.h | 2 +- services/camera/libcameraservice/CameraService.cpp | 83 +++++++++++++++++----- services/camera/libcameraservice/CameraService.h | 34 ++++----- 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 #include +#include #include #include @@ -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, return NO_ERROR; } +String8 CameraService::toString(std::set 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::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 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 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(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> 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& oldUserIds, + const std::set& 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& 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 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 static char const* getServiceName() { return "media.camera"; } @@ -141,7 +136,7 @@ public: virtual status_t setTorchMode(const String16& cameraId, bool enabled, const sp& 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& device); - // Lock guarding camera service state Mutex mServiceLock; @@ -492,8 +489,8 @@ private: RingBuffer mEventLog; Mutex mLogLock; - // UID of last user. - int mLastUserId; + // Currently allowed user IDs + std::set 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& oldUserIds, + const std::set& 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* client); + + status_t checkCameraAccess(const String16& opPackageName); + + static String8 toString(std::set intSet); + }; template @@ -775,15 +778,6 @@ status_t CameraService::connectHelper(const sp& 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 -- cgit v1.1 From 11ad1b8bec5f8daa10ec023153e95eba46a4fbff Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Tue, 19 May 2015 10:56:40 -0700 Subject: stagefright: don't use stale pointer after disconnecting NuCachedSource2 bug: 20858729 Change-Id: I7d680accb43a4aa08620acd96659b97e80d1a5e8 --- media/libstagefright/NuCachedSource2.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp index 1c53b40..f82636b 100644 --- a/media/libstagefright/NuCachedSource2.cpp +++ b/media/libstagefright/NuCachedSource2.cpp @@ -583,6 +583,13 @@ ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) { Mutex::Autolock autoLock(mLock); + // If we're disconnecting, return EOS and don't access *data pointer. + // data could be on the stack of the caller to NuCachedSource2::readAt(), + // which may have exited already. + if (mDisconnecting) { + return ERROR_END_OF_STREAM; + } + if (!mFetching) { mLastAccessPos = offset; restartPrefetcherIfNecessary_l( -- cgit v1.1 From 893343f7f06a9aeff17ff5faecd4df97faf134df Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Tue, 19 May 2015 17:25:13 -0700 Subject: camera: Add AIDL interface for CameraServiceProxy. - Adds an AIDL interface to allow the proxy camera service running in system server to accept RPCs from the camera service running in mediaserver. - Request an update to the valid user set from the proxy camera service when mediaserver restarts to initialize properly + avoid DOS after a crash. Bug: 21267484 Change-Id: Ib821582794ddd1e3574b5dc6c79f7cb197b57f10 --- camera/Android.mk | 1 + camera/ICameraServiceProxy.cpp | 55 ++++++++++++++++++++++ include/camera/ICameraServiceProxy.h | 52 ++++++++++++++++++++ services/camera/libcameraservice/CameraService.cpp | 13 +++++ services/camera/libcameraservice/CameraService.h | 2 + 5 files changed, 123 insertions(+) create mode 100644 camera/ICameraServiceProxy.cpp create mode 100644 include/camera/ICameraServiceProxy.h diff --git a/camera/Android.mk b/camera/Android.mk index 4c4700b..471cb0d 100644 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES:= \ ICameraClient.cpp \ ICameraService.cpp \ ICameraServiceListener.cpp \ + ICameraServiceProxy.cpp \ ICameraRecordingProxy.cpp \ ICameraRecordingProxyListener.cpp \ camera2/ICameraDeviceUser.cpp \ diff --git a/camera/ICameraServiceProxy.cpp b/camera/ICameraServiceProxy.cpp new file mode 100644 index 0000000..06a5afb --- /dev/null +++ b/camera/ICameraServiceProxy.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015 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 "BpCameraServiceProxy" + +#include + +#include + +#include + +namespace android { + +class BpCameraServiceProxy: public BpInterface { +public: + BpCameraServiceProxy(const sp& impl) : BpInterface(impl) {} + + virtual void pingForUserUpdate() { + Parcel data, reply; + data.writeInterfaceToken(ICameraServiceProxy::getInterfaceDescriptor()); + remote()->transact(BnCameraServiceProxy::PING_FOR_USER_UPDATE, data, &reply, + IBinder::FLAG_ONEWAY); + } +}; + + +IMPLEMENT_META_INTERFACE(CameraServiceProxy, "android.hardware.ICameraServiceProxy"); + +status_t BnCameraServiceProxy::onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags) { + switch(code) { + case PING_FOR_USER_UPDATE: { + CHECK_INTERFACE(ICameraServiceProxy, data, reply); + pingForUserUpdate(); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} +}; // namespace android + diff --git a/include/camera/ICameraServiceProxy.h b/include/camera/ICameraServiceProxy.h new file mode 100644 index 0000000..12a555f --- /dev/null +++ b/include/camera/ICameraServiceProxy.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef ANDROID_HARDWARE_ICAMERASERVICEPROXY_H +#define ANDROID_HARDWARE_ICAMERASERVICEPROXY_H + +#include +#include +#include + +namespace android { + +class ICameraServiceProxy : public IInterface { +public: + enum { + PING_FOR_USER_UPDATE = IBinder::FIRST_CALL_TRANSACTION, + }; + + DECLARE_META_INTERFACE(CameraServiceProxy); + + virtual void pingForUserUpdate() = 0; +}; + +class BnCameraServiceProxy: public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + + + +}; // namespace android + +#endif // ANDROID_HARDWARE_ICAMERASERVICEPROXY_H + + diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 82aa566..79e73f9 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,18 @@ void CameraService::onFirstRef() } CameraDeviceFactory::registerService(this); + + CameraService::pingCameraServiceProxy(); +} + +void CameraService::pingCameraServiceProxy() { + sp sm = defaultServiceManager(); + sp binder = sm->getService(String16("media.camera.proxy")); + if (binder == nullptr) { + return; + } + sp proxyBinder = interface_cast(binder); + proxyBinder->pingForUserUpdate(); } CameraService::~CameraService() { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 9b7163a..ce3cb44 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -702,6 +702,8 @@ private: static String8 toString(std::set intSet); + static void pingCameraServiceProxy(); + }; template -- cgit v1.1 From 1b4fa53af7d69185d0f12783f793b653a230eb03 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Wed, 10 Jun 2015 11:07:37 -0700 Subject: stagefright: fix legacy support for CameraSource - allocate big enough buffers for native metadata source even in CameraSource mode - don't check range when using native metadata mode (and converting it to GrallocSource) as OMX buffer will be smaller than input - log allocated vs. OMX reported sizes in OMXNodeInstance logs Bug: 21708032 Change-Id: I7eeffc5116079e5b368f84980e8e7524260aaccf --- media/libstagefright/ACodec.cpp | 7 ++++-- media/libstagefright/omx/OMXNodeInstance.cpp | 36 +++++++++++++++------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 71cb194..a57d4cf 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -777,10 +777,13 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { // If using gralloc or native source input metadata buffers, allocate largest // metadata size as we prefer to generate native source metadata, but component - // may require gralloc source. + // may require gralloc source. For camera source, allocate at least enough + // size for native metadata buffers. int32_t allottedSize = bufSize; - if (portIndex == kPortIndexInput && type > 0) { + if (portIndex == kPortIndexInput && type >= kMetadataBufferTypeGrallocSource) { bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata)); + } else if (portIndex == kPortIndexInput && type == kMetadataBufferTypeCameraSource) { + bufSize = max(bufSize, (int32_t)sizeof(VideoNativeMetadata)); } ALOGV("[%s] Allocating %u buffers of size %d/%d (from %u using %s) on %s port", diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 7e92da8..692667f 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -683,7 +683,7 @@ status_t OMXNodeInstance::useBuffer( } CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT( - *buffer, portIndex, "%u@%p", allottedSize, params->pointer())); + *buffer, portIndex, "%u(%zu)@%p", allottedSize, params->size(), params->pointer())); return OK; } @@ -1024,8 +1024,8 @@ status_t OMXNodeInstance::allocateBufferWithBackup( bufferSource->addCodecBuffer(header); } - CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%u@%p :> %p", - allottedSize, params->pointer(), header->pBuffer)); + CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p :> %u@%p", + params->size(), params->pointer(), allottedSize, header->pBuffer)); return OK; } @@ -1087,18 +1087,6 @@ status_t OMXNodeInstance::emptyBuffer( Mutex::Autolock autoLock(mLock); OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); - // rangeLength and rangeOffset must be a subset of the allocated data in the buffer. - // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0. - if (rangeOffset > header->nAllocLen - || rangeLength > header->nAllocLen - rangeOffset) { - if (fenceFd >= 0) { - ::close(fenceFd); - } - return BAD_VALUE; - } - header->nFilledLen = rangeLength; - header->nOffset = rangeOffset; - BufferMeta *buffer_meta = static_cast(header->pAppPrivate); sp backup = buffer_meta->getBuffer(header, true /* backup */); @@ -1112,11 +1100,25 @@ status_t OMXNodeInstance::emptyBuffer( == kMetadataBufferTypeANWBuffer) { VideoNativeMetadata &backupMeta = *(VideoNativeMetadata *)backup->base(); VideoGrallocMetadata &codecMeta = *(VideoGrallocMetadata *)codec->base(); - ALOGV("converting ANWB %p to handle %p", backupMeta.pBuffer, backupMeta.pBuffer->handle); + CLOG_BUFFER(emptyBuffer, "converting ANWB %p to handle %p", + backupMeta.pBuffer, backupMeta.pBuffer->handle); codecMeta.pHandle = backupMeta.pBuffer->handle; codecMeta.eType = kMetadataBufferTypeGrallocSource; - header->nFilledLen = sizeof(codecMeta); + header->nFilledLen = rangeLength ? sizeof(codecMeta) : 0; + header->nOffset = 0; } else { + // rangeLength and rangeOffset must be a subset of the allocated data in the buffer. + // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0. + if (rangeOffset > header->nAllocLen + || rangeLength > header->nAllocLen - rangeOffset) { + if (fenceFd >= 0) { + ::close(fenceFd); + } + return BAD_VALUE; + } + header->nFilledLen = rangeLength; + header->nOffset = rangeOffset; + buffer_meta->CopyToOMX(header); } -- cgit v1.1 From d2ff0854bff60d86222deee2d07235bce9d0c8a3 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Fri, 12 Jun 2015 12:52:27 -0700 Subject: stagefright: relax check of OMX buffer header - move check to after FillBufferDone only. - add support for NULL graphicBuffer - just in case Bug: 21773260 Change-Id: I804574c30ce47fd98bf09f5fe8ad00ae454ed1af --- media/libstagefright/omx/OMXNodeInstance.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 6ee1a77..c121163 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -121,9 +121,10 @@ struct BufferMeta { return; } - memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, - header->pBuffer + header->nOffset, - header->nFilledLen); + // check component returns proper range + sp codec = getBuffer(header, false /* backup */, true /* limit */); + + memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, codec->data(), codec->size()); } void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { @@ -137,14 +138,16 @@ struct BufferMeta { } // return either the codec or the backup buffer - sp getBuffer(const OMX_BUFFERHEADERTYPE *header, bool backup) { + sp getBuffer(const OMX_BUFFERHEADERTYPE *header, bool backup, bool limit) { sp buf; if (backup && mMem != NULL) { buf = new ABuffer(mMem->pointer(), mMem->size()); } else { buf = new ABuffer(header->pBuffer, header->nAllocLen); } - buf->setRange(header->nOffset, header->nFilledLen); + if (limit) { + buf->setRange(header->nOffset, header->nFilledLen); + } return buf; } @@ -1089,10 +1092,11 @@ status_t OMXNodeInstance::emptyBuffer( OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); BufferMeta *buffer_meta = static_cast(header->pAppPrivate); - sp backup = buffer_meta->getBuffer(header, true /* backup */); - sp codec = buffer_meta->getBuffer(header, false /* backup */); + sp backup = buffer_meta->getBuffer(header, true /* backup */, false /* limit */); + sp codec = buffer_meta->getBuffer(header, false /* backup */, false /* limit */); // convert incoming ANW meta buffers if component is configured for gralloc metadata mode + // ignore rangeOffset in this case if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource && backup->capacity() >= sizeof(VideoNativeMetadata) && codec->capacity() >= sizeof(VideoGrallocMetadata) @@ -1102,7 +1106,7 @@ status_t OMXNodeInstance::emptyBuffer( VideoGrallocMetadata &codecMeta = *(VideoGrallocMetadata *)codec->base(); CLOG_BUFFER(emptyBuffer, "converting ANWB %p to handle %p", backupMeta.pBuffer, backupMeta.pBuffer->handle); - codecMeta.pHandle = backupMeta.pBuffer->handle; + codecMeta.pHandle = backupMeta.pBuffer != NULL ? backupMeta.pBuffer->handle : NULL; codecMeta.eType = kMetadataBufferTypeGrallocSource; header->nFilledLen = rangeLength ? sizeof(codecMeta) : 0; header->nOffset = 0; -- cgit v1.1