summaryrefslogtreecommitdiffstats
path: root/services/camera
diff options
context:
space:
mode:
authorRuben Brunk <rubenbrunk@google.com>2015-06-02 01:48:21 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-06-02 01:48:23 +0000
commitcb18ec05b7097a63262b81afe1e866105d400f4a (patch)
tree4b13077360dfb54722298be1b793a8df5ddc6d7a /services/camera
parentcc7cc67349b7a3f498882087aa42ffc05a2daf11 (diff)
parent99e69716215cd0665379bc90d708f2ea8689831d (diff)
downloadframeworks_av-cb18ec05b7097a63262b81afe1e866105d400f4a.zip
frameworks_av-cb18ec05b7097a63262b81afe1e866105d400f4a.tar.gz
frameworks_av-cb18ec05b7097a63262b81afe1e866105d400f4a.tar.bz2
Merge "Track camera and flashlight usage in battery stats." into mnc-dev
Diffstat (limited to 'services/camera')
-rw-r--r--services/camera/libcameraservice/Android.mk1
-rw-r--r--services/camera/libcameraservice/CameraService.cpp96
-rw-r--r--services/camera/libcameraservice/CameraService.h26
-rw-r--r--services/camera/libcameraservice/utils/ClientManager.h133
4 files changed, 205 insertions, 51 deletions
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 9c60911..cbead32 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -62,6 +62,7 @@ LOCAL_SHARED_LIBRARIES:= \
libbinder \
libcutils \
libmedia \
+ libmediautils \
libcamera_client \
libgui \
libhardware \
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 79e73f9..6f073ed 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -41,6 +41,7 @@
#include <media/AudioSystem.h>
#include <media/IMediaHTTPService.h>
#include <media/mediaplayer.h>
+#include <mediautils/BatteryNotifier.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/String16.h>
@@ -140,6 +141,11 @@ void CameraService::onFirstRef()
BnCameraService::onFirstRef();
+ // Update battery life tracking if service is restarting
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
+ notifier.noteResetCamera();
+ notifier.noteResetFlashlight();
+
camera_module_t *rawModule;
int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&rawModule);
@@ -336,12 +342,39 @@ void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
res = setTorchStatusLocked(cameraId, newStatus);
if (res) {
- ALOGE("%s: Failed to set the torch status", __FUNCTION__,
- (uint32_t)newStatus);
+ ALOGE("%s: Failed to set the torch status", __FUNCTION__, (uint32_t)newStatus);
return;
}
{
+ // Update battery life logging for flashlight
+ Mutex::Autolock al(mTorchClientMapMutex);
+ auto iter = mTorchUidMap.find(cameraId);
+ if (iter != mTorchUidMap.end()) {
+ int oldUid = iter->second.second;
+ int newUid = iter->second.first;
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
+ if (oldUid != newUid) {
+ // If the UID has changed, log the status and update current UID in mTorchUidMap
+ if (status == ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON) {
+ notifier.noteFlashlightOff(cameraId, oldUid);
+ }
+ if (newStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON) {
+ notifier.noteFlashlightOn(cameraId, newUid);
+ }
+ iter->second.second = newUid;
+ } else {
+ // If the UID has not changed, log the status
+ if (newStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON) {
+ notifier.noteFlashlightOn(cameraId, oldUid);
+ } else {
+ notifier.noteFlashlightOff(cameraId, oldUid);
+ }
+ }
+ }
+ }
+
+ {
Mutex::Autolock lock(mStatusListenerLock);
for (auto& i : mListenerList) {
i->onTorchStatusChanged(newStatus, String16{cameraId});
@@ -1154,12 +1187,13 @@ status_t CameraService::connectDevice(
status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
const sp<IBinder>& clientBinder) {
- if (enabled && clientBinder == NULL) {
+ if (enabled && clientBinder == nullptr) {
ALOGE("%s: torch client binder is NULL", __FUNCTION__);
return -EINVAL;
}
String8 id = String8(cameraId.string());
+ int uid = getCallingUid();
// verify id is valid.
auto state = getCameraState(id);
@@ -1198,7 +1232,21 @@ status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
}
}
+ {
+ // Update UID map - this is used in the torch status changed callbacks, so must be done
+ // before setTorchMode
+ Mutex::Autolock al(mTorchClientMapMutex);
+ if (mTorchUidMap.find(id) == mTorchUidMap.end()) {
+ mTorchUidMap[id].first = uid;
+ mTorchUidMap[id].second = uid;
+ } else {
+ // Set the pending UID
+ mTorchUidMap[id].first = uid;
+ }
+ }
+
status_t res = mFlashlight->setTorchMode(id, enabled);
+
if (res) {
ALOGE("%s: setting torch mode of camera %s to %d failed. %s (%d)",
__FUNCTION__, id.string(), enabled, strerror(-res), res);
@@ -1209,19 +1257,17 @@ status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
// update the link to client's death
Mutex::Autolock al(mTorchClientMapMutex);
ssize_t index = mTorchClientMap.indexOfKey(id);
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
if (enabled) {
if (index == NAME_NOT_FOUND) {
mTorchClientMap.add(id, clientBinder);
} else {
- const sp<IBinder> oldBinder = mTorchClientMap.valueAt(index);
- oldBinder->unlinkToDeath(this);
-
+ mTorchClientMap.valueAt(index)->unlinkToDeath(this);
mTorchClientMap.replaceValueAt(index, clientBinder);
}
clientBinder->linkToDeath(this);
} else if (index != NAME_NOT_FOUND) {
- sp<IBinder> oldBinder = mTorchClientMap.valueAt(index);
- oldBinder->unlinkToDeath(this);
+ mTorchClientMap.valueAt(index)->unlinkToDeath(this);
}
}
@@ -1243,8 +1289,7 @@ void CameraService::notifySystemEvent(int32_t eventId, const int32_t* args, size
}
}
-status_t CameraService::addListener(
- const sp<ICameraServiceListener>& listener) {
+status_t CameraService::addListener(const sp<ICameraServiceListener>& listener) {
ALOGV("%s: Add listener %p", __FUNCTION__, listener.get());
if (listener == 0) {
@@ -1965,9 +2010,40 @@ String8 CameraService::CameraState::getId() const {
}
// ----------------------------------------------------------------------------
+// ClientEventListener
+// ----------------------------------------------------------------------------
+
+void CameraService::ClientEventListener::onClientAdded(
+ const resource_policy::ClientDescriptor<String8,
+ sp<CameraService::BasicClient>>& descriptor) {
+ auto basicClient = descriptor.getValue();
+ if (basicClient.get() != nullptr) {
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
+ notifier.noteStartCamera(descriptor.getKey(),
+ static_cast<int>(basicClient->getClientUid()));
+ }
+}
+
+void CameraService::ClientEventListener::onClientRemoved(
+ const resource_policy::ClientDescriptor<String8,
+ sp<CameraService::BasicClient>>& descriptor) {
+ auto basicClient = descriptor.getValue();
+ if (basicClient.get() != nullptr) {
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
+ notifier.noteStopCamera(descriptor.getKey(),
+ static_cast<int>(basicClient->getClientUid()));
+ }
+}
+
+
+// ----------------------------------------------------------------------------
// CameraClientManager
// ----------------------------------------------------------------------------
+CameraService::CameraClientManager::CameraClientManager() {
+ setListener(std::make_shared<ClientEventListener>());
+}
+
CameraService::CameraClientManager::~CameraClientManager() {}
sp<CameraService::BasicClient> CameraService::CameraClientManager::getCameraClient(
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ce3cb44..3298772 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -46,6 +46,7 @@
#include <string>
#include <map>
#include <memory>
+#include <utility>
namespace android {
@@ -327,6 +328,20 @@ public:
}; // class Client
+ /**
+ * A listener class that implements the LISTENER interface for use with a ClientManager, and
+ * implements the following methods:
+ * void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
+ * void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
+ */
+ class ClientEventListener {
+ public:
+ void onClientAdded(const resource_policy::ClientDescriptor<String8,
+ sp<CameraService::BasicClient>>& descriptor);
+ void onClientRemoved(const resource_policy::ClientDescriptor<String8,
+ sp<CameraService::BasicClient>>& descriptor);
+ }; // class ClientEventListener
+
typedef std::shared_ptr<resource_policy::ClientDescriptor<String8,
sp<CameraService::BasicClient>>> DescriptorPtr;
@@ -338,9 +353,10 @@ public:
* This class manages the eviction behavior for the camera clients. See the parent class
* implementation in utils/ClientManager for the specifics of this behavior.
*/
- class CameraClientManager :
- public resource_policy::ClientManager<String8, sp<CameraService::BasicClient>> {
+ class CameraClientManager : public resource_policy::ClientManager<String8,
+ sp<CameraService::BasicClient>, ClientEventListener> {
public:
+ CameraClientManager();
virtual ~CameraClientManager();
/**
@@ -624,13 +640,15 @@ private:
sp<CameraFlashlight> mFlashlight;
// guard mTorchStatusMap
Mutex mTorchStatusMutex;
- // guard mTorchClientMap
+ // guard mTorchClientMap, mTorchUidMap
Mutex mTorchClientMapMutex;
// camera id -> torch status
KeyedVector<String8, ICameraServiceListener::TorchStatus> mTorchStatusMap;
// camera id -> torch client binder
// only store the last client that turns on each camera's torch mode
- KeyedVector<String8, sp<IBinder> > mTorchClientMap;
+ KeyedVector<String8, sp<IBinder>> mTorchClientMap;
+ // camera id -> [incoming uid, current uid] pair
+ std::map<String8, std::pair<int, int>> mTorchUidMap;
// check and handle if torch client's process has died
void handleTorchClientBinderDied(const wp<IBinder> &who);
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index 5afb7a3..7ae58d5 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -172,6 +172,26 @@ void ClientDescriptor<KEY, VALUE>::setPriority(int32_t priority) {
// --------------------------------------------------------------------------------
/**
+ * A default class implementing the LISTENER interface used by ClientManager.
+ */
+template<class KEY, class VALUE>
+class DefaultEventListener {
+public:
+ void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
+ void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
+};
+
+template<class KEY, class VALUE>
+void DefaultEventListener<KEY, VALUE>::onClientAdded(
+ const ClientDescriptor<KEY, VALUE>& /*descriptor*/) {}
+
+template<class KEY, class VALUE>
+void DefaultEventListener<KEY, VALUE>::onClientRemoved(
+ const ClientDescriptor<KEY, VALUE>& /*descriptor*/) {}
+
+// --------------------------------------------------------------------------------
+
+/**
* The ClientManager class wraps an LRU-ordered list of active clients and implements eviction
* behavior for handling shared resource access.
*
@@ -189,7 +209,7 @@ void ClientDescriptor<KEY, VALUE>::setPriority(int32_t priority) {
* incoming descriptor has the highest priority. Otherwise, the incoming descriptor is
* removed instead.
*/
-template<class KEY, class VALUE>
+template<class KEY, class VALUE, class LISTENER=DefaultEventListener<KEY, VALUE>>
class ClientManager {
public:
// The default maximum "cost" allowed before evicting
@@ -275,6 +295,24 @@ public:
status_t waitUntilRemoved(const std::shared_ptr<ClientDescriptor<KEY, VALUE>> client,
nsecs_t timeout) const;
+ /**
+ * Set the current listener for client add/remove events.
+ *
+ * The listener instance must inherit from the LISTENER class and implement the following
+ * methods:
+ * void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
+ * void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
+ *
+ * These callback methods will be called with the ClientManager's lock held, and should
+ * not call any further ClientManager methods.
+ *
+ * The onClientRemoved method will be called when the client has been removed or evicted
+ * from the ClientManager that this event listener has been added to. The onClientAdded
+ * method will be called when the client has been added to the ClientManager that this
+ * event listener has been added to.
+ */
+ void setListener(const std::shared_ptr<LISTENER>& listener);
+
protected:
~ClientManager();
@@ -300,36 +338,38 @@ private:
int32_t mMaxCost;
// LRU ordered, most recent at end
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> mClients;
+ std::shared_ptr<LISTENER> mListener;
}; // class ClientManager
-template<class KEY, class VALUE>
-ClientManager<KEY, VALUE>::ClientManager() :
+template<class KEY, class VALUE, class LISTENER>
+ClientManager<KEY, VALUE, LISTENER>::ClientManager() :
ClientManager(DEFAULT_MAX_COST) {}
-template<class KEY, class VALUE>
-ClientManager<KEY, VALUE>::ClientManager(int32_t totalCost) : mMaxCost(totalCost) {}
+template<class KEY, class VALUE, class LISTENER>
+ClientManager<KEY, VALUE, LISTENER>::ClientManager(int32_t totalCost) : mMaxCost(totalCost) {}
-template<class KEY, class VALUE>
-ClientManager<KEY, VALUE>::~ClientManager() {}
+template<class KEY, class VALUE, class LISTENER>
+ClientManager<KEY, VALUE, LISTENER>::~ClientManager() {}
-template<class KEY, class VALUE>
-std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VALUE>::wouldEvict(
+template<class KEY, class VALUE, class LISTENER>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
+ClientManager<KEY, VALUE, LISTENER>::wouldEvict(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
Mutex::Autolock lock(mLock);
return wouldEvictLocked(client);
}
-template<class KEY, class VALUE>
+template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
-ClientManager<KEY, VALUE>::getIncompatibleClients(
+ClientManager<KEY, VALUE, LISTENER>::getIncompatibleClients(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
Mutex::Autolock lock(mLock);
return wouldEvictLocked(client, /*returnIncompatibleClients*/true);
}
-template<class KEY, class VALUE>
+template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
-ClientManager<KEY, VALUE>::wouldEvictLocked(
+ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
bool returnIncompatibleClients) const {
@@ -420,8 +460,9 @@ ClientManager<KEY, VALUE>::wouldEvictLocked(
}
-template<class KEY, class VALUE>
-std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VALUE>::addAndEvict(
+template<class KEY, class VALUE, class LISTENER>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
+ClientManager<KEY, VALUE, LISTENER>::addAndEvict(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) {
Mutex::Autolock lock(mLock);
auto evicted = wouldEvictLocked(client);
@@ -433,6 +474,9 @@ std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VA
auto iter = evicted.cbegin();
if (iter != evicted.cend()) {
+
+ if (mListener != nullptr) mListener->onClientRemoved(**iter);
+
// Remove evicted clients from list
mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
[&iter] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
@@ -444,21 +488,22 @@ std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VA
}), mClients.end());
}
+ if (mListener != nullptr) mListener->onClientAdded(*client);
mClients.push_back(client);
mRemovedCondition.broadcast();
return evicted;
}
-template<class KEY, class VALUE>
+template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
-ClientManager<KEY, VALUE>::getAll() const {
+ClientManager<KEY, VALUE, LISTENER>::getAll() const {
Mutex::Autolock lock(mLock);
return mClients;
}
-template<class KEY, class VALUE>
-std::vector<KEY> ClientManager<KEY, VALUE>::getAllKeys() const {
+template<class KEY, class VALUE, class LISTENER>
+std::vector<KEY> ClientManager<KEY, VALUE, LISTENER>::getAllKeys() const {
Mutex::Autolock lock(mLock);
std::vector<KEY> keys(mClients.size());
for (const auto& i : mClients) {
@@ -467,8 +512,8 @@ std::vector<KEY> ClientManager<KEY, VALUE>::getAllKeys() const {
return keys;
}
-template<class KEY, class VALUE>
-std::vector<int32_t> ClientManager<KEY, VALUE>::getAllOwners() const {
+template<class KEY, class VALUE, class LISTENER>
+std::vector<int32_t> ClientManager<KEY, VALUE, LISTENER>::getAllOwners() const {
Mutex::Autolock lock(mLock);
std::set<int32_t> owners;
for (const auto& i : mClients) {
@@ -477,8 +522,8 @@ std::vector<int32_t> ClientManager<KEY, VALUE>::getAllOwners() const {
return std::vector<int32_t>(owners.begin(), owners.end());
}
-template<class KEY, class VALUE>
-void ClientManager<KEY, VALUE>::updatePriorities(
+template<class KEY, class VALUE, class LISTENER>
+void ClientManager<KEY, VALUE, LISTENER>::updatePriorities(
const std::map<int32_t,int32_t>& ownerPriorityList) {
Mutex::Autolock lock(mLock);
for (auto& i : mClients) {
@@ -489,8 +534,8 @@ void ClientManager<KEY, VALUE>::updatePriorities(
}
}
-template<class KEY, class VALUE>
-std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::get(
+template<class KEY, class VALUE, class LISTENER>
+std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::get(
const KEY& key) const {
Mutex::Autolock lock(mLock);
for (const auto& i : mClients) {
@@ -499,23 +544,30 @@ std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::get(
return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
}
-template<class KEY, class VALUE>
-void ClientManager<KEY, VALUE>::removeAll() {
+template<class KEY, class VALUE, class LISTENER>
+void ClientManager<KEY, VALUE, LISTENER>::removeAll() {
Mutex::Autolock lock(mLock);
+ if (mListener != nullptr) {
+ for (const auto& i : mClients) {
+ mListener->onClientRemoved(*i);
+ }
+ }
mClients.clear();
mRemovedCondition.broadcast();
}
-template<class KEY, class VALUE>
-std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::remove(const KEY& key) {
+template<class KEY, class VALUE, class LISTENER>
+std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::remove(
+ const KEY& key) {
Mutex::Autolock lock(mLock);
std::shared_ptr<ClientDescriptor<KEY, VALUE>> ret;
// Remove evicted clients from list
mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
- [&key, &ret] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
+ [this, &key, &ret] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
if (curClientPtr->getKey() == key) {
+ if (mListener != nullptr) mListener->onClientRemoved(*curClientPtr);
ret = curClientPtr;
return true;
}
@@ -526,8 +578,8 @@ std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::remove(
return ret;
}
-template<class KEY, class VALUE>
-status_t ClientManager<KEY, VALUE>::waitUntilRemoved(
+template<class KEY, class VALUE, class LISTENER>
+status_t ClientManager<KEY, VALUE, LISTENER>::waitUntilRemoved(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>> client,
nsecs_t timeout) const {
status_t ret = NO_ERROR;
@@ -558,14 +610,21 @@ status_t ClientManager<KEY, VALUE>::waitUntilRemoved(
return ret;
}
-template<class KEY, class VALUE>
-void ClientManager<KEY, VALUE>::remove(
+template<class KEY, class VALUE, class LISTENER>
+void ClientManager<KEY, VALUE, LISTENER>::setListener(const std::shared_ptr<LISTENER>& listener) {
+ Mutex::Autolock lock(mLock);
+ mListener = listener;
+}
+
+template<class KEY, class VALUE, class LISTENER>
+void ClientManager<KEY, VALUE, LISTENER>::remove(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value) {
Mutex::Autolock lock(mLock);
// Remove evicted clients from list
mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
- [&value] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
+ [this, &value] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
if (curClientPtr == value) {
+ if (mListener != nullptr) mListener->onClientRemoved(*curClientPtr);
return true;
}
return false;
@@ -573,8 +632,8 @@ void ClientManager<KEY, VALUE>::remove(
mRemovedCondition.broadcast();
}
-template<class KEY, class VALUE>
-int64_t ClientManager<KEY, VALUE>::getCurrentCostLocked() const {
+template<class KEY, class VALUE, class LISTENER>
+int64_t ClientManager<KEY, VALUE, LISTENER>::getCurrentCostLocked() const {
int64_t totalCost = 0;
for (const auto& x : mClients) {
totalCost += x->getCost();