diff options
-rw-r--r-- | include/media/IMediaPlayerService.h | 16 | ||||
-rw-r--r-- | media/java/android/media/MediaPlayer.java | 8 | ||||
-rw-r--r-- | media/jni/android_media_MediaPlayer.cpp | 18 | ||||
-rw-r--r-- | media/libmedia/IMediaPlayerService.cpp | 28 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 92 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 24 | ||||
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 44 |
7 files changed, 228 insertions, 2 deletions
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h index 0bfb166..cce9129 100644 --- a/include/media/IMediaPlayerService.h +++ b/include/media/IMediaPlayerService.h @@ -54,6 +54,22 @@ public: virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; 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 + enum BatteryDataBits { + // tracking audio codec + kBatteryDataTrackAudio = 1, + // tracking video codec + kBatteryDataTrackVideo = 2, + // codec is started, otherwise codec is paused + kBatteryDataCodecStarted = 4, + // tracking decoder (for media player), + // otherwise tracking encoder (for media recorder) + kBatteryDataTrackDecoder = 8, + }; + + virtual void addBatteryData(uint32_t params) = 0; + virtual status_t pullBatteryData(Parcel* reply) = 0; }; // ---------------------------------------------------------------------------- diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index f61ac0f..d8ba34b 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -1228,6 +1228,14 @@ public class MediaPlayer private native final void native_setup(Object mediaplayer_this); private native final void native_finalize(); + /** + * @param reply Parcel with audio/video duration info for battery + tracking usage + * @return The status code. + * {@hide} + */ + public native static int native_pullBatteryData(Parcel reply); + @Override protected void finalize() { native_finalize(); } diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 0884e35..ca54432 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -36,6 +36,8 @@ #include "android_util_Binder.h" #include <binder/Parcel.h> #include <surfaceflinger/Surface.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> // ---------------------------------------------------------------------------- @@ -723,6 +725,21 @@ static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env, jobject thiz process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL ); } +static jint +android_media_MediaPlayer_pullBatteryData(JNIEnv *env, jobject thiz, jobject java_reply) +{ + sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player")); + sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); + if (service.get() == NULL) { + jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService"); + return UNKNOWN_ERROR; + } + + Parcel *reply = parcelForJavaObject(env, java_reply); + + return service->pullBatteryData(reply); +} + // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { @@ -758,6 +775,7 @@ static JNINativeMethod gMethods[] = { {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id}, {"setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel}, {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect}, + {"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData}, }; static const char* const kClassPathName = "android/media/MediaPlayer"; diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index 77199e1..17a0362 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -37,7 +37,9 @@ enum { DECODE_FD, CREATE_MEDIA_RECORDER, CREATE_METADATA_RETRIEVER, - GET_OMX + GET_OMX, + ADD_BATTERY_DATA, + PULL_BATTERY_DATA }; class BpMediaPlayerService: public BpInterface<IMediaPlayerService> @@ -156,6 +158,19 @@ public: remote()->transact(GET_OMX, data, &reply); return interface_cast<IOMX>(reply.readStrongBinder()); } + + virtual void addBatteryData(uint32_t params) { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(params); + remote()->transact(ADD_BATTERY_DATA, data, &reply); + } + + virtual status_t pullBatteryData(Parcel* reply) { + Parcel data; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + return remote()->transact(PULL_BATTERY_DATA, data, reply); + } }; IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService"); @@ -270,6 +285,17 @@ status_t BnMediaPlayerService::onTransact( reply->writeStrongBinder(omx->asBinder()); return NO_ERROR; } break; + case ADD_BATTERY_DATA: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + uint32_t params = data.readInt32(); + addBatteryData(params); + return NO_ERROR; + } break; + case PULL_BATTERY_DATA: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + pullBatteryData(reply); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 60bdd62..8c6f76b 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -23,6 +23,7 @@ #include <sys/types.h> #include <sys/stat.h> +#include <sys/time.h> #include <dirent.h> #include <unistd.h> @@ -51,6 +52,8 @@ #include <media/Metadata.h> #include <media/AudioTrack.h> +#include <private/android_filesystem_config.h> + #include "MediaRecorderClient.h" #include "MediaPlayerService.h" #include "MetadataRetrieverClient.h" @@ -1762,4 +1765,93 @@ int MediaPlayerService::AudioCache::getSessionId() return 0; } +void MediaPlayerService::addBatteryData(uint32_t params) +{ + Mutex::Autolock lock(mLock); + 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; + info.audioTotalTime = 0; + info.videoTotalTime = 0; + info.audioLastTime = 0; + info.videoLastTime = 0; + info.refCount = 0; + + mBatteryData.add(uid, info); + } + + BatteryUsageInfo &info = mBatteryData.editValueFor(uid); + + if (params & kBatteryDataCodecStarted) { + if (params & kBatteryDataTrackAudio) { + info.audioLastTime -= time; + info.refCount ++; + } + if (params & kBatteryDataTrackVideo) { + info.videoLastTime -= time; + info.refCount ++; + } + } else { + if (info.refCount == 0) { + LOGW("Battery track warning: refCount is already 0"); + return; + } else if (info.refCount < 0) { + LOGE("Battery track error: refCount < 0"); + mBatteryData.removeItem(uid); + return; + } + + if (params & kBatteryDataTrackAudio) { + info.audioLastTime += time; + info.refCount --; + } + if (params & kBatteryDataTrackVideo) { + info.videoLastTime += time; + info.refCount --; + } + + // no stream is being played by this UID + if (info.refCount == 0) { + info.audioTotalTime += info.audioLastTime; + info.audioLastTime = 0; + info.videoTotalTime += info.videoLastTime; + info.videoLastTime = 0; + } + } +} + +status_t MediaPlayerService::pullBatteryData(Parcel* reply) { + Mutex::Autolock lock(mLock); + BatteryUsageInfo info; + int size = mBatteryData.size(); + + reply->writeInt32(size); + int i = 0; + + while (i < size) { + info = mBatteryData.valueAt(i); + + reply->writeInt32(mBatteryData.keyAt(i)); //UID + reply->writeInt32(info.audioTotalTime); + reply->writeInt32(info.videoTotalTime); + + info.audioTotalTime = 0; + info.videoTotalTime = 0; + + // remove the UID entry where no stream is being played + if (info.refCount <= 0) { + mBatteryData.removeItemsAt(i); + size --; + i --; + } + i++; + } + return NO_ERROR; +} } // namespace android diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 62f8ed6..9f41db0 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -204,7 +204,31 @@ public: void removeClient(wp<Client> client); + // For battery usage tracking purpose + struct BatteryUsageInfo { + // how many streams are being played by one UID + int refCount; + // a temp variable to store the duration(ms) of audio codecs + // when we start a audio codec, we minus the system time from audioLastTime + // when we pause it, we add the system time back to the audioLastTime + // so after the pause, audioLastTime = pause time - start time + // if multiple audio streams are played (or recorded), then audioLastTime + // = the total playing time of all the streams + int32_t audioLastTime; + // when all the audio streams are being paused, we assign audioLastTime to + // this variable, so this value could be provided to the battery app + // in the next pullBatteryData call + int32_t audioTotalTime; + + int32_t videoLastTime; + int32_t videoTotalTime; + }; + KeyedVector<int, BatteryUsageInfo> mBatteryData; + // 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 + virtual status_t pullBatteryData(Parcel* reply); private: class Client : public BnMediaPlayer { diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index b1d3630..1b63ab2 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -28,6 +28,8 @@ #include "include/MPEG2TSExtractor.h" #include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <media/IMediaPlayerService.h> #include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/AudioPlayer.h> @@ -155,8 +157,17 @@ private: const AwesomeNativeWindowRenderer &); }; -//////////////////////////////////////////////////////////////////////////////// +// To collect the decoder usage +void addBatteryData(uint32_t params) { + sp<IBinder> binder = + defaultServiceManager()->getService(String16("media.player")); + sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); + CHECK(service.get() != NULL); + + service->addBatteryData(params); +} +//////////////////////////////////////////////////////////////////////////////// AwesomePlayer::AwesomePlayer() : mQueueStarted(false), mTimeSource(NULL), @@ -379,6 +390,17 @@ void AwesomePlayer::reset_l() { mDrmManagerClient = NULL; } + if (mFlags & PLAYING) { + uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; + if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { + params |= IMediaPlayerService::kBatteryDataTrackAudio; + } + if (mVideoSource != NULL) { + params |= IMediaPlayerService::kBatteryDataTrackVideo; + } + addBatteryData(params); + } + if (mFlags & PREPARING) { mFlags |= PREPARE_CANCELLED; if (mConnectingDataSource != NULL) { @@ -779,6 +801,16 @@ status_t AwesomePlayer::play_l() { seekTo_l(0); } + uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted + | IMediaPlayerService::kBatteryDataTrackDecoder; + if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { + params |= IMediaPlayerService::kBatteryDataTrackAudio; + } + if (mVideoSource != NULL) { + params |= IMediaPlayerService::kBatteryDataTrackVideo; + } + addBatteryData(params); + return OK; } @@ -933,6 +965,16 @@ status_t AwesomePlayer::pause_l(bool at_eos) { Playback::PAUSE, 0); } + uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; + if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { + params |= IMediaPlayerService::kBatteryDataTrackAudio; + } + if (mVideoSource != NULL) { + params |= IMediaPlayerService::kBatteryDataTrackVideo; + } + + addBatteryData(params); + return OK; } |