diff options
| -rw-r--r-- | core/java/android/os/RecoverySystem.java | 4 | ||||
| -rw-r--r-- | core/java/android/server/BluetoothEventLoop.java | 12 | ||||
| -rwxr-xr-x | core/res/res/values/strings.xml | 76 | ||||
| -rw-r--r-- | packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png | bin | 1021 -> 210 bytes | |||
| -rw-r--r-- | packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png | bin | 4468 -> 1331 bytes | |||
| -rw-r--r--[-rwxr-xr-x] | packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png | bin | 4491 -> 1359 bytes | |||
| -rw-r--r-- | packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png | bin | 809 -> 199 bytes | |||
| -rw-r--r-- | telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java | 94 | ||||
| -rw-r--r-- | voip/java/android/net/rtp/AudioCodec.java | 2 | ||||
| -rw-r--r-- | voip/jni/rtp/AmrCodec.cpp | 97 | ||||
| -rw-r--r-- | voip/jni/rtp/Android.mk | 12 | ||||
| -rw-r--r-- | voip/jni/rtp/AudioCodec.cpp | 2 | ||||
| -rw-r--r-- | voip/jni/rtp/AudioGroup.cpp | 51 |
13 files changed, 280 insertions, 70 deletions
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index e56e257..6d19f41 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -68,6 +68,7 @@ public class RecoverySystem { private static File RECOVERY_DIR = new File("/cache/recovery"); private static File COMMAND_FILE = new File(RECOVERY_DIR, "command"); private static File LOG_FILE = new File(RECOVERY_DIR, "log"); + private static String LAST_LOG_FILENAME = "last_log"; // Length limits for reading files. private static int LOG_FILE_MAX_LENGTH = 64 * 1024; @@ -399,9 +400,10 @@ public class RecoverySystem { Log.e(TAG, "Error reading recovery log", e); } - // Delete everything in RECOVERY_DIR + // Delete everything in RECOVERY_DIR except LAST_LOG_FILENAME String[] names = RECOVERY_DIR.list(); for (int i = 0; names != null && i < names.length; i++) { + if (names[i].equals(LAST_LOG_FILENAME)) continue; File f = new File(RECOVERY_DIR, names[i]); if (!f.delete()) { Log.e(TAG, "Can't delete: " + f); diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index e05fe7b..bcb151a 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -225,10 +225,10 @@ class BluetoothEventLoop { } String name = propValues[0]; if (name.equals("Name")) { + mBluetoothService.setProperty(name, propValues[1]); Intent intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, propValues[1]); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setProperty(name, propValues[1]); } else if (name.equals("Pairable") || name.equals("Discoverable")) { String pairable = name.equals("Pairable") ? propValues[1] : mBluetoothService.getPropertyInternal("Pairable"); @@ -239,6 +239,7 @@ class BluetoothEventLoop { if (pairable == null || discoverable == null) return; + mBluetoothService.setProperty(name, propValues[1]); int mode = BluetoothService.bluezStringToScanMode( pairable.equals("true"), discoverable.equals("true")); @@ -248,9 +249,9 @@ class BluetoothEventLoop { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - mBluetoothService.setProperty(name, propValues[1]); } else if (name.equals("Discovering")) { Intent intent; + mBluetoothService.setProperty(name, propValues[1]); if (propValues[1].equals("true")) { mBluetoothService.setIsDiscovering(true); intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED); @@ -261,7 +262,6 @@ class BluetoothEventLoop { intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); } mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setProperty(name, propValues[1]); } else if (name.equals("Devices")) { String value = null; int len = Integer.valueOf(propValues[1]); @@ -294,19 +294,20 @@ class BluetoothEventLoop { } BluetoothDevice device = mAdapter.getRemoteDevice(address); if (name.equals("Name")) { + mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); Intent intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothDevice.EXTRA_NAME, propValues[1]); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); } else if (name.equals("Class")) { + mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); Intent intent = new Intent(BluetoothDevice.ACTION_CLASS_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothDevice.EXTRA_CLASS, new BluetoothClass(Integer.valueOf(propValues[1]))); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); } else if (name.equals("Connected")) { + mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); Intent intent = null; if (propValues[1].equals("true")) { intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED); @@ -320,7 +321,6 @@ class BluetoothEventLoop { } intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); } else if (name.equals("UUIDs")) { String uuid = null; int len = Integer.valueOf(propValues[1]); diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index e377f49..d9177e7 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -381,8 +381,10 @@ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> <string name="permgrouplab_storage">Storage</string> + <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] --> + <string name="permgroupdesc_storage" product="nosdcard">Access the shared storage.</string> <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permgroupdesc_storage">Access the SD card.</string> + <string name="permgroupdesc_storage" product="default">Access the SD card.</string> <!-- Permissions --> @@ -1224,10 +1226,14 @@ <string name="permdesc_writeDictionary">Allows an application to write new words into the user dictionary.</string> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] --> + <string name="permlab_sdcardWrite" product="nosdcard">modify/delete shared storage contents</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_sdcardWrite">modify/delete SD card contents</string> + <string name="permlab_sdcardWrite" product="default">modify/delete SD card contents</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] --> + <string name="permdesc_sdcardWrite" product="nosdcard">Allows an application to write to the shared storage.</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_sdcardWrite">Allows an application to write to the SD card.</string> + <string name="permdesc_sdcardWrite" product="default">Allows an application to write to the SD card.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_cache_filesystem">access the cache filesystem</string> @@ -2079,12 +2085,16 @@ <!-- See USB_STORAGE. USB_STORAGE_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to mount. This is the title. --> <string name="usb_storage_title">USB connected</string> + <!-- See USB_STORAGE. This is the message. [CHAR LIMIT=NONE] --> + <string name="usb_storage_message" product="nosdcard">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s shared storage.</string> <!-- See USB_STORAGE. This is the message. --> - <string name="usb_storage_message">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s SD card.</string> + <string name="usb_storage_message" product="default">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s SD card.</string> <!-- See USB_STORAGE. This is the button text to mount the phone on the computer. --> <string name="usb_storage_button_mount">Turn on USB storage</string> + <!-- See USB_STORAGE_DIALOG. If there was an error mounting, this is the text. [CHAR LIMIT=NONE] --> + <string name="usb_storage_error_message" product="nosdcard">There is a problem using your shared storage for USB storage.</string> <!-- See USB_STORAGE_DIALOG. If there was an error mounting, this is the text. --> - <string name="usb_storage_error_message">There is a problem using your SD card for USB storage.</string> + <string name="usb_storage_error_message" product="default">There is a problem using your SD card for USB storage.</string> <!-- USB_STORAGE: When the user connects the phone to a computer via USB, we show a notification asking if he wants to share files across. This is the title --> <string name="usb_storage_notification_title">USB connected</string> <!-- See USB_STORAGE. This is the message. --> @@ -2099,8 +2109,10 @@ <!-- This is the label for the activity, and should never be visible to the user. --> <!-- See USB_STORAGE_STOP. USB_STORAGE_STOP_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to stop usb storage. This is the title. --> <string name="usb_storage_stop_title">USB storage in use</string> + <!-- See USB_STORAGE_STOP. This is the message. [CHAR LIMIT=NONE] --> + <string name="usb_storage_stop_message" product="nosdcard">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s shared storage from your computer.</string> <!-- See USB_STORAGE_STOP. This is the message. --> - <string name="usb_storage_stop_message">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s SD card from your computer.</string> + <string name="usb_storage_stop_message" product="default">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s SD card from your computer.</string> <!-- See USB_STORAGE_STOP. This is the button text to stop usb storage. --> <string name="usb_storage_stop_button_mount">Turn off USB storage</string> <!-- See USB_STORAGE_STOP_DIALOG. If there was an error stopping, this is the text. --> @@ -2117,10 +2129,14 @@ <!-- External media format dialog strings --> <!-- This is the label for the activity, and should never be visible to the user. --> + <!-- See EXTMEDIA_FORMAT. EXTMEDIA_FORMAT_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to format the SD card. This is the title. [CHAR LIMIT=20] --> + <string name="extmedia_format_title" product="nosdcard">Format shared storage</string> <!-- See EXTMEDIA_FORMAT. EXTMEDIA_FORMAT_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to format the SD card. This is the title. --> - <string name="extmedia_format_title">Format SD card</string> + <string name="extmedia_format_title" product="default">Format SD card</string> + <!-- See EXTMEDIA_FORMAT. This is the message. [CHAR LIMIT=NONE] --> + <string name="extmedia_format_message" product="nosdcard">Format shared storage, erasing all files stored there? Action cannot be reversed!</string> <!-- See EXTMEDIA_FORMAT. This is the message. --> - <string name="extmedia_format_message">Are you sure you want to format the SD card? All data on your card will be lost.</string> + <string name="extmedia_format_message" product="default">Are you sure you want to format the SD card? All data on your card will be lost.</string> <!-- See EXTMEDIA_FORMAT. This is the button text to format the sd card. --> <string name="extmedia_format_button_format">Format</string> @@ -2145,29 +2161,51 @@ <string name="candidates_style"><u>candidates</u></string> <!-- External media notification strings --> + <!-- Shown when external media is being checked [CHAR LIMIT=30] --> + <string name="ext_media_checking_notification_title" product="nosdcard">Preparing shared storage</string> <!-- Shown when external media is being checked --> - <string name="ext_media_checking_notification_title">Preparing SD card</string> + <string name="ext_media_checking_notification_title" product="default">Preparing SD card</string> <string name="ext_media_checking_notification_message">Checking for errors.</string> + <!-- Shown when external media is blank (or unsupported filesystem) [CHAR LIMIT=30] --> + <string name="ext_media_nofs_notification_title" product="nosdcard">Blank shared storage</string> <!-- Shown when external media is blank (or unsupported filesystem) --> - <string name="ext_media_nofs_notification_title">Blank SD card</string> - <string name="ext_media_nofs_notification_message">SD card blank or has unsupported filesystem.</string> + <string name="ext_media_nofs_notification_title" product="default">Blank SD card</string> + <!-- Shown when shared storage cannot be read. [CHAR LIMIT=NONE] --> + <string name="ext_media_nofs_notification_message" product="nosdcard">Shared storage blank or has unsupported filesystem.</string> + <string name="ext_media_nofs_notification_message" product="default">SD card blank or has unsupported filesystem.</string> + <!-- Shown when external media is unmountable (corrupt)) [CHAR LIMIT=30] --> + <string name="ext_media_unmountable_notification_title" product="nosdcard">Damaged shared storage</string> <!-- Shown when external media is unmountable (corrupt)) --> - <string name="ext_media_unmountable_notification_title">Damaged SD card</string> - <string name="ext_media_unmountable_notification_message">SD card damaged. You may have to reformat it.</string> + <string name="ext_media_unmountable_notification_title" product="default">Damaged SD card</string> + <!-- Shown when shared storage cannot be read. [CHAR LIMIT=NONE] --> + <string name="ext_media_unmountable_notification_message" product="nosdcard">Shared storage damaged. You may have to reformat it.</string> + <string name="ext_media_unmountable_notification_message" product="default">SD card damaged. You may have to reformat it.</string> + <!-- Shown when external media is unsafely removed [CHAR LIMIT=30] --> + <string name="ext_media_badremoval_notification_title" product="nosdcard">Shared storage unexpectedly removed</string> <!-- Shown when external media is unsafely removed --> - <string name="ext_media_badremoval_notification_title">SD card unexpectedly removed</string> - <string name="ext_media_badremoval_notification_message">Unmount SD card before removing to avoid data loss.</string> + <string name="ext_media_badremoval_notification_title" product="default">SD card unexpectedly removed</string> + <!-- Shown when external media is unsafely removed. [CHAR LIMIT=NONE] --> + <string name="ext_media_badremoval_notification_message" product="nosdcard">Unmount shared storage before removing to avoid data loss.</string> + <string name="ext_media_badremoval_notification_message" product="default">Unmount SD card before removing to avoid data loss.</string> + <!-- Shown when external media has been safely removed [CHAR LIMIT=30] --> + <string name="ext_media_safe_unmount_notification_title" product="nosdcard">Shared storage safe to remove</string> <!-- Shown when external media has been safely removed --> - <string name="ext_media_safe_unmount_notification_title">SD card safe to remove</string> - <string name="ext_media_safe_unmount_notification_message">You can safely remove SD card.</string> + <string name="ext_media_safe_unmount_notification_title" product="default">SD card safe to remove</string> + <!-- Shown when external media has been safely removed. [CHAR LIMIT=NONE] --> + <string name="ext_media_safe_unmount_notification_message" product="nosdcard">You can safely remove shared storage.</string> + <string name="ext_media_safe_unmount_notification_message" product="default">You can safely remove SD card.</string> + <!-- Shown when external media is missing [CHAR LIMIT=30] --> + <string name="ext_media_nomedia_notification_title" product="nosdcard">Removed shared storage</string> <!-- Shown when external media is missing --> - <string name="ext_media_nomedia_notification_title">Removed SD card</string> - <string name="ext_media_nomedia_notification_message">SD card removed. Insert a new one.</string> + <string name="ext_media_nomedia_notification_title" product="default">Removed SD card</string> + <!-- Shown when external media is missing. [CHAR LIMIT=NONE] --> + <string name="ext_media_nomedia_notification_message" product="nosdcard">Shared storage removed. Insert new media.</string> + <string name="ext_media_nomedia_notification_message" product="default">SD card removed. Insert a new one.</string> <!-- Shown in LauncherActivity when the requested target Intent didn't return any matching Activities, leaving the list empty. --> <string name="activity_list_empty">No matching activities found</string> diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png Binary files differindex 157491e..a0e59cf 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png Binary files differindex aea18ed..1626895 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png Binary files differindex 1a25a2c..3c2e2b9 100755..100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png Binary files differindex 2134d49..bb41db0 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index 798a5a5..25ca559 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -24,9 +24,10 @@ import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.provider.ContactsContract.CommonDataKinds.SipAddress; +import android.provider.ContactsContract.Data; import android.provider.ContactsContract.PhoneLookup; import android.telephony.PhoneNumberUtils; -import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -36,7 +37,7 @@ import android.util.Log; public class CallerInfoAsyncQuery { - private static final boolean DBG = false; + private static final boolean DBG = true; // STOPSHIP: disable debugging before ship private static final String LOG_TAG = "CallerInfoAsyncQuery"; private static final int EVENT_NEW_QUERY = 1; @@ -189,7 +190,7 @@ public class CallerInfoAsyncQuery { */ @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { - if (DBG) log("query complete for token: " + token); + if (DBG) log("##### onQueryComplete() ##### query complete for token: " + token); //get the cookie and notify the listener. CookieWrapper cw = (CookieWrapper) cookie; @@ -227,6 +228,8 @@ public class CallerInfoAsyncQuery { mCallerInfo = new CallerInfo().markAsVoiceMail(); } else { mCallerInfo = CallerInfo.getCallerInfo(mQueryContext, mQueryUri, cursor); + if (DBG) log("==> Got mCallerInfo: " + mCallerInfo); + // Use the number entered by the user for display. if (!TextUtils.isEmpty(cw.number)) { mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number); @@ -238,7 +241,7 @@ public class CallerInfoAsyncQuery { //notify that we can clean up the queue after this. CookieWrapper endMarker = new CookieWrapper(); endMarker.event = EVENT_END_OF_QUEUE; - startQuery (token, endMarker, null, null, null, null, null); + startQuery(token, endMarker, null, null, null, null, null); } //notify the listener that the query is complete. @@ -274,24 +277,82 @@ public class CallerInfoAsyncQuery { cw.cookie = cookie; cw.event = EVENT_NEW_QUERY; - c.mHandler.startQuery (token, cw, contactRef, null, null, null, null); + c.mHandler.startQuery(token, cw, contactRef, null, null, null, null); return c; } /** - * Factory method to start query with a number + * Factory method to start the query based on a number. + * + * Note: if the number contains an "@" character we treat it + * as a SIP address, and look it up directly in the Data table + * rather than using the PhoneLookup table. + * TODO: But eventually we should expose two separate methods, one for + * numbers and one for SIP addresses, and then have + * PhoneUtils.startGetCallerInfo() decide which one to call based on + * the phone type of the incoming connection. */ public static CallerInfoAsyncQuery startQuery(int token, Context context, String number, OnQueryCompleteListener listener, Object cookie) { - //construct the URI object and start Query. - Uri contactRef = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); + if (DBG) { + log("##### CallerInfoAsyncQuery startQuery()... #####"); + log("- number: " + number); + log("- cookie: " + cookie); + } + + // Construct the URI object and query params, and start the query. + + Uri contactRef; + String selection; + String[] selectionArgs; + + if (PhoneNumberUtils.isUriNumber(number)) { + // "number" is really a SIP address. + if (DBG) log(" - Treating number as a SIP address: " + number); + + // We look up SIP addresses directly in the Data table: + contactRef = Data.CONTENT_URI; + + // Note Data.DATA1 and SipAddress.SIP_ADDRESS are equivalent. + // + // Also note we use "upper(data1)" in the WHERE clause, and + // uppercase the incoming SIP address, in order to do a + // case-insensitive match. + // + // TODO: need to confirm that the use of upper() doesn't + // prevent us from using the index! (Linear scan of the whole + // contacts DB can be very slow.) + // + // TODO: May also need to normalize by adding "sip:" as a + // prefix, if we start storing SIP addresses that way in the + // database. + + selection = "upper(" + Data.DATA1 + ")=?" + + " AND " + + Data.MIMETYPE + "='" + SipAddress.CONTENT_ITEM_TYPE + "'"; + selectionArgs = new String[] { number.toUpperCase() }; + + } else { + // "number" is a regular phone number. Use the PhoneLookup table: + contactRef = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); + selection = null; + selectionArgs = null; + } + + if (DBG) { + log("==> contactRef: " + contactRef); + log("==> selection: " + selection); + if (selectionArgs != null) { + for (int i = 0; i < selectionArgs.length; i++) { + log("==> selectionArgs[" + i + "]: " + selectionArgs[i]); + } + } + } CallerInfoAsyncQuery c = new CallerInfoAsyncQuery(); c.allocate(context, contactRef); - if (DBG) log("starting query for number: " + number + " handler: " + c.toString()); - //create cookieWrapper, start query CookieWrapper cw = new CookieWrapper(); cw.listener = listener; @@ -307,10 +368,15 @@ public class CallerInfoAsyncQuery { cw.event = EVENT_NEW_QUERY; } - c.mHandler.startQuery (token, cw, contactRef, null, null, null, null); - + c.mHandler.startQuery(token, + cw, // cookie + contactRef, // uri + null, // projection + selection, // selection + selectionArgs, // selectionArgs + null); // orderBy return c; - } + } /** * Method to add listeners to a currently running query @@ -326,7 +392,7 @@ public class CallerInfoAsyncQuery { cw.cookie = cookie; cw.event = EVENT_ADD_LISTENER; - mHandler.startQuery (token, cw, null, null, null, null, null); + mHandler.startQuery(token, cw, null, null, null, null, null); } /** diff --git a/voip/java/android/net/rtp/AudioCodec.java b/voip/java/android/net/rtp/AudioCodec.java index dfa6841..f171806 100644 --- a/voip/java/android/net/rtp/AudioCodec.java +++ b/voip/java/android/net/rtp/AudioCodec.java @@ -81,7 +81,7 @@ public class AudioCodec { public static final AudioCodec AMR = new AudioCodec(97, "AMR/8000", null); // TODO: add rest of the codecs when the native part is done. - private static final AudioCodec[] sCodecs = {GSM, PCMU, PCMA}; + private static final AudioCodec[] sCodecs = {GSM_EFR, GSM, PCMU, PCMA}; private AudioCodec(int type, String rtpmap, String fmtp) { this.type = type; diff --git a/voip/jni/rtp/AmrCodec.cpp b/voip/jni/rtp/AmrCodec.cpp new file mode 100644 index 0000000..9a2227d --- /dev/null +++ b/voip/jni/rtp/AmrCodec.cpp @@ -0,0 +1,97 @@ +/* + * Copyrightm (C) 2010 The Android Open Source 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. + */ + +#include "AudioCodec.h" + +#include "gsmamr_dec.h" +#include "gsmamr_enc.h" + +namespace { + +class GsmEfrCodec : public AudioCodec +{ +public: + GsmEfrCodec() { + if (AMREncodeInit(&mEncoder, &mSidSync, false)) { + mEncoder = NULL; + } + if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) { + mDecoder = NULL; + } + } + + ~GsmEfrCodec() { + if (mEncoder) { + AMREncodeExit(&mEncoder, &mSidSync); + } + if (mDecoder) { + GSMDecodeFrameExit(&mDecoder); + } + } + + int set(int sampleRate, const char *fmtp) { + return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1; + } + + int encode(void *payload, int16_t *samples); + int decode(int16_t *samples, void *payload, int length); + +private: + void *mEncoder; + void *mSidSync; + void *mDecoder; +}; + +int GsmEfrCodec::encode(void *payload, int16_t *samples) +{ + unsigned char *bytes = (unsigned char *)payload; + Frame_Type_3GPP type; + + int length = AMREncode(mEncoder, mSidSync, MR122, + samples, bytes, &type, AMR_TX_WMF); + + if (type == AMR_122 && length == 32) { + bytes[0] = 0xC0 | (bytes[1] >> 4); + for (int i = 1; i < 31; ++i) { + bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4); + } + return 31; + } + return -1; +} + +int GsmEfrCodec::decode(int16_t *samples, void *payload, int length) +{ + unsigned char *bytes = (unsigned char *)payload; + if (length == 31 && (bytes[0] >> 4) == 0x0C) { + for (int i = 0; i < 30; ++i) { + bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4); + } + bytes[30] <<= 4; + + if (AMRDecode(mDecoder, AMR_122, bytes, samples, MIME_IETF) == 31) { + return 160; + } + } + return -1; +} + +} // namespace + +AudioCodec *newGsmEfrCodec() +{ + return new GsmEfrCodec; +} diff --git a/voip/jni/rtp/Android.mk b/voip/jni/rtp/Android.mk index 29683bd..5909c0d 100644 --- a/voip/jni/rtp/Android.mk +++ b/voip/jni/rtp/Android.mk @@ -27,6 +27,7 @@ LOCAL_SRC_FILES := \ rtp_jni.cpp LOCAL_SRC_FILES += \ + AmrCodec.cpp \ G711Codec.cpp \ GsmCodec.cpp @@ -34,13 +35,20 @@ LOCAL_SHARED_LIBRARIES := \ libnativehelper \ libcutils \ libutils \ - libmedia + libmedia \ + libstagefright LOCAL_STATIC_LIBRARIES := libgsm LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ - external/libgsm/inc + external/libgsm/inc \ + frameworks/base/media/libstagefright/codecs/amrnb/common/include \ + frameworks/base/media/libstagefright/codecs/amrnb/common/ \ + frameworks/base/media/libstagefright/codecs/amrnb/enc/include \ + frameworks/base/media/libstagefright/codecs/amrnb/enc/src \ + frameworks/base/media/libstagefright/codecs/amrnb/dec/include \ + frameworks/base/media/libstagefright/codecs/amrnb/dec/src LOCAL_CFLAGS += -fvisibility=hidden diff --git a/voip/jni/rtp/AudioCodec.cpp b/voip/jni/rtp/AudioCodec.cpp index fc33ef2..afc193c 100644 --- a/voip/jni/rtp/AudioCodec.cpp +++ b/voip/jni/rtp/AudioCodec.cpp @@ -21,6 +21,7 @@ extern AudioCodec *newAlawCodec(); extern AudioCodec *newUlawCodec(); extern AudioCodec *newGsmCodec(); +extern AudioCodec *newGsmEfrCodec(); struct AudioCodecType { const char *name; @@ -29,6 +30,7 @@ struct AudioCodecType { {"PCMA", newAlawCodec}, {"PCMU", newUlawCodec}, {"GSM", newGsmCodec}, + {"GSM-EFR", newGsmEfrCodec}, {NULL, NULL}, }; diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp index 72c882b..f09edb6 100644 --- a/voip/jni/rtp/AudioGroup.cpp +++ b/voip/jni/rtp/AudioGroup.cpp @@ -86,8 +86,6 @@ public: void decode(int tick); private: - bool isNatAddress(struct sockaddr_storage *addr); - enum { NORMAL = 0, SEND_ONLY = 1, @@ -101,6 +99,7 @@ private: AudioCodec *mCodec; uint32_t mCodecMagic; uint32_t mDtmfMagic; + bool mFixRemote; int mTick; int mSampleRate; @@ -181,6 +180,20 @@ bool AudioStream::set(int mode, int socket, sockaddr_storage *remote, if (codec) { mRemote = *remote; mCodec = codec; + + // Here we should never get an private address, but some buggy proxy + // servers do give us one. To solve this, we replace the address when + // the first time we successfully decode an incoming packet. + mFixRemote = false; + if (remote->ss_family == AF_INET) { + unsigned char *address = + (unsigned char *)&((sockaddr_in *)remote)->sin_addr; + if (address[0] == 10 || + (address[0] == 172 && (address[1] >> 4) == 1) || + (address[0] == 192 && address[1] == 168)) { + mFixRemote = true; + } + } } LOGD("stream[%d] is configured as %s %dkHz %dms", mSocket, @@ -318,16 +331,6 @@ void AudioStream::encode(int tick, AudioStream *chain) sizeof(mRemote)); } -bool AudioStream::isNatAddress(struct sockaddr_storage *addr) { - if (addr->ss_family != AF_INET) return false; - struct sockaddr_in *s4 = (struct sockaddr_in *)addr; - unsigned char *d = (unsigned char *) &s4->sin_addr; - if ((d[0] == 10) - || ((d[0] == 172) && (d[1] & 0x10)) - || ((d[0] == 192) && (d[1] == 168))) return true; - return false; -} - void AudioStream::decode(int tick) { char c; @@ -375,21 +378,11 @@ void AudioStream::decode(int tick) MSG_TRUNC | MSG_DONTWAIT) >> 1; } else { __attribute__((aligned(4))) uint8_t buffer[2048]; - struct sockaddr_storage src_addr; - socklen_t addrlen; + sockaddr_storage remote; + socklen_t len = sizeof(remote); + length = recvfrom(mSocket, buffer, sizeof(buffer), - MSG_TRUNC|MSG_DONTWAIT, (sockaddr*)&src_addr, &addrlen); - - // The following if clause is for fixing the target address if - // proxy server did not replace the NAT address with its media - // port in SDP. Although it is proxy server's responsibility for - // replacing the connection address with correct one, we will change - // the target address as we detect the difference for now until we - // know the best way to get rid of this issue. - if ((memcmp((void*)&src_addr, (void*)&mRemote, addrlen) != 0) && - isNatAddress(&mRemote)) { - memcpy((void*)&mRemote, (void*)&src_addr, addrlen); - } + MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)&remote, &len); // Do we need to check SSRC, sequence, and timestamp? They are not // reliable but at least they can be used to identify duplicates? @@ -409,8 +402,12 @@ void AudioStream::decode(int tick) if (length >= 0) { length = mCodec->decode(samples, &buffer[offset], length); } + if (length > 0 && mFixRemote) { + mRemote = remote; + mFixRemote = false; + } } - if (length != mSampleCount) { + if (length <= 0) { LOGD("stream[%d] decoder error", mSocket); return; } |
