Skip to content

Commit 3de193c

Browse files
nadlabakQuarx2k
authored andcommitted
add call recording option
Change-Id: Ic66a8627f7afed283572c821d079d1a449d98d6d Conflicts: src/com/android/phone/CallFeaturesSetting.java src/com/android/phone/PhoneUtils.java Conflicts: src/com/android/phone/PhoneUtils.java
1 parent 2082c74 commit 3de193c

4 files changed

Lines changed: 111 additions & 0 deletions

File tree

res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,10 @@
15221522
[CHAR LIMIT=40] -->
15231523
<string name="preference_category_ringtone">Ringtone</string>
15241524

1525+
<!-- Call recording -->
1526+
<string name="call_recording_title">Call recording</string>
1527+
<string name="call_recording_summary">"WARNING: Call recording may be illegal in some countries! Consult your local laws before you enable this option! When enabled, recordings are stored in CallRecordings folder on SD Card."</string>
1528+
15251529
<!-- Voice quality filter -->
15261530
<string name="voice_quality_preferences_title">Voice quality</string>
15271531
<string name="voice_quality_summary">Voice profile is currently set to: %s</string>

res/xml/call_feature_setting.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@
187187
android:entries="@array/dtmf_tone_entries"
188188
android:entryValues="@array/dtmf_tone_values"/>
189189

190+
<CheckBoxPreference
191+
android:key="button_call_recording"
192+
android:title="@string/call_recording_title"
193+
android:persistent="true"
194+
android:summary="@string/call_recording_summary"/>
195+
190196
<CheckBoxPreference
191197
android:key="button_noise_suppression_key"
192198
android:title="@string/noise_suppression_title"

src/com/android/phone/CallNotifier.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ public class CallNotifier extends Handler
167167
private boolean mVoicePrivacyState = false;
168168
private boolean mIsCdmaRedialCall = false;
169169

170+
private Call.State mLastCallState = null;
171+
170172
// Emergency call tone and vibrate:
171173
private int mIsEmergencyToneOn;
172174
private int mCurrentEmergencyToneState = EMERGENCY_TONE_OFF;
@@ -909,7 +911,19 @@ private void onPhoneStateChanged(AsyncResult r) {
909911
mInCallRingbackTonePlayer.stopTone();
910912
mInCallRingbackTonePlayer = null;
911913
}
914+
if (PhoneUtils.PhoneSettings.callRecordingEnabled(mApplication)) {
915+
if (callState == Call.State.ACTIVE && callState != mLastCallState) {
916+
log("onPhoneStateChanged: State ACTIVE - startRecording, last state was: " + mLastCallState);
917+
Call call = PhoneUtils.getCurrentCall(fgPhone);
918+
Connection c = PhoneUtils.getConnection(fgPhone, call);
919+
PhoneUtils.startRecording(c.getAddress(), c.isIncoming() ? "in":"out");
920+
} else if (callState != Call.State.ACTIVE && mLastCallState == Call.State.ACTIVE) {
921+
log("onPhoneStateChanged: State not ACTIVE - stopRecording");
922+
PhoneUtils.stopRecording();
923+
}
924+
}
912925
}
926+
mLastCallState = callState;
913927
}
914928
}
915929
}

src/com/android/phone/PhoneUtils.java

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import android.content.pm.PackageManager;
3030
import android.graphics.drawable.Drawable;
3131
import android.media.AudioManager;
32+
import android.media.MediaRecorder;
3233
import android.net.Uri;
3334
import android.net.sip.SipManager;
3435
import android.os.AsyncResult;
@@ -65,7 +66,11 @@
6566
import com.android.internal.telephony.cdma.CdmaConnection;
6667
import com.android.internal.telephony.sip.SipPhone;
6768

69+
import java.io.File;
70+
import java.io.IOException;
71+
import java.text.SimpleDateFormat;
6872
import java.util.ArrayList;
73+
import java.util.Calendar;
6974
import java.util.Hashtable;
7075
import java.util.Iterator;
7176
import java.util.List;
@@ -98,9 +103,13 @@ public class PhoneUtils {
98103
static final int AUDIO_RINGING = 1; /** audio behaviour while ringing */
99104
static final int AUDIO_OFFHOOK = 2; /** audio behaviour while in call. */
100105

106+
private static MediaRecorder recorder = null;
107+
101108
/** Speaker state, persisting between wired headset connection events */
102109
private static boolean sIsSpeakerEnabled = false;
103110

111+
private static boolean sIsFirstCall = true;
112+
104113
/** Hash table to store mute (Boolean) values based upon the connection.*/
105114
private static Hashtable<Connection, Boolean> sConnectionMuteTable =
106115
new Hashtable<Connection, Boolean>();
@@ -430,6 +439,10 @@ static boolean keepProximitySensorOn(Context context) {
430439
return PreferenceManager.getDefaultSharedPreferences(context)
431440
.getBoolean("keep_proximity_sensor_on", false);
432441
}
442+
static boolean callRecordingEnabled(Context context) {
443+
return PreferenceManager.getDefaultSharedPreferences(context)
444+
.getBoolean("button_call_recording", false);
445+
}
433446
};
434447

435448
static boolean hangupRingingCall(Call ringing) {
@@ -2078,6 +2091,71 @@ static boolean getMute() {
20782091
}
20792092
}
20802093

2094+
private static File createRecordingTempFile(String path) {
2095+
File dir = new File(path);
2096+
if (!dir.exists()) {
2097+
try {
2098+
dir.mkdirs();
2099+
} catch (Exception e) {
2100+
Log.e("PhoneUtils", "unable to create directory " + dir + ": " + e);
2101+
return null;
2102+
}
2103+
} else if (!dir.canWrite()) {
2104+
Log.e("PhoneUtils", "no write permission for directory: " + dir);
2105+
return null;
2106+
}
2107+
try {
2108+
return File.createTempFile("call", ".tmp", dir);
2109+
} catch (IOException e) {
2110+
Log.e("PhoneUtils", "unable to create temp file in " + dir + ": " + e);
2111+
return null;
2112+
}
2113+
}
2114+
2115+
static void startRecording(String address, String inOut) {
2116+
String dirName = "/sdcard/CallRecordings";
2117+
log("startRecording");
2118+
if (recorder == null) {
2119+
log("startRecording: create new recorder");
2120+
File recording = null;
2121+
recorder = new MediaRecorder();
2122+
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
2123+
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
2124+
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
2125+
recording = createRecordingTempFile(dirName);
2126+
if (recording == null) {
2127+
recorder.release();
2128+
recorder = null;
2129+
return;
2130+
}
2131+
// name recording filename based on call data
2132+
Calendar cl = Calendar.getInstance();
2133+
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss-(");
2134+
String newRecordingName = dirName + "/" + sdf.format(cl.getTime()) + address + ")-" + inOut + ".m4a";
2135+
recording.renameTo(new File(newRecordingName));
2136+
recorder.setOutputFile(newRecordingName);
2137+
try {
2138+
recorder.prepare();
2139+
recorder.start();
2140+
} catch (IOException e) {
2141+
Log.e("PhoneUtils", "io problems while preparing [" +
2142+
newRecordingName + "]: " + e.getMessage());
2143+
recorder.release();
2144+
recorder = null;
2145+
}
2146+
}
2147+
}
2148+
2149+
static void stopRecording() {
2150+
log("stopRecording");
2151+
if (recorder != null) {
2152+
log("stopRecording: release old recorder");
2153+
recorder.stop();
2154+
recorder.release();
2155+
recorder = null;
2156+
}
2157+
}
2158+
20812159
/* package */ static void setAudioMode() {
20822160
setAudioMode(PhoneApp.getInstance().mCM);
20832161
}
@@ -2556,7 +2634,16 @@ private static int checkCnapSpecialCases(String n) {
25562634
private static boolean activateSpeakerIfDocked(Phone phone) {
25572635
if (DBG) log("activateSpeakerIfDocked()...");
25582636

2637+
/* TODO: hack for Defy+ libaudio on Milestone (first call is mute),
2638+
should be removed when a proper fix is ready */
2639+
if (sIsFirstCall) {
2640+
sIsFirstCall = false;
2641+
turnOnSpeaker(phone.getContext(), true, false);
2642+
restoreSpeakerMode(phone.getContext());
2643+
}
2644+
25592645
boolean activated = false;
2646+
25602647
if (PhoneApp.mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
25612648
if (DBG) log("activateSpeakerIfDocked(): In a dock -> may need to turn on speaker.");
25622649
PhoneApp app = PhoneApp.getInstance();

0 commit comments

Comments
 (0)