diff options
19 files changed, 1669 insertions, 69 deletions
diff --git a/core/java/android/preference/ListPreferenceMultiSelect.java b/core/java/android/preference/ListPreferenceMultiSelect.java index a7dc1bd6..a8c711b 100644 --- a/core/java/android/preference/ListPreferenceMultiSelect.java +++ b/core/java/android/preference/ListPreferenceMultiSelect.java @@ -31,6 +31,8 @@ public class ListPreferenceMultiSelect extends ListPreference { private boolean[] mClickedDialogEntryIndices; + private String mSummary; + public ListPreferenceMultiSelect(Context context) { super(context); } @@ -106,4 +108,24 @@ public class ListPreferenceMultiSelect extends ListPreference { } } } + + @Override + public CharSequence getSummary() { + final CharSequence entry = getEntry(); + if (mSummary == null) { + return super.getSummary(); + } else { + return mSummary; + } + } + + @Override + public void setSummary(CharSequence summary) { + super.setSummary(summary); + if (summary == null && mSummary != null) { + mSummary = null; + } else if (summary != null && !summary.equals(mSummary)) { + mSummary = summary.toString(); + } + } } diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java index 0d9cf9a..5f756db 100644 --- a/core/java/com/android/internal/widget/LockPatternView.java +++ b/core/java/com/android/internal/widget/LockPatternView.java @@ -64,6 +64,7 @@ public class LockPatternView extends View { private Paint mPaint = new Paint(); private Paint mPathPaint = new Paint(); + private Paint mMsgPaint = new Paint(); // TODO: make this common with PhoneWindow static final int STATUS_BAR_HEIGHT = 25; @@ -115,6 +116,8 @@ public class LockPatternView extends View { private Bitmap mBitmapCircleGreen; private Bitmap mBitmapCircleRed; + private String mIncorrectPatternMsg; + private Bitmap mBitmapArrowGreenUp; private Bitmap mBitmapArrowRedUp; @@ -267,6 +270,12 @@ public class LockPatternView extends View { mPathPaint.setStrokeJoin(Paint.Join.ROUND); mPathPaint.setStrokeCap(Paint.Cap.ROUND); + mMsgPaint.setAntiAlias(true); + mMsgPaint.setDither(true); + mMsgPaint.setColor(Color.RED); // TODO this should be from the style + mMsgPaint.setTextAlign(Paint.Align.CENTER); + + // lot's of bitmaps! mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default_holo); mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched_holo); @@ -286,6 +295,8 @@ public class LockPatternView extends View { mBitmapHeight = Math.max(mBitmapHeight, bitmap.getHeight()); } + // incorrect pattern message + mIncorrectPatternMsg = context.getResources().getString(R.string.lockscreen_pattern_wrong); } private Bitmap getBitmapFor(int resId) { @@ -452,6 +463,9 @@ public class LockPatternView extends View { final int height = h - mPaddingTop - mPaddingBottom; mSquareHeight = height / 3.0f; + + // Try to set a message size relative to square size + mMsgPaint.setTextSize(mSquareHeight / 6); } private int resolveMeasured(int measureSpec, int desired) @@ -930,11 +944,17 @@ public class LockPatternView extends View { } } + // If lock pattern is in stealth mode and the pattern was wrong + // show a text advising of the pattern failure + float msgLeftX = paddingLeft + squareWidth + (squareWidth / 2); + float msgTopY = paddingTop + (squareHeight * 2); + drawMsg(canvas, (int) msgLeftX, (int) msgTopY); + // TODO: the path should be created and cached every time we hit-detect a cell // only the last segment of the path should be computed here // draw the path of the pattern (unless the user is in progress, and // we are in stealth mode) - final boolean drawPath = (!mInStealthMode || mPatternDisplayMode == DisplayMode.Wrong); + final boolean drawPath = !mInStealthMode; // draw the arrows associated with the path (unless the user is in progress, and // we are in stealth mode) @@ -1038,7 +1058,7 @@ public class LockPatternView extends View { Bitmap outerCircle; Bitmap innerCircle; - if (!partOfPattern || (mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)) { + if (!partOfPattern || (mInStealthMode)) { // unselected circle outerCircle = mBitmapCircleDefault; innerCircle = mBitmapBtnDefault; @@ -1081,6 +1101,17 @@ public class LockPatternView extends View { canvas.drawBitmap(innerCircle, mCircleMatrix, mPaint); } + /** + * @param canvas + * @param leftX + * @param topY + */ + private void drawMsg(Canvas canvas, int leftX, int topY) { + if (mInStealthMode && mPatternDisplayMode == DisplayMode.Wrong) { + canvas.drawText(mIncorrectPatternMsg, leftX, topY, mMsgPaint); + } + } + @Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 3709906..903326f 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -36,6 +36,24 @@ <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string> <string name="mmiError" msgid="5154499457739052907">"出现连接问题或 MMI 码无效。"</string> <string name="mmiFdnError" msgid="5224398216385316471">"只能对固定拨号号码执行此类操作。"</string> + + <!-- Names of default profiles. --> + <string name="profileNameDefault">默认</string> + <string name="profileNameWork">工作</string> + <string name="profileNameHome">住宅</string> + <string name="profileNameSilent">静音</string> + <string name="profileNameNight">夜晚</string> + + <!-- Names of application groups. --> + <string name="profileGroupPhone">电话</string> + <string name="profileGroupCalendar">日历</string> + <string name="profileGroupGmail">Gmail</string> + <string name="profileGroupEmail">电子邮件</string> + <string name="profileGroupSMS">短信</string> + + <!-- Name of wildcard profile. --> + <string name="wildcardProfile">其他</string> + <string name="serviceEnabled" msgid="8147278346414714315">"已启用服务。"</string> <string name="serviceEnabledFor" msgid="6856228140453471041">"已针对以下内容启用了服务:"</string> <string name="serviceDisabled" msgid="1937553226592516411">"已停用服务。"</string> @@ -100,6 +118,7 @@ <string name="roamingText11" msgid="4154476854426920970">"启用漫游横幅"</string> <string name="roamingText12" msgid="1189071119992726320">"禁用漫游横幅"</string> <string name="roamingTextSearching" msgid="8360141885972279963">"正在搜索服务"</string> + <string name="roamingTextAirplaneMode">飞行模式</string> <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string> <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string> <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g> 秒后<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string> @@ -141,13 +160,14 @@ <string name="reboot_system" product="default">"重启手机"</string> <string name="global_action_screenshot">"屏幕截图"</string> <string name="reboot_reboot">"重启"</string> - <string name="reboot_recovery">"恢复"</string> - <string name="reboot_bootloader">"引导"</string> + <string name="global_action_choose_profile">场景模式</string> + <string name="reboot_recovery">"恢复模式"</string> + <string name="reboot_bootloader">"引导程序"</string> <string name="reboot_bootmenu">"引导菜单"</string> - <string name="reboot_fastboot">"快速启动"</string> - <string name="reboot_download">"下载"</string> + <string name="reboot_fastboot">"Fastboot"</string> + <string name="reboot_download">"下载模式"</string> <string name="reboot_progress">"正在重启..."</string> - <string name="reboot_confirm">"您的手机会重启。"</string> + <string name="reboot_confirm">"您的手机将会重启。"</string> <string name="silent_mode_silent" msgid="319298163018473078">"振铃器关闭"</string> <string name="silent_mode_vibrate" msgid="7072043388581551395">"振铃器振动"</string> <string name="silent_mode_ring" msgid="8592241816194074353">"振铃器开启"</string> @@ -313,6 +333,12 @@ <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"允许应用程序通过删除应用程序缓存目录中的文件释放手机存储空间。通常此权限只适用于系统进程。"</string> <string name="permlab_movePackage" msgid="728454979946503926">"移动应用程序资源"</string> <string name="permdesc_movePackage" msgid="6323049291923925277">"允许应用程序在内部介质和外部介质之间移动应用程序资源。"</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_preventpower">阻止电源键</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_preventpower">允许应用程序完全掌控电源键。</string> + <string name="permlab_readLogs" msgid="6615778543198967614">"查阅敏感日志数据"</string> <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"允许应用程序从系统的各种日志文件中读取信息。这样,应用程序就可以发现关于您平板电脑使用情况的一般信息,其中可能包含个人信息或私密信息。"</string> <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"允许应用程序从系统的各个日志文件中读取信息。这样,应用程序就可以发现关于您手机使用情况的一般信息,其中可能包含个人信息或私密信息。"</string> @@ -586,6 +612,11 @@ <item msgid="2506857312718630823">"ICQ"</item> <item msgid="1648797903785279353">"Jabber"</item> </string-array> + + <!-- Hardware Rotation lock string --> + <string name="toast_rotation_unlocked">屏幕方向已解锁</string> + <string name="toast_rotation_locked">屏幕方向已锁定</string> + <string name="phoneTypeCustom" msgid="1644738059053355820">"自定义"</string> <string name="phoneTypeHome" msgid="2570923463033985887">"住宅"</string> <string name="phoneTypeMobile" msgid="6501463557754751037">"手机"</string> @@ -1240,4 +1271,72 @@ <string name="launchBrowserDefault" msgid="2057951947297614725">"要启动浏览器吗?"</string> <string name="SetupCallDefault" msgid="6870275517518479651">"要接听电话吗?"</string> <string name="app_killed_message">应用程序已被杀死</string> + + <!-- Lock screen Weather - Weather codes --> + <string name="weather_0">龙卷风</string> + <string name="weather_1">热带风暴</string> + <string name="weather_2">飓风</string> + <string name="weather_3">强雷暴</string> + <string name="weather_4">雷暴</string> + <string name="weather_5">雨夹雪</string> + <string name="weather_6">混合雨和冻雨</string> + <string name="weather_7">混合雪和冻雨</string> + <string name="weather_8">冻毛毛雨</string> + <string name="weather_9">毛毛雨</string> + <string name="weather_10">冰雨</string> + <string name="weather_11">阵雨</string> + <string name="weather_12">阵雨</string> + <string name="weather_13">飘雪</string> + <string name="weather_14">小雪</string> + <string name="weather_15">吹雪</string> + <string name="weather_16">雪</string> + <string name="weather_17">冰雹</string> + <string name="weather_18">冻雨</string> + <string name="weather_19">沙尘</string> + <string name="weather_20">多雾</string> + <string name="weather_21">阴霾</string> + <string name="weather_22">烟雾</string> + <string name="weather_23">强风</string> + <string name="weather_24">大风</string> + <string name="weather_25">冷</string> + <string name="weather_26">多云</string> + <string name="weather_27">大部多云</string> <!-- Night --> + <string name="weather_28">大部多云</string> <!-- Day --> + <string name="weather_29">部分多云</string> <!-- Night --> + <string name="weather_30">部分多云</string> <!-- Day --> + <string name="weather_31">晴天</string> <!-- Night --> + <string name="weather_32">晴天</string> + <string name="weather_33">晴天积云</string> <!-- Night --> + <string name="weather_34">晴天积云</string> <!-- Day --> + <string name="weather_35">雨夹冰雹</string> + <string name="weather_36">热</string> + <string name="weather_37">局部性雷暴雨</string> + <string name="weather_38">分散雷雨</string> + <string name="weather_39">分散雷雨</string> + <string name="weather_40">零星阵雨</string> + <string name="weather_41">大雪</string> + <string name="weather_42">零星阵雪</string> + <string name="weather_43">大雪</string> + <string name="weather_44">晴间多云</string> + <string name="weather_45">雷阵雨</string> + <string name="weather_46">阵雪</string> + <string name="weather_47">局部雷阵雨</string> + <!-- Forecast unavailable --> + <string name="weather_3200"></string> + + <!-- Lock screen Weather - Wind directions --> + <string name="weather_N">北</string> + <string name="weather_NE">东北</string> + <string name="weather_E">东</string> + <string name="weather_SE">东南</string> + <string name="weather_S">南</string> + <string name="weather_SW">西南</string> + <string name="weather_W">西</string> + <string name="weather_NW">西北</string> + + <!-- Lock screen Weather - error messages --> + <string name="weather_no_data">无数据</string> + <string name="weather_tap_to_refresh">请点击刷新</string> + <string name="weather_refreshing">正在刷新</string> + </resources> diff --git a/data/fonts/Roboto-Bold.ttf b/data/fonts/Roboto-Bold.ttf Binary files differindex 40ecd14..f9af089 100644 --- a/data/fonts/Roboto-Bold.ttf +++ b/data/fonts/Roboto-Bold.ttf diff --git a/data/fonts/Roboto-BoldCondensed.ttf b/data/fonts/Roboto-BoldCondensed.ttf Binary files differindex 61da020..fa6f7cc 100755 --- a/data/fonts/Roboto-BoldCondensed.ttf +++ b/data/fonts/Roboto-BoldCondensed.ttf diff --git a/data/fonts/Roboto-BoldCondensedItalic.ttf b/data/fonts/Roboto-BoldCondensedItalic.ttf Binary files differindex b946dce..aea6167 100755 --- a/data/fonts/Roboto-BoldCondensedItalic.ttf +++ b/data/fonts/Roboto-BoldCondensedItalic.ttf diff --git a/data/fonts/Roboto-BoldItalic.ttf b/data/fonts/Roboto-BoldItalic.ttf Binary files differindex d9067c5..217bf26 100644 --- a/data/fonts/Roboto-BoldItalic.ttf +++ b/data/fonts/Roboto-BoldItalic.ttf diff --git a/data/fonts/Roboto-Condensed.ttf b/data/fonts/Roboto-Condensed.ttf Binary files differindex 73a868f..371399b 100755 --- a/data/fonts/Roboto-Condensed.ttf +++ b/data/fonts/Roboto-Condensed.ttf diff --git a/data/fonts/Roboto-CondensedItalic.ttf b/data/fonts/Roboto-CondensedItalic.ttf Binary files differindex a0969bb..6426a64 100755 --- a/data/fonts/Roboto-CondensedItalic.ttf +++ b/data/fonts/Roboto-CondensedItalic.ttf diff --git a/data/fonts/Roboto-Italic.ttf b/data/fonts/Roboto-Italic.ttf Binary files differindex 88e4a5b..9332545 100644 --- a/data/fonts/Roboto-Italic.ttf +++ b/data/fonts/Roboto-Italic.ttf diff --git a/data/fonts/Roboto-Regular.ttf b/data/fonts/Roboto-Regular.ttf Binary files differindex f592adf..0f0b2c2 100644 --- a/data/fonts/Roboto-Regular.ttf +++ b/data/fonts/Roboto-Regular.ttf diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index b557dd9..8cfed1b 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -226,6 +226,10 @@ public class AudioService extends IAudioService.Stub { "AudioService.SAVED_NOTIFICATION_SPEAKER_VOL", }; + private static final int HEADSET_VOLUME_RESTORE_CAP_VOICE_CALL = 3; // Out of 5 + private static final int HEADSET_VOLUME_RESTORE_CAP_MUSIC = 8; // Out of 15 + private static final int HEADSET_VOLUME_RESTORE_CAP_OTHER = 4; // Out of 7 + private AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() { public void onError(int error) { switch (error) { @@ -2573,56 +2577,60 @@ public class AudioService extends IAudioService.Stub { int lastVolume; if (state == 1) { // Headset plugged in - int volumeRestoreCap; - if (Settings.System.getInt(mContentResolver, - Settings.System.SAFE_HEADSET_VOLUME_RESTORE, 1) == 0) { - // Don't cap - volumeRestoreCap = 8; - } else { - volumeRestoreCap = 4; - } + final boolean capVolumeRestore = Settings.System.getInt(mContentResolver, + Settings.System.SAFE_HEADSET_VOLUME_RESTORE, 1) == 1; for (int stream = 0; stream < STREAM_VOLUME_HEADSET_SETTINGS.length; stream++) { + final int streamAlias = STREAM_VOLUME_ALIAS[stream]; + // Save speaker volume + System.putInt(mContentResolver, STREAM_VOLUME_SPEAKER_SETTINGS[stream], + getStreamVolume(streamAlias)); + // Restore headset volume try { lastVolume = System.getInt(mContentResolver, - STREAM_VOLUME_HEADSET_SETTINGS[stream]); + STREAM_VOLUME_HEADSET_SETTINGS[streamAlias]); } catch (SettingNotFoundException e) { lastVolume = -1; } - System.putInt(mContentResolver, STREAM_VOLUME_SPEAKER_SETTINGS[stream], - getStreamVolume(stream)); - if (lastVolume >= 0) - if (stream == 0) { - // Don't touch voice call volume - setStreamVolume(stream, lastVolume, 0); - } else if (stream != 3) { - if (lastVolume > volumeRestoreCap) { - setStreamVolume(stream, volumeRestoreCap, 0); - } else { - setStreamVolume(stream, lastVolume, 0); + if (lastVolume >= 0) { + if (capVolumeRestore) { + final int volumeCap; + switch (streamAlias) { + case AudioSystem.STREAM_VOICE_CALL: + volumeCap = HEADSET_VOLUME_RESTORE_CAP_VOICE_CALL; + break; + case AudioSystem.STREAM_MUSIC: + volumeCap = HEADSET_VOLUME_RESTORE_CAP_MUSIC; + break; + case AudioSystem.STREAM_SYSTEM: + case AudioSystem.STREAM_RING: + case AudioSystem.STREAM_ALARM: + case AudioSystem.STREAM_NOTIFICATION: + default: + volumeCap = HEADSET_VOLUME_RESTORE_CAP_OTHER; + break; } + setStreamVolume(streamAlias, Math.min(volumeCap, lastVolume), 0); } else { - // For media volume the cap is doubled to correspond - // with its finer granularity - if (lastVolume > (volumeRestoreCap * 2)) { - setStreamVolume(stream, (volumeRestoreCap * 2), 0); - } else { - setStreamVolume(stream, lastVolume, 0); - } + setStreamVolume(streamAlias, lastVolume, 0); } + } } } else { // Headset disconnected for (int stream = 0; stream < STREAM_VOLUME_SPEAKER_SETTINGS.length; stream++) { + final int streamAlias = STREAM_VOLUME_ALIAS[stream]; + // Save headset volume + System.putInt(mContentResolver, STREAM_VOLUME_HEADSET_SETTINGS[stream], + getStreamVolume(streamAlias)); + // Restore speaker volume try { lastVolume = System.getInt(mContentResolver, - STREAM_VOLUME_SPEAKER_SETTINGS[stream]); + STREAM_VOLUME_SPEAKER_SETTINGS[streamAlias]); } catch (SettingNotFoundException e) { lastVolume = -1; } - System.putInt(mContentResolver, STREAM_VOLUME_HEADSET_SETTINGS[stream], - getStreamVolume(stream)); if (lastVolume >= 0) - setStreamVolume(stream, lastVolume, 0); + setStreamVolume(streamAlias, lastVolume, 0); } } diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index bf00b22..0d0d64f 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -21,6 +21,8 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="7164937344850004466">"Rendszer UI"</string> <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Törlés"</string> + <string name="notifications_off_title">Értesítések kikapcsolva</string> + <string name="notifications_off_text">Érintse meg az értesítések engedélyezéséhez.</string> <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne zavarjanak"</string> <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Értesítések megjelenítése"</string> <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Eltávolítás a listából"</string> @@ -41,7 +43,13 @@ <string name="battery_low_why" msgid="7279169609518386372">"Akkumulátorhasználat"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Beállítások"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> + <string name="status_bar_settings_bluetooth_button">Bluetooth</string> <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Repülőgép üzemmód"</string> + <string name="status_bar_settings_location">GPS</string> + <string name="status_bar_settings_flashlight">LED villanófény</string> + <string name="status_bar_settings_mobile_data">Mobilinternet</string> + <string name="status_bar_settings_network_mode">2G/3G</string> + <string name="status_bar_settings_sound_mode">Hang</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Képernyő automatikus forgatása"</string> <string name="status_bar_settings_mute_label" msgid="554682549917429396">"NÉMÍT"</string> <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string> @@ -138,5 +146,17 @@ <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS keresése"</string> <string name="gps_notification_found_text" msgid="4619274244146446464">"A GPS beállította a helyet"</string> <string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string> + + <!-- Dialog title for navigation bar button selection --> + <string name="navbar_dialog_title">Válasszon eseményt</string> + <string name="navbar_home_button">Kezdőlap</string> + <string name="navbar_recent_button">Előzmények</string> + <string name="navbar_search_button">Keresés</string> + <string name="navbar_back_button">Vissza</string> + <string name="navbar_empty_button">Gomb törlése</string> + <string name="navbar_menu_conditional_button">Menü (auto elrejtés)</string> + <string name="navbar_menu_always_button">Menü (mindig látszik)</string> + <string name="navbar_menu_big_button">Menü</string> + <string name="powerwidget_screen_timeout_toast">"Képernyő időkorlátja beállítva a következőre: %1$d %2$s"</string> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerWidget.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerWidget.java index 5f8f91f..1fc48d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerWidget.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerWidget.java @@ -272,11 +272,6 @@ public class PowerWidget extends FrameLayout { mScrollView.setFadingEdgeLength(mContext.getResources().getDisplayMetrics().widthPixels / LAYOUT_SCROLL_BUTTON_THRESHOLD); mScrollView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET); mScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER); - // set the padding on the linear layout to the size of our scrollbar, so we don't have them overlap - mButtonLayout.setPadding(mButtonLayout.getPaddingLeft(), - mButtonLayout.getPaddingTop(), - mButtonLayout.getPaddingRight(), - mScrollView.getVerticalScrollbarWidth()); mScrollView.addView(mButtonLayout, WIDGET_LAYOUT_PARAMS); updateScrollbar(); addView(mScrollView, WIDGET_LAYOUT_PARAMS); @@ -370,6 +365,15 @@ public class PowerWidget extends FrameLayout { boolean hideScrollBar = Settings.System.getInt(mContext.getContentResolver(), Settings.System.EXPANDED_HIDE_SCROLLBAR, 0) == 1; mScrollView.setHorizontalScrollBarEnabled(!hideScrollBar); + + // set the padding on the linear layout to the size of our scrollbar, + // so we don't have them overlap + // need to be here for make use of EXPANDED_HIDE_SCROLLBAR, expanding or collapsing + // the space used by the scrollbar + if (mButtonLayout != null) { + mButtonLayout.setPadding(0, 0, 0, + !hideScrollBar ? mScrollView.getVerticalScrollbarWidth() : 0); + } } private void updateHapticFeedbackSetting() { @@ -486,7 +490,8 @@ public class PowerWidget extends FrameLayout { updateVisibility(); // now check for scrollbar hiding } else if(uri.equals(Settings.System.getUriFor(Settings.System.EXPANDED_HIDE_SCROLLBAR))) { - updateScrollbar(); + // Needed to remove scrollview to gain the space of the scrollable area + recreateButtonLayout(); } if (uri.equals(Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED)) diff --git a/telephony/java/com/android/internal/telephony/QualcommSharedRIL.java b/telephony/java/com/android/internal/telephony/QualcommSharedRIL.java index 811919d..4c29b2f 100644 --- a/telephony/java/com/android/internal/telephony/QualcommSharedRIL.java +++ b/telephony/java/com/android/internal/telephony/QualcommSharedRIL.java @@ -629,7 +629,7 @@ public class QualcommSharedRIL extends RIL implements CommandsInterface { } } - private void setRadioStateFromRILInt (int stateCode) { + protected void setRadioStateFromRILInt (int stateCode) { CommandsInterface.RadioState radioState; HandlerThread handlerThread; Looper looper; diff --git a/telephony/java/com/android/internal/telephony/SamsungCDMAQualcommRIL.java b/telephony/java/com/android/internal/telephony/SamsungCDMAQualcommRIL.java index 7d827d5..643c181 100644 --- a/telephony/java/com/android/internal/telephony/SamsungCDMAQualcommRIL.java +++ b/telephony/java/com/android/internal/telephony/SamsungCDMAQualcommRIL.java @@ -44,6 +44,7 @@ import java.util.Collections; * Samsung CDMA RIL doesn't send CDMA NV in RIUM infomation format which causes the CDMA RIL stack to crash and end up not being provisioned. * Samsung put CDMA NV in GSM format. I forced the RIL stack to process CDMA NV request as a GSM SIM in CDMA mode. * Custom Qualcomm No SimReady RIL using the latest Uicc stack + * Check for CDMA phone on RADIO_ON* event and if so set status to RUIM_NOT_READY to trigger CSIM/RUIM processing * * {@hide} */ @@ -101,7 +102,6 @@ public class SamsungCDMAQualcommRIL extends QualcommSharedRIL implements Command appIndex = status.getGsmUmtsSubscriptionAppIndex(); Log.d(LOG_TAG, "This is a CDMA PHONE " + appIndex); - if (numApplications > 0) { IccCardApplication application = status.getApplication(appIndex); mAid = application.aid; @@ -117,7 +117,8 @@ public class SamsungCDMAQualcommRIL extends QualcommSharedRIL implements Command return status; } - private void setRadioStateFromRILInt (int stateCode) { + @Override + protected void setRadioStateFromRILInt (int stateCode) { CommandsInterface.RadioState radioState; HandlerThread handlerThread; Looper looper; @@ -147,8 +148,12 @@ public class SamsungCDMAQualcommRIL extends QualcommSharedRIL implements Command mIccHandler = new IccHandler(this,looper); mIccHandler.run(); } - radioState = CommandsInterface.RadioState.SIM_NOT_READY; + if (mPhoneType == RILConstants.CDMA_PHONE) { + radioState = CommandsInterface.RadioState.RUIM_NOT_READY; + } else { + radioState = CommandsInterface.RadioState.SIM_NOT_READY; + } setRadioState(radioState); break; default: @@ -157,6 +162,7 @@ public class SamsungCDMAQualcommRIL extends QualcommSharedRIL implements Command setRadioState (radioState); } + @Override protected Object responseSignalStrength(Parcel p) { diff --git a/telephony/java/com/android/internal/telephony/SamsungCDMAv6RIL.java b/telephony/java/com/android/internal/telephony/SamsungCDMAv6RIL.java new file mode 100644 index 0000000..505adc0 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SamsungCDMAv6RIL.java @@ -0,0 +1,936 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2011, 2012 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.internal.telephony; + +import java.util.ArrayList; +import java.util.Collections; +import java.lang.Runtime; +import java.io.IOException; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.os.Handler; +import android.os.Message; +import android.os.AsyncResult; +import android.os.Parcel; +import android.os.SystemProperties; +import android.telephony.PhoneNumberUtils; +import android.telephony.SmsManager; +import android.telephony.SmsMessage; +import static com.android.internal.telephony.RILConstants.*; + +import com.android.internal.telephony.CallForwardInfo; +import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.DataCallState; +import com.android.internal.telephony.DataConnection.FailCause; +import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; +import com.android.internal.telephony.gsm.SuppServiceNotification; +import com.android.internal.telephony.IccCardApplication; +import com.android.internal.telephony.IccCardStatus; +import com.android.internal.telephony.IccUtils; +import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.SmsResponse; +import com.android.internal.telephony.cdma.CdmaCallWaitingNotification; +import com.android.internal.telephony.cdma.CdmaInformationRecords; +import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec; +import com.android.internal.telephony.cdma.SignalToneUtil; + +import android.util.Log; + +public class SamsungCDMAv6RIL extends RIL implements CommandsInterface { + + public SamsungCDMAv6RIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + // SAMSUNG SGS STATES + static final int RIL_UNSOL_O2_HOME_ZONE_INFO = 11007; + static final int RIL_UNSOL_DEVICE_READY_NOTI = 11008; + static final int RIL_UNSOL_GPS_NOTI = 11009; + static final int RIL_UNSOL_AM = 11010; + static final int RIL_UNSOL_DATA_SUSPEND_RESUME = 11012; + static final int RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL = 11011; + static final int RIL_UNSOL_HSDPA_STATE_CHANGED = 11016; + static final int RIL_REQUEST_DIAL_EMERGENCY = 10016; + + static String + requestToString(int request) { + switch (request) { + case RIL_REQUEST_DIAL_EMERGENCY: return "DIAL_EMERGENCY"; + default: return RIL.requestToString(request); + } + } + + static String + samsungResponseToString(int request) + { + switch(request) { + // SAMSUNG STATES + case RIL_UNSOL_AM: return "RIL_UNSOL_AM"; + case RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL: return "RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL"; + case RIL_UNSOL_DATA_SUSPEND_RESUME: return "RIL_UNSOL_DATA_SUSPEND_RESUME"; + default: return "<unknown response: "+request+">"; + } +} + + protected void samsungUnsljLogRet(int response, Object ret) { + riljLog("[UNSL]< " + samsungResponseToString(response) + " " + retToString(response, ret)); + } + + @Override + public void + setRadioPower(boolean on, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result); + + if (on) { + rr.mp.writeInt(1); + rr.mp.writeInt(1); + } else { + rr.mp.writeInt(2); + rr.mp.writeInt(0); + rr.mp.writeInt(0); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + send(rr); + } + + @Override + protected void + processSolicited (Parcel p) { + int serial, error; + + serial = p.readInt(); + error = p.readInt(); + + Log.d(LOG_TAG, "Serial: " + serial); + Log.d(LOG_TAG, "Error: " + error); + + RILRequest rr; + + rr = findAndRemoveRequestFromList(serial); + + if (rr == null) { + Log.w(LOG_TAG, "Unexpected solicited response! sn: " + + serial + " error: " + error); + return; + } + + Object ret = null; + + if (error == 0 || p.dataAvail() > 0) { + // either command succeeds or command fails but with data payload + try {switch (rr.mRequest) { + /* + cat libs/telephony/ril_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: ret = \2(p); break;/' + */ + case RIL_REQUEST_GET_SIM_STATUS: ret = responseIccCardStatus(p); break; + case RIL_REQUEST_ENTER_SIM_PIN: ret = responseInts(p); break; + case RIL_REQUEST_ENTER_SIM_PUK: ret = responseInts(p); break; + case RIL_REQUEST_ENTER_SIM_PIN2: ret = responseInts(p); break; + case RIL_REQUEST_ENTER_SIM_PUK2: ret = responseInts(p); break; + case RIL_REQUEST_CHANGE_SIM_PIN: ret = responseInts(p); break; + case RIL_REQUEST_CHANGE_SIM_PIN2: ret = responseInts(p); break; + case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: ret = responseInts(p); break; + case RIL_REQUEST_GET_CURRENT_CALLS: ret = responseCallList(p); break; + case RIL_REQUEST_DIAL: ret = responseVoid(p); break; + case RIL_REQUEST_GET_IMSI: ret = responseString(p); break; + case RIL_REQUEST_HANGUP: ret = responseVoid(p); break; + case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: ret = responseVoid(p); break; + case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: ret = responseVoid(p); break; + case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: ret = responseVoid(p); break; + case RIL_REQUEST_CONFERENCE: ret = responseVoid(p); break; + case RIL_REQUEST_UDUB: ret = responseVoid(p); break; + case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: ret = responseLastCallFailCause(p); break; + case RIL_REQUEST_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break; + case RIL_REQUEST_VOICE_REGISTRATION_STATE: ret = responseVoiceRegistrationState(p); break; + case RIL_REQUEST_DATA_REGISTRATION_STATE: ret = responseStrings(p); break; + case RIL_REQUEST_OPERATOR: ret = responseStrings(p); break; + case RIL_REQUEST_RADIO_POWER: ret = responseVoid(p); break; + case RIL_REQUEST_DTMF: ret = responseVoid(p); break; + case RIL_REQUEST_SEND_SMS: ret = responseSMS(p); break; + case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret = responseSMS(p); break; + case RIL_REQUEST_SETUP_DATA_CALL: ret = responseSetupDataCall(p); break; + case RIL_REQUEST_SIM_IO: ret = responseICC_IO(p); break; + case RIL_REQUEST_SEND_USSD: ret = responseVoid(p); break; + case RIL_REQUEST_CANCEL_USSD: ret = responseVoid(p); break; + case RIL_REQUEST_GET_CLIR: ret = responseInts(p); break; + case RIL_REQUEST_SET_CLIR: ret = responseVoid(p); break; + case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS: ret = responseCallForward(p); break; + case RIL_REQUEST_SET_CALL_FORWARD: ret = responseVoid(p); break; + case RIL_REQUEST_QUERY_CALL_WAITING: ret = responseInts(p); break; + case RIL_REQUEST_SET_CALL_WAITING: ret = responseVoid(p); break; + case RIL_REQUEST_SMS_ACKNOWLEDGE: ret = responseVoid(p); break; + case RIL_REQUEST_GET_IMEI: ret = responseString(p); break; + case RIL_REQUEST_GET_IMEISV: ret = responseString(p); break; + case RIL_REQUEST_ANSWER: ret = responseVoid(p); break; + case RIL_REQUEST_DEACTIVATE_DATA_CALL: ret = responseVoid(p); break; + case RIL_REQUEST_QUERY_FACILITY_LOCK: ret = responseInts(p); break; + case RIL_REQUEST_SET_FACILITY_LOCK: ret = responseInts(p); break; + case RIL_REQUEST_CHANGE_BARRING_PASSWORD: ret = responseVoid(p); break; + case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: ret = responseInts(p); break; + case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: ret = responseVoid(p); break; + case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: ret = responseVoid(p); break; + case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS : ret = responseOperatorInfos(p); break; + case RIL_REQUEST_DTMF_START: ret = responseVoid(p); break; + case RIL_REQUEST_DTMF_STOP: ret = responseVoid(p); break; + case RIL_REQUEST_BASEBAND_VERSION: ret = responseString(p); break; + case RIL_REQUEST_SEPARATE_CONNECTION: ret = responseVoid(p); break; + case RIL_REQUEST_SET_MUTE: ret = responseVoid(p); break; + case RIL_REQUEST_GET_MUTE: ret = responseInts(p); break; + case RIL_REQUEST_QUERY_CLIP: ret = responseInts(p); break; + case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: ret = responseInts(p); break; + case RIL_REQUEST_DATA_CALL_LIST: ret = responseDataCallList(p); break; + case RIL_REQUEST_RESET_RADIO: ret = responseVoid(p); break; + case RIL_REQUEST_OEM_HOOK_RAW: ret = responseRaw(p); break; + case RIL_REQUEST_OEM_HOOK_STRINGS: ret = responseStrings(p); break; + case RIL_REQUEST_SCREEN_STATE: ret = responseVoid(p); break; + case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: ret = responseVoid(p); break; + case RIL_REQUEST_WRITE_SMS_TO_SIM: ret = responseInts(p); break; + case RIL_REQUEST_DELETE_SMS_ON_SIM: ret = responseVoid(p); break; + case RIL_REQUEST_SET_BAND_MODE: ret = responseVoid(p); break; + case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: ret = responseInts(p); break; + case RIL_REQUEST_STK_GET_PROFILE: ret = responseString(p); break; + case RIL_REQUEST_STK_SET_PROFILE: ret = responseVoid(p); break; + case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: ret = responseString(p); break; + case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: ret = responseVoid(p); break; + case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: ret = responseInts(p); break; + case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret = responseVoid(p); break; + case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret = responseVoid(p); break; + case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret = responseNetworkType(p); break; + case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: ret = responseCellList(p); break; + case RIL_REQUEST_SET_LOCATION_UPDATES: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE: ret = responseInts(p); break; + case RIL_REQUEST_SET_TTY_MODE: ret = responseVoid(p); break; + case RIL_REQUEST_QUERY_TTY_MODE: ret = responseInts(p); break; + case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: ret = responseInts(p); break; + case RIL_REQUEST_CDMA_FLASH: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_BURST_DTMF: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_SEND_SMS: ret = responseSMS(p); break; + case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: ret = responseVoid(p); break; + case RIL_REQUEST_GSM_GET_BROADCAST_CONFIG: ret = responseGmsBroadcastConfig(p); break; + case RIL_REQUEST_GSM_SET_BROADCAST_CONFIG: ret = responseVoid(p); break; + case RIL_REQUEST_GSM_BROADCAST_ACTIVATION: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG: ret = responseCdmaBroadcastConfig(p); break; + case RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_BROADCAST_ACTIVATION: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY: ret = responseVoid(p); break; + case RIL_REQUEST_CDMA_SUBSCRIPTION: ret = responseCdmaSubscription(p); break; + case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: ret = responseInts(p); break; + case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: ret = responseVoid(p); break; + case RIL_REQUEST_DEVICE_IDENTITY: ret = responseStrings(p); break; + case RIL_REQUEST_GET_SMSC_ADDRESS: ret = responseString(p); break; + case RIL_REQUEST_SET_SMSC_ADDRESS: ret = responseVoid(p); break; + case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break; + case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: ret = responseVoid(p); break; + case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: ret = responseVoid(p); break; + case RIL_REQUEST_DIAL_EMERGENCY: ret = responseVoid(p); break; + case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break; + default: + throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest); + //break; + }} catch (Throwable tr) { + // Exceptions here usually mean invalid RIL responses + + Log.w(LOG_TAG, rr.serialString() + "< " + + requestToString(rr.mRequest) + + " exception, possible invalid RIL response", tr); + + if (rr.mResult != null) { + AsyncResult.forMessage(rr.mResult, null, tr); + rr.mResult.sendToTarget(); + } + rr.release(); + return; + } + } + + if (error != 0) { + // Ugly fix for Samsung messing up SMS_SEND request fail in binary RIL + if (error == -1 && rr.mRequest == RIL_REQUEST_SEND_SMS) + { + try + { + ret = responseSMS(p); + } catch (Throwable tr) { + Log.w(LOG_TAG, rr.serialString() + "< " + + requestToString(rr.mRequest) + + " exception, Processing Samsung SMS fix ", tr); + rr.onError(error, ret); + rr.release(); + return; + } + } else { + rr.onError(error, ret); + rr.release(); + return; + } + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest) + + " " + retToString(rr.mRequest, ret)); + + if (rr.mResult != null) { + AsyncResult.forMessage(rr.mResult, ret, null); + rr.mResult.sendToTarget(); + } + + rr.release(); + } + + @Override + public void + dial(String address, int clirMode, UUSInfo uusInfo, Message result) { + RILRequest rr; + + rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); + rr.mp.writeString(address); + rr.mp.writeInt(clirMode); + rr.mp.writeInt(0); // UUS information is absent + + if (uusInfo == null) { + rr.mp.writeInt(0); // UUS information is absent + } else { + rr.mp.writeInt(1); // UUS information is present + rr.mp.writeInt(uusInfo.getType()); + rr.mp.writeInt(uusInfo.getDcs()); + rr.mp.writeByteArray(uusInfo.getUserData()); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + dialEmergencyCall(String address, int clirMode, Message result) { + RILRequest rr; + Log.v(LOG_TAG, "Emergency dial: " + address); + + rr = RILRequest.obtain(RIL_REQUEST_DIAL_EMERGENCY, result); + rr.mp.writeString(address + "/"); + rr.mp.writeInt(clirMode); + rr.mp.writeInt(0); + rr.mp.writeInt(0); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override + protected void + processUnsolicited (Parcel p) { + int response; + Object ret; + int dataPosition = p.dataPosition(); + + response = p.readInt(); + + switch(response) { + /* + cat libs/telephony/ril_unsol_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: \2(rr, p); break;/' + */ + + case RIL_UNSOL_NITZ_TIME_RECEIVED: ret = responseString(p); break; + case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break; + case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break; + case RIL_UNSOL_HSDPA_STATE_CHANGED: ret = responseInts(p); break; + case RIL_UNSOL_O2_HOME_ZONE_INFO: ret = responseVoid(p); break; + case RIL_UNSOL_DEVICE_READY_NOTI: ret = responseVoid(p); break; + case RIL_UNSOL_GPS_NOTI: ret = responseVoid(p); break; // Ignored in TW RIL. + // SAMSUNG STATES + case RIL_UNSOL_AM: ret = responseString(p); break; + case RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL: ret = responseVoid(p); break; + case RIL_UNSOL_DATA_SUSPEND_RESUME: ret = responseInts(p); break; + case RIL_UNSOL_RIL_CONNECTED: ret = responseString(p); break; + + default: + // Rewind the Parcel + p.setDataPosition(dataPosition); + + // Forward responses that we are not overriding to the super class + super.processUnsolicited(p); + return; + } + + switch(response) { + case RIL_UNSOL_HSDPA_STATE_CHANGED: + if (RILJ_LOGD) unsljLog(response); + + boolean newHsdpa = ((int[])ret)[0] == 1; + String curState = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE); + boolean curHsdpa = false; + + if (curState.equals("HSDPA:9")) { + curHsdpa = true; + } else if (!curState.equals("UMTS:3")) { + // Don't send poll request if not on 3g + break; + } + + if (curHsdpa != newHsdpa) { + mVoiceNetworkStateRegistrants + .notifyRegistrants(new AsyncResult(null, null, null)); + } + break; + + case RIL_UNSOL_NITZ_TIME_RECEIVED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + // has bonus long containing milliseconds since boot that the NITZ + // time was received + long nitzReceiveTime = p.readLong(); + + Object[] result = new Object[2]; + + String nitz = (String)ret; + if (RILJ_LOGD) riljLog(" RIL_UNSOL_NITZ_TIME_RECEIVED length = " + + nitz.split("[/:,+-]").length); + + // remove the tailing information that samsung added to the string + if(nitz.split("[/:,+-]").length >= 9) + nitz = nitz.substring(0,(nitz.lastIndexOf(","))); + + if (RILJ_LOGD) riljLog(" RIL_UNSOL_NITZ_TIME_RECEIVED striped nitz = " + + nitz); + + result[0] = nitz; + result[1] = Long.valueOf(nitzReceiveTime); + + if (mNITZTimeRegistrant != null) { + + mNITZTimeRegistrant + .notifyRegistrant(new AsyncResult (null, result, null)); + } else { + // in case NITZ time registrant isnt registered yet + mLastNITZTimeInfo = nitz; + } + break; + + case RIL_UNSOL_SIGNAL_STRENGTH: + // Note this is set to "verbose" because it happens + // frequently + if (RILJ_LOGV) unsljLogvRet(response, ret); + + if (mSignalStrengthRegistrant != null) { + mSignalStrengthRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_INFO_REC: + ArrayList<CdmaInformationRecords> listInfoRecs; + + try { + listInfoRecs = (ArrayList<CdmaInformationRecords>)ret; + } catch (ClassCastException e) { + Log.e(LOG_TAG, "Unexpected exception casting to listInfoRecs", e); + break; + } + + for (CdmaInformationRecords rec : listInfoRecs) { + if (RILJ_LOGD) unsljLogRet(response, rec); + notifyRegistrantsCdmaInfoRec(rec); + } + break; + + case RIL_UNSOL_RIL_CONNECTED: + // FIXME: Processing this state breaks data call. + break; + // SAMSUNG STATES + case RIL_UNSOL_AM: + String amString = (String) ret; + Log.d(LOG_TAG, "Executing AM: " + amString); + + try { + Runtime.getRuntime().exec("am " + amString); + } catch (IOException e) { + e.printStackTrace(); + Log.e(LOG_TAG, "am " + amString + " could not be executed."); + } + break; + case RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL: + if (RILJ_LOGD) samsungUnsljLogRet(response, ret); + break; + case RIL_UNSOL_DATA_SUSPEND_RESUME: + if (RILJ_LOGD) samsungUnsljLogRet(response, ret); + break; + } + } + + @Override + protected Object + responseCallList(Parcel p) { + int num; + boolean isVideo; + ArrayList<DriverCall> response; + DriverCall dc; + int dataAvail = p.dataAvail(); + int pos = p.dataPosition(); + int size = p.dataSize(); + + Log.d(LOG_TAG, "Parcel size = " + size); + Log.d(LOG_TAG, "Parcel pos = " + pos); + Log.d(LOG_TAG, "Parcel dataAvail = " + dataAvail); + + num = p.readInt(); + response = new ArrayList<DriverCall>(num); + + for (int i = 0 ; i < num ; i++) { + dc = new SamsungDriverCall(); + + dc.state = DriverCall.stateFromCLCC(p.readInt()); + dc.index = p.readInt(); + dc.TOA = p.readInt(); + dc.isMpty = (0 != p.readInt()); + dc.isMT = (0 != p.readInt()); + dc.als = p.readInt(); + dc.isVoice = (0 != p.readInt()); + isVideo = (0 != p.readInt()); + dc.isVoicePrivacy = (0 != p.readInt()); + dc.number = p.readString(); + int np = p.readInt(); + dc.numberPresentation = DriverCall.presentationFromCLIP(np); + dc.name = p.readString(); + dc.namePresentation = p.readInt(); + int uusInfoPresent = p.readInt(); + + Log.d(LOG_TAG, "state = " + dc.state); + Log.d(LOG_TAG, "index = " + dc.index); + Log.d(LOG_TAG, "state = " + dc.TOA); + Log.d(LOG_TAG, "isMpty = " + dc.isMpty); + Log.d(LOG_TAG, "isMT = " + dc.isMT); + Log.d(LOG_TAG, "als = " + dc.als); + Log.d(LOG_TAG, "isVoice = " + dc.isVoice); + Log.d(LOG_TAG, "isVideo = " + isVideo); + Log.d(LOG_TAG, "number = " + dc.number); + Log.d(LOG_TAG, "numberPresentation = " + np); + Log.d(LOG_TAG, "name = " + dc.name); + Log.d(LOG_TAG, "namePresentation = " + dc.namePresentation); + Log.d(LOG_TAG, "uusInfoPresent = " + uusInfoPresent); + + if (uusInfoPresent == 1) { + dc.uusInfo = new UUSInfo(); + dc.uusInfo.setType(p.readInt()); + dc.uusInfo.setDcs(p.readInt()); + byte[] userData = p.createByteArray(); + dc.uusInfo.setUserData(userData); + Log + .v(LOG_TAG, String.format("Incoming UUS : type=%d, dcs=%d, length=%d", + dc.uusInfo.getType(), dc.uusInfo.getDcs(), + dc.uusInfo.getUserData().length)); + Log.v(LOG_TAG, "Incoming UUS : data (string)=" + + new String(dc.uusInfo.getUserData())); + Log.v(LOG_TAG, "Incoming UUS : data (hex): " + + IccUtils.bytesToHexString(dc.uusInfo.getUserData())); + } else { + Log.v(LOG_TAG, "Incoming UUS : NOT present!"); + } + + // Make sure there's a leading + on addresses with a TOA of 145 + dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA); + + response.add(dc); + + if (dc.isVoicePrivacy) { + mVoicePrivacyOnRegistrants.notifyRegistrants(); + Log.d(LOG_TAG, "InCall VoicePrivacy is enabled"); + } else { + mVoicePrivacyOffRegistrants.notifyRegistrants(); + Log.d(LOG_TAG, "InCall VoicePrivacy is disabled"); + } + } + + Collections.sort(response); + + return response; + } + + protected Object + responseLastCallFailCause(Parcel p) { + int response[] = (int[])responseInts(p); + + if (response.length > 0 && + response[0] == com.android.internal.telephony.cdma.CallFailCause.ERROR_UNSPECIFIED) { + + // Far-end hangup returns ERROR_UNSPECIFIED, which shows "Call Lost" dialog. + Log.d(LOG_TAG, "Overriding ERROR_UNSPECIFIED fail cause with NORMAL_CLEARING."); + response[0] = com.android.internal.telephony.cdma.CallFailCause.NORMAL_CLEARING; + } + + return response; + } + + @Override + protected Object + responseSignalStrength(Parcel p) { + int numInts = 12; + int response[]; + + /* TODO: Add SignalStrength class to match RIL_SignalStrength */ + response = new int[numInts]; + for (int i = 0 ; i < 7 ; i++) { + response[i] = p.readInt(); + } + + if(response[3] < 0){ + response[3] = -response[3]; + } + // Scale cdmaDbm so Samsung's -95..-105 range for SIGNAL_STRENGTH_POOR + // fits in AOSP's -95..-100 range + if(response[2] > 95){ + // Log.d(LOG_TAG, "SignalStrength: Scaling cdmaDbm \"" + response[2] + "\" for smaller SIGNAL_STRENGTH_POOR bucket."); + response[2] = ((response[2]-96)/2)+96; + } + // Framework takes care of the rest for us. + return response; + } + + protected Object + responseVoiceRegistrationState(Parcel p) { + String response[] = (String[])responseStrings(p); + + // These values are provided in hex, convert to dec. + response[4] = Integer.toString(Integer.parseInt(response[4], 16)); // baseStationId + response[5] = Integer.toString(Integer.parseInt(response[5], 16)); // baseStationLatitude + response[6] = Integer.toString(Integer.parseInt(response[6], 16)); // baseStationLongitude + + return response; + } + + protected Object + responseNetworkType(Parcel p) { + int response[] = (int[]) responseInts(p); + + return response; + } + + @Override + protected Object + responseSetupDataCall(Parcel p) { + DataCallState dataCall = new DataCallState(); + String strings[] = (String []) responseStrings(p); + + if (strings.length >= 2) { + dataCall.cid = Integer.parseInt(strings[0]); + + // We're responsible for starting/stopping the pppd_cdma service. + if (!startPppdCdmaService(strings[1])) { + // pppd_cdma service didn't respond timely. + dataCall.status = FailCause.ERROR_UNSPECIFIED.getErrorCode(); + return dataCall; + } + + // pppd_cdma service responded, pull network parameters set by ip-up script. + dataCall.ifname = SystemProperties.get("net.cdma.ppp.interface"); + String ifprop = "net." + dataCall.ifname; + + dataCall.addresses = new String[] {SystemProperties.get(ifprop + ".local-ip")}; + dataCall.gateways = new String[] {SystemProperties.get(ifprop + ".remote-ip")}; + dataCall.dnses = new String[] {SystemProperties.get(ifprop + ".dns1"), + SystemProperties.get(ifprop + ".dns2")}; + } else { + // On rare occasion the pppd_cdma service is left active from a stale + // session, causing the data call setup to fail. Make sure that pppd_cdma + // is stopped now, so that the next setup attempt may succeed. + Log.d(LOG_TAG, "Set ril.cdma.data_state=0 to make sure pppd_cdma is stopped."); + SystemProperties.set("ril.cdma.data_state", "0"); + + dataCall.status = FailCause.ERROR_UNSPECIFIED.getErrorCode(); // Who knows? + } + + return dataCall; + } + + private boolean startPppdCdmaService(String ttyname) { + SystemProperties.set("net.cdma.datalinkinterface", ttyname); + + // Connecting: Set ril.cdma.data_state=1 to (re)start pppd_cdma service, + // which responds by setting ril.cdma.data_state=2 once connection is up. + SystemProperties.set("ril.cdma.data_state", "1"); + Log.d(LOG_TAG, "Set ril.cdma.data_state=1, waiting for ril.cdma.data_state=2."); + + // Typically takes < 200 ms on my Epic, so sleep in 100 ms intervals. + for (int i = 0; i < 10; i++) { + try {Thread.sleep(100);} catch (InterruptedException e) {} + + if (SystemProperties.getInt("ril.cdma.data_state", 1) == 2) { + Log.d(LOG_TAG, "Got ril.cdma.data_state=2, connected."); + return true; + } + } + + // Taking > 1 s here, try up to 10 s, which is hopefully long enough. + for (int i = 1; i < 10; i++) { + try {Thread.sleep(1000);} catch (InterruptedException e) {} + + if (SystemProperties.getInt("ril.cdma.data_state", 1) == 2) { + Log.d(LOG_TAG, "Got ril.cdma.data_state=2, connected."); + return true; + } + } + + // Disconnect: Set ril.cdma.data_state=0 to stop pppd_cdma service. + Log.d(LOG_TAG, "Didn't get ril.cdma.data_state=2 timely, aborting."); + SystemProperties.set("ril.cdma.data_state", "0"); + + return false; + } + + @Override + public void + deactivateDataCall(int cid, int reason, Message result) { + // Disconnect: Set ril.cdma.data_state=0 to stop pppd_cdma service. + Log.d(LOG_TAG, "Set ril.cdma.data_state=0."); + SystemProperties.set("ril.cdma.data_state", "0"); + + super.deactivateDataCall(cid, reason, result); + } + + protected Object + responseCdmaSubscription(Parcel p) { + String response[] = (String[])responseStrings(p); + + if (response.length == 4) { + // PRL version is missing in subscription parcel, add it from properties. + String prlVersion = SystemProperties.get("ril.prl_ver_1").split(":")[1]; + response = new String[] {response[0], response[1], response[2], + response[3], prlVersion}; + } + + return response; + } + + // Workaround for Samsung CDMA "ring of death" bug: + // + // Symptom: As soon as the phone receives notice of an incoming call, an + // audible "old fashioned ring" is emitted through the earpiece and + // persists through the duration of the call, or until reboot if the call + // isn't answered. + // + // Background: The CDMA telephony stack implements a number of "signal info + // tones" that are locally generated by ToneGenerator and mixed into the + // voice call path in response to radio RIL_UNSOL_CDMA_INFO_REC requests. + // One of these tones, IS95_CONST_IR_SIG_IS54B_L, is requested by the + // radio just prior to notice of an incoming call when the voice call + // path is muted. CallNotifier is responsible for stopping all signal + // tones (by "playing" the TONE_CDMA_SIGNAL_OFF tone) upon receipt of a + // "new ringing connection", prior to unmuting the voice call path. + // + // Problem: CallNotifier's incoming call path is designed to minimize + // latency to notify users of incoming calls ASAP. Thus, + // SignalInfoTonePlayer requests are handled asynchronously by spawning a + // one-shot thread for each. Unfortunately the ToneGenerator API does + // not provide a mechanism to specify an ordering on requests, and thus, + // unexpected thread interleaving may result in ToneGenerator processing + // them in the opposite order that CallNotifier intended. In this case, + // playing the "signal off" tone first, followed by playing the "old + // fashioned ring" indefinitely. + // + // Solution: An API change to ToneGenerator is required to enable + // SignalInfoTonePlayer to impose an ordering on requests (i.e., drop any + // request that's older than the most recent observed). Such a change, + // or another appropriate fix should be implemented in AOSP first. + // + // Workaround: Intercept RIL_UNSOL_CDMA_INFO_REC requests from the radio, + // check for a signal info record matching IS95_CONST_IR_SIG_IS54B_L, and + // drop it so it's never seen by CallNotifier. If other signal tones are + // observed to cause this problem, they should be dropped here as well. + @Override + protected void + notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) { + final int response = RIL_UNSOL_CDMA_INFO_REC; + + if (infoRec.record instanceof CdmaSignalInfoRec) { + CdmaSignalInfoRec sir = (CdmaSignalInfoRec)infoRec.record; + if (sir != null && sir.isPresent && + sir.signalType == SignalToneUtil.IS95_CONST_IR_SIGNAL_IS54B && + sir.alertPitch == SignalToneUtil.IS95_CONST_IR_ALERT_MED && + sir.signal == SignalToneUtil.IS95_CONST_IR_SIG_IS54B_L) { + + Log.d(LOG_TAG, "Dropping \"" + responseToString(response) + " " + + retToString(response, sir) + "\" to prevent \"ring of death\" bug."); + return; + } + } + + super.notifyRegistrantsCdmaInfoRec(infoRec); + } + + protected class SamsungDriverCall extends DriverCall { + @Override + public String + toString() { + // Samsung CDMA devices' call parcel is formatted differently + // fake unused data for video calls, and fix formatting + // so that voice calls' information can be correctly parsed + return "id=" + index + "," + + state + "," + + "toa=" + TOA + "," + + (isMpty ? "conf" : "norm") + "," + + (isMT ? "mt" : "mo") + "," + + "als=" + als + "," + + (isVoice ? "voc" : "nonvoc") + "," + + "nonvid" + "," + + number + "," + + "cli=" + numberPresentation + "," + + "name=" + name + "," + + namePresentation; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setCurrentPreferredNetworkType() { + if (RILJ_LOGD) riljLog("setCurrentPreferredNetworkType IGNORED"); + /* Google added this as a fix for crespo loosing network type after + * taking an OTA. This messes up the data connection state for us + * due to the way we handle network type change (disable data + * then change then re-enable). + */ + } + + @Override + public void setPreferredNetworkType(int networkType , Message response) { + /* Samsung modem implementation does bad things when a datacall is running + * while switching the preferred networktype. + */ + ConnectivityManager cm = + (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + + if(cm.getMobileDataEnabled()) + { + ConnectivityHandler handler = new ConnectivityHandler(mContext); + handler.setPreferedNetworkType(networkType, response); + } else { + sendPreferredNetworkType(networkType, response); + } + } + + + //Sends the real RIL request to the modem. + private void sendPreferredNetworkType(int networkType, Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response); + + rr.mp.writeInt(1); + rr.mp.writeInt(networkType); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + networkType); + + send(rr); + } + /* private class that does the handling for the dataconnection + * dataconnection is done async, so we send the request for disabling it, + * wait for the response, set the prefered networktype and notify the + * real sender with its result. + */ + private class ConnectivityHandler extends Handler{ + + private static final int MESSAGE_SET_PREFERRED_NETWORK_TYPE = 30; + private Context mContext; + private int mDesiredNetworkType; + //the original message, we need it for calling back the original caller when done + private Message mNetworktypeResponse; + private ConnectivityBroadcastReceiver mConnectivityReceiver = new ConnectivityBroadcastReceiver(); + + public ConnectivityHandler(Context context) + { + mContext = context; + } + + private void startListening() { + IntentFilter filter = new IntentFilter(); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + mContext.registerReceiver(mConnectivityReceiver, filter); + } + + private synchronized void stopListening() { + mContext.unregisterReceiver(mConnectivityReceiver); + } + + public void setPreferedNetworkType(int networkType, Message response) + { + Log.d(LOG_TAG, "Mobile Dataconnection is online setting it down"); + mDesiredNetworkType = networkType; + mNetworktypeResponse = response; + ConnectivityManager cm = + (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + //start listening for the connectivity change broadcast + startListening(); + cm.setMobileDataEnabled(false); + } + + @Override + public void handleMessage(Message msg) { + switch(msg.what) { + //networktype was set, now we can enable the dataconnection again + case MESSAGE_SET_PREFERRED_NETWORK_TYPE: + ConnectivityManager cm = + (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + + Log.d(LOG_TAG, "preferred NetworkType set upping Mobile Dataconnection"); + + cm.setMobileDataEnabled(true); + //everything done now call back that we have set the networktype + AsyncResult.forMessage(mNetworktypeResponse, null, null); + mNetworktypeResponse.sendToTarget(); + mNetworktypeResponse = null; + break; + default: + throw new RuntimeException("unexpected event not handled"); + } + } + + private class ConnectivityBroadcastReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + Log.w(LOG_TAG, "onReceived() called with " + intent); + return; + } + boolean noConnectivity = + intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); + + if (noConnectivity) { + //Ok dataconnection is down, now set the networktype + Log.w(LOG_TAG, "Mobile Dataconnection is now down setting preferred NetworkType"); + stopListening(); + sendPreferredNetworkType(mDesiredNetworkType, obtainMessage(MESSAGE_SET_PREFERRED_NETWORK_TYPE)); + mDesiredNetworkType = -1; + } + } + } + } +} diff --git a/telephony/java/com/android/internal/telephony/Smdk4210RIL.java b/telephony/java/com/android/internal/telephony/Smdk4210RIL.java index fa60598..b385627 100644 --- a/telephony/java/com/android/internal/telephony/Smdk4210RIL.java +++ b/telephony/java/com/android/internal/telephony/Smdk4210RIL.java @@ -630,7 +630,7 @@ public class Smdk4210RIL extends RIL implements CommandsInterface { protected Object responseCallList(Parcel p) { int num; - int voiceSettings; + boolean isVideo; ArrayList<DriverCall> response; DriverCall dc; int dataAvail = p.dataAvail(); @@ -649,38 +649,35 @@ public class Smdk4210RIL extends RIL implements CommandsInterface { for (int i = 0 ; i < num ; i++) { - dc = new DriverCall(); + dc = new DriverCall(); + dc.state = DriverCall.stateFromCLCC(p.readInt()); + dc.index = p.readInt(); + dc.TOA = p.readInt(); + dc.isMpty = (0 != p.readInt()); + dc.isMT = (0 != p.readInt()); + dc.als = p.readInt(); + dc.isVoice = (0 != p.readInt()); + isVideo = (0 != p.readInt()); + dc.isVoicePrivacy = (0 != p.readInt()); + dc.number = p.readString(); + int np = p.readInt(); + dc.numberPresentation = DriverCall.presentationFromCLIP(np); + dc.name = p.readString(); + dc.namePresentation = p.readInt(); + int uusInfoPresent = p.readInt(); - dc.state = DriverCall.stateFromCLCC(p.readInt()); Log.d(LOG_TAG, "state = " + dc.state); - dc.index = p.readInt(); Log.d(LOG_TAG, "index = " + dc.index); - dc.TOA = p.readInt(); Log.d(LOG_TAG, "state = " + dc.TOA); - dc.isMpty = (0 != p.readInt()); Log.d(LOG_TAG, "isMpty = " + dc.isMpty); - dc.isMT = (0 != p.readInt()); Log.d(LOG_TAG, "isMT = " + dc.isMT); - dc.als = p.readInt(); Log.d(LOG_TAG, "als = " + dc.als); - voiceSettings = p.readInt(); - dc.isVoice = (0 == voiceSettings) ? false : true; Log.d(LOG_TAG, "isVoice = " + dc.isVoice); - dc.isVoicePrivacy = (0 != p.readInt()); - //Some Samsung magic data for Videocalls - voiceSettings = p.readInt(); - //printing it to cosole for later investigation - Log.d(LOG_TAG, "Samsung magic = " + voiceSettings); - dc.number = p.readString(); + Log.d(LOG_TAG, "isVideo = " + isVideo); Log.d(LOG_TAG, "number = " + dc.number); - int np = p.readInt(); Log.d(LOG_TAG, "np = " + np); - dc.numberPresentation = DriverCall.presentationFromCLIP(np); - dc.name = p.readString(); Log.d(LOG_TAG, "name = " + dc.name); - dc.namePresentation = p.readInt(); Log.d(LOG_TAG, "namePresentation = " + dc.namePresentation); - int uusInfoPresent = p.readInt(); Log.d(LOG_TAG, "uusInfoPresent = " + uusInfoPresent); if (uusInfoPresent == 1) { diff --git a/telephony/java/com/android/internal/telephony/SonyQualcommRIL.java b/telephony/java/com/android/internal/telephony/SonyQualcommRIL.java new file mode 100644 index 0000000..ffd03e1 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SonyQualcommRIL.java @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2012 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.internal.telephony; + +import static com.android.internal.telephony.RILConstants.*; + +import android.content.Context; +import android.os.AsyncResult; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.Parcel; +import android.telephony.SmsMessage; +import android.os.SystemProperties; +import android.text.TextUtils; +import android.util.Log; + +import java.util.ArrayList; + +/** + * Custom Qualcomm No SimReady RIL for Sony + * + * {@hide} + */ + +public class SonyQualcommRIL extends RIL implements CommandsInterface { + protected String mAid = ""; + protected HandlerThread mIccThread; + protected IccHandler mIccHandler; + boolean RILJ_LOGV = true; + boolean RILJ_LOGD = true; + + private final int RIL_INT_RADIO_OFF = 0; + private final int RIL_INT_RADIO_UNAVALIABLE = 1; + private final int RIL_INT_RADIO_ON = 10; + + public SonyQualcommRIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + @Override + public void + iccIO (int command, int fileid, String path, int p1, int p2, int p3, + String data, String pin2, Message result) { + //Note: This RIL request has not been renamed to ICC, + // but this request is also valid for SIM and RUIM + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SIM_IO, result); + + rr.mp.writeInt(command); + rr.mp.writeInt(fileid); + rr.mp.writeString(path); + rr.mp.writeInt(p1); + rr.mp.writeInt(p2); + rr.mp.writeInt(p3); + rr.mp.writeString(data); + rr.mp.writeString(pin2); + rr.mp.writeString(mAid); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: " + requestToString(rr.mRequest) + + " 0x" + Integer.toHexString(command) + + " 0x" + Integer.toHexString(fileid) + " " + + " path: " + path + "," + + p1 + "," + p2 + "," + p3); + + send(rr); + } + + @Override public void + supplyIccPin(String pin, Message result) { + supplyIccPinForApp(pin, mAid, result); + } + + @Override public void + changeIccPin(String oldPin, String newPin, Message result) { + changeIccPinForApp(oldPin, newPin, mAid, result); + } + + @Override public void + supplyIccPin2(String pin, Message result) { + supplyIccPin2ForApp(pin, mAid, result); + } + + @Override public void + changeIccPin2(String oldPin2, String newPin2, Message result) { + changeIccPin2ForApp(oldPin2, newPin2, mAid, result); + } + + @Override public void + supplyIccPuk(String puk, String newPin, Message result) { + supplyIccPukForApp(puk, newPin, mAid, result); + } + + @Override public void + supplyIccPuk2(String puk2, String newPin2, Message result) { + supplyIccPuk2ForApp(puk2, newPin2, mAid, result); + } + + @Override + public void + queryFacilityLock(String facility, String password, int serviceClass, + Message response) { + queryFacilityLockForApp(facility, password, serviceClass, mAid, response); + } + + @Override + public void + setFacilityLock (String facility, boolean lockState, String password, + int serviceClass, Message response) { + setFacilityLockForApp(facility, lockState, password, serviceClass, mAid, response); + } + + @Override + protected Object + responseIccCardStatus(Parcel p) { + IccCardApplication ca; + + IccCardStatus status = new IccCardStatus(); + status.setCardState(p.readInt()); + status.setUniversalPinState(p.readInt()); + status.setGsmUmtsSubscriptionAppIndex(p.readInt()); + status.setCdmaSubscriptionAppIndex(p.readInt()); + status.setImsSubscriptionAppIndex(p.readInt()); + + int numApplications = p.readInt(); + // limit to maximum allowed applications + if (numApplications > IccCardStatus.CARD_MAX_APPS) { + numApplications = IccCardStatus.CARD_MAX_APPS; + } + status.setNumApplications(numApplications); + + for (int i = 0 ; i < numApplications ; i++) { + ca = new IccCardApplication(); + ca.app_type = ca.AppTypeFromRILInt(p.readInt()); + ca.app_state = ca.AppStateFromRILInt(p.readInt()); + ca.perso_substate = ca.PersoSubstateFromRILInt(p.readInt()); + ca.aid = p.readString(); + ca.app_label = p.readString(); + ca.pin1_replaced = p.readInt(); + ca.pin1 = ca.PinStateFromRILInt(p.readInt()); + ca.pin2 = ca.PinStateFromRILInt(p.readInt()); + status.addApplication(ca); + } + + updateIccType(status); + return status; + } + + private void updateIccType(IccCardStatus icccardstatus) + { + IccCardApplication.AppType apptype = IccCardApplication.AppType.APPTYPE_UNKNOWN; + if(icccardstatus.getNumApplications() > 0) + { + CommandsInterface.RadioState radiostate = getRadioState(); + int i; + IccCardApplication icccardapplication; + if(radiostate == CommandsInterface.RadioState.RUIM_LOCKED_OR_ABSENT || radiostate == CommandsInterface.RadioState.RUIM_NOT_READY || radiostate == CommandsInterface.RadioState.RUIM_READY) + i = icccardstatus.getCdmaSubscriptionAppIndex(); + else + i = icccardstatus.getGsmUmtsSubscriptionAppIndex(); + icccardapplication = icccardstatus.getApplication(i); + Log.i("RILJ", (new StringBuilder()).append("app_state ").append(icccardapplication.app_state).append(", perso_substate ").append(icccardapplication.perso_substate).append(", app_type ").append(icccardapplication.app_type).toString()); + mAid = icccardapplication.aid; + riljLog((new StringBuilder()).append("Will use ").append(mAid).append(" as default application id. Hopefully you wont mind").toString()); + apptype = icccardapplication.app_type; + } + SystemProperties.set("ril.icctype", Integer.toString(apptype.ordinal())); + } + + @Override + public void + getIMSI(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result); + rr.mp.writeInt(1); + rr.mp.writeString(mAid); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override + protected Object + responseOperatorInfos(Parcel p) { + String strings[] = (String [])responseStrings(p); + ArrayList<OperatorInfo> ret; + + if (strings.length % 5 != 0) { + throw new RuntimeException( + "RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: invalid response. Got " + + strings.length + " strings, expected multible of 5"); + } + + ret = new ArrayList<OperatorInfo>(strings.length / 4); + + for (int i = 0 ; i < strings.length ; i += 5) { + ret.add ( + new OperatorInfo( + strings[i+0], + strings[i+1], + strings[i+2], + strings[i+3])); + } + return ret; + } + + @Override + public void + dial(String address, int clirMode, UUSInfo uusInfo, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); + + rr.mp.writeString(address); + rr.mp.writeInt(clirMode); + + if (uusInfo == null) { + rr.mp.writeInt(0); // UUS information is absent + } else { + rr.mp.writeInt(1); // UUS information is present + rr.mp.writeInt(uusInfo.getType()); + rr.mp.writeInt(uusInfo.getDcs()); + rr.mp.writeByteArray(uusInfo.getUserData()); + } + rr.mp.writeInt(255); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + setNetworkSelectionMode(String operatorNumeric, Message response) { + RILRequest rr; + + if (operatorNumeric == null) + rr = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, response); + else + rr = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, response); + + rr.mp.writeString(operatorNumeric); + rr.mp.writeInt(-1); + + send(rr); + } + + @Override + public void + setNetworkSelectionModeAutomatic(Message response) { + setNetworkSelectionMode(null, response); + } + + @Override + public void + setNetworkSelectionModeManual(String operatorNumeric, Message response) { + setNetworkSelectionMode(operatorNumeric, response); + } + + @Override + protected Object + responseSignalStrength(Parcel p) { + int numInts = 12; + int response[]; + + boolean noLte = false; + + /* TODO: Add SignalStrength class to match RIL_SignalStrength */ + response = new int[numInts]; + for (int i = 0 ; i < numInts ; i++) { + if (noLte && i > 6 && i < 12) { + response[i] = -1; + } else { + response[i] = p.readInt(); + } + if (i == 7 && response[i] == 99) { + response[i] = -1; + noLte = true; + } + if (i == 8 && !noLte) { + response[i] *= -1; + } + } + + return response; + } + + @Override + protected void + processUnsolicited (Parcel p) { + Object ret; + int dataPosition = p.dataPosition(); // save off position within the Parcel + int response = p.readInt(); + + switch(response) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break; + + default: + // Rewind the Parcel + p.setDataPosition(dataPosition); + + // Forward responses that we are not overriding to the super class + super.processUnsolicited(p); + return; + } + + switch(response) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: + int state = p.readInt(); + setRadioStateFromRILInt(state); + break; + } + } + + private void setRadioStateFromRILInt (int stateCode) { + CommandsInterface.RadioState radioState; + HandlerThread handlerThread; + Looper looper; + IccHandler iccHandler; + + switch (stateCode) { + case RIL_INT_RADIO_OFF: + radioState = CommandsInterface.RadioState.RADIO_OFF; + if (mIccHandler != null) { + mIccThread = null; + mIccHandler = null; + } + break; + case RIL_INT_RADIO_UNAVALIABLE: + radioState = CommandsInterface.RadioState.RADIO_UNAVAILABLE; + break; + case RIL_INT_RADIO_ON: + if (mIccHandler == null) { + handlerThread = new HandlerThread("IccHandler"); + mIccThread = handlerThread; + + mIccThread.start(); + + looper = mIccThread.getLooper(); + mIccHandler = new IccHandler(this,looper); + mIccHandler.run(); + } + if (mPhoneType == RILConstants.CDMA_PHONE) { + radioState = CommandsInterface.RadioState.RUIM_NOT_READY; + } else { + radioState = CommandsInterface.RadioState.SIM_NOT_READY; + } + break; + default: + throw new RuntimeException("Unrecognized RIL_RadioState: " + stateCode); + } + + setRadioState(radioState); + } + + class IccHandler extends Handler implements Runnable { + private static final int EVENT_GET_ICC_STATUS_DONE = 1; + private static final int EVENT_ICC_STATUS_CHANGED = 2; + private static final int EVENT_RADIO_ON = 3; + private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 4; + + private RIL mRil; + private boolean mRadioOn = false; + + public IccHandler (RIL ril, Looper looper) { + super (looper); + mRil = ril; + } + + public void handleMessage (Message paramMessage) { + switch (paramMessage.what) { + case EVENT_RADIO_ON: + mRadioOn = true; + Log.d(LOG_TAG, "Radio on -> Forcing sim status update"); + sendMessage(obtainMessage(EVENT_ICC_STATUS_CHANGED)); + break; + case EVENT_GET_ICC_STATUS_DONE: + AsyncResult asyncResult = (AsyncResult) paramMessage.obj; + if (asyncResult.exception != null) { + Log.e (LOG_TAG, "IccCardStatusDone shouldn't return exceptions!", asyncResult.exception); + break; + } + IccCardStatus status = (IccCardStatus) asyncResult.result; + if (status.getNumApplications() == 0) { + if (!mRil.getRadioState().isOn()) { + break; + } + if (mPhoneType == RILConstants.CDMA_PHONE) { + mRil.setRadioState(CommandsInterface.RadioState.RUIM_LOCKED_OR_ABSENT); + } else { + mRil.setRadioState(CommandsInterface.RadioState.SIM_LOCKED_OR_ABSENT); + } + } else { + int appIndex = -1; + if (mPhoneType == RILConstants.CDMA_PHONE) { + appIndex = status.getCdmaSubscriptionAppIndex(); + Log.d(LOG_TAG, "This is a CDMA PHONE " + appIndex); + } else { + appIndex = status.getGsmUmtsSubscriptionAppIndex(); + Log.d(LOG_TAG, "This is a GSM PHONE " + appIndex); + } + + IccCardApplication application = status.getApplication(appIndex); + IccCardApplication.AppState app_state = application.app_state; + IccCardApplication.AppType app_type = application.app_type; + switch (app_state) { + case APPSTATE_PIN: + case APPSTATE_PUK: + switch (app_type) { + case APPTYPE_SIM: + case APPTYPE_USIM: + mRil.setRadioState(CommandsInterface.RadioState.SIM_LOCKED_OR_ABSENT); + break; + case APPTYPE_RUIM: + mRil.setRadioState(CommandsInterface.RadioState.RUIM_LOCKED_OR_ABSENT); + break; + default: + Log.e(LOG_TAG, "Currently we don't handle SIMs of type: " + app_type); + return; + } + break; + case APPSTATE_READY: + switch (app_type) { + case APPTYPE_SIM: + case APPTYPE_USIM: + mRil.setRadioState(CommandsInterface.RadioState.SIM_READY); + break; + case APPTYPE_RUIM: + mRil.setRadioState(CommandsInterface.RadioState.RUIM_READY); + break; + default: + Log.e(LOG_TAG, "Currently we don't handle SIMs of type: " + app_type); + return; + } + break; + default: + return; + } + } + break; + case EVENT_ICC_STATUS_CHANGED: + if (mRadioOn) { + Log.d(LOG_TAG, "Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); + mRil.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, paramMessage.obj)); + } else { + Log.d(LOG_TAG, "Received EVENT_ICC_STATUS_CHANGED while radio is not ON. Ignoring"); + } + break; + case EVENT_RADIO_OFF_OR_UNAVAILABLE: + mRadioOn = false; + // disposeCards(); // to be verified; + default: + Log.e(LOG_TAG, " Unknown Event " + paramMessage.what); + break; + } + } + + public void run () { + mRil.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); + Message msg = obtainMessage(EVENT_RADIO_ON); + mRil.getIccCardStatus(msg); + } + } +} |