diff options
author | Gloria Wang <gwang@google.com> | 2011-02-24 14:51:45 -0800 |
---|---|---|
committer | Gloria Wang <gwang@google.com> | 2011-03-02 16:53:24 -0800 |
commit | 9ee159b79022b2e1a050acb3890ce948e99e9ccb (patch) | |
tree | 3f8c908cd6d5a69f1f6c5eb7c4e0a833890107e9 | |
parent | 5f5354e35ab3b2a0cb4cabb6d0aa5a160225ccc8 (diff) | |
download | frameworks_av-9ee159b79022b2e1a050acb3890ce948e99e9ccb.zip frameworks_av-9ee159b79022b2e1a050acb3890ce948e99e9ccb.tar.gz frameworks_av-9ee159b79022b2e1a050acb3890ce948e99e9ccb.tar.bz2 |
- To track the usage of all audio output devices
- To track the currently used audio device
- The devices are separated as speaker and other audio devices
- Provide the collected data to battery application through pullBatteryData()
Change-Id: I374c755266b5ac6b1c6c630400f4daf901ea8acc
-rw-r--r-- | include/media/IMediaPlayerService.h | 18 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 112 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 19 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 50 |
4 files changed, 192 insertions, 7 deletions
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h index cce9129..7956788 100644 --- a/include/media/IMediaPlayerService.h +++ b/include/media/IMediaPlayerService.h @@ -55,17 +55,25 @@ public: virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; virtual sp<IOMX> getOMX() = 0; - // codecs usage tracking for the battery app + // codecs and audio devices usage tracking for the battery app enum BatteryDataBits { // tracking audio codec - kBatteryDataTrackAudio = 1, + kBatteryDataTrackAudio = 0x1, // tracking video codec - kBatteryDataTrackVideo = 2, + kBatteryDataTrackVideo = 0x2, // codec is started, otherwise codec is paused - kBatteryDataCodecStarted = 4, + kBatteryDataCodecStarted = 0x4, // tracking decoder (for media player), // otherwise tracking encoder (for media recorder) - kBatteryDataTrackDecoder = 8, + kBatteryDataTrackDecoder = 0x8, + // start to play an audio on an audio device + kBatteryDataAudioFlingerStart = 0x10, + // stop/pause the audio playback + kBatteryDataAudioFlingerStop = 0x20, + // audio is rounted to speaker + kBatteryDataSpeakerOn = 0x40, + // audio is rounted to devices other than speaker + kBatteryDataOtherAudioDeviceOn = 0x80, }; virtual void addBatteryData(uint32_t params) = 0; diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index ec6188f..a42cca5 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -214,6 +214,15 @@ MediaPlayerService::MediaPlayerService() { LOGV("MediaPlayerService created"); mNextConnId = 1; + + mBatteryAudio.refCount = 0; + for (int i = 0; i < NUM_AUDIO_DEVICES; i++) { + mBatteryAudio.deviceOn[i] = 0; + mBatteryAudio.lastTime[i] = 0; + mBatteryAudio.totalTime[i] = 0; + } + // speaker is on by default + mBatteryAudio.deviceOn[SPEAKER] = 1; } MediaPlayerService::~MediaPlayerService() @@ -1777,12 +1786,88 @@ int MediaPlayerService::AudioCache::getSessionId() void MediaPlayerService::addBatteryData(uint32_t params) { Mutex::Autolock lock(mLock); + + int32_t time = systemTime() / 1000000L; + + // change audio output devices. This notification comes from AudioFlinger + if ((params & kBatteryDataSpeakerOn) + || (params & kBatteryDataOtherAudioDeviceOn)) { + + int deviceOn[NUM_AUDIO_DEVICES]; + for (int i = 0; i < NUM_AUDIO_DEVICES; i++) { + deviceOn[i] = 0; + } + + if ((params & kBatteryDataSpeakerOn) + && (params & kBatteryDataOtherAudioDeviceOn)) { + deviceOn[SPEAKER_AND_OTHER] = 1; + } else if (params & kBatteryDataSpeakerOn) { + deviceOn[SPEAKER] = 1; + } else { + deviceOn[OTHER_AUDIO_DEVICE] = 1; + } + + for (int i = 0; i < NUM_AUDIO_DEVICES; i++) { + if (mBatteryAudio.deviceOn[i] != deviceOn[i]){ + + if (mBatteryAudio.refCount > 0) { // if playing audio + if (!deviceOn[i]) { + mBatteryAudio.lastTime[i] += time; + mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i]; + mBatteryAudio.lastTime[i] = 0; + } else { + mBatteryAudio.lastTime[i] = 0 - time; + } + } + + mBatteryAudio.deviceOn[i] = deviceOn[i]; + } + } + return; + } + + // an sudio stream is started + if (params & kBatteryDataAudioFlingerStart) { + // record the start time only if currently no other audio + // is being played + if (mBatteryAudio.refCount == 0) { + for (int i = 0; i < NUM_AUDIO_DEVICES; i++) { + if (mBatteryAudio.deviceOn[i]) { + mBatteryAudio.lastTime[i] -= time; + } + } + } + + mBatteryAudio.refCount ++; + return; + + } else if (params & kBatteryDataAudioFlingerStop) { + if (mBatteryAudio.refCount <= 0) { + LOGW("Battery track warning: refCount is <= 0"); + return; + } + + // record the stop time only if currently this is the only + // audio being played + if (mBatteryAudio.refCount == 1) { + for (int i = 0; i < NUM_AUDIO_DEVICES; i++) { + if (mBatteryAudio.deviceOn[i]) { + mBatteryAudio.lastTime[i] += time; + mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i]; + mBatteryAudio.lastTime[i] = 0; + } + } + } + + mBatteryAudio.refCount --; + return; + } + int uid = IPCThreadState::self()->getCallingUid(); if (uid == AID_MEDIA) { return; } int index = mBatteryData.indexOfKey(uid); - int32_t time = systemTime() / 1000000L; if (index < 0) { // create a new entry for this UID BatteryUsageInfo info; @@ -1792,7 +1877,10 @@ void MediaPlayerService::addBatteryData(uint32_t params) info.videoLastTime = 0; info.refCount = 0; - mBatteryData.add(uid, info); + if (mBatteryData.add(uid, info) == NO_MEMORY) { + LOGE("Battery track error: no memory for new app"); + return; + } } BatteryUsageInfo &info = mBatteryData.editValueFor(uid); @@ -1837,6 +1925,26 @@ void MediaPlayerService::addBatteryData(uint32_t params) status_t MediaPlayerService::pullBatteryData(Parcel* reply) { Mutex::Autolock lock(mLock); + + // audio output devices usage + int32_t time = systemTime() / 1000000L; //in ms + int32_t totalTime; + + for (int i = 0; i < NUM_AUDIO_DEVICES; i++) { + totalTime = mBatteryAudio.totalTime[i]; + + if (mBatteryAudio.deviceOn[i] + && (mBatteryAudio.lastTime[i] != 0)) { + int32_t tmpTime = mBatteryAudio.lastTime[i] + time; + totalTime += tmpTime; + } + + reply->writeInt32(totalTime); + // reset the total time + mBatteryAudio.totalTime[i] = 0; + } + + // codec usage BatteryUsageInfo info; int size = mBatteryData.size(); diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 1175ed0..ff6ccf5 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -225,6 +225,25 @@ public: }; KeyedVector<int, BatteryUsageInfo> mBatteryData; + enum { + SPEAKER, + OTHER_AUDIO_DEVICE, + SPEAKER_AND_OTHER, + NUM_AUDIO_DEVICES + }; + + struct BatteryAudioFlingerUsageInfo { + int refCount; // how many audio streams are being played + int deviceOn[NUM_AUDIO_DEVICES]; // whether the device is currently used + int32_t lastTime[NUM_AUDIO_DEVICES]; // in ms + // totalTime[]: total time of audio output devices usage + int32_t totalTime[NUM_AUDIO_DEVICES]; // in ms + }; + + // This varialble is used to record the usage of audio output device + // for battery app + BatteryAudioFlingerUsageInfo mBatteryAudio; + // Collect info of the codec usage from media player and media recorder virtual void addBatteryData(uint32_t params); // API for the Battery app to pull the data of codecs usage diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index a07ebfc..2b08ab5 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -24,6 +24,7 @@ #include <sys/time.h> #include <sys/resource.h> +#include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <utils/Log.h> #include <binder/Parcel.h> @@ -35,6 +36,7 @@ #include <media/AudioTrack.h> #include <media/AudioRecord.h> +#include <media/IMediaPlayerService.h> #include <private/media/AudioTrackShared.h> #include <private/media/AudioEffectShared.h> @@ -121,6 +123,19 @@ static bool settingsAllowed() { #endif } +// To collect the amplifier usage +static void addBatteryData(uint32_t params) { + sp<IBinder> binder = + defaultServiceManager()->getService(String16("media.player")); + sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); + if (service.get() == NULL) { + LOGW("Cannot connect to the MediaPlayerService for battery tracking"); + return; + } + + service->addBatteryData(params); +} + // ---------------------------------------------------------------------------- AudioFlinger::AudioFlinger() @@ -1833,6 +1848,27 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() } } if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) { + // when changing the audio output device, call addBatteryData to notify + // the change + if (mDevice != value) { + uint32_t params = 0; + // check whether speaker is on + if (value & AudioSystem::DEVICE_OUT_SPEAKER) { + params |= IMediaPlayerService::kBatteryDataSpeakerOn; + } + + int deviceWithoutSpeaker + = AudioSystem::DEVICE_OUT_ALL & ~AudioSystem::DEVICE_OUT_SPEAKER; + // check if any other device (except speaker) is on + if (value & deviceWithoutSpeaker ) { + params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn; + } + + if (params != 0) { + addBatteryData(params); + } + } + // forward device change to effects that have requested to be // aware of attached audio device. mDevice = (uint32_t)value; @@ -2831,6 +2867,9 @@ void AudioFlinger::PlaybackThread::Track::destroy() AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType, mSessionId); + + // to track the speaker usage + addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop); } AudioSystem::releaseOutput(thread->id()); } @@ -2941,6 +2980,11 @@ status_t AudioFlinger::PlaybackThread::Track::start() (AudioSystem::stream_type)mStreamType, mSessionId); thread->mLock.lock(); + + // to track the speaker usage + if (status == NO_ERROR) { + addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart); + } } if (status == NO_ERROR) { PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); @@ -2976,6 +3020,9 @@ void AudioFlinger::PlaybackThread::Track::stop() (AudioSystem::stream_type)mStreamType, mSessionId); thread->mLock.lock(); + + // to track the speaker usage + addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop); } } } @@ -2995,6 +3042,9 @@ void AudioFlinger::PlaybackThread::Track::pause() (AudioSystem::stream_type)mStreamType, mSessionId); thread->mLock.lock(); + + // to track the speaker usage + addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop); } } } |