summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoremancebo <emancebo@cyngn.com>2014-08-04 17:07:05 -0700
committerDanesh M <daneshm90@gmail.com>2015-02-17 22:19:53 +0000
commitd226720aa226ae4ec20df24696be5b2b84ab9ef3 (patch)
treead3900db6a035c39da4183ec1fe53711f889fd0e
parent61c5541428394e254950068fc5a7c1ac5d65ea42 (diff)
downloadandroid_packages_apps_Dialer-d226720aa226ae4ec20df24696be5b2b84ab9ef3.tar.gz
android_packages_apps_Dialer-d226720aa226ae4ec20df24696be5b2b84ab9ef3.tar.bz2
android_packages_apps_Dialer-d226720aa226ae4ec20df24696be5b2b84ab9ef3.zip
Call recording service implementation and playback
Combination of the following commits: commit df7f323089af7aebfc29e253b13b67789fa23ccb Author: emancebo <emancebo@cyngn.com> Date: Mon Aug 4 17:07:05 2014 -0700 Call recording service implementation, show recordings and allow playback in call history commit 04656cfe2380fbc62f1f54d1b1b2af62aaf92673 Author: emancebo <emancebo@cyngn.com> Date: Thu Aug 14 14:17:18 2014 -0700 blacklist call recording for US/EU mccs, remove sysprop flag for enabling commit 44ef8f7f59f89bbcadcb557c781047646523300e Author: Brinly Taylor <uberlaggydarwin@gmail.com> Date: Tue Aug 19 10:14:02 2014 +0930 Dialer: Blacklist call recording for Australia. Same as European/US laws as regards to this therefore to protect CM I think we should disable this. . Feel free to check with lawyers though. commit bc3df8ea3e7f73a2f48e34a3737cda1833c84d0a Author: emancebo <emancebo@cyngn.com> Date: Mon Nov 17 16:53:05 2014 -0800 update call recording file format TOMATO-282 Change-Id: I56bf6857d87260e20b6a84c4db6e463b0fd87dcc
-rw-r--r--Android.mk2
-rw-r--r--AndroidManifest.xml4
-rw-r--r--res/drawable-hdpi/ic_playback_dk.pngbin0 -> 15930 bytes
-rw-r--r--res/drawable-hdpi/ic_playback_stop_dk.pngbin0 -> 15870 bytes
-rw-r--r--res/drawable-mdpi/ic_playback_dk.pngbin0 -> 15593 bytes
-rw-r--r--res/drawable-mdpi/ic_playback_stop_dk.pngbin0 -> 15562 bytes
-rw-r--r--res/drawable-xhdpi/ic_playback_dk.pngbin0 -> 16086 bytes
-rw-r--r--res/drawable-xhdpi/ic_playback_stop_dk.pngbin0 -> 15951 bytes
-rw-r--r--res/layout/call_detail_history_item.xml7
-rw-r--r--res/values-mcc202/config.xml19
-rw-r--r--res/values-mcc204/config.xml19
-rw-r--r--res/values-mcc206/config.xml19
-rw-r--r--res/values-mcc208/config.xml19
-rw-r--r--res/values-mcc214/config.xml19
-rw-r--r--res/values-mcc216/config.xml19
-rw-r--r--res/values-mcc218/config.xml19
-rw-r--r--res/values-mcc219/config.xml19
-rw-r--r--res/values-mcc222/config.xml19
-rw-r--r--res/values-mcc226/config.xml19
-rw-r--r--res/values-mcc230/config.xml19
-rw-r--r--res/values-mcc231/config.xml19
-rw-r--r--res/values-mcc232/config.xml19
-rw-r--r--res/values-mcc234/config.xml19
-rw-r--r--res/values-mcc238/config.xml19
-rw-r--r--res/values-mcc240/config.xml19
-rw-r--r--res/values-mcc244/config.xml19
-rw-r--r--res/values-mcc246/config.xml19
-rw-r--r--res/values-mcc247/config.xml19
-rw-r--r--res/values-mcc248/config.xml19
-rw-r--r--res/values-mcc260/config.xml19
-rw-r--r--res/values-mcc262/config.xml19
-rw-r--r--res/values-mcc268/config.xml19
-rw-r--r--res/values-mcc270/config.xml19
-rw-r--r--res/values-mcc272/config.xml19
-rw-r--r--res/values-mcc278/config.xml19
-rw-r--r--res/values-mcc280/config.xml19
-rw-r--r--res/values-mcc284/config.xml19
-rw-r--r--res/values-mcc293/config.xml19
-rw-r--r--res/values-mcc310/config.xml19
-rw-r--r--res/values-mcc362/config.xml19
-rw-r--r--res/values-mcc505/config.xml19
-rw-r--r--res/values/cm_strings.xml4
-rw-r--r--res/values/config.xml20
-rw-r--r--src/com/android/dialer/CallDetailActivity.java14
-rw-r--r--src/com/android/dialer/calllog/CallDetailHistoryAdapter.java32
-rw-r--r--src/com/android/dialer/util/CallRecordingPlayer.java154
-rw-r--r--src/com/android/services/callrecorder/CallRecorderService.java188
-rw-r--r--src/com/android/services/callrecorder/CallRecordingDataStore.java177
-rw-r--r--src/com/android/services/callrecorder/common/CallRecording.aidl3
-rw-r--r--src/com/android/services/callrecorder/common/CallRecording.java82
-rw-r--r--src/com/android/services/callrecorder/common/ICallRecorderService.aidl39
51 files changed, 1331 insertions, 3 deletions
diff --git a/Android.mk b/Android.mk
index 70102cf9f..572b948e0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -17,7 +17,7 @@ res_dirs := res \
$(contacts_common_dir)/res \
$(phone_common_dir)/res
-LOCAL_SRC_FILES := $(call all-java-files-under, $(src_dirs))
+LOCAL_SRC_FILES := $(call all-java-files-under, $(src_dirs)) $(call all-Iaidl-files-under, $(src_dirs))
LOCAL_SRC_FILES += ../../providers/ContactsProvider/src/com/android/providers/contacts/NameSplitter.java \
../../providers/ContactsProvider/src/com/android/providers/contacts/HanziToPinyin.java \
../../providers/ContactsProvider/src/com/android/providers/contacts/util/NeededForTesting.java
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2b1176254..49df40816 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -301,6 +301,10 @@
android:screenOrientation="nosensor" >
</activity>
+ <service android:name="com.android.services.callrecorder.CallRecorderService"
+ android:process="com.android.incallui">
+ </service>
+
<!-- BroadcastReceiver for receiving Intents from Notification mechanism. -->
<receiver android:name="com.android.incallui.InCallApp$NotificationBroadcastReceiver"
android:exported="false"
diff --git a/res/drawable-hdpi/ic_playback_dk.png b/res/drawable-hdpi/ic_playback_dk.png
new file mode 100644
index 000000000..54b4e55fb
--- /dev/null
+++ b/res/drawable-hdpi/ic_playback_dk.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_playback_stop_dk.png b/res/drawable-hdpi/ic_playback_stop_dk.png
new file mode 100644
index 000000000..af58de533
--- /dev/null
+++ b/res/drawable-hdpi/ic_playback_stop_dk.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_playback_dk.png b/res/drawable-mdpi/ic_playback_dk.png
new file mode 100644
index 000000000..4b277e341
--- /dev/null
+++ b/res/drawable-mdpi/ic_playback_dk.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_playback_stop_dk.png b/res/drawable-mdpi/ic_playback_stop_dk.png
new file mode 100644
index 000000000..d9cb874d7
--- /dev/null
+++ b/res/drawable-mdpi/ic_playback_stop_dk.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_playback_dk.png b/res/drawable-xhdpi/ic_playback_dk.png
new file mode 100644
index 000000000..8a5c28df0
--- /dev/null
+++ b/res/drawable-xhdpi/ic_playback_dk.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_playback_stop_dk.png b/res/drawable-xhdpi/ic_playback_stop_dk.png
new file mode 100644
index 000000000..0c5ba2260
--- /dev/null
+++ b/res/drawable-xhdpi/ic_playback_stop_dk.png
Binary files differ
diff --git a/res/layout/call_detail_history_item.xml b/res/layout/call_detail_history_item.xml
index cbe844234..658c503e8 100644
--- a/res/layout/call_detail_history_item.xml
+++ b/res/layout/call_detail_history_item.xml
@@ -53,4 +53,11 @@
android:layout_height="wrap_content"
android:textColor="?attr/call_log_secondary_text_color"
android:textSize="@dimen/call_log_secondary_text_size" />
+
+ <LinearLayout
+ android:id="@+id/recording_playback_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ />
</LinearLayout>
diff --git a/res/values-mcc202/config.xml b/res/values-mcc202/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc202/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc204/config.xml b/res/values-mcc204/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc204/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc206/config.xml b/res/values-mcc206/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc206/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc208/config.xml b/res/values-mcc208/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc208/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc214/config.xml b/res/values-mcc214/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc214/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc216/config.xml b/res/values-mcc216/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc216/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc218/config.xml b/res/values-mcc218/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc218/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc219/config.xml b/res/values-mcc219/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc219/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc222/config.xml b/res/values-mcc222/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc222/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc226/config.xml b/res/values-mcc226/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc226/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc230/config.xml b/res/values-mcc230/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc230/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc231/config.xml b/res/values-mcc231/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc231/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc232/config.xml b/res/values-mcc232/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc232/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc234/config.xml b/res/values-mcc234/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc234/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc238/config.xml b/res/values-mcc238/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc238/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc240/config.xml b/res/values-mcc240/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc240/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc244/config.xml b/res/values-mcc244/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc244/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc246/config.xml b/res/values-mcc246/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc246/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc247/config.xml b/res/values-mcc247/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc247/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc248/config.xml b/res/values-mcc248/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc248/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc260/config.xml b/res/values-mcc260/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc260/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc262/config.xml b/res/values-mcc262/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc262/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc268/config.xml b/res/values-mcc268/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc268/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc270/config.xml b/res/values-mcc270/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc270/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc272/config.xml b/res/values-mcc272/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc272/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc278/config.xml b/res/values-mcc278/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc278/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc280/config.xml b/res/values-mcc280/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc280/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc284/config.xml b/res/values-mcc284/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc284/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc293/config.xml b/res/values-mcc293/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc293/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc310/config.xml b/res/values-mcc310/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc310/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc362/config.xml b/res/values-mcc362/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc362/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values-mcc505/config.xml b/res/values-mcc505/config.xml
new file mode 100644
index 000000000..def954f23
--- /dev/null
+++ b/res/values-mcc505/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+</resources>
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 4d05a7e3c..237b51532 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -120,4 +120,8 @@
<!-- Filter by blacklist calls option -->
<string name="call_log_blacklist_header">Blacklist calls only</string>
+
+ <string name="start_call_playback">Play recording</string>
+ <string name="stop_call_playback">Stop</string>
+ <string name="call_playback_error_message">Failed to play recording</string>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
new file mode 100644
index 000000000..e8b6eca2b
--- /dev/null
+++ b/res/values/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="call_recording_enabled">false</bool>
+ <integer name="call_recording_audio_source">1</integer>
+</resources>
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index 7aac92017..8d579f89a 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -63,12 +63,14 @@ import com.android.dialer.calllog.PhoneNumberUtilsWrapper;
import com.android.dialer.util.AsyncTaskExecutor;
import com.android.dialer.util.AsyncTaskExecutors;
import com.android.dialer.util.DialerUtils;
+import com.android.dialer.util.CallRecordingPlayer;
import com.android.dialer.voicemail.VoicemailPlaybackFragment;
import com.android.dialer.voicemail.VoicemailStatusHelper;
import com.android.dialer.voicemail.VoicemailStatusHelper.StatusMessage;
import com.android.dialer.voicemail.VoicemailStatusHelperImpl;
import com.android.dialerbind.analytics.AnalyticsActivity;
import com.android.internal.telephony.PhoneConstants;
+import com.android.services.callrecorder.CallRecordingDataStore;
import java.util.List;
@@ -142,6 +144,9 @@ public class CallDetailActivity extends AnalyticsActivity implements ProximitySe
private ProximitySensorManager mProximitySensorManager;
private final ProximitySensorListener mProximitySensorListener = new ProximitySensorListener();
+ private CallRecordingDataStore mCallRecordingDataStore = new CallRecordingDataStore();
+ private CallRecordingPlayer mCallRecordingPlayer = new CallRecordingPlayer();
+
/** Listener to changes in the proximity sensor state. */
private class ProximitySensorListener implements ProximitySensorManager.Listener {
/** Used to show a blank view and hide the action bar. */
@@ -253,6 +258,13 @@ public class CallDetailActivity extends AnalyticsActivity implements ProximitySe
}
@Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mCallRecordingDataStore.close();
+ mCallRecordingPlayer.stop();
+ }
+
+ @Override
public void onResume() {
super.onResume();
updateData(getCallLogEntryUris());
@@ -428,7 +440,7 @@ public class CallDetailActivity extends AnalyticsActivity implements ProximitySe
ListView historyList = (ListView) findViewById(R.id.history);
historyList.setAdapter(
new CallDetailHistoryAdapter(CallDetailActivity.this, mInflater,
- mCallTypeHelper, details));
+ mCallTypeHelper, details, mCallRecordingDataStore, mCallRecordingPlayer));
mCallDetailHeader.loadContactPhotos(firstDetails, contactType);
findViewById(R.id.call_detail).setVisibility(View.VISIBLE);
}
diff --git a/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java b/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java
index e1bd15794..114cf0f1c 100644
--- a/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java
+++ b/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java
@@ -24,6 +24,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
+import android.widget.Button;
import android.widget.TextView;
import com.android.contacts.common.CallUtil;
@@ -32,7 +33,13 @@ import com.android.dialer.R;
import com.android.dialer.util.DialerUtils;
import com.google.common.collect.Lists;
+import com.android.dialer.util.CallRecordingPlayer;
+import com.android.services.callrecorder.common.CallRecording;
+import com.android.services.callrecorder.CallRecorderService;
+import com.android.services.callrecorder.CallRecordingDataStore;
+
import java.util.ArrayList;
+import java.util.List;
/**
* Adapter for a ListView containing history items from the details of a call.
@@ -53,12 +60,19 @@ public class CallDetailHistoryAdapter extends BaseAdapter {
*/
private ArrayList<CharSequence> mDurationItems = Lists.newArrayList();
+ private CallRecordingDataStore mCallRecordingDataStore;
+ private CallRecordingPlayer mCallRecordingPlayer;
+
public CallDetailHistoryAdapter(Context context, LayoutInflater layoutInflater,
- CallTypeHelper callTypeHelper, PhoneCallDetails[] phoneCallDetails) {
+ CallTypeHelper callTypeHelper, PhoneCallDetails[] phoneCallDetails,
+ CallRecordingDataStore callRecordingDataStore,
+ CallRecordingPlayer callRecordingPlayer) {
mContext = context;
mLayoutInflater = layoutInflater;
mCallTypeHelper = callTypeHelper;
mPhoneCallDetails = phoneCallDetails;
+ mCallRecordingDataStore = callRecordingDataStore;
+ mCallRecordingPlayer = callRecordingPlayer;
}
@Override
@@ -144,6 +158,22 @@ public class CallDetailHistoryAdapter extends BaseAdapter {
formatDurationAndDataUsage(details.duration, details.dataUsage, details.durationType));
}
+ // do this synchronously to prevent recordings from "popping in"
+ // after detail item is displayed
+ if (CallRecorderService.isEnabled(mContext)) {
+ mCallRecordingDataStore.open(mContext); // opens unless already open
+ List<CallRecording> recordings =
+ mCallRecordingDataStore.getRecordings(details.number.toString(), details.date);
+
+ ViewGroup playbackView =
+ (ViewGroup) result.findViewById(R.id.recording_playback_layout);
+ playbackView.removeAllViews();
+ for (CallRecording recording : recordings) {
+ Button button = mCallRecordingPlayer.createPlaybackButton(mContext, recording);
+ playbackView.addView(button);
+ }
+ }
+
return result;
}
diff --git a/src/com/android/dialer/util/CallRecordingPlayer.java b/src/com/android/dialer/util/CallRecordingPlayer.java
new file mode 100644
index 000000000..9f7c143bd
--- /dev/null
+++ b/src/com/android/dialer/util/CallRecordingPlayer.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dialer.util;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.media.MediaPlayer;
+import android.os.Environment;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+import com.android.dialer.R;
+import com.android.services.callrecorder.CallRecorderService;
+import com.android.services.callrecorder.common.CallRecording;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Simple playback for call recordings
+ */
+public class CallRecordingPlayer implements MediaPlayer.OnCompletionListener {
+ private static final String TAG = "CallRecordingPlayer";
+
+ private MediaPlayer mPlayer = null;
+ private boolean mPlaying = false;
+ private PlayButton mButton;
+
+ public Button createPlaybackButton(Context context, CallRecording recording) {
+ return new PlayButton(context, recording, this);
+ }
+
+ // button to toggle playback for a call recording
+ private static class PlayButton extends Button implements View.OnClickListener {
+ private boolean mPlaying = false;
+ private CallRecording mRecording;
+ private CallRecordingPlayer mPlayer;
+
+ public PlayButton(Context context, CallRecording recording, CallRecordingPlayer player) {
+ super(context);
+ mRecording = recording;
+ mPlayer = player;
+ reset();
+ setBackgroundColor(Color.TRANSPARENT);
+ setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (!mPlaying) {
+ mPlayer.play(mRecording, this);
+ if (!mPlayer.isPlaying()) {
+ Toast.makeText(mContext, R.string.call_playback_error_message,
+ Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ mPlayer.stop();
+ }
+
+ mPlaying = mPlayer.isPlaying();
+ updateState();
+ }
+
+ private void updateState() {
+ setText(mPlaying ? R.string.stop_call_playback : R.string.start_call_playback);
+ setCompoundDrawablesRelativeWithIntrinsicBounds(mPlaying
+ ? R.drawable.ic_playback_stop_dk : R.drawable.ic_playback_dk,
+ 0, 0, 0);
+ }
+
+ public void reset() {
+ mPlaying = false;
+ updateState();
+ }
+ }
+
+ private void play(CallRecording recording, PlayButton button) {
+ if (mPlayer != null) {
+ // stop and cleanup current session first
+ stop();
+ }
+
+ mButton = button;
+
+ String filePath = recording.getFile().getAbsolutePath();
+
+ mPlayer = new MediaPlayer();
+ mPlayer.setOnCompletionListener(this);
+ try {
+ mPlayer.setDataSource(filePath);
+ mPlayer.prepare();
+ } catch (IOException e) {
+ Log.w(TAG, "Error opening " + filePath, e);
+ return;
+ }
+
+ try {
+ mPlayer.start();
+ mPlaying = true;
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Could not start player", e);
+ }
+ }
+
+ public void stop() {
+ if (mPlayer != null) {
+ try {
+ mPlayer.stop();
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Exception stopping player", e);
+ }
+ mPlayer.release();
+ mPlayer = null;
+ resetButton();
+ }
+ mPlaying = false;
+ }
+
+ private boolean isPlaying() {
+ return mPlaying;
+ }
+
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ resetButton();
+
+ mPlayer.release();
+ mPlayer = null;
+ mPlaying = false;
+ }
+
+ private void resetButton() {
+ if (mButton != null) {
+ mButton.reset();
+ mButton = null;
+ }
+ }
+}
diff --git a/src/com/android/services/callrecorder/CallRecorderService.java b/src/com/android/services/callrecorder/CallRecorderService.java
new file mode 100644
index 000000000..83eec3bbf
--- /dev/null
+++ b/src/com/android/services/callrecorder/CallRecorderService.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.callrecorder;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.media.MediaRecorder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import com.android.services.callrecorder.common.CallRecording;
+import com.android.services.callrecorder.common.ICallRecorderService;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.android.dialer.R;
+
+public class CallRecorderService extends Service {
+ private static final String TAG = "CallRecorderService";
+ private static final boolean DBG = false;
+
+ private static enum RecorderState {
+ IDLE,
+ RECORDING
+ };
+
+ private MediaRecorder mMediaRecorder = null;
+ private RecorderState mState = RecorderState.IDLE;
+ private CallRecording mCurrentRecording = null;
+
+ private static final String AUDIO_SOURCE_PROPERTY = "persist.call_recording.src";
+
+ private SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyMMdd_HHmmssSSS");
+
+ private final ICallRecorderService.Stub mBinder = new ICallRecorderService.Stub() {
+ @Override
+ public CallRecording stopRecording() {
+ if (getState() == RecorderState.RECORDING) {
+ stopRecordingInternal();
+ return mCurrentRecording;
+ }
+ return null;
+ }
+
+ @Override
+ public boolean startRecording(String phoneNumber, long creationTime)
+ throws RemoteException {
+ String fileName = generateFilename(phoneNumber);
+ mCurrentRecording = new CallRecording(phoneNumber, creationTime,
+ fileName, System.currentTimeMillis());
+ return startRecordingInternal(mCurrentRecording.getFile());
+
+ }
+
+ @Override
+ public boolean isRecording() throws RemoteException {
+ return getState() == RecorderState.RECORDING;
+ }
+
+ @Override
+ public CallRecording getActiveRecording() throws RemoteException {
+ return mCurrentRecording;
+ }
+ };
+
+ @Override
+ public void onCreate() {
+ if (DBG) Log.d(TAG, "Creating CallRecorderService");
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ private int getAudioSource() {
+ int defaultValue = getResources().getInteger(R.integer.call_recording_audio_source);
+ return SystemProperties.getInt(AUDIO_SOURCE_PROPERTY, defaultValue);
+ }
+
+ private synchronized boolean startRecordingInternal(File file) {
+ if (mMediaRecorder != null) {
+ if (DBG) {
+ Log.d(TAG, "Start called with recording in progress, stopping current recording");
+ }
+ stopRecordingInternal();
+ }
+
+ if (DBG) Log.d(TAG, "Starting recording");
+
+ mMediaRecorder = new MediaRecorder();
+ try {
+ int audioSource = getAudioSource();
+ if (DBG) Log.d(TAG, "Creating media recorder with audio source " + audioSource);
+ mMediaRecorder.setAudioSource(audioSource);
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Error initializing media recorder", e);
+ return false;
+ }
+
+ file.getParentFile().mkdirs();
+ String outputPath = file.getAbsolutePath();
+ if (DBG) Log.d(TAG, "Writing output to file " + outputPath);
+
+ try {
+ mMediaRecorder.setOutputFile(outputPath);
+ mMediaRecorder.prepare();
+ mMediaRecorder.start();
+ mState = RecorderState.RECORDING;
+ return true;
+ } catch (IOException e) {
+ Log.w(TAG, "Could not start recording for file " + outputPath, e);
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Could not start recording for file " + outputPath, e);
+ } catch (RuntimeException e) {
+ // only catch exceptions thrown by the MediaRecorder JNI code
+ if (e.getMessage().indexOf("start failed") >= 0) {
+ Log.w(TAG, "Could not start recording for file " + outputPath, e);
+ } else {
+ throw e;
+ }
+ }
+
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ return false;
+ }
+
+ private synchronized void stopRecordingInternal() {
+ if (DBG) Log.d(TAG, "Stopping current recording");
+ if (mMediaRecorder != null) {
+ try {
+ if (getState() == RecorderState.RECORDING) {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ }
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Exception closing media recorder", e);
+ }
+ mMediaRecorder = null;
+ mState = RecorderState.IDLE;
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (DBG) Log.d(TAG, "Destroying CallRecorderService");
+ }
+
+ private synchronized RecorderState getState() {
+ return mState;
+ }
+
+ private String generateFilename(String number) {
+ String timestamp = DATE_FORMAT.format(new Date());
+ return number + "_" + timestamp + ".amr";
+ }
+
+ public static boolean isEnabled(Context context) {
+ return context.getResources().getBoolean(R.bool.call_recording_enabled);
+ }
+}
diff --git a/src/com/android/services/callrecorder/CallRecordingDataStore.java b/src/com/android/services/callrecorder/CallRecordingDataStore.java
new file mode 100644
index 000000000..4310c1ad2
--- /dev/null
+++ b/src/com/android/services/callrecorder/CallRecordingDataStore.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.callrecorder;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteStatement;
+import android.provider.BaseColumns;
+import android.util.Log;
+
+import com.android.services.callrecorder.common.CallRecording;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Persistent data store for call recordings. Usage:
+ * open()
+ * read/write operations
+ * close()
+ */
+public class CallRecordingDataStore {
+ private static final String TAG = "CallRecordingStore";
+ private SQLiteOpenHelper mOpenHelper = null;
+ private SQLiteDatabase mDatabase = null;
+
+ /**
+ * Open before reading/writing. Will not open handle if one is already open.
+ */
+ public void open(Context context) {
+ if (mDatabase == null) {
+ mOpenHelper = new CallRecordingSQLiteOpenHelper(context);
+ mDatabase = mOpenHelper.getWritableDatabase();
+ }
+ }
+
+ /**
+ * close when finished reading/writing
+ */
+ public void close() {
+ if (mDatabase != null) {
+ mDatabase.close();
+ }
+ if (mOpenHelper != null) {
+ mOpenHelper.close();
+ }
+ mDatabase = null;
+ mOpenHelper = null;
+ }
+
+ /**
+ * Save a recording in the data store
+ *
+ * @param recording the recording to store
+ */
+ public void putRecording(CallRecording recording) {
+ final String insertSql = "INSERT INTO " +
+ CallRecordingsContract.CallRecording.TABLE_NAME + " (" +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_PHONE_NUMBER + ", " +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_CALL_DATE + ", " +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_RECORDING_FILENAME + ", " +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_CREATION_DATE + ") " +
+ " VALUES (?, ?, ?, ?)";
+
+ try {
+ SQLiteStatement stmt = mDatabase.compileStatement(insertSql);
+ int idx = 1;
+ stmt.bindString(idx++, recording.phoneNumber);
+ stmt.bindLong(idx++, recording.creationTime);
+ stmt.bindString(idx++, recording.fileName);
+ stmt.bindLong(idx++, System.currentTimeMillis());
+ long id = stmt.executeInsert();
+ Log.i(TAG, "Saved recording " + recording + " with id " + id);
+ } catch (SQLiteException e) {
+ Log.w(TAG, "Failed to save recording " + recording, e);
+ }
+ }
+
+ /**
+ * Get all recordings associated with a phone call
+ *
+ * @param phoneNumber phone number no spaces
+ * @param callCreationDate time that the call was created
+ * @return list of recordings
+ */
+ public List<CallRecording> getRecordings(String phoneNumber, long callCreationDate) {
+ List<CallRecording> resultList = new ArrayList<CallRecording>();
+
+ final String query = "SELECT " +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_RECORDING_FILENAME +
+ " FROM " + CallRecordingsContract.CallRecording.TABLE_NAME +
+ " WHERE " + CallRecordingsContract.CallRecording.COLUMN_NAME_PHONE_NUMBER + " = ?" +
+ " AND " + CallRecordingsContract.CallRecording.COLUMN_NAME_CALL_DATE + " = ?" +
+ " ORDER BY " + CallRecordingsContract.CallRecording.COLUMN_NAME_CREATION_DATE;
+
+ String args[] = {
+ phoneNumber, String.valueOf(callCreationDate)
+ };
+
+ try {
+ Cursor cursor = mDatabase.rawQuery(query, args);
+ while (cursor.moveToNext()) {
+ String fileName = cursor.getString(0);
+ CallRecording recording =
+ new CallRecording(phoneNumber, callCreationDate, fileName, 0);
+ if (recording.getFile().exists()) {
+ resultList.add(recording);
+ }
+ }
+ cursor.close();
+ } catch (SQLiteException e) {
+ Log.w(TAG, "Failed to fetch recordings for number " + phoneNumber +
+ ", date " + callCreationDate, e);
+ }
+
+ return resultList;
+ }
+
+ static class CallRecordingsContract {
+ static interface CallRecording extends BaseColumns {
+ static final String TABLE_NAME = "call_recordings";
+ static final String COLUMN_NAME_PHONE_NUMBER = "phone_number";
+ static final String COLUMN_NAME_CALL_DATE = "call_date";
+ static final String COLUMN_NAME_RECORDING_FILENAME = "recording_filename";
+ static final String COLUMN_NAME_CREATION_DATE = "creation_date";
+ }
+ }
+
+ static class CallRecordingSQLiteOpenHelper extends SQLiteOpenHelper {
+ private static final int VERSION = 1;
+ private static final String DB_NAME = "callrecordings.db";
+
+ public CallRecordingSQLiteOpenHelper(Context context) {
+ super(context, DB_NAME, null, VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE " + CallRecordingsContract.CallRecording.TABLE_NAME + " (" +
+ CallRecordingsContract.CallRecording._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_PHONE_NUMBER + " TEXT," +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_CALL_DATE + " LONG," +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_RECORDING_FILENAME + " TEXT, " +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_CREATION_DATE + " LONG" +
+ ");"
+ );
+
+ db.execSQL("CREATE INDEX IF NOT EXISTS phone_number_call_date_index ON " +
+ CallRecordingsContract.CallRecording.TABLE_NAME + " (" +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_PHONE_NUMBER + ", " +
+ CallRecordingsContract.CallRecording.COLUMN_NAME_CALL_DATE + ");"
+ );
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ // implement if we change the schema
+ }
+ }
+}
diff --git a/src/com/android/services/callrecorder/common/CallRecording.aidl b/src/com/android/services/callrecorder/common/CallRecording.aidl
new file mode 100644
index 000000000..5ab84a09e
--- /dev/null
+++ b/src/com/android/services/callrecorder/common/CallRecording.aidl
@@ -0,0 +1,3 @@
+package com.android.services.callrecorder.common;
+
+parcelable CallRecording;
diff --git a/src/com/android/services/callrecorder/common/CallRecording.java b/src/com/android/services/callrecorder/common/CallRecording.java
new file mode 100644
index 000000000..0bb192f8d
--- /dev/null
+++ b/src/com/android/services/callrecorder/common/CallRecording.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.callrecorder.common;
+
+import android.os.Environment;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.File;
+
+public final class CallRecording implements Parcelable {
+ public String phoneNumber;
+ public long creationTime;
+ public String fileName;
+ public long startRecordingTime;
+
+ private static final String PUBLIC_DIRECTORY_NAME = "CallRecordings";
+
+ public static final Parcelable.Creator<CallRecording> CREATOR = new
+ Parcelable.Creator<CallRecording>() {
+ public CallRecording createFromParcel(Parcel in) {
+ return new CallRecording(in);
+ }
+
+ public CallRecording[] newArray(int size) {
+ return new CallRecording[size];
+ }
+ };
+
+ public CallRecording(String phoneNumber, long creationTime,
+ String fileName, long startRecordingTime) {
+ this.phoneNumber = phoneNumber;
+ this.creationTime = creationTime;
+ this.fileName = fileName;
+ this.startRecordingTime = startRecordingTime;
+ }
+
+ public CallRecording(Parcel in) {
+ phoneNumber = in.readString();
+ creationTime = in.readLong();
+ fileName = in.readString();
+ startRecordingTime = in.readLong();
+ }
+
+ public File getFile() {
+ File dir = Environment.getExternalStoragePublicDirectory(PUBLIC_DIRECTORY_NAME);
+ return new File(dir, fileName);
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(phoneNumber);
+ out.writeLong(creationTime);
+ out.writeString(fileName);
+ out.writeLong(startRecordingTime);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "phoneNumber=" + phoneNumber + ", creationTime=" + creationTime +
+ ", fileName=" + fileName + ", startRecordingTime=" + startRecordingTime;
+ }
+}
diff --git a/src/com/android/services/callrecorder/common/ICallRecorderService.aidl b/src/com/android/services/callrecorder/common/ICallRecorderService.aidl
new file mode 100644
index 000000000..d6d96d712
--- /dev/null
+++ b/src/com/android/services/callrecorder/common/ICallRecorderService.aidl
@@ -0,0 +1,39 @@
+package com.android.services.callrecorder.common;
+
+import com.android.services.callrecorder.common.CallRecording;
+
+/**
+ * Service for recording phone calls. Only one recording may be active at a time
+ * (i.e. every call to startRecording should be followed by a call to stopRecording).
+ */
+interface ICallRecorderService {
+
+ /**
+ * Start a recording.
+ *
+ * @return true if recording started successfully
+ */
+ boolean startRecording(String phoneNumber, long creationTime);
+
+ /**
+ * stops the current recording
+ *
+ * @return call recording data including the output filename
+ */
+ CallRecording stopRecording();
+
+ /**
+ * Recording status
+ *
+ * @return true if there is an active recording
+ */
+ boolean isRecording();
+
+ /**
+ * Get recording currently in progress
+ *
+ * @return call recording object
+ */
+ CallRecording getActiveRecording();
+
+}