diff options
author | emancebo <emancebo@cyngn.com> | 2014-08-04 17:07:05 -0700 |
---|---|---|
committer | Danesh M <daneshm90@gmail.com> | 2015-02-17 22:19:53 +0000 |
commit | d226720aa226ae4ec20df24696be5b2b84ab9ef3 (patch) | |
tree | ad3900db6a035c39da4183ec1fe53711f889fd0e | |
parent | 61c5541428394e254950068fc5a7c1ac5d65ea42 (diff) | |
download | android_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
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 Binary files differnew file mode 100644 index 000000000..54b4e55fb --- /dev/null +++ b/res/drawable-hdpi/ic_playback_dk.png diff --git a/res/drawable-hdpi/ic_playback_stop_dk.png b/res/drawable-hdpi/ic_playback_stop_dk.png Binary files differnew file mode 100644 index 000000000..af58de533 --- /dev/null +++ b/res/drawable-hdpi/ic_playback_stop_dk.png diff --git a/res/drawable-mdpi/ic_playback_dk.png b/res/drawable-mdpi/ic_playback_dk.png Binary files differnew file mode 100644 index 000000000..4b277e341 --- /dev/null +++ b/res/drawable-mdpi/ic_playback_dk.png diff --git a/res/drawable-mdpi/ic_playback_stop_dk.png b/res/drawable-mdpi/ic_playback_stop_dk.png Binary files differnew file mode 100644 index 000000000..d9cb874d7 --- /dev/null +++ b/res/drawable-mdpi/ic_playback_stop_dk.png diff --git a/res/drawable-xhdpi/ic_playback_dk.png b/res/drawable-xhdpi/ic_playback_dk.png Binary files differnew file mode 100644 index 000000000..8a5c28df0 --- /dev/null +++ b/res/drawable-xhdpi/ic_playback_dk.png diff --git a/res/drawable-xhdpi/ic_playback_stop_dk.png b/res/drawable-xhdpi/ic_playback_stop_dk.png Binary files differnew file mode 100644 index 000000000..0c5ba2260 --- /dev/null +++ b/res/drawable-xhdpi/ic_playback_stop_dk.png 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(); + +} |