- 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:
@ -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;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -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(); }
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user