diff options
| author | Ruben Brunk <rubenbrunk@google.com> | 2015-05-26 17:25:07 -0700 | 
|---|---|---|
| committer | Ruben Brunk <rubenbrunk@google.com> | 2015-06-01 16:53:45 -0700 | 
| commit | 99e69716215cd0665379bc90d708f2ea8689831d (patch) | |
| tree | d013b8e9273ea6032ddf24ba701eccb755b672bb /services/camera | |
| parent | 4a95e69406aa2e9896d865962d6d947ebbdac6fc (diff) | |
| download | frameworks_av-99e69716215cd0665379bc90d708f2ea8689831d.zip frameworks_av-99e69716215cd0665379bc90d708f2ea8689831d.tar.gz frameworks_av-99e69716215cd0665379bc90d708f2ea8689831d.tar.bz2  | |
Track camera and flashlight usage in battery stats.
Bug: 15986092
Change-Id: I9dc6828332e4091fd93bf2d82839e8e3862a2fc2
Diffstat (limited to 'services/camera')
| -rw-r--r-- | services/camera/libcameraservice/Android.mk | 1 | ||||
| -rw-r--r-- | services/camera/libcameraservice/CameraService.cpp | 96 | ||||
| -rw-r--r-- | services/camera/libcameraservice/CameraService.h | 26 | ||||
| -rw-r--r-- | services/camera/libcameraservice/utils/ClientManager.h | 133 | 
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 fc9a332..527e80b 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -40,6 +40,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> @@ -139,6 +140,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); @@ -323,12 +329,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}); @@ -1137,12 +1170,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); @@ -1181,7 +1215,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); @@ -1192,19 +1240,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);          }      } @@ -1226,8 +1272,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) { @@ -1948,9 +1993,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 9b7163a..2e4743f 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();  | 
