- Add method in MediaPlayerService to collect and pull

codec usage (duration) for the battery app
- Collect MediaPlayer decoding usage data

Change-Id: I0ef4e32b6a041ba1fe73c19f9c67185c61d03965
This commit is contained in:
Gloria Wang
2011-02-19 18:37:57 -08:00
parent 25474a2230
commit d211f41f76
7 changed files with 228 additions and 2 deletions

View File

@ -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;
};
// ----------------------------------------------------------------------------

View File

@ -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(); }

View File

@ -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";

View File

@ -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);
}

View File

@ -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

View File

@ -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 {

View File

@ -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;
}