diff options
85 files changed, 2795 insertions, 1112 deletions
diff --git a/api/current.txt b/api/current.txt index 630ab00..68fb4bc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10813,8 +10813,6 @@ package android.media { ctor public MediaRecorder(); method public static final int getAudioSourceMax(); method public int getMaxAmplitude() throws java.lang.IllegalStateException; - method public void native_start() throws java.lang.IllegalStateException; - method public void native_stop() throws java.lang.IllegalStateException; method public void prepare() throws java.io.IOException, java.lang.IllegalStateException; method public void release(); method public void reset(); @@ -10853,13 +10851,9 @@ package android.media { public final class MediaRecorder.AudioEncoder { field public static final int AAC = 3; // 0x3 - field public static final int AAC_PLUS = 4; // 0x4 field public static final int AMR_NB = 1; // 0x1 field public static final int AMR_WB = 2; // 0x2 field public static final int DEFAULT = 0; // 0x0 - field public static final int EAAC_PLUS = 5; // 0x5 - field public static final int EVRC = 6; // 0x6 - field public static final int QCELP = 7; // 0x7 } public final class MediaRecorder.AudioSource { @@ -10886,10 +10880,8 @@ package android.media { field public static final int AMR_WB = 4; // 0x4 field public static final int DEFAULT = 0; // 0x0 field public static final int MPEG_4 = 2; // 0x2 - field public static final int QCP = 9; // 0x9 field public static final int RAW_AMR = 3; // 0x3 field public static final int THREE_GPP = 1; // 0x1 - field public static final int THREE_GPP2 = 10; // 0xa } public final class MediaRecorder.VideoEncoder { @@ -22208,9 +22200,6 @@ package android.view { field public static final int KEYCODE_BACKSLASH = 73; // 0x49 field public static final int KEYCODE_BOOKMARK = 174; // 0xae field public static final int KEYCODE_BREAK = 121; // 0x79 - field public static final int KEYCODE_BRIGHTNESS_AUTO = 216; // 0xd8 - field public static final int KEYCODE_BRIGHTNESS_DOWN = 214; // 0xd6 - field public static final int KEYCODE_BRIGHTNESS_UP = 215; // 0xd7 field public static final int KEYCODE_BUTTON_1 = 188; // 0xbc field public static final int KEYCODE_BUTTON_10 = 197; // 0xc5 field public static final int KEYCODE_BUTTON_11 = 198; // 0xc6 @@ -22364,7 +22353,6 @@ package android.view { field public static final int KEYCODE_R = 46; // 0x2e field public static final int KEYCODE_RIGHT_BRACKET = 72; // 0x48 field public static final int KEYCODE_S = 47; // 0x2f - field public static final int KEYCODE_SCREENSHOT = 217; // 0xd9 field public static final int KEYCODE_SCROLL_LOCK = 116; // 0x74 field public static final int KEYCODE_SEARCH = 84; // 0x54 field public static final int KEYCODE_SEMICOLON = 74; // 0x4a @@ -22383,9 +22371,6 @@ package android.view { field public static final int KEYCODE_SYSRQ = 120; // 0x78 field public static final int KEYCODE_T = 48; // 0x30 field public static final int KEYCODE_TAB = 61; // 0x3d - field public static final int KEYCODE_TOGGLE_BT = 212; // 0xd4 - field public static final int KEYCODE_TOGGLE_TOUCHPAD = 213; // 0xd5 - field public static final int KEYCODE_TOGGLE_WIFI = 211; // 0xd3 field public static final int KEYCODE_TV = 170; // 0xaa field public static final int KEYCODE_TV_INPUT = 178; // 0xb2 field public static final int KEYCODE_TV_POWER = 177; // 0xb1 diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c index 5c9a8b3..1bd21a6 100644 --- a/cmds/servicemanager/service_manager.c +++ b/cmds/servicemanager/service_manager.c @@ -37,6 +37,7 @@ static struct { #ifdef YAMAHAPLAYER { AID_MEDIA, "media.yamahaplayer" }, #endif + { AID_MEDIA, "media.nvidia.audio_alsa" }, #ifdef SECTVOUT { AID_MEDIA, "SecTVOutService" }, #endif diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 86725ac..0b1dc44 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -1656,7 +1656,7 @@ public class Camera { private static final String KEY_SCENE_DETECT = "scene-detect"; private static final String KEY_FLASH_MODE = "flash-mode"; private static final String KEY_FOCUS_MODE = "focus-mode"; - private static final String KEY_ISO_MODE = "iso"; + private static final String KEY_ISO_MODE = "iso"; private static final String KEY_LENSSHADE = "lensshade"; private static final String KEY_HISTOGRAM = "histogram"; private static final String KEY_SKIN_TONE_ENHANCEMENT = "skinToneEnhancement"; @@ -1703,7 +1703,7 @@ public class Camera { private static final String KEY_SELECTABLE_ZONE_AF = "selectable-zone-af"; private static final String KEY_FACE_DETECTION = "face-detection"; private static final String KEY_MEMORY_COLOR_ENHANCEMENT = "mce"; - private static final String KEY_REDEYE_REDUCTION = "redeye-reduction"; + private static final String KEY_REDEYE_REDUCTION = "redeye-reduction"; private static final String KEY_ZSL = "zsl"; private static final String KEY_CAMERA_MODE = "camera-mode"; private static final String KEY_VIDEO_HIGH_FRAME_RATE = "video-hfr"; @@ -1753,8 +1753,8 @@ public class Camera { public static final String ANTIBANDING_50HZ = "50hz"; public static final String ANTIBANDING_60HZ = "60hz"; public static final String ANTIBANDING_OFF = "off"; - //Values for ISO settings + //Values for ISO settings /** @hide */ public static final String ISO_AUTO = "auto"; /** @hide */ @@ -3787,7 +3787,7 @@ public class Camera { * @hide * Gets the supported ISO values. * - * @return a List of FLASH_MODE_XXX string constants. null if flash mode + * @return a list of ISO_XXX string constants. null if ISO * setting is not supported. */ public List<String> getSupportedIsoValues() { diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java index fe5e76c..e0491d0 100644 --- a/core/java/android/preference/VolumePreference.java +++ b/core/java/android/preference/VolumePreference.java @@ -146,6 +146,11 @@ public class VolumePreference extends SeekBarDialogPreference implements } } + /** @hide */ + protected boolean onVolumeChange(SeekBarVolumizer volumizer, int value) { + return true; + } + @Override protected Parcelable onSaveInstanceState() { final Parcelable superState = super.onSaveInstanceState(); @@ -307,10 +312,14 @@ public class VolumePreference extends SeekBarDialogPreference implements } void postSetVolume(int progress) { - // Do the volume changing separately to give responsive UI - mLastProgress = progress; - mHandler.removeCallbacks(this); - mHandler.post(this); + if (onVolumeChange(this, progress)) { + // Do the volume changing separately to give responsive UI + mLastProgress = progress; + mHandler.removeCallbacks(this); + mHandler.post(this); + } else { + mSeekBar.setProgress(mLastProgress); + } } public void onStartTrackingTouch(SeekBar seekBar) { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 81ccf66..4c4a6d5 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1661,6 +1661,24 @@ public final class Settings { "notifications_use_ring_volume"; /** + * Whether the phone ringtone should be played in an increasing manner + * @hide + */ + public static final String INCREASING_RING = "increasing_ring"; + + /** + * Minimum volume index for increasing ring volume + * @hide + */ + public static final String INCREASING_RING_MIN_VOLUME = "increasing_ring_min_vol"; + + /** + * Time (in ms) between ringtone volume increases + * @hide + */ + public static final String INCREASING_RING_INTERVAL = "increasing_ring_interval"; + + /** * Whether silent mode should allow vibration feedback. This is used * internally in AudioService and the Sound settings activity to * coordinate decoupling of vibrate and silent modes. This setting @@ -1912,6 +1930,13 @@ public final class Settings { public static final String TTY_MODE = "tty_mode"; /** + * Whether noise suppression is enabled. The value is + * boolean (1 or 0). + * @hide + */ + public static final String NOISE_SUPPRESSION = "noise_suppression"; + + /** * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is * boolean (1 or 0). */ @@ -1938,13 +1963,6 @@ public final class Settings { public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse"; /** - * Whether the battery LED should repeatedly flash when the battery is low - * on charge. The value is boolean (1 or 0). - * @hide - */ - public static final String BATTERY_LIGHT_PULSE = "battery_light_pulse"; - - /** * What color to use for the notification LED by default * @hide */ @@ -2010,6 +2028,38 @@ public final class Settings { */ public static final String NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES = "notification_light_pulse_custom_values"; + /** + * Whether the battery light should be enabled (if hardware supports it) + * The value is boolean (1 or 0). + * @hide + */ + public static final String BATTERY_LIGHT_ENABLED = "battery_light_enabled"; + + /** + * Whether the battery LED should repeatedly flash when the battery is low + * on charge. The value is boolean (1 or 0). + * @hide + */ + public static final String BATTERY_LIGHT_PULSE = "battery_light_pulse"; + + /** + * What color to use for the battery LED while charging - low + * @hide + */ + public static final String BATTERY_LIGHT_LOW_COLOR = "battery_light_low_color"; + + /** + * What color to use for the battery LED while charging - medium + * @hide + */ + public static final String BATTERY_LIGHT_MEDIUM_COLOR = "battery_light_medium_color"; + + /** + * What color to use for the battery LED while charging - full + * @hide + */ + public static final String BATTERY_LIGHT_FULL_COLOR = "battery_light_full_color"; + /** Sprint MWI Quirk: Show message wait indicator notifications * @hide */ @@ -2593,6 +2643,7 @@ public final class Settings { CALL_AUTO_RETRY, HEARING_AID, TTY_MODE, + NOISE_SUPPRESSION, SOUND_EFFECTS_ENABLED, HAPTIC_FEEDBACK_ENABLED, POWER_SOUNDS_ENABLED, diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java index 192257b..8c37daa 100644 --- a/core/java/android/text/method/QwertyKeyListener.java +++ b/core/java/android/text/method/QwertyKeyListener.java @@ -129,6 +129,12 @@ public class QwertyKeyListener extends BaseKeyListener { return true; } + if (i == KeyCharacterMap.DOT_WWW_INPUT || i == KeyCharacterMap.DOT_COM_INPUT) { + content.replace(selStart, selEnd, selStart == 0 ? "www." : ".com"); + adjustMetaAfterKeypress(content); + return true; + } + if (i == KeyCharacterMap.HEX_INPUT) { int start; @@ -423,78 +429,75 @@ public class QwertyKeyListener extends BaseKeyListener { Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } - private static SparseArray<String> PICKER_SETS = - new SparseArray<String>(); + private static SparseArray<Integer> SYM_PICKER_RES_ID = + new SparseArray<Integer>(); + static { - PICKER_SETS.put('A', "\u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5\u0104\u0100"); - PICKER_SETS.put('C', "\u00C7\u0106\u010C"); - PICKER_SETS.put('D', "\u010E"); - PICKER_SETS.put('E', "\u00C8\u00C9\u00CA\u00CB\u0118\u011A\u0112"); - PICKER_SETS.put('G', "\u011E"); - PICKER_SETS.put('L', "\u0141"); - PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF\u012A\u0130"); - PICKER_SETS.put('N', "\u00D1\u0143\u0147"); - PICKER_SETS.put('O', "\u00D8\u0152\u00D5\u00D2\u00D3\u00D4\u00D6\u014C"); - PICKER_SETS.put('R', "\u0158"); - PICKER_SETS.put('S', "\u015A\u0160\u015E"); - PICKER_SETS.put('T', "\u0164"); - PICKER_SETS.put('U', "\u00D9\u00DA\u00DB\u00DC\u016E\u016A"); - PICKER_SETS.put('Y', "\u00DD\u0178"); - PICKER_SETS.put('Z', "\u0179\u017B\u017D"); - PICKER_SETS.put('a', "\u00E0\u00E1\u00E2\u00E4\u00E6\u00E3\u00E5\u0105\u0101"); - PICKER_SETS.put('c', "\u00E7\u0107\u010D"); - PICKER_SETS.put('d', "\u010F"); - PICKER_SETS.put('e', "\u00E8\u00E9\u00EA\u00EB\u0119\u011B\u0113"); - PICKER_SETS.put('g', "\u011F"); - PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF\u012B\u0131"); - PICKER_SETS.put('l', "\u0142"); - PICKER_SETS.put('n', "\u00F1\u0144\u0148"); - PICKER_SETS.put('o', "\u00F8\u0153\u00F5\u00F2\u00F3\u00F4\u00F6\u014D"); - PICKER_SETS.put('r', "\u0159"); - PICKER_SETS.put('s', "\u00A7\u00DF\u015B\u0161\u015F"); - PICKER_SETS.put('t', "\u0165"); - PICKER_SETS.put('u', "\u00F9\u00FA\u00FB\u00FC\u016F\u016B"); - PICKER_SETS.put('y', "\u00FD\u00FF"); - PICKER_SETS.put('z', "\u017A\u017C\u017E"); - PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT, - "\u2026\u00A5\u2022\u00AE\u00A9\u00B1[]{}<>`^\\|"); - PICKER_SETS.put('/', "\\"); - - // From packages/inputmethods/LatinIME/res/xml/kbd_symbols.xml - - PICKER_SETS.put('1', "\u00b9\u00bd\u2153\u00bc\u215b"); - PICKER_SETS.put('2', "\u00b2\u2154"); - PICKER_SETS.put('3', "\u00b3\u00be\u215c"); - PICKER_SETS.put('4', "\u2074"); - PICKER_SETS.put('5', "\u215d"); - PICKER_SETS.put('7', "\u215e"); - PICKER_SETS.put('0', "\u207f\u2205"); - PICKER_SETS.put('$', "\u00a2\u00a3\u20ac\u00a5\u20a3\u20a4\u20b1"); - PICKER_SETS.put('%', "\u2030"); - PICKER_SETS.put('*', "\u2020\u2021"); - PICKER_SETS.put('-', "\u2013\u2014"); - PICKER_SETS.put('+', "\u00b1"); - PICKER_SETS.put('(', "[{<"); - PICKER_SETS.put(')', "]}>"); - PICKER_SETS.put('!', "\u00a1"); - PICKER_SETS.put('"', "\u201c\u201d\u00ab\u00bb\u02dd"); - PICKER_SETS.put('?', "\u00bf"); - PICKER_SETS.put(',', "\u201a\u201e"); - - // From packages/inputmethods/LatinIME/res/xml/kbd_symbols_shift.xml - - PICKER_SETS.put('=', "\u2260\u2248\u221e"); - PICKER_SETS.put('<', "\u2264\u00ab\u2039"); - PICKER_SETS.put('>', "\u2265\u00bb\u203a"); + SYM_PICKER_RES_ID.put('A', com.android.internal.R.string.symbol_picker_A); + SYM_PICKER_RES_ID.put('C', com.android.internal.R.string.symbol_picker_C); + SYM_PICKER_RES_ID.put('D', com.android.internal.R.string.symbol_picker_D); + SYM_PICKER_RES_ID.put('E', com.android.internal.R.string.symbol_picker_E); + SYM_PICKER_RES_ID.put('G', com.android.internal.R.string.symbol_picker_G); + SYM_PICKER_RES_ID.put('L', com.android.internal.R.string.symbol_picker_L); + SYM_PICKER_RES_ID.put('I', com.android.internal.R.string.symbol_picker_I); + SYM_PICKER_RES_ID.put('N', com.android.internal.R.string.symbol_picker_N); + SYM_PICKER_RES_ID.put('O', com.android.internal.R.string.symbol_picker_O); + SYM_PICKER_RES_ID.put('R', com.android.internal.R.string.symbol_picker_R); + SYM_PICKER_RES_ID.put('S', com.android.internal.R.string.symbol_picker_S); + SYM_PICKER_RES_ID.put('T', com.android.internal.R.string.symbol_picker_T); + SYM_PICKER_RES_ID.put('U', com.android.internal.R.string.symbol_picker_U); + SYM_PICKER_RES_ID.put('Y', com.android.internal.R.string.symbol_picker_Y); + SYM_PICKER_RES_ID.put('Z', com.android.internal.R.string.symbol_picker_Z); + SYM_PICKER_RES_ID.put('a', com.android.internal.R.string.symbol_picker_a); + SYM_PICKER_RES_ID.put('c', com.android.internal.R.string.symbol_picker_c); + SYM_PICKER_RES_ID.put('d', com.android.internal.R.string.symbol_picker_d); + SYM_PICKER_RES_ID.put('e', com.android.internal.R.string.symbol_picker_e); + SYM_PICKER_RES_ID.put('g', com.android.internal.R.string.symbol_picker_g); + SYM_PICKER_RES_ID.put('i', com.android.internal.R.string.symbol_picker_i); + SYM_PICKER_RES_ID.put('l', com.android.internal.R.string.symbol_picker_l); + SYM_PICKER_RES_ID.put('n', com.android.internal.R.string.symbol_picker_n); + SYM_PICKER_RES_ID.put('o', com.android.internal.R.string.symbol_picker_o); + SYM_PICKER_RES_ID.put('r', com.android.internal.R.string.symbol_picker_r); + SYM_PICKER_RES_ID.put('s', com.android.internal.R.string.symbol_picker_s); + SYM_PICKER_RES_ID.put('t', com.android.internal.R.string.symbol_picker_t); + SYM_PICKER_RES_ID.put('u', com.android.internal.R.string.symbol_picker_u); + SYM_PICKER_RES_ID.put('y', com.android.internal.R.string.symbol_picker_y); + SYM_PICKER_RES_ID.put('z', com.android.internal.R.string.symbol_picker_z); + SYM_PICKER_RES_ID.put('1', com.android.internal.R.string.symbol_picker_1); + SYM_PICKER_RES_ID.put('2', com.android.internal.R.string.symbol_picker_2); + SYM_PICKER_RES_ID.put('3', com.android.internal.R.string.symbol_picker_3); + SYM_PICKER_RES_ID.put('4', com.android.internal.R.string.symbol_picker_4); + SYM_PICKER_RES_ID.put('5', com.android.internal.R.string.symbol_picker_5); + SYM_PICKER_RES_ID.put('7', com.android.internal.R.string.symbol_picker_7); + SYM_PICKER_RES_ID.put('0', com.android.internal.R.string.symbol_picker_0); + SYM_PICKER_RES_ID.put(KeyCharacterMap.PICKER_DIALOG_INPUT,com.android.internal.R.string.symbol_picker_sym); + SYM_PICKER_RES_ID.put('/', com.android.internal.R.string.symbol_picker_slash); + SYM_PICKER_RES_ID.put('$', com.android.internal.R.string.symbol_picker_dollar); + SYM_PICKER_RES_ID.put('%', com.android.internal.R.string.symbol_picker_percent); + SYM_PICKER_RES_ID.put('*', com.android.internal.R.string.symbol_picker_star); + SYM_PICKER_RES_ID.put('-', com.android.internal.R.string.symbol_picker_minus); + SYM_PICKER_RES_ID.put('+', com.android.internal.R.string.symbol_picker_plus); + SYM_PICKER_RES_ID.put('(', com.android.internal.R.string.symbol_picker_opening_parenthesis); + SYM_PICKER_RES_ID.put(')', com.android.internal.R.string.symbol_picker_closing_parenthesis); + SYM_PICKER_RES_ID.put('!', com.android.internal.R.string.symbol_picker_exclamation); + SYM_PICKER_RES_ID.put('"', com.android.internal.R.string.symbol_picker_quote); + SYM_PICKER_RES_ID.put('?', com.android.internal.R.string.symbol_picker_question); + SYM_PICKER_RES_ID.put(',', com.android.internal.R.string.symbol_picker_comma); + SYM_PICKER_RES_ID.put('=', com.android.internal.R.string.symbol_picker_equal); + SYM_PICKER_RES_ID.put('<', com.android.internal.R.string.symbol_picker_lt); + SYM_PICKER_RES_ID.put('>', com.android.internal.R.string.symbol_picker_gt); }; private boolean showCharacterPicker(View view, Editable content, char c, boolean insert, int count) { - String set = PICKER_SETS.get(c); - if (set == null) { + Integer resId = SYM_PICKER_RES_ID.get(c); + + if (resId == null) { return false; } + String set = view.getContext().getString(resId); + if (count == 1) { new CharacterPickerDialog(view.getContext(), view, content, set, insert).show(); diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java index 575af3b..4e4116d 100644 --- a/core/java/android/view/KeyCharacterMap.java +++ b/core/java/android/view/KeyCharacterMap.java @@ -120,6 +120,18 @@ public class KeyCharacterMap { public static final char PICKER_DIALOG_INPUT = '\uEF01'; /** + * Private use character denoting a .com suffix + * @hide + */ + public static final char DOT_COM_INPUT = '\uEF03'; + + /** + * Private use character denoting a www. prefix + * @hide + */ + public static final char DOT_WWW_INPUT = '\uEF04'; + + /** * Modifier keys may be chorded with character keys. * * @see {#link #getModifierBehavior()} for more details. diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 458eb85..0d15d66 100755 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -592,15 +592,53 @@ public class KeyEvent extends InputEvent implements Parcelable { * Used to launch a calculator application. */ public static final int KEYCODE_CALCULATOR = 210; + /** Please note all remaining keycodes need to be + * hidden from the api */ + + /** @hide */ public static final int KEYCODE_TOGGLE_WIFI = 211; + /** @hide */ public static final int KEYCODE_TOGGLE_BT = 212; + /** @hide */ public static final int KEYCODE_TOGGLE_TOUCHPAD = 213; + /** @hide */ public static final int KEYCODE_BRIGHTNESS_DOWN = 214; + /** @hide */ public static final int KEYCODE_BRIGHTNESS_UP = 215; + /** @hide */ public static final int KEYCODE_BRIGHTNESS_AUTO = 216; + /** @hide */ public static final int KEYCODE_SCREENSHOT = 217; + /** @hide */ + /** FUNC_1 through USER5 to support keypad mapping */ + /** @hide */ + public static final int KEYCODE_FUNC_1 = 218; + /** @hide */ + public static final int KEYCODE_FUNC_2 = 219; + /** @hide */ + public static final int KEYCODE_FUNC_3 = 220; + /** @hide */ + public static final int KEYCODE_FUNC_4 = 221; + /** @hide */ + public static final int KEYCODE_FUNC_5 = 222; + /** @hide */ + public static final int KEYCODE_FUNC_6 = 223; + /** @hide */ + public static final int KEYCODE_FUNC_7 = 224; + /** @hide */ + public static final int KEYCODE_FUNC_8 = 225; + /** @hide */ + public static final int KEYCODE_USER1 = 226; + /** @hide */ + public static final int KEYCODE_USER2 = 227; + /** @hide */ + public static final int KEYCODE_USER3 = 228; + /** @hide */ + public static final int KEYCODE_USER4 = 229; + /** @hide */ + public static final int KEYCODE_USER5 = 230; - private static final int LAST_KEYCODE = KEYCODE_SCREENSHOT; + private static final int LAST_KEYCODE = KEYCODE_USER5; // NOTE: If you add a new keycode here you must also add it to: // isSystem() @@ -833,13 +871,46 @@ public class KeyEvent extends InputEvent implements Parcelable { names.append(KEYCODE_CALENDAR, "KEYCODE_CALENDAR"); names.append(KEYCODE_MUSIC, "KEYCODE_MUSIC"); names.append(KEYCODE_CALCULATOR, "KEYCODE_CALCULATOR"); + /** @hide */ names.append(KEYCODE_TOGGLE_WIFI, "KEYCODE_TOGGLE_WIFI"); + /** @hide */ names.append(KEYCODE_TOGGLE_BT, "KEYCODE_TOGGLE_BT"); + /** @hide */ names.append(KEYCODE_TOGGLE_TOUCHPAD, "KEYCODE_TOGGLE_TOUCHPAD"); + /** @hide */ names.append(KEYCODE_BRIGHTNESS_DOWN, "KEYCODE_BRIGHTNESS_DOWN"); + /** @hide */ names.append(KEYCODE_BRIGHTNESS_UP, "KEYCODE_BRIGHTNESS_UP"); + /** @hide */ names.append(KEYCODE_BRIGHTNESS_AUTO, "KEYCODE_BRIGHTNESS_AUTO"); + /** @hide */ names.append(KEYCODE_SCREENSHOT, "KEYCODE_SCREENSHOT"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_FUNC_1"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_FUNC_2"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_FUNC_3"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_FUNC_4"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_FUNC_5"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_FUNC_6"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_FUNC_7"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_FUNC_8"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_USER1"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_USER2"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_USER3"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_USER4"); + /** @hide */ + names.append(KEYCODE_SCREENSHOT, "KEYCODE_USER5"); }; // Symbolic names of all metakeys in bit order from least significant to most significant. diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 91414c4..297e4e2 100755 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1340,4 +1340,6 @@ <string name="weather_tap_to_refresh">Aperte para atualizar</string> <string name="weather_no_data">Sem dados</string> <string name="weather_refreshing">Atualizando</string> + <string name="toast_rotation_unlocked">Rotação da Tela está Desbloqueada</string> + <string name="toast_rotation_locked">Rotação da Tela está Bloqueada</string> </resources>
\ No newline at end of file diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 320aac9..49162ea 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1504,6 +1504,19 @@ <enum name="KEYCODE_BRIGHTNESS_UP" value="215" /> <enum name="KEYCODE_BRIGHTNESS_AUTO" value="216" /> <enum name="KEYCODE_SCREENSHOT" value="217" /> + <enum name="KEYCODE_FUNC_1" value="218" /> + <enum name="KEYCODE_FUNC_2" value="219" /> + <enum name="KEYCODE_FUNC_3" value="220" /> + <enum name="KEYCODE_FUNC_4" value="221" /> + <enum name="KEYCODE_FUNC_5" value="222" /> + <enum name="KEYCODE_FUNC_6" value="223" /> + <enum name="KEYCODE_FUNC_7" value="224" /> + <enum name="KEYCODE_FUNC_8" value="225" /> + <enum name="KEYCODE_USER1" value="226" /> + <enum name="KEYCODE_USER2" value="227" /> + <enum name="KEYCODE_USER3" value="228" /> + <enum name="KEYCODE_USER4" value="229" /> + <enum name="KEYCODE_USER5" value="230" /> </attr> <!-- ***************************************************************** --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 4185659..c656bec 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -453,6 +453,9 @@ <!-- Is the battery LED intrusive? Used to decide if there should be a disable option --> <bool name="config_intrusiveBatteryLed">false</bool> + <!-- Does the battery LED support multiple colors? Used to decide if the user can change the colors --> + <bool name="config_multiColorBatteryLed">false</bool> + <!-- Default value for LED off time when the battery is low on charge in miliseconds --> <integer name="config_notificationsBatteryLedOff">2875</integer> @@ -832,4 +835,11 @@ kill the foreground app. --> <integer name="config_backKillTimeout">2000</integer> + + <!-- Device has a h/w rotation lock switch --> + <bool name="config_hasRotationLockSwitch">false</bool> + + <!--Boolean to enable stk functionality on Samsung phones--> + <bool name="config_samsung_stk">false</bool> + </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 087aeb3..16d7d08 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1665,6 +1665,10 @@ <item>Jabber</item> </string-array> + <!-- Hardware Rotation lock string --> + <string name="toast_rotation_unlocked">Display Rotation Unlocked</string> + <string name="toast_rotation_locked">Display Rotation Locked</string> + <!-- Custom phone number type --> <string name="phoneTypeCustom">Custom</string> <!-- Home phone number type --> @@ -3511,4 +3515,59 @@ <string name="weather_tap_to_refresh">Tap to refresh</string> <string name="weather_refreshing">Refreshing</string> + <!-- Options that show upon long-pressing a key on the physical keyboard --> + <string name="symbol_picker_A">\u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5\u0104\u0100</string> + <string name="symbol_picker_C">\u00C7\u0106\u010C</string> + <string name="symbol_picker_D">\u010E</string> + <string name="symbol_picker_E">\u00C8\u00C9\u00CA\u00CB\u0118\u011A\u0112</string> + <string name="symbol_picker_G">\u011E</string> + <string name="symbol_picker_L">\u0141</string> + <string name="symbol_picker_I">\u00CC\u00CD\u00CE\u00CF\u012A\u0130</string> + <string name="symbol_picker_N">\u00D1\u0143\u0147</string> + <string name="symbol_picker_O">\u00D8\u0152\u00D5\u00D2\u00D3\u00D4\u00D6\u014C</string> + <string name="symbol_picker_R">\u0158</string> + <string name="symbol_picker_S">\u015A\u0160\u015E</string> + <string name="symbol_picker_T">\u0164</string> + <string name="symbol_picker_U">\u00D9\u00DA\u00DB\u00DC\u016E\u016A</string> + <string name="symbol_picker_Y">\u00DD\u0178</string> + <string name="symbol_picker_Z">\u0179\u017B\u017D</string> + <string name="symbol_picker_a">\u00E0\u00E1\u00E2\u00E4\u00E6\u00E3\u00E5\u0105\u0101</string> + <string name="symbol_picker_c">\u00E7\u0107\u010D</string> + <string name="symbol_picker_d">\u010F</string> + <string name="symbol_picker_e">\u00E8\u00E9\u00EA\u00EB\u0119\u011B\u0113</string> + <string name="symbol_picker_g">\u011F</string> + <string name="symbol_picker_i">\u00EC\u00ED\u00EE\u00EF\u012B\u0131</string> + <string name="symbol_picker_l">\u0142</string> + <string name="symbol_picker_n">\u00F1\u0144\u0148</string> + <string name="symbol_picker_o">\u00F8\u0153\u00F5\u00F2\u00F3\u00F4\u00F6\u014D</string> + <string name="symbol_picker_r">\u0159</string> + <string name="symbol_picker_s">\u00A7\u00DF\u015B\u0161\u015F</string> + <string name="symbol_picker_t">\u0165</string> + <string name="symbol_picker_u">\u00F9\u00FA\u00FB\u00FC\u016F\u016B</string> + <string name="symbol_picker_y">\u00FD\u00FF</string> + <string name="symbol_picker_z">\u017A\u017C\u017E</string> + <string name="symbol_picker_sym">\u2026\u00A5\u2022\u00AE\u00A9\u00B1[]{}\u003C>`^\\|</string> + <string name="symbol_picker_slash">\\</string> + <string name="symbol_picker_1">\u00b9\u00bd\u2153\u00bc\u215b</string> + <string name="symbol_picker_2">\u00b2\u2154</string> + <string name="symbol_picker_3">\u00b3\u00be\u215c</string> + <string name="symbol_picker_4">\u2074</string> + <string name="symbol_picker_5">\u215d</string> + <string name="symbol_picker_7">\u215e</string> + <string name="symbol_picker_0">\u207f\u2205</string> + <string name="symbol_picker_dollar">\u00a2\u00a3\u20ac\u00a5\u20a3\u20a4\u20b1</string> + <string name="symbol_picker_percent">\u2030</string> + <string name="symbol_picker_star">\u2020\u2021</string> + <string name="symbol_picker_minus">\u2013\u2014</string> + <string name="symbol_picker_plus">\u00b1</string> + <string name="symbol_picker_opening_parenthesis">[{\u003C</string> + <string name="symbol_picker_closing_parenthesis">]}></string> + <string name="symbol_picker_exclamation">\u00a1</string> + <string name="symbol_picker_quote">\u201c\u201d\u00ab\u00bb\u02dd</string> + <string name="symbol_picker_question">\u00bf</string> + <string name="symbol_picker_comma">\u201a\u201e</string> + <string name="symbol_picker_equal">\u2260\u2248\u221e</string> + <string name="symbol_picker_lt">\u2264\u00ab\u2039</string> + <string name="symbol_picker_gt">\u2265\u00bb\u203a</string> + </resources> diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h index 7d92506..7cc3d4e 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -580,8 +580,6 @@ public: static const char KEY_FULL_VIDEO_SNAP_SUPPORTED[]; #ifdef QCOM_HARDWARE - static const char KEY_ISO_MODE[]; - static const char KEY_SUPPORTED_ISO_MODES[]; static const char KEY_LENSSHADE[] ; static const char KEY_SUPPORTED_LENSSHADE_MODES[] ; @@ -593,6 +591,10 @@ public: static const char KEY_GPS_ALTITUDE_REF[]; static const char KEY_GPS_STATUS[]; static const char KEY_EXIF_DATETIME[]; +#ifndef SAMSUNG_CAMERA_HARDWARE + static const char KEY_ISO_MODE[]; + static const char KEY_SUPPORTED_ISO_MODES[]; +#endif #endif // The state of the video stabilization. If set to true, both the @@ -656,9 +658,11 @@ public: #endif #ifdef SAMSUNG_CAMERA_HARDWARE - static const char KEY_METERING[]; - static const char KEY_WDR[]; - static const char KEY_ANTI_SHAKE_MODE[]; + static const char KEY_METERING[]; + static const char KEY_WDR[]; + static const char KEY_ANTI_SHAKE_MODE[]; + static const char KEY_ISO_MODE[]; + static const char KEY_SUPPORTED_ISO_MODES[]; #endif // Values for white balance settings. diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h index a443232..dde50f7 100755 --- a/include/ui/KeycodeLabels.h +++ b/include/ui/KeycodeLabels.h @@ -242,6 +242,19 @@ static const KeycodeLabel KEYCODES[] = { { "BRIGHTNESS_UP", 215 }, { "BRIGHTNESS_AUTO", 216 }, { "SCREENSHOT", 217 }, + { "FUNC_1", 218 }, + { "FUNC_2", 219 }, + { "FUNC_3", 220 }, + { "FUNC_4", 221 }, + { "FUNC_5", 222 }, + { "FUNC_6", 223 }, + { "FUNC_7", 224 }, + { "FUNC_8", 225 }, + { "USER1", 226 }, + { "USER2", 227 }, + { "USER3", 228 }, + { "USER4", 229 }, + { "USER5", 230 }, // NOTE: If you add a new keycode here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp index 94c7481..6ed7a25 100644 --- a/libs/camera/CameraParameters.cpp +++ b/libs/camera/CameraParameters.cpp @@ -119,8 +119,6 @@ const char CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED[] = "smooth-zoom-supporte const char CameraParameters::KEY_FOCUS_DISTANCES[] = "focus-distances"; const char CameraParameters::KEY_VIDEO_FRAME_FORMAT[] = "video-frame-format"; #ifdef QCOM_HARDWARE -const char CameraParameters::KEY_ISO_MODE[] = "iso"; -const char CameraParameters::KEY_SUPPORTED_ISO_MODES[] = "iso-values"; const char CameraParameters::KEY_LENSSHADE[] = "lensshade"; const char CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES[] = "lensshade-values"; const char CameraParameters::KEY_AUTO_EXPOSURE[] = "auto-exposure"; @@ -139,11 +137,17 @@ const char CameraParameters::KEY_REDEYE_REDUCTION[] = "redeye-reduction"; const char CameraParameters::KEY_SUPPORTED_REDEYE_REDUCTION[] = "redeye-reduction-values"; const char CameraParameters::KEY_HIGH_DYNAMIC_RANGE_IMAGING[] = "hdr"; const char CameraParameters::KEY_SUPPORTED_HDR_IMAGING_MODES[] = "hdr-values"; +#ifndef SAMSUNG_CAMERA_HARDWARE +const char CameraParameters::KEY_ISO_MODE[] = "iso"; +const char CameraParameters::KEY_SUPPORTED_ISO_MODES[] = "iso-values"; +#endif #endif #ifdef SAMSUNG_CAMERA_HARDWARE const char CameraParameters::KEY_METERING[] = "metering"; const char CameraParameters::KEY_WDR[] = "wdr"; const char CameraParameters::KEY_ANTI_SHAKE_MODE[] = "anti-shake"; +const char CameraParameters::KEY_ISO_MODE[] = "iso"; +const char CameraParameters::KEY_SUPPORTED_ISO_MODES[] = "iso-values"; #endif const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size"; const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values"; diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index e38b479..94d3fab 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -221,6 +221,7 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); Caches::getInstance().fboCache.put(fbo); + layer->setFbo(0); layer->deleteTexture(); delete layer; @@ -307,6 +308,7 @@ void LayerRenderer::destroyLayer(Layer* layer) { if (layer->getFbo()) { Caches::getInstance().fboCache.put(layer->getFbo()); + layer->setFbo(0); } if (!Caches::getInstance().layerCache.put(layer)) { diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index dd377be..9dda80e 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -228,9 +228,11 @@ public class MediaRecorder /** @hide H.264/AAC data encapsulated in MPEG2/TS */ public static final int OUTPUT_FORMAT_MPEG2TS = 8; - /** QCP file format */ + /** QCP file format + * @hide */ public static final int QCP = 9; - /** 3GPP2 media file format*/ + /** 3GPP2 media file format + * @hide */ public static final int THREE_GPP2 = 10; }; @@ -250,13 +252,17 @@ public class MediaRecorder public static final int AMR_WB = 2; /** AAC audio codec */ public static final int AAC = 3; - /** enhanced AAC audio codec */ + /** enhanced AAC audio codec + * @hide */ public static final int AAC_PLUS = 4; - /** enhanced AAC plus audio codec */ + /** enhanced AAC plus audio codec + * @hide */ public static final int EAAC_PLUS = 5; - /** EVRC audio codec */ + /** EVRC audio codec + * @hide */ public static final int EVRC = 6; - /** QCELP audio codec */ + /** QCELP audio codec + * @hide */ public static final int QCELP =7; } @@ -669,6 +675,8 @@ public class MediaRecorder * * @throws IllegalStateException if it is called before * prepare(). + * + * @hide */ public native void native_start() throws IllegalStateException; @@ -683,6 +691,8 @@ public class MediaRecorder * the output file is not properly constructed when this happens. * * @throws IllegalStateException if it is called before start() + * + * @hide */ public native void native_stop() throws IllegalStateException; diff --git a/native/include/android/keycodes.h b/native/include/android/keycodes.h index f9c808d..44611e0 100644 --- a/native/include/android/keycodes.h +++ b/native/include/android/keycodes.h @@ -261,6 +261,19 @@ enum { AKEYCODE_BRIGHTNESS_UP = 215, AKEYCODE_BRIGHTNESS_AUTO = 216, AKEYCODE_SCREENSHOT = 217, + AKEYCODE_FUNC_1 = 218, + AKEYCODE_FUNC_2 = 219, + AKEYCODE_FUNC_3 = 220, + AKEYCODE_FUNC_4 = 221, + AKEYCODE_FUNC_5 = 222, + AKEYCODE_FUNC_6 = 223, + AKEYCODE_FUNC_7 = 224, + AKEYCODE_FUNC_8 = 225, + AKEYCODE_USER1 = 226, + AKEYCODE_USER2 = 227, + AKEYCODE_USER3 = 228, + AKEYCODE_USER4 = 229, + AKEYCODE_USER5 = 230, // NOTE: If you add a new keycode here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 630dfa5..e0753d0 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -1355,6 +1355,9 @@ public class DatabaseHelper extends SQLiteOpenHelper { // Set default tty mode loadSetting(stmt, Settings.System.TTY_MODE, 0); + + // Set default noise suppression value + loadSetting(stmt, Settings.System.NOISE_SUPPRESSION, 0); loadBooleanSetting(stmt, Settings.System.AIRPLANE_MODE_ON, R.bool.def_airplane_mode_on); diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_settings_button.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_settings_button.xml new file mode 100644 index 0000000..ebf0102 --- /dev/null +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_settings_button.xml @@ -0,0 +1,15 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + style="@style/StatusBarPanelSettingsRow"> + + <ImageView + style="@style/StatusBarPanelSettingsIcon"/> + + <TextView + style="@style/StatusBarPanelSettingsContents"/> + + <Switch android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginRight="5dp"/> + +</LinearLayout> diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_settings_view.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_settings_view.xml index b315432..45152a0 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_settings_view.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_settings_view.xml @@ -18,165 +18,18 @@ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui" android:layout_height="match_parent" android:layout_width="match_parent"> <com.android.systemui.statusbar.tablet.SettingsView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > - <!-- Toggle 1 --> - <LinearLayout - android:id="@+id/toggle_1" - style="@style/StatusBarPanelSettingsRow" - > - <ImageView - android:id="@+id/toggle_1_icon" - style="@style/StatusBarPanelSettingsIcon" - android:src="@drawable/ic_sysbar_airplane_on" - /> - <TextView - android:id="@+id/toggle_1_label" - style="@style/StatusBarPanelSettingsContents" - android:text="@string/status_bar_settings_airplane" - /> - <Switch - android:id="@+id/toggle_1_checkbox" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_marginRight="5dp" - /> - </LinearLayout> - <View style="@style/StatusBarPanelSettingsPanelSeparator" /> - - <!-- Toggle 2 --> - <LinearLayout - android:id="@+id/toggle_2" - style="@style/StatusBarPanelSettingsRow" - > - <ImageView - android:id="@+id/toggle_2_icon" - style="@style/StatusBarPanelSettingsIcon" - android:src="@drawable/ic_sysbar_wifi_on" - /> - <TextView - android:id="@+id/toggle_2_label" - style="@style/StatusBarPanelSettingsContents" - android:text="@string/status_bar_settings_wifi_button" - /> - <Switch - android:id="@+id/toggle_2_checkbox" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_marginRight="5dp" - /> - </LinearLayout> - <View style="@style/StatusBarPanelSettingsPanelSeparator" /> - - <!-- Toggle 3 --> - <LinearLayout - android:id="@+id/toggle_3" - style="@style/StatusBarPanelSettingsRow" - > - <ImageView - android:id="@+id/toggle_3_icon" - style="@style/StatusBarPanelSettingsIcon" - android:src="@drawable/stat_sys_data_bluetooth" - /> - <TextView - android:id="@+id/toggle_3_label" - style="@style/StatusBarPanelSettingsContents" - android:text="@string/status_bar_settings_bluetooth_button" - /> - <Switch - android:id="@+id/toggle_3_checkbox" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_marginRight="5dp" - /> - </LinearLayout> - <View style="@style/StatusBarPanelSettingsPanelSeparator" /> + <!-- Power widget buttons will be added here --> - <!-- Toggle 4 --> - <LinearLayout - android:id="@+id/toggle_4" - style="@style/StatusBarPanelSettingsRow" - > - <ImageView - android:id="@+id/toggle_4_icon" - style="@style/StatusBarPanelSettingsIcon" - android:src="@drawable/ic_sysbar_rotate_on" - /> - <TextView - android:id="@+id/toggle_4_label" - style="@style/StatusBarPanelSettingsContents" - android:text="@string/status_bar_settings_auto_rotation" - /> - <Switch - android:id="@+id/toggle_4_checkbox" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_marginRight="5dp" - /> - </LinearLayout> - <View style="@style/StatusBarPanelSettingsPanelSeparator" /> - - <!-- Toggle 5 --> - <LinearLayout - android:id="@+id/toggle_5" - style="@style/StatusBarPanelSettingsRow" - > - <ImageView - android:id="@+id/toggle_5_icon" - style="@style/StatusBarPanelSettingsIcon" - android:src="@drawable/stat_gps_on" - /> - <TextView - android:id="@+id/toggle_5_label" - style="@style/StatusBarPanelSettingsContents" - android:text="@string/status_bar_settings_location" - /> - <Switch - android:id="@+id/toggle_5_checkbox" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_marginRight="5dp" - /> - </LinearLayout> - <View style="@style/StatusBarPanelSettingsPanelSeparator" /> - - <!-- Toggle 6 --> - <LinearLayout - android:id="@+id/toggle_6" - style="@style/StatusBarPanelSettingsRow" - > - <ImageView - android:id="@+id/toggle_6_icon" - style="@style/StatusBarPanelSettingsIcon" - android:src="@drawable/stat_flashlight_on" - /> - <TextView - android:id="@+id/toggle_6_label" - style="@style/StatusBarPanelSettingsContents" - android:text="@string/status_bar_settings_flashlight" - /> - <Switch - android:id="@+id/toggle_6_checkbox" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_marginRight="5dp" - /> - </LinearLayout> <View style="@style/StatusBarPanelSettingsPanelSeparator" /> <!-- Brightness --> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 9fc2256..cf033c9 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -140,4 +140,5 @@ <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS wird gesucht"</string> <string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string> <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string> + <string name="powerwidget_screen_timeout_toast">Bildschirm-Timeout ist jetzt %1$d %2$s</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 3b47b83..06fec81 100755 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -155,4 +155,5 @@ <string name="status_bar_settings_flashlight">Lanterna de LED</string> <string name="status_bar_settings_mobile_data">Dados móveis</string> <string name="status_bar_settings_sound_mode">Som</string> + <string name="powerwidget_screen_timeout_toast">Tempo limite da tela ajustado para: %1$d %2$s</string> </resources>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 664bfb1..19c9c5f 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -403,4 +403,6 @@ <string name="navbar_menu_conditional_button">Menu (autoHide) button</string> <string name="navbar_menu_always_button">Menu (alwaysShow) button</string> <string name="navbar_menu_big_button">Menu button</string> + + <string name="powerwidget_screen_timeout_toast">Screen timeout set to: %1$d %2$s</string> </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 51bd0cf..2b0fdba 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -95,5 +95,28 @@ <!-- Note: must be dp to fit in status bar --> <item name="android:textSize">14dp</item> </style> + + <style name="StatusBarPanelSettingsIcon"> + <item name="android:layout_height">match_parent</item> + <item name="android:layout_width">64dp</item> + <item name="android:scaleType">center</item> + </style> + + <style name="StatusBarPanelSettingsRow"> + <item name="android:paddingRight">16dp</item> + <item name="android:layout_height">64dp</item> + <item name="android:layout_width">match_parent</item> + <item name="android:orientation">horizontal</item> + <item name="android:background">?android:attr/listChoiceBackgroundIndicator</item> + </style> + + <style name="StatusBarPanelSettingsContents"> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_width">0dp</item> + <item name="android:layout_weight">1</item> + <item name="android:layout_gravity">left|center_vertical</item> + <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textSize">18sp</item> + </style> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index e2ae054..d0fba75 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -401,7 +401,6 @@ public class PhoneStatusBar extends StatusBar { mPowerWidget = (PowerWidget)expanded.findViewById(R.id.exp_power_stat); - mPowerWidget.setupSettingsObserver(mHandler); mPowerWidget.setGlobalButtonOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(Settings.System.getInt(mContext.getContentResolver(), @@ -612,7 +611,7 @@ public class PhoneStatusBar extends StatusBar { StatusBarIconView view = new StatusBarIconView(mContext, slot, null); view.set(icon); mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize)); - mPowerWidget.updateWidget(); + mPowerWidget.updateAllButtons(); } public void updateIcon(String slot, int index, int viewIndex, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/AirplaneButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/AirplaneButton.java index 7e2f20c..e1820ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/AirplaneButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/AirplaneButton.java @@ -21,8 +21,8 @@ public class AirplaneButton extends PowerButton { public AirplaneButton() { mType = BUTTON_AIRPLANE; } @Override - protected void updateState() { - if (getState(mView.getContext())) { + protected void updateState(Context context) { + if (getState(context)) { mIcon = R.drawable.stat_airplane_on; mState = STATE_ENABLED; } else { @@ -32,8 +32,7 @@ public class AirplaneButton extends PowerButton { } @Override - protected void toggleState() { - Context context = mView.getContext(); + protected void toggleState(Context context) { boolean state = getState(context); Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, state ? 0 : 1); @@ -45,11 +44,11 @@ public class AirplaneButton extends PowerButton { } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.AIRPLANE_MODE_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } @@ -58,7 +57,7 @@ public class AirplaneButton extends PowerButton { return OBSERVED_URIS; } - private static boolean getState(Context context) { + private boolean getState(Context context) { return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,0) == 1; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/AutoRotateButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/AutoRotateButton.java index 2cc4715..7e93d4f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/AutoRotateButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/AutoRotateButton.java @@ -28,8 +28,8 @@ public class AutoRotateButton extends PowerButton { public AutoRotateButton() { mType = BUTTON_AUTOROTATE; } @Override - protected void updateState() { - if (getAutoRotation()) { + protected void updateState(Context context) { + if (getAutoRotation(context)) { mIcon = R.drawable.stat_orientation_on; mState = STATE_ENABLED; } else { @@ -39,16 +39,16 @@ public class AutoRotateButton extends PowerButton { } @Override - protected void toggleState() { - setAutoRotation(!getAutoRotation()); + protected void toggleState(Context context) { + setAutoRotation(!getAutoRotation(context)); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.DISPLAY_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } @@ -57,9 +57,9 @@ public class AutoRotateButton extends PowerButton { return OBSERVED_URIS; } - private boolean getAutoRotation() { - ContentResolver cr = mView.getContext().getContentResolver(); - return 0 != Settings.System.getInt(cr, Settings.System.ACCELEROMETER_ROTATION, 0); + private boolean getAutoRotation(Context context) { + ContentResolver cr = context.getContentResolver(); + return Settings.System.getInt(cr, Settings.System.ACCELEROMETER_ROTATION, 0) != 0; } private void setAutoRotation(final boolean autorotate) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/BluetoothButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/BluetoothButton.java index fad57d3..6b1a2a2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/BluetoothButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/BluetoothButton.java @@ -80,8 +80,8 @@ public class BluetoothButton extends PowerButton { public BluetoothButton() { mType = BUTTON_BLUETOOTH; } @Override - protected void updateState() { - mState = sBluetoothState.getTriState(mView.getContext()); + protected void updateState(Context context) { + mState = sBluetoothState.getTriState(context); switch (mState) { case STATE_DISABLED: mIcon = R.drawable.stat_bluetooth_off; @@ -105,16 +105,16 @@ public class BluetoothButton extends PowerButton { } @Override - protected void toggleState() { - sBluetoothState.toggleState(mView.getContext()); + protected void toggleState(Context context) { + sBluetoothState.toggleState(context); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.BLUETOOTH_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/BrightnessButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/BrightnessButton.java index 1804cf38..edd04d2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/BrightnessButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/BrightnessButton.java @@ -7,8 +7,8 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.os.IPowerManager; import android.os.Power; +import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.preference.ListPreferenceMultiSelect; @@ -79,12 +79,12 @@ public class BrightnessButton extends PowerButton { Context context = mView.getContext(); mAutoBrightnessSupported = context.getResources().getBoolean( com.android.internal.R.bool.config_automatic_brightness_available); - updateSettings(); + updateSettings(context.getContentResolver()); } } @Override - protected void updateState() { + protected void updateState(Context context) { if (mAutoBrightness) { mIcon = R.drawable.stat_brightness_auto; mState = STATE_ENABLED; @@ -101,42 +101,37 @@ public class BrightnessButton extends PowerButton { } @Override - protected void toggleState() { - try { - IPowerManager power = IPowerManager.Stub - .asInterface(ServiceManager.getService("power")); - if (power != null) { - ContentResolver resolver = mView.getContext().getContentResolver(); - mCurrentBacklightIndex++; - if (mCurrentBacklightIndex > mBacklightValues.length - 1) { - mCurrentBacklightIndex = 0; - } - int backlightIndex = mBacklightValues[mCurrentBacklightIndex]; - int brightness = BACKLIGHTS[backlightIndex]; - if (brightness == AUTO_BACKLIGHT) { - Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, - Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); - } else { - if (mAutoBrightnessSupported) { - Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, - Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); - } - power.setBacklightBrightness(brightness); - Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS, brightness); - } - } - } catch (RemoteException e) { - Log.e(TAG, "toggleState()", e); + protected void toggleState(Context context) { + PowerManager power = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + ContentResolver resolver = context.getContentResolver(); + + mCurrentBacklightIndex++; + if (mCurrentBacklightIndex > mBacklightValues.length - 1) { + mCurrentBacklightIndex = 0; } + int backlightIndex = mBacklightValues[mCurrentBacklightIndex]; + int brightness = BACKLIGHTS[backlightIndex]; + + if (brightness == AUTO_BACKLIGHT) { + Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + } else { + if (mAutoBrightnessSupported) { + Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); + } + power.setBacklightBrightness(brightness); + Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS, brightness); + } } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.DISPLAY_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } @@ -146,8 +141,7 @@ public class BrightnessButton extends PowerButton { } @Override - protected void onChangeUri(Uri uri) { - ContentResolver resolver = mView.getContext().getContentResolver(); + protected void onChangeUri(ContentResolver resolver, Uri uri) { if (BRIGHTNESS_URI.equals(uri)) { mCurrentBrightness = Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS, 0); @@ -155,13 +149,11 @@ public class BrightnessButton extends PowerButton { mAutoBrightness = (Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, 0) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); } else { - updateSettings(); + updateSettings(resolver); } } - private void updateSettings() { - ContentResolver resolver = mView.getContext().getContentResolver(); - + private void updateSettings(ContentResolver resolver) { boolean lightSensorCustom = (Settings.System.getInt(resolver, Settings.System.LIGHT_SENSOR_CUSTOM, 0) != 0); if (lightSensorCustom) { @@ -198,7 +190,5 @@ public class BrightnessButton extends PowerButton { } } } - updateState(); } - } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/FlashlightButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/FlashlightButton.java index a9f17bc..cf8ed2d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/FlashlightButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/FlashlightButton.java @@ -20,8 +20,8 @@ public class FlashlightButton extends PowerButton { public FlashlightButton() { mType = BUTTON_FLASHLIGHT; } @Override - protected void updateState() { - boolean enabled = Settings.System.getInt(mView.getContext().getContentResolver(), Settings.System.TORCH_STATE, 0) == 1; + protected void updateState(Context context) { + boolean enabled = Settings.System.getInt(context.getContentResolver(), Settings.System.TORCH_STATE, 0) == 1; if(enabled) { mIcon = R.drawable.stat_flashlight_on; mState = STATE_ENABLED; @@ -32,8 +32,7 @@ public class FlashlightButton extends PowerButton { } @Override - protected void toggleState() { - Context context = mView.getContext(); + protected void toggleState(Context context) { boolean bright = Settings.System.getInt(context.getContentResolver(), Settings.System.EXPANDED_FLASH_MODE, 0) == 1; Intent i = new Intent("net.cactii.flash2.TOGGLE_FLASHLIGHT"); @@ -42,13 +41,13 @@ public class FlashlightButton extends PowerButton { } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { // it may be better to make an Intent action for the Torch // we may want to look at that option later Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName("net.cactii.flash2", "net.cactii.flash2.MainActivity"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/GPSButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/GPSButton.java index 32a1ea3..579d1d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/GPSButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/GPSButton.java @@ -22,8 +22,8 @@ public class GPSButton extends PowerButton { public GPSButton() { mType = BUTTON_GPS; } @Override - protected void updateState() { - if(getGpsState(mView.getContext())) { + protected void updateState(Context context) { + if (getGpsState(context)) { mIcon = R.drawable.stat_gps_on; mState = STATE_ENABLED; } else { @@ -33,8 +33,7 @@ public class GPSButton extends PowerButton { } @Override - protected void toggleState() { - Context context = mView.getContext(); + protected void toggleState(Context context) { ContentResolver resolver = context.getContentResolver(); boolean enabled = getGpsState(context); Settings.Secure.setLocationProviderEnabled(resolver, @@ -42,11 +41,11 @@ public class GPSButton extends PowerButton { } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.LOCATION_SOURCE_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } @@ -55,7 +54,7 @@ public class GPSButton extends PowerButton { return OBSERVED_URIS; } - private static boolean getGpsState(Context context) { + private boolean getGpsState(Context context) { ContentResolver resolver = context.getContentResolver(); return Settings.Secure.isLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/LTEButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/LTEButton.java index bb12f84..52028ea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/LTEButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/LTEButton.java @@ -24,9 +24,9 @@ public class LTEButton extends PowerButton{ public LTEButton() { mType = BUTTON_LTE; } @Override - protected void updateState() { - ContentResolver resolver = mView.getContext().getContentResolver(); - int network = getCurrentPreferredNetworkMode(mView.getContext()); + protected void updateState(Context context) { + ContentResolver resolver = context.getContentResolver(); + int network = getCurrentPreferredNetworkMode(context); switch(network) { case Phone.NT_MODE_GLOBAL: case Phone.NT_MODE_LTE_GSM_WCDMA: @@ -44,11 +44,11 @@ public class LTEButton extends PowerButton{ } @Override - protected void toggleState() { - TelephonyManager tm = (TelephonyManager) mView.getContext() - .getSystemService(Context.TELEPHONY_SERVICE); - int network = getCurrentPreferredNetworkMode(mView.getContext()); - ContentResolver resolver = mView.getContext().getContentResolver(); + protected void toggleState(Context context) { + TelephonyManager tm = (TelephonyManager) + context.getSystemService(Context.TELEPHONY_SERVICE); + int network = getCurrentPreferredNetworkMode(context); + ContentResolver resolver = context.getContentResolver(); if (Phone.NT_MODE_GLOBAL == network || Phone.NT_MODE_LTE_GSM_WCDMA == network) { tm.toggleLTE(false); @@ -63,11 +63,11 @@ public class LTEButton extends PowerButton{ } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName("com.android.phone", "com.android.phone.Settings"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/LockScreenButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/LockScreenButton.java index a36c495..0a1959f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/LockScreenButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/LockScreenButton.java @@ -2,30 +2,24 @@ package com.android.systemui.statusbar.powerwidget; import com.android.systemui.R; -import android.app.Activity; import android.app.KeyguardManager; import android.app.KeyguardManager.KeyguardLock; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.view.Gravity; -import android.widget.Toast; +import android.view.View; public class LockScreenButton extends PowerButton { - - private static Boolean LOCK_SCREEN_STATE = null; + private static final String KEY_DISABLED = "lockscreen_disabled"; private KeyguardLock mLock = null; + private boolean mDisabledLockscreen = false; public LockScreenButton() { mType = BUTTON_LOCKSCREEN; } @Override - protected void updateState() { - getState(); - if (LOCK_SCREEN_STATE == null) { - mIcon = R.drawable.stat_lock_screen_off; - mState = STATE_INTERMEDIATE; - } else if (LOCK_SCREEN_STATE) { + protected void updateState(Context context) { + if (!mDisabledLockscreen) { mIcon = R.drawable.stat_lock_screen_on; mState = STATE_ENABLED; } else { @@ -35,54 +29,50 @@ public class LockScreenButton extends PowerButton { } @Override - protected void toggleState() { - Context context = mView.getContext(); - getState(); - if(LOCK_SCREEN_STATE == null) { - Toast msg = Toast.makeText(context, "Not yet initialized", Toast.LENGTH_LONG); - msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2); - msg.show(); - } else { - getLock(context); - if (mLock != null) { - if (LOCK_SCREEN_STATE) { - mLock.disableKeyguard(); - LOCK_SCREEN_STATE = false; - } else { - mLock.reenableKeyguard(); - LOCK_SCREEN_STATE = true; - } - } + protected void setupButton(View view) { + super.setupButton(view); + + if (view == null && mDisabledLockscreen) { + mLock.reenableKeyguard(); + mLock = null; + } else if (view != null) { + Context context = view.getContext(); + mDisabledLockscreen = getPreferences(context).getBoolean(KEY_DISABLED, false); + applyState(context); } + } - // we're handling this, so just update our buttons now - // this is UGLY, do it better later >.> - update(); + @Override + protected void toggleState(Context context) { + mDisabledLockscreen = !mDisabledLockscreen; + + SharedPreferences.Editor editor = getPreferences(context).edit(); + editor.putBoolean(KEY_DISABLED, mDisabledLockscreen); + editor.apply(); + + applyState(context); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.SECURITY_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } - private KeyguardLock getLock(Context context) { + private void applyState(Context context) { if (mLock == null) { - KeyguardManager keyguardManager = (KeyguardManager)context. - getSystemService(Activity.KEYGUARD_SERVICE); - mLock = keyguardManager.newKeyguardLock(Context.KEYGUARD_SERVICE); + KeyguardManager keyguardManager = (KeyguardManager) + context.getSystemService(Context.KEYGUARD_SERVICE); + mLock = keyguardManager.newKeyguardLock("PowerWidget"); } - return mLock; - } - - private static boolean getState() { - if (LOCK_SCREEN_STATE == null) { - LOCK_SCREEN_STATE = true; + if (mDisabledLockscreen) { + mLock.disableKeyguard(); + } else { + mLock.reenableKeyguard(); } - return LOCK_SCREEN_STATE; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaKeyEventButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaKeyEventButton.java index f722036..62ddbbd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaKeyEventButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaKeyEventButton.java @@ -14,10 +14,9 @@ import android.view.View; public abstract class MediaKeyEventButton extends PowerButton { private static final String TAG = "MediaKeyEventButton"; - private static AudioManager AUDIO_MANAGER = null; + private AudioManager mAM = null; - protected void sendMediaKeyEvent(int code) { - Context context = mView.getContext(); + protected void sendMediaKeyEvent(Context context, int code) { long eventtime = SystemClock.uptimeMillis(); Intent downIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); @@ -31,11 +30,11 @@ public abstract class MediaKeyEventButton extends PowerButton { context.sendOrderedBroadcast(upIntent, null); } - protected static AudioManager getAudioManager(Context context) { - if(AUDIO_MANAGER == null) { - AUDIO_MANAGER = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + protected AudioManager getAudioManager(Context context) { + if (mAM == null) { + mAM = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); } - return AUDIO_MANAGER; + return mAM; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaNextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaNextButton.java index d416c9a..c5c0791 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaNextButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaNextButton.java @@ -9,18 +9,18 @@ public class MediaNextButton extends MediaKeyEventButton { public MediaNextButton() { mType = BUTTON_MEDIA_NEXT; } @Override - protected void updateState() { + protected void updateState(Context context) { mIcon = R.drawable.stat_media_next; mState = STATE_DISABLED; } @Override - protected void toggleState() { - sendMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_NEXT); + protected void toggleState(Context context) { + sendMediaKeyEvent(context, KeyEvent.KEYCODE_MEDIA_NEXT); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { return false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaPlayPauseButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaPlayPauseButton.java index ea814e3..9a6ec71 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaPlayPauseButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaPlayPauseButton.java @@ -16,9 +16,9 @@ public class MediaPlayPauseButton extends MediaKeyEventButton { private int mCurrentState = MEDIA_STATE_UNKNOWN; @Override - protected void updateState() { + protected void updateState(Context context) { mState = STATE_DISABLED; - if(isMusicActive()) { + if (isMusicActive(context)) { mIcon = R.drawable.stat_media_pause; } else { mIcon = R.drawable.stat_media_play; @@ -26,24 +26,24 @@ public class MediaPlayPauseButton extends MediaKeyEventButton { } @Override - protected void toggleState() { - sendMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE); + protected void toggleState(Context context) { + sendMediaKeyEvent(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE); - mCurrentState = (isMusicActive() ? MEDIA_STATE_INACTIVE : MEDIA_STATE_ACTIVE); + mCurrentState = (isMusicActive(context) ? MEDIA_STATE_INACTIVE : MEDIA_STATE_ACTIVE); - update(); + update(context); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { return false; } - private boolean isMusicActive() { - if(mCurrentState == MEDIA_STATE_UNKNOWN) { + private boolean isMusicActive(Context context) { + if (mCurrentState == MEDIA_STATE_UNKNOWN) { mCurrentState = MEDIA_STATE_INACTIVE; - AudioManager am = getAudioManager(mView.getContext()); - if(am != null) { + AudioManager am = getAudioManager(context); + if (am != null) { mCurrentState = (am.isMusicActive() ? MEDIA_STATE_ACTIVE : MEDIA_STATE_INACTIVE); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaPreviousButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaPreviousButton.java index b7657f6..362b1f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaPreviousButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MediaPreviousButton.java @@ -9,18 +9,18 @@ public class MediaPreviousButton extends MediaKeyEventButton { public MediaPreviousButton() { mType = BUTTON_MEDIA_PREVIOUS; } @Override - protected void updateState() { + protected void updateState(Context context) { mIcon = R.drawable.stat_media_previous; mState = STATE_DISABLED; } @Override - protected void toggleState() { - sendMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PREVIOUS); + protected void toggleState(Context context) { + sendMediaKeyEvent(context, KeyEvent.KEYCODE_MEDIA_PREVIOUS); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { return false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MobileDataButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MobileDataButton.java index d5d3282..e53d1fa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MobileDataButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/MobileDataButton.java @@ -13,18 +13,14 @@ import com.android.internal.telephony.TelephonyIntents; public class MobileDataButton extends PowerButton { - public static final String MOBILE_DATA_CHANGED = "com.android.internal.telephony.MOBILE_DATA_CHANGED"; - - public static boolean STATE_CHANGE_REQUEST = false; + public static final String ACTION_MODIFY_NETWORK_MODE = "com.android.internal.telephony.MODIFY_NETWORK_MODE"; + public static final String EXTRA_NETWORK_MODE = "networkMode"; public MobileDataButton() { mType = BUTTON_MOBILEDATA; } @Override - protected void updateState() { - if (STATE_CHANGE_REQUEST) { - mIcon = R.drawable.stat_data_on; - mState = STATE_INTERMEDIATE; - } else if (getDataState(mView.getContext())) { + protected void updateState(Context context) { + if (getDataState(context)) { mIcon = R.drawable.stat_data_on; mState = STATE_ENABLED; } else { @@ -34,8 +30,7 @@ public class MobileDataButton extends PowerButton { } @Override - protected void toggleState() { - Context context = mView.getContext(); + protected void toggleState(Context context) { boolean enabled = getDataState(context); ConnectivityManager cm = (ConnectivityManager) context @@ -48,13 +43,13 @@ public class MobileDataButton extends PowerButton { } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { // it may be better to make an Intent action for this or find the appropriate one // we may want to look at that option later Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName("com.android.phone", "com.android.phone.Settings"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } @@ -65,24 +60,9 @@ public class MobileDataButton extends PowerButton { return filter; } - private static boolean getDataRomingEnabled(Context context) { - return Settings.Secure.getInt(context.getContentResolver(), - Settings.Secure.DATA_ROAMING,0) > 0; - } - - private static boolean getDataState(Context context) { + private boolean getDataState(Context context) { ConnectivityManager cm = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); return cm.getMobileDataEnabled(); } - - public void networkModeChanged(Context context, int networkMode) { - if (STATE_CHANGE_REQUEST) { - ConnectivityManager cm = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - cm.setMobileDataEnabled(true); - STATE_CHANGE_REQUEST=false; - } - } - } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/NetworkModeButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/NetworkModeButton.java index 8aa5e5c..028d49c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/NetworkModeButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/NetworkModeButton.java @@ -36,16 +36,15 @@ public class NetworkModeButton extends PowerButton{ private static final int CM_MODE_3GONLY = 1; private static final int CM_MODE_BOTH = 2; - private static int NETWORK_MODE = NO_NETWORK_MODE_YET; - private static int INTENDED_NETWORK_MODE = NO_NETWORK_MODE_YET; - private static int CURRENT_INTERNAL_STATE = STATE_INTERMEDIATE; + private int mMode = NO_NETWORK_MODE_YET; + private int mIntendedMode = NO_NETWORK_MODE_YET; + private int mInternalState = STATE_INTERMEDIATE; public NetworkModeButton() { mType = BUTTON_NETWORKMODE; } @Override - protected void updateState() { - Context context = mView.getContext(); - NETWORK_MODE = get2G3G(context); + protected void updateState(Context context) { + mMode = get2G3G(context); mState = networkModeToState(context); switch (mState) { @@ -53,7 +52,7 @@ public class NetworkModeButton extends PowerButton{ mIcon = R.drawable.stat_2g3g_off; break; case STATE_ENABLED: - if (NETWORK_MODE == Phone.NT_MODE_WCDMA_ONLY) { + if (mMode == Phone.NT_MODE_WCDMA_ONLY) { mIcon = R.drawable.stat_3g_on; } else { mIcon = R.drawable.stat_2g3g_on; @@ -65,8 +64,8 @@ public class NetworkModeButton extends PowerButton{ // the top dark-gray-or-bright-white logo shows the // user's intent. This is much easier to see in // sunlight. - if (CURRENT_INTERNAL_STATE == STATE_TURNING_ON) { - if (INTENDED_NETWORK_MODE == Phone.NT_MODE_WCDMA_ONLY) { + if (mInternalState == STATE_TURNING_ON) { + if (mIntendedMode == Phone.NT_MODE_WCDMA_ONLY) { mIcon = R.drawable.stat_3g_on; } else { mIcon = R.drawable.stat_2g3g_on; @@ -79,76 +78,67 @@ public class NetworkModeButton extends PowerButton{ } @Override - protected void toggleState() { - Context context = mView.getContext(); + protected void toggleState(Context context) { int currentMode = getCurrentCMMode(context); Intent intent = new Intent(ACTION_MODIFY_NETWORK_MODE); - switch (NETWORK_MODE) { + switch (mMode) { case Phone.NT_MODE_WCDMA_PREF: case Phone.NT_MODE_GSM_UMTS: intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_GSM_ONLY); - CURRENT_INTERNAL_STATE = STATE_TURNING_OFF; - INTENDED_NETWORK_MODE=Phone.NT_MODE_GSM_ONLY; + mInternalState = STATE_TURNING_OFF; + mIntendedMode = Phone.NT_MODE_GSM_ONLY; break; case Phone.NT_MODE_WCDMA_ONLY: - if(currentMode == CM_MODE_3GONLY) { + if (currentMode == CM_MODE_3GONLY) { intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_GSM_ONLY); - CURRENT_INTERNAL_STATE = STATE_TURNING_OFF; - INTENDED_NETWORK_MODE = Phone.NT_MODE_GSM_ONLY; + mInternalState = STATE_TURNING_OFF; + mIntendedMode = Phone.NT_MODE_GSM_ONLY; } else { intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_WCDMA_PREF); - CURRENT_INTERNAL_STATE = STATE_TURNING_ON; - INTENDED_NETWORK_MODE = Phone.NT_MODE_WCDMA_PREF; + mInternalState = STATE_TURNING_ON; + mIntendedMode = Phone.NT_MODE_WCDMA_PREF; } break; case Phone.NT_MODE_GSM_ONLY: - if(currentMode == CM_MODE_3GONLY || currentMode == CM_MODE_BOTH) { + if (currentMode == CM_MODE_3GONLY || currentMode == CM_MODE_BOTH) { intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_WCDMA_ONLY); - CURRENT_INTERNAL_STATE = STATE_TURNING_ON; - INTENDED_NETWORK_MODE = Phone.NT_MODE_WCDMA_ONLY; + mInternalState = STATE_TURNING_ON; + mIntendedMode = Phone.NT_MODE_WCDMA_ONLY; } else { intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_WCDMA_PREF); - CURRENT_INTERNAL_STATE = STATE_TURNING_ON; - INTENDED_NETWORK_MODE = Phone.NT_MODE_WCDMA_PREF; + mInternalState = STATE_TURNING_ON; + mIntendedMode = Phone.NT_MODE_WCDMA_PREF; } break; } - NETWORK_MODE = NETWORK_MODE_UNKNOWN; + mMode = NETWORK_MODE_UNKNOWN; context.sendBroadcast(intent); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { // it may be better to make an Intent action for this or find the appropriate one // we may want to look at that option later Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName("com.android.phone", "com.android.phone.Settings"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } @Override public void onReceive(Context context, Intent intent) { if (intent.getExtras() != null) { - NETWORK_MODE = intent.getExtras().getInt(EXTRA_NETWORK_MODE); + mMode = intent.getExtras().getInt(EXTRA_NETWORK_MODE); //Update to actual state - INTENDED_NETWORK_MODE = NETWORK_MODE; + mIntendedMode = mMode; } //need to clear intermediate states - CURRENT_INTERNAL_STATE = STATE_ENABLED; - - int widgetState = networkModeToState(context); - CURRENT_INTERNAL_STATE = widgetState; - if (widgetState == STATE_ENABLED) { - MobileDataButton mdb = (MobileDataButton)getLoadedButton(BUTTON_MOBILEDATA); - if(mdb != null) { - mdb.networkModeChanged(context, NETWORK_MODE); - } - } + mInternalState = STATE_ENABLED; + mInternalState = networkModeToState(context); } @Override @@ -173,12 +163,12 @@ public class NetworkModeButton extends PowerButton{ return state; } - private static int networkModeToState(Context context) { - if (CURRENT_INTERNAL_STATE == STATE_TURNING_ON || - CURRENT_INTERNAL_STATE == STATE_TURNING_OFF) + private int networkModeToState(Context context) { + if (mInternalState == STATE_TURNING_ON || mInternalState == STATE_TURNING_OFF) { return STATE_INTERMEDIATE; + } - switch(NETWORK_MODE) { + switch (mMode) { case Phone.NT_MODE_WCDMA_PREF: case Phone.NT_MODE_WCDMA_ONLY: case Phone.NT_MODE_GSM_UMTS: @@ -190,7 +180,7 @@ public class NetworkModeButton extends PowerButton{ case Phone.NT_MODE_EVDO_NO_CDMA: case Phone.NT_MODE_GLOBAL: // need to check wtf is going on - Log.d(TAG, "Unexpected network mode (" + NETWORK_MODE + ")"); + Log.d(TAG, "Unexpected network mode (" + mMode + ")"); return STATE_DISABLED; } return STATE_INTERMEDIATE; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerButton.java index a4549bd..4b9750d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerButton.java @@ -3,9 +3,11 @@ package com.android.systemui.statusbar.powerwidget; import com.android.systemui.R; import android.app.ActivityManagerNative; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.graphics.PorterDuff.Mode; @@ -13,14 +15,13 @@ import android.net.Uri; import android.os.Handler; import android.os.Message; import android.os.RemoteException; +import android.os.Vibrator; import android.util.Log; import android.widget.ImageView; import android.provider.Settings; import android.view.View; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; public abstract class PowerButton { public static final String TAG = "PowerButton"; @@ -56,92 +57,64 @@ public abstract class PowerButton { private static final Mode MASK_MODE = Mode.SCREEN; - // this is a list of all of our buttons and their corresponding classes - private static final HashMap<String, Class<? extends PowerButton>> BUTTONS = new HashMap<String, Class<? extends PowerButton>>(); - static { - BUTTONS.put(BUTTON_WIFI, WifiButton.class); - BUTTONS.put(BUTTON_GPS, GPSButton.class); - BUTTONS.put(BUTTON_BLUETOOTH, BluetoothButton.class); - BUTTONS.put(BUTTON_BRIGHTNESS, BrightnessButton.class); - BUTTONS.put(BUTTON_SOUND, SoundButton.class); - BUTTONS.put(BUTTON_SYNC, SyncButton.class); - BUTTONS.put(BUTTON_WIFIAP, WifiApButton.class); - BUTTONS.put(BUTTON_SCREENTIMEOUT, ScreenTimeoutButton.class); - BUTTONS.put(BUTTON_MOBILEDATA, MobileDataButton.class); - BUTTONS.put(BUTTON_LOCKSCREEN, LockScreenButton.class); - BUTTONS.put(BUTTON_NETWORKMODE, NetworkModeButton.class); - BUTTONS.put(BUTTON_AUTOROTATE, AutoRotateButton.class); - BUTTONS.put(BUTTON_AIRPLANE, AirplaneButton.class); - BUTTONS.put(BUTTON_FLASHLIGHT, FlashlightButton.class); - BUTTONS.put(BUTTON_SLEEP, SleepButton.class); - BUTTONS.put(BUTTON_MEDIA_PLAY_PAUSE, MediaPlayPauseButton.class); - BUTTONS.put(BUTTON_MEDIA_PREVIOUS, MediaPreviousButton.class); - BUTTONS.put(BUTTON_MEDIA_NEXT, MediaNextButton.class); - BUTTONS.put(BUTTON_LTE, LTEButton.class); - BUTTONS.put(BUTTON_WIMAX, WimaxButton.class); - } - // this is a list of our currently loaded buttons - private static final HashMap<String, PowerButton> BUTTONS_LOADED = new HashMap<String, PowerButton>(); - protected int mIcon; protected int mState; protected View mView; protected String mType = BUTTON_UNKNOWN; - // a static onclicklistener that can be set to register a callback when ANY button is clicked - private static View.OnClickListener GLOBAL_ON_CLICK_LISTENER = null; + private ImageView mIconView; + private ImageView mIndicatorView; + + private View.OnClickListener mExternalClickListener; + private View.OnLongClickListener mExternalLongClickListener; - // a static onlongclicklistener that can be set to register a callback when ANY button is long clicked - private static View.OnLongClickListener GLOBAL_ON_LONG_CLICK_LISTENER = null; + protected boolean mHapticFeedback; + protected Vibrator mVibrator; + private long[] mClickPattern; + private long[] mLongClickPattern; // we use this to ensure we update our views on the UI thread private Handler mViewUpdateHandler = new Handler() { - public void handleMessage(Message msg) { - // this is only used to update the view, so do it - if(mView != null) { - Context context = mView.getContext(); - Resources res = context.getResources(); - int buttonLayer = R.id.power_widget_button; - int buttonIcon = R.id.power_widget_button_image; - int buttonState = R.id.power_widget_button_indic; - ImageView indic = (ImageView)mView.findViewById(R.id.power_widget_button_indic); - if ((Settings.System.getInt(context.getContentResolver(),Settings.System.EXPANDED_HIDE_INDICATOR, 0)) == 1){ - indic.setVisibility(8); - }else{ - indic.setVisibility(0); - } - updateImageView(buttonIcon, mIcon); - - int sColorMaskBase = res.getColor(android.R.color.holo_blue_light); - int sColorMaskOn = sColorMaskBase; - int sColorMaskOff = (sColorMaskBase & 0x00FFFFFF) | 0x33000000; - int sColorMaskInter = (sColorMaskBase & 0x00FFFFFF) | 0x60000000; - - /* Button State */ - switch(mState) { - case STATE_ENABLED: - updateImageView(buttonState, - res.getDrawable(R.drawable.stat_bgon_custom, sColorMaskOn, MASK_MODE)); - break; - case STATE_DISABLED: - updateImageView(buttonState, - res.getDrawable(R.drawable.stat_bgon_custom, sColorMaskOff, MASK_MODE)); - break; - default: - updateImageView(buttonState, - res.getDrawable(R.drawable.stat_bgon_custom, sColorMaskInter, MASK_MODE)); - break; - } + @Override + public void handleMessage(Message msg) { + if (mIconView != null) { + mIconView.setImageResource(mIcon); + } + if (mIndicatorView != null) { + Context context = mIndicatorView.getContext(); + ContentResolver cr = context.getContentResolver(); + Resources res = context.getResources(); + + boolean visible = Settings.System.getInt(cr, + Settings.System.EXPANDED_HIDE_INDICATOR, 0) != 1; + int colorMask = res.getColor(android.R.color.holo_blue_light); + + mIndicatorView.setVisibility(visible ? View.VISIBLE : View.GONE); + + switch (mState) { + case STATE_ENABLED: + colorMask = (colorMask & 0x00FFFFFF) | 0xA0000000; + break; + case STATE_DISABLED: + colorMask = (colorMask & 0x00FFFFFF) | 0x33000000; + break; + default: + colorMask = (colorMask & 0x00FFFFFF) | 0x60000000; + break; } + + mIndicatorView.setImageDrawable(context.getResources().getDrawable( + R.drawable.stat_bgon_custom, colorMask, MASK_MODE)); } - }; + } + }; - protected abstract void updateState(); - protected abstract void toggleState(); - protected abstract boolean handleLongClick(); + protected abstract void updateState(Context context); + protected abstract void toggleState(Context context); + protected abstract boolean handleLongClick(Context context); - protected void update() { - updateState(); + protected void update(Context context) { + updateState(context); updateView(); } @@ -150,11 +123,18 @@ public abstract class PowerButton { // to broadcast events from the StatusBarService broadcast receiver } - protected void onChangeUri(Uri uri) { + protected void onChangeUri(ContentResolver resolver, Uri uri) { // do nothing as a standard, override this if the button needs to respond // to a changed setting } + /* package */ void setHapticFeedback(boolean enabled, + long[] clickPattern, long[] longClickPattern) { + mHapticFeedback = enabled; + mClickPattern = clickPattern; + mLongClickPattern = longClickPattern; + } + protected IntentFilter getBroadcastIntentFilter() { return new IntentFilter(); } @@ -165,10 +145,17 @@ public abstract class PowerButton { protected void setupButton(View view) { mView = view; - if(mView != null) { + if (mView != null) { mView.setTag(mType); mView.setOnClickListener(mClickListener); mView.setOnLongClickListener(mLongClickListener); + + mIconView = (ImageView) mView.findViewById(R.id.power_widget_button_image); + mIndicatorView = (ImageView) mView.findViewById(R.id.power_widget_button_indic); + mVibrator = (Vibrator) mView.getContext().getSystemService(Context.VIBRATOR_SERVICE); + } else { + mIconView = null; + mIndicatorView = null; } } @@ -176,197 +163,49 @@ public abstract class PowerButton { mViewUpdateHandler.sendEmptyMessage(0); } - private void updateImageView(int id, int resId) { - ImageView imageIcon = (ImageView)mView.findViewById(id); - imageIcon.setImageResource(resId); - } - - private void updateImageView(int id, Drawable resDraw) { - ImageView imageIcon = (ImageView)mView.findViewById(id); - imageIcon.setImageResource(R.drawable.stat_bgon_custom); - imageIcon.setImageDrawable(resDraw); - } - private View.OnClickListener mClickListener = new View.OnClickListener() { public void onClick(View v) { - String type = (String)v.getTag(); - - for(Map.Entry<String, PowerButton> entry : BUTTONS_LOADED.entrySet()) { - if(entry.getKey().equals(type)) { - entry.getValue().toggleState(); - break; - } + if (mHapticFeedback && mClickPattern != null) { + mVibrator.vibrate(mClickPattern, -1); } + toggleState(v.getContext()); + update(v.getContext()); - // call our static listener if it's set - if(GLOBAL_ON_CLICK_LISTENER != null) { - GLOBAL_ON_CLICK_LISTENER.onClick(v); + if (mExternalClickListener != null) { + mExternalClickListener.onClick(v); } } }; private View.OnLongClickListener mLongClickListener = new View.OnLongClickListener() { public boolean onLongClick(View v) { - boolean result = false; - String type = (String)v.getTag(); - for (Map.Entry<String, PowerButton> entry : BUTTONS_LOADED.entrySet()) { - if(entry.getKey().endsWith(type)) { - result = entry.getValue().handleLongClick(); - try { - ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); - } catch (RemoteException e) { - } - break; - } - } - - if(result && GLOBAL_ON_LONG_CLICK_LISTENER != null) { - GLOBAL_ON_LONG_CLICK_LISTENER.onLongClick(v); - } - return result; - } - }; + boolean result = handleLongClick(v.getContext()); - public static boolean loadButton(String key, View view) { - // first make sure we have a valid button - if(BUTTONS.containsKey(key) && view != null) { - synchronized (BUTTONS_LOADED) { - if(BUTTONS_LOADED.containsKey(key)) { - // setup the button again - BUTTONS_LOADED.get(key).setupButton(view); - } else { - try { - // we need to instantiate a new button and add it - PowerButton pb = BUTTONS.get(key).newInstance(); - // set it up - pb.setupButton(view); - // save it - BUTTONS_LOADED.put(key, pb); - } catch(Exception e) { - Log.e(TAG, "Error loading button: " + key, e); - } - } + if (result && mHapticFeedback && mLongClickPattern != null) { + mVibrator.vibrate(mLongClickPattern, -1); } - return true; - } else { - return false; - } - } - public static void unloadButton(String key) { - synchronized (BUTTONS_LOADED) { - // first make sure we have a valid button - if(BUTTONS_LOADED.containsKey(key)) { - // wipe out the button view - BUTTONS_LOADED.get(key).setupButton(null); - // remove the button from our list of loaded ones - BUTTONS_LOADED.remove(key); + try { + ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); + } catch (RemoteException e) { } - } - } - public static void unloadAllButtons() { - synchronized (BUTTONS_LOADED) { - // cycle through setting the buttons to null - for(PowerButton pb : BUTTONS_LOADED.values()) { - pb.setupButton(null); - } - - // clear our list - BUTTONS_LOADED.clear(); - } - } - - public static void updateAllButtons() { - synchronized (BUTTONS_LOADED) { - // cycle through our buttons and update them - for(PowerButton pb : BUTTONS_LOADED.values()) { - pb.update(); - } - } - } - - // glue for broadcast receivers - public static IntentFilter getAllBroadcastIntentFilters() { - IntentFilter filter = new IntentFilter(); - - synchronized(BUTTONS_LOADED) { - for(PowerButton button : BUTTONS_LOADED.values()) { - IntentFilter tmp = button.getBroadcastIntentFilter(); - - // cycle through these actions, and see if we need them - int num = tmp.countActions(); - for(int i = 0; i < num; i++) { - String action = tmp.getAction(i); - if(!filter.hasAction(action)) { - filter.addAction(action); - } - } - } - } - - // return our merged filter - return filter; - } - - // glue for content observation - public static List<Uri> getAllObservedUris() { - List<Uri> uris = new ArrayList<Uri>(); - - synchronized(BUTTONS_LOADED) { - for(PowerButton button : BUTTONS_LOADED.values()) { - List<Uri> tmp = button.getObservedUris(); - - for(Uri uri : tmp) { - if(!uris.contains(uri)) { - uris.add(uri); - } - } - } - } - - return uris; - } - - public static void handleOnReceive(Context context, Intent intent) { - String action = intent.getAction(); - - // cycle through power buttons - synchronized(BUTTONS_LOADED) { - for(PowerButton button : BUTTONS_LOADED.values()) { - // call "onReceive" on those that matter - if(button.getBroadcastIntentFilter().hasAction(action)) { - button.onReceive(context, intent); - } - } - } - } - - public static void handleOnChangeUri(Uri uri) { - synchronized(BUTTONS_LOADED) { - for(PowerButton button : BUTTONS_LOADED.values()) { - if(button.getObservedUris().contains(uri)) { - button.onChangeUri(uri); - } + if (result && mExternalLongClickListener != null) { + mExternalLongClickListener.onLongClick(v); } + return result; } - } + }; - public static void setGlobalOnClickListener(View.OnClickListener listener) { - GLOBAL_ON_CLICK_LISTENER = listener; + void setExternalClickListener(View.OnClickListener listener) { + mExternalClickListener = listener; } - public static void setGlobalOnLongClickListener(View.OnLongClickListener listener) { - GLOBAL_ON_LONG_CLICK_LISTENER = listener; + void setExternalLongClickListener(View.OnLongClickListener listener) { + mExternalLongClickListener = listener; } - protected static PowerButton getLoadedButton(String key) { - synchronized(BUTTONS_LOADED) { - if(BUTTONS_LOADED.containsKey(key)) { - return BUTTONS_LOADED.get(key); - } else { - return null; - } - } + protected SharedPreferences getPreferences(Context context) { + return context.getSharedPreferences("PowerButton-" + mType, Context.MODE_PRIVATE); } } 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 251d62a..5f8f91f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerWidget.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/PowerWidget.java @@ -41,6 +41,8 @@ import com.android.systemui.R; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; public class PowerWidget extends FrameLayout { private static final String TAG = "PowerWidget"; @@ -65,41 +67,98 @@ public class PowerWidget extends FrameLayout { private static final int LAYOUT_SCROLL_BUTTON_THRESHOLD = 6; + // this is a list of all possible buttons and their corresponding classes + private static final HashMap<String, Class<? extends PowerButton>> sPossibleButtons = + new HashMap<String, Class<? extends PowerButton>>(); + + static { + sPossibleButtons.put(PowerButton.BUTTON_WIFI, WifiButton.class); + sPossibleButtons.put(PowerButton.BUTTON_GPS, GPSButton.class); + sPossibleButtons.put(PowerButton.BUTTON_BLUETOOTH, BluetoothButton.class); + sPossibleButtons.put(PowerButton.BUTTON_BRIGHTNESS, BrightnessButton.class); + sPossibleButtons.put(PowerButton.BUTTON_SOUND, SoundButton.class); + sPossibleButtons.put(PowerButton.BUTTON_SYNC, SyncButton.class); + sPossibleButtons.put(PowerButton.BUTTON_WIFIAP, WifiApButton.class); + sPossibleButtons.put(PowerButton.BUTTON_SCREENTIMEOUT, ScreenTimeoutButton.class); + sPossibleButtons.put(PowerButton.BUTTON_MOBILEDATA, MobileDataButton.class); + sPossibleButtons.put(PowerButton.BUTTON_LOCKSCREEN, LockScreenButton.class); + sPossibleButtons.put(PowerButton.BUTTON_NETWORKMODE, NetworkModeButton.class); + sPossibleButtons.put(PowerButton.BUTTON_AUTOROTATE, AutoRotateButton.class); + sPossibleButtons.put(PowerButton.BUTTON_AIRPLANE, AirplaneButton.class); + sPossibleButtons.put(PowerButton.BUTTON_FLASHLIGHT, FlashlightButton.class); + sPossibleButtons.put(PowerButton.BUTTON_SLEEP, SleepButton.class); + sPossibleButtons.put(PowerButton.BUTTON_MEDIA_PLAY_PAUSE, MediaPlayPauseButton.class); + sPossibleButtons.put(PowerButton.BUTTON_MEDIA_PREVIOUS, MediaPreviousButton.class); + sPossibleButtons.put(PowerButton.BUTTON_MEDIA_NEXT, MediaNextButton.class); + sPossibleButtons.put(PowerButton.BUTTON_WIMAX, WimaxButton.class); + sPossibleButtons.put(PowerButton.BUTTON_LTE, LTEButton.class); + } + + // this is a list of our currently loaded buttons + private final HashMap<String, PowerButton> mButtons = new HashMap<String, PowerButton>(); + private final ArrayList<String> mButtonNames = new ArrayList<String>(); + + private View.OnClickListener mAllButtonClickListener; + private View.OnLongClickListener mAllButtonLongClickListener; + private Context mContext; + private Handler mHandler; private LayoutInflater mInflater; private WidgetBroadcastReceiver mBroadcastReceiver = null; private WidgetSettingsObserver mObserver = null; + private long[] mShortPressVibePattern; + private long[] mLongPressVibePattern; + + private LinearLayout mButtonLayout; private HorizontalScrollView mScrollView; public PowerWidget(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; + mHandler = new Handler(); mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mShortPressVibePattern = getLongIntArray(mContext.getResources(), + com.android.internal.R.array.config_virtualKeyVibePattern); + mLongPressVibePattern = getLongIntArray(mContext.getResources(), + com.android.internal.R.array.config_longPressVibePattern); + // get an initial width updateButtonLayoutWidth(); setupWidget(); updateVisibility(); } + static long[] getLongIntArray(Resources r, int resid) { + int[] ar = r.getIntArray(resid); + if (ar == null) { + return null; + } + long[] out = new long[ar.length]; + for (int i=0; i < ar.length; i++) { + out[i] = ar[i]; + } + return out; + } + public void destroyWidget() { Log.i(TAG, "Clearing any old widget stuffs"); // remove all views from the layout removeAllViews(); // unregister our content receiver - if(mBroadcastReceiver != null) { + if (mBroadcastReceiver != null) { mContext.unregisterReceiver(mBroadcastReceiver); } // unobserve our content - if(mObserver != null) { + if (mObserver != null) { mObserver.unobserve(); } // clear the button instances - PowerButton.unloadAllButtons(); + unloadAllButtons(); } public void setupWidget() { @@ -108,7 +167,7 @@ public class PowerWidget extends FrameLayout { Log.i(TAG, "Setting up widget"); String buttons = Settings.System.getString(mContext.getContentResolver(), Settings.System.WIDGET_BUTTONS); - if(buttons == null) { + if (buttons == null) { Log.i(TAG, "Default buttons being loaded"); buttons = BUTTONS_DEFAULT; // Add the WiMAX button if it's supported @@ -118,28 +177,95 @@ public class PowerWidget extends FrameLayout { } Log.i(TAG, "Button list: " + buttons); - // create a linearlayout to hold our buttons - LinearLayout ll = new LinearLayout(mContext); - ll.setOrientation(LinearLayout.HORIZONTAL); - ll.setGravity(Gravity.CENTER_HORIZONTAL); - - int buttonCount = 0; - for(String button : buttons.split("\\|")) { - Log.i(TAG, "Setting up button: " + button); - // inflate our button, we don't add it to a parent and don't do any layout shit yet - View buttonView = mInflater.inflate(R.layout.power_widget_button, null, false); - - if(PowerButton.loadButton(button, buttonView)) { - // add the button here - ll.addView(buttonView, BUTTON_LAYOUT_PARAMS); - buttonCount++; + for (String button : buttons.split("\\|")) { + if (loadButton(button)) { + mButtonNames.add(button); } else { Log.e(TAG, "Error setting up button: " + button); } } + recreateButtonLayout(); + updateHapticFeedbackSetting(); + + // set up a broadcast receiver for our intents, based off of what our power buttons have been loaded + setupBroadcastReceiver(); + IntentFilter filter = getMergedBroadcastIntentFilter(); + // we add this so we can update views and such if the settings for our widget change + filter.addAction(Settings.SETTINGS_CHANGED); + // we need to detect orientation changes and update the static button width value appropriately + filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); + // register the receiver + mContext.registerReceiver(mBroadcastReceiver, filter); + // register our observer + mObserver = new WidgetSettingsObserver(mHandler); + mObserver.observe(); + } + + private boolean loadButton(String key) { + // first make sure we have a valid button + if (!sPossibleButtons.containsKey(key)) { + return false; + } + + if (mButtons.containsKey(key)) { + return true; + } + + try { + // we need to instantiate a new button and add it + PowerButton pb = sPossibleButtons.get(key).newInstance(); + pb.setExternalClickListener(mAllButtonClickListener); + pb.setExternalLongClickListener(mAllButtonLongClickListener); + // save it + mButtons.put(key, pb); + } catch (Exception e) { + Log.e(TAG, "Error loading button: " + key, e); + return false; + } + + return true; + } + + private void unloadButton(String key) { + // first make sure we have a valid button + if (mButtons.containsKey(key)) { + // wipe out the button view + mButtons.get(key).setupButton(null); + // remove the button from our list of loaded ones + mButtons.remove(key); + } + } + + private void unloadAllButtons() { + // cycle through setting the buttons to null + for (PowerButton pb : mButtons.values()) { + pb.setupButton(null); + } + + // clear our list + mButtons.clear(); + mButtonNames.clear(); + } + + private void recreateButtonLayout() { + removeAllViews(); + + // create a linearlayout to hold our buttons + mButtonLayout = new LinearLayout(mContext); + mButtonLayout.setOrientation(LinearLayout.HORIZONTAL); + mButtonLayout.setGravity(Gravity.CENTER_HORIZONTAL); + + for (String button : mButtonNames) { + PowerButton pb = mButtons.get(button); + if (pb != null) { + View buttonView = mInflater.inflate(R.layout.power_widget_button, null, false); + pb.setupButton(buttonView); + mButtonLayout.addView(buttonView, BUTTON_LAYOUT_PARAMS); + } + } // we determine if we're using a horizontal scroll view based on a threshold of button counts - if(buttonCount > LAYOUT_SCROLL_BUTTON_THRESHOLD) { + if (mButtonLayout.getChildCount() > LAYOUT_SCROLL_BUTTON_THRESHOLD) { // we need our horizontal scroll view to wrap the linear layout mScrollView = new HorizontalScrollView(mContext); // make the fading edge the size of a button (makes it more noticible that we can scroll @@ -147,50 +273,78 @@ public class PowerWidget extends FrameLayout { 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 - ll.setPadding(ll.getPaddingLeft(), ll.getPaddingTop(), ll.getPaddingRight(), mScrollView.getVerticalScrollbarWidth()); - mScrollView.addView(ll, WIDGET_LAYOUT_PARAMS); + mButtonLayout.setPadding(mButtonLayout.getPaddingLeft(), + mButtonLayout.getPaddingTop(), + mButtonLayout.getPaddingRight(), + mScrollView.getVerticalScrollbarWidth()); + mScrollView.addView(mButtonLayout, WIDGET_LAYOUT_PARAMS); updateScrollbar(); addView(mScrollView, WIDGET_LAYOUT_PARAMS); } else { // not needed, just add the linear layout - addView(ll, WIDGET_LAYOUT_PARAMS); + addView(mButtonLayout, WIDGET_LAYOUT_PARAMS); } + } - // set up a broadcast receiver for our intents, based off of what our power buttons have been loaded - setupBroadcastReceiver(); - IntentFilter filter = PowerButton.getAllBroadcastIntentFilters(); - // we add this so we can update views and such if the settings for our widget change - filter.addAction(Settings.SETTINGS_CHANGED); - // we need to detect orientation changes and update the static button width value appropriately - filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); - // register the receiver - mContext.registerReceiver(mBroadcastReceiver, filter); - // register our observer - if(mObserver != null) { - mObserver.observe(); + public void updateAllButtons() { + // cycle through our buttons and update them + for (PowerButton pb : mButtons.values()) { + pb.update(mContext); } } - public void updateWidget() { - PowerButton.updateAllButtons(); + private IntentFilter getMergedBroadcastIntentFilter() { + IntentFilter filter = new IntentFilter(); + + for (PowerButton button : mButtons.values()) { + IntentFilter tmp = button.getBroadcastIntentFilter(); + + // cycle through these actions, and see if we need them + int num = tmp.countActions(); + for (int i = 0; i < num; i++) { + String action = tmp.getAction(i); + if(!filter.hasAction(action)) { + filter.addAction(action); + } + } + } + + // return our merged filter + return filter; } - public void setupSettingsObserver(Handler handler) { - if(mObserver == null) { - mObserver = new WidgetSettingsObserver(handler); + private List<Uri> getAllObservedUris() { + List<Uri> uris = new ArrayList<Uri>(); + + for (PowerButton button : mButtons.values()) { + List<Uri> tmp = button.getObservedUris(); + + for (Uri uri : tmp) { + if (!uris.contains(uri)) { + uris.add(uri); + } + } } + + return uris; } public void setGlobalButtonOnClickListener(View.OnClickListener listener) { - PowerButton.setGlobalOnClickListener(listener); + mAllButtonClickListener = listener; + for (PowerButton pb : mButtons.values()) { + pb.setExternalClickListener(listener); + } } public void setGlobalButtonOnLongClickListener(View.OnLongClickListener listener) { - PowerButton.setGlobalOnLongClickListener(listener); + mAllButtonLongClickListener = listener; + for (PowerButton pb : mButtons.values()) { + pb.setExternalLongClickListener(listener); + } } private void setupBroadcastReceiver() { - if(mBroadcastReceiver == null) { + if (mBroadcastReceiver == null) { mBroadcastReceiver = new WidgetBroadcastReceiver(); } } @@ -218,19 +372,50 @@ public class PowerWidget extends FrameLayout { mScrollView.setHorizontalScrollBarEnabled(!hideScrollBar); } + private void updateHapticFeedbackSetting() { + ContentResolver cr = mContext.getContentResolver(); + int expandedHapticFeedback = Settings.System.getInt(cr, + Settings.System.EXPANDED_HAPTIC_FEEDBACK, 2); + long[] clickPattern = null, longClickPattern = null; + boolean hapticFeedback; + + if (expandedHapticFeedback == 2) { + hapticFeedback = Settings.System.getInt(cr, + Settings.System.HAPTIC_FEEDBACK_ENABLED, 1) == 1; + } else { + hapticFeedback = (expandedHapticFeedback == 1); + } + + if (hapticFeedback) { + clickPattern = mShortPressVibePattern; + longClickPattern = mLongPressVibePattern; + } + + for (PowerButton button : mButtons.values()) { + button.setHapticFeedback(hapticFeedback, clickPattern, longClickPattern); + } + } + // our own broadcast receiver :D private class WidgetBroadcastReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { - if(intent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) { + String action = intent.getAction(); + + if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { updateButtonLayoutWidth(); - setupWidget(); + recreateButtonLayout(); } else { // handle the intent through our power buttons - PowerButton.handleOnReceive(context, intent); + for (PowerButton button : mButtons.values()) { + // call "onReceive" on those that matter + if (button.getBroadcastIntentFilter().hasAction(action)) { + button.onReceive(context, intent); + } + } } // update our widget - updateWidget(); + updateAllButtons(); } }; @@ -257,6 +442,9 @@ public class PowerWidget extends FrameLayout { resolver.registerContentObserver( Settings.System.getUriFor(Settings.System.EXPANDED_HAPTIC_FEEDBACK), false, this); + resolver.registerContentObserver( + Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED), + false, this); // watch for changes in buttons resolver.registerContentObserver( @@ -274,7 +462,7 @@ public class PowerWidget extends FrameLayout { false, this); // watch for power-button specifc stuff that has been loaded - for(Uri uri : PowerButton.getAllObservedUris()) { + for(Uri uri : getAllObservedUris()) { resolver.registerContentObserver(uri, false, this); } } @@ -301,11 +489,20 @@ public class PowerWidget extends FrameLayout { updateScrollbar(); } + if (uri.equals(Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED)) + || uri.equals(Settings.System.getUriFor(Settings.System.EXPANDED_HAPTIC_FEEDBACK))) { + updateHapticFeedbackSetting(); + } + // do whatever the individual buttons must - PowerButton.handleOnChangeUri(uri); + for (PowerButton button : mButtons.values()) { + if (button.getObservedUris().contains(uri)) { + button.onChangeUri(resolver, uri); + } + } // something happened so update the widget - updateWidget(); + updateAllButtons(); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/ScreenTimeoutButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/ScreenTimeoutButton.java index acac53e..70a0d87 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/ScreenTimeoutButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/ScreenTimeoutButton.java @@ -5,9 +5,11 @@ import com.android.systemui.R; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.res.Resources; import android.net.Uri; import android.provider.Settings; import android.view.Gravity; +import android.view.View; import android.widget.Toast; import java.util.ArrayList; @@ -26,7 +28,7 @@ public class ScreenTimeoutButton extends PowerButton { private static final int CM_MODE_15_60_300 = 0; private static final int CM_MODE_30_120_300 = 1; - private static Toast TOAST = null; + private Toast mToast = null; private static final List<Uri> OBSERVED_URIS = new ArrayList<Uri>(); static { @@ -36,8 +38,17 @@ public class ScreenTimeoutButton extends PowerButton { public ScreenTimeoutButton() { mType = BUTTON_SCREENTIMEOUT; } @Override - protected void updateState() { - int timeout=getScreenTtimeout(mView.getContext()); + protected void setupButton(View view) { + super.setupButton(view); + if (view == null && mToast != null) { + mToast.cancel(); + mToast = null; + } + } + + @Override + protected void updateState(Context context) { + int timeout = getScreenTimeout(context); if (timeout <= SCREEN_TIMEOUT_LOW) { mIcon = R.drawable.stat_screen_timeout_off; @@ -52,59 +63,56 @@ public class ScreenTimeoutButton extends PowerButton { } @Override - protected void toggleState() { - Context context = mView.getContext(); - int screentimeout = getScreenTtimeout(context); + protected void toggleState(Context context) { + int screenTimeout = getScreenTimeout(context); int currentMode = getCurrentCMMode(context); - if (screentimeout < SCREEN_TIMEOUT_MIN) { + if (screenTimeout < SCREEN_TIMEOUT_MIN) { if (currentMode == CM_MODE_15_60_300) { - screentimeout = SCREEN_TIMEOUT_MIN; + screenTimeout = SCREEN_TIMEOUT_MIN; } else { - screentimeout = SCREEN_TIMEOUT_LOW; + screenTimeout = SCREEN_TIMEOUT_LOW; } - } else if (screentimeout < SCREEN_TIMEOUT_LOW) { + } else if (screenTimeout < SCREEN_TIMEOUT_LOW) { if (currentMode == CM_MODE_15_60_300) { - screentimeout = SCREEN_TIMEOUT_NORMAL; + screenTimeout = SCREEN_TIMEOUT_NORMAL; } else { - screentimeout = SCREEN_TIMEOUT_LOW; + screenTimeout = SCREEN_TIMEOUT_LOW; } - } else if (screentimeout < SCREEN_TIMEOUT_NORMAL) { + } else if (screenTimeout < SCREEN_TIMEOUT_NORMAL) { if (currentMode == CM_MODE_15_60_300) { - screentimeout = SCREEN_TIMEOUT_NORMAL; + screenTimeout = SCREEN_TIMEOUT_NORMAL; } else { - screentimeout = SCREEN_TIMEOUT_HIGH; + screenTimeout = SCREEN_TIMEOUT_HIGH; } - } else if (screentimeout < SCREEN_TIMEOUT_HIGH) { + } else if (screenTimeout < SCREEN_TIMEOUT_HIGH) { if (currentMode == CM_MODE_15_60_300) { - screentimeout = SCREEN_TIMEOUT_MAX; + screenTimeout = SCREEN_TIMEOUT_MAX; } else { - screentimeout = SCREEN_TIMEOUT_HIGH; + screenTimeout = SCREEN_TIMEOUT_HIGH; } - } else if (screentimeout < SCREEN_TIMEOUT_MAX) { - screentimeout = SCREEN_TIMEOUT_MAX; + } else if (screenTimeout < SCREEN_TIMEOUT_MAX) { + screenTimeout = SCREEN_TIMEOUT_MAX; } else if (currentMode == CM_MODE_30_120_300) { - screentimeout = SCREEN_TIMEOUT_LOW; + screenTimeout = SCREEN_TIMEOUT_LOW; } else { - screentimeout = SCREEN_TIMEOUT_MIN; + screenTimeout = SCREEN_TIMEOUT_MIN; } Settings.System.putInt( context.getContentResolver(), - Settings.System.SCREEN_OFF_TIMEOUT, screentimeout); - - // create our toast - if(TOAST == null) { - TOAST = Toast.makeText(context, "", Toast.LENGTH_LONG); - } + Settings.System.SCREEN_OFF_TIMEOUT, screenTimeout); // cancel any previous toast - TOAST.cancel(); + if (mToast != null) { + mToast.cancel(); + } // inform users of how long the timeout is now - TOAST.setText("Screen timeout set to: " + timeoutToString(screentimeout)); - TOAST.setGravity(Gravity.CENTER, TOAST.getXOffset() / 2, TOAST.getYOffset() / 2); - TOAST.show(); + final String toast = makeTimeoutToastString(context, screenTimeout); + mToast = Toast.makeText(context, toast, Toast.LENGTH_LONG); + mToast.setGravity(Gravity.CENTER, mToast.getXOffset() / 2, mToast.getYOffset() / 2); + mToast.show(); } @Override @@ -113,39 +121,51 @@ public class ScreenTimeoutButton extends PowerButton { } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.DISPLAY_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } - private static int getScreenTtimeout(Context context) { + private String makeTimeoutToastString(Context context, int timeout) { + Resources res = context.getResources(); + int resId; + + /* ms -> seconds */ + timeout /= 1000; + + if (timeout >= 60 && timeout % 60 == 0) { + /* seconds -> minutes */ + timeout /= 60; + if (timeout >= 60 && timeout % 60 == 0) { + /* minutes -> hours */ + timeout /= 60; + resId = timeout == 1 + ? com.android.internal.R.string.hour + : com.android.internal.R.string.hours; + } else { + resId = timeout == 1 + ? com.android.internal.R.string.minute + : com.android.internal.R.string.minutes; + } + } else { + resId = timeout == 1 + ? com.android.internal.R.string.second + : com.android.internal.R.string.seconds; + } + + return res.getString(R.string.powerwidget_screen_timeout_toast, + timeout, res.getString(resId)); + } + + private static int getScreenTimeout(Context context) { return Settings.System.getInt( context.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 0); } - private static String timeoutToString(int timeout) { - String[] tags = new String[] { - "second(s)", - "minute(s)", - "hour(s)" - }; - - // default to however many seconds we have - int tmp = (timeout / 1000); - String sTimeout = tmp + " " + tags[0]; - - for(int i = 1; i < tags.length && tmp >= 60; i++) { - tmp /= (60 * i); - sTimeout = tmp + " " + tags[i]; - } - - return sTimeout; - } - private static int getCurrentCMMode(Context context) { return Settings.System.getInt(context.getContentResolver(), Settings.System.EXPANDED_SCREENTIMEOUT_MODE, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SleepButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SleepButton.java index 61fecc9..65f3963 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SleepButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SleepButton.java @@ -13,24 +13,24 @@ public class SleepButton extends PowerButton { public SleepButton() { mType = BUTTON_SLEEP; } @Override - protected void updateState() { + protected void updateState(Context context) { mIcon = R.drawable.stat_sleep; mState = STATE_DISABLED; } @Override - protected void toggleState() { - PowerManager pm = (PowerManager)mView.getContext() - .getSystemService(Context.POWER_SERVICE); + protected void toggleState(Context context) { + PowerManager pm = (PowerManager) + context.getSystemService(Context.POWER_SERVICE); pm.goToSleep(SystemClock.uptimeMillis() + 1); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.DISPLAY_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SoundButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SoundButton.java index 20b96a6..f248377 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SoundButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SoundButton.java @@ -9,7 +9,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.net.Uri; -import android.os.Vibrator; import android.preference.ListPreferenceMultiSelect; import android.provider.Settings; import android.view.View; @@ -21,7 +20,7 @@ public class SoundButton extends PowerButton { private static final String TAG = "SoundButton"; - private static final int VIBRATE_DURATION = 500; // 0.5s + private static final int VIBRATE_DURATION = 250; // 0.25s private static final IntentFilter INTENT_FILTER = new IntentFilter(); static { @@ -32,8 +31,6 @@ public class SoundButton extends PowerButton { private static final List<Uri> OBSERVED_URIS = new ArrayList<Uri>(); static { OBSERVED_URIS.add(Settings.System.getUriFor(Settings.System.EXPANDED_RING_MODE)); - OBSERVED_URIS.add(Settings.System.getUriFor(Settings.System.EXPANDED_HAPTIC_FEEDBACK)); - OBSERVED_URIS.add(Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED)); } private final Ringer mSilentRinger = new Ringer(false, AudioManager.VIBRATE_SETTING_OFF, @@ -54,10 +51,7 @@ public class SoundButton extends PowerButton { }; private int mRingerValuesIndex = 2; - private boolean mHapticFeedbackEnabled = false; - private AudioManager mAudioManager; - private Vibrator mVibrator; public SoundButton() { mType = BUTTON_SOUND; @@ -68,15 +62,13 @@ public class SoundButton extends PowerButton { super.setupButton(view); if (mView != null) { Context context = mView.getContext(); - mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); - updateSettings(); + updateSettings(context.getContentResolver()); } } @Override - protected void updateState() { - findCurrentState(); + protected void updateState(Context context) { + findCurrentState(context); switch (mRingersIndex) { case 0: mIcon = R.drawable.stat_silent; @@ -104,7 +96,7 @@ public class SoundButton extends PowerButton { } @Override - protected void toggleState() { + protected void toggleState(Context context) { mRingerValuesIndex++; if (mRingerValuesIndex > mRingerValues.length - 1) { mRingerValuesIndex = 0; @@ -114,21 +106,21 @@ public class SoundButton extends PowerButton { mRingersIndex = 0; } Ringer ringer = mRingers[mRingersIndex]; - ringer.execute(); + ringer.execute(context); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.SOUND_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } @Override - protected void onChangeUri(Uri uri) { - updateSettings(); + protected void onChangeUri(ContentResolver cr, Uri uri) { + updateSettings(cr); } @Override @@ -141,18 +133,7 @@ public class SoundButton extends PowerButton { return INTENT_FILTER; } - private void updateSettings() { - ContentResolver resolver = mView.getContext().getContentResolver(); - - int expandedHapticFeedback = Settings.System.getInt(resolver, - Settings.System.EXPANDED_HAPTIC_FEEDBACK, 2); - if (expandedHapticFeedback == 2) { - mHapticFeedbackEnabled = (Settings.System.getInt(resolver, - Settings.System.HAPTIC_FEEDBACK_ENABLED, 1) == 1); - } else { - mHapticFeedbackEnabled = (expandedHapticFeedback == 1); - } - + private void updateSettings(ContentResolver resolver) { String[] modes = ListPreferenceMultiSelect.parseStoredValue(Settings.System.getString( resolver, Settings.System.EXPANDED_RING_MODE)); if (modes == null || modes.length == 0) { @@ -165,13 +146,12 @@ public class SoundButton extends PowerButton { mRingerValues[i] = Integer.valueOf(modes[i]); } } - - updateState(); } - private void findCurrentState() { - ContentResolver resolver = mView.getContext().getContentResolver(); - boolean vibrateInSilent = Settings.System.getInt(resolver, + private void findCurrentState(Context context) { + ensureAudioManager(context); + + boolean vibrateInSilent = Settings.System.getInt(context.getContentResolver(), Settings.System.VIBRATE_IN_SILENT, 0) == 1; int vibrateSetting = mAudioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); int ringerMode = mAudioManager.getRingerMode(); @@ -198,8 +178,13 @@ public class SoundButton extends PowerButton { } } - private class Ringer { + private void ensureAudioManager(Context context) { + if (mAudioManager == null) { + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + } + } + private class Ringer { final boolean mVibrateInSilent; final int mVibrateSetting; final int mRingerMode; @@ -212,13 +197,15 @@ public class SoundButton extends PowerButton { mDoHapticFeedback = doHapticFeedback; } - void execute() { - ContentResolver resolver = mView.getContext().getContentResolver(); + void execute(Context context) { + ContentResolver resolver = context.getContentResolver(); Settings.System.putInt(resolver, Settings.System.VIBRATE_IN_SILENT, (mVibrateInSilent ? 1 : 0)); + + ensureAudioManager(context); mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, mVibrateSetting); mAudioManager.setRingerMode(mRingerMode); - if (mDoHapticFeedback && mHapticFeedbackEnabled) { + if (mDoHapticFeedback && mHapticFeedback) { mVibrator.vibrate(VIBRATE_DURATION); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SyncButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SyncButton.java index 81167c2..3c5f547 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SyncButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/SyncButton.java @@ -18,7 +18,9 @@ public class SyncButton extends PowerButton { private SyncStatusObserver mSyncObserver = new SyncStatusObserver() { public void onStatusChanged(int which) { // update state/view if something happened - update(); + if (mView != null) { + update(mView.getContext()); + } } }; private Object mSyncObserverHandle = null; @@ -38,8 +40,8 @@ public class SyncButton extends PowerButton { } @Override - protected void updateState() { - if (getSyncState(mView.getContext())) { + protected void updateState(Context context) { + if (getSyncState(context)) { mIcon = R.drawable.stat_sync_on; mState = STATE_ENABLED; } else { @@ -49,10 +51,9 @@ public class SyncButton extends PowerButton { } @Override - protected void toggleState() { - Context context = mView.getContext(); - ConnectivityManager connManager = (ConnectivityManager)context - .getSystemService(Context.CONNECTIVITY_SERVICE); + protected void toggleState(Context context) { + ConnectivityManager connManager = (ConnectivityManager) + context.getSystemService(Context.CONNECTIVITY_SERVICE); boolean backgroundData = getBackgroundDataState(context); boolean sync = ContentResolver.getMasterSyncAutomatically(); @@ -82,21 +83,21 @@ public class SyncButton extends PowerButton { } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.SYNC_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } - private static boolean getBackgroundDataState(Context context) { - ConnectivityManager connManager = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); + private boolean getBackgroundDataState(Context context) { + ConnectivityManager connManager = (ConnectivityManager) + context.getSystemService(Context.CONNECTIVITY_SERVICE); return connManager.getBackgroundDataSetting(); } - private static boolean getSyncState(Context context) { + private boolean getSyncState(Context context) { boolean backgroundData = getBackgroundDataState(context); boolean sync = ContentResolver.getMasterSyncAutomatically(); return backgroundData && sync; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WifiApButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WifiApButton.java index 3df4578..f90fb87 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WifiApButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WifiApButton.java @@ -99,8 +99,8 @@ public class WifiApButton extends PowerButton { public WifiApButton() { mType = BUTTON_WIFIAP; } @Override - protected void updateState() { - mState = sWifiApState.getTriState(mView.getContext()); + protected void updateState(Context context) { + mState = sWifiApState.getTriState(context); switch (mState) { case STATE_DISABLED: mIcon = R.drawable.stat_wifi_ap_off; @@ -124,18 +124,18 @@ public class WifiApButton extends PowerButton { } @Override - protected void toggleState() { - sWifiApState.toggleState(mView.getContext()); + protected void toggleState(Context context) { + sWifiApState.toggleState(context); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { // it may be better to make an Intent action for the WifiAp settings // we may want to look at that option later Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName("com.android.settings", "com.android.settings.TetherSettings"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WifiButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WifiButton.java index bc0aca9..b55ba36 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WifiButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WifiButton.java @@ -95,8 +95,8 @@ public class WifiButton extends PowerButton{ public WifiButton() { mType = BUTTON_WIFI; } @Override - protected void updateState() { - mState = sWifiState.getTriState(mView.getContext()); + protected void updateState(Context context) { + mState = sWifiState.getTriState(context); switch (mState) { case STATE_DISABLED: mIcon = R.drawable.stat_wifi_off; @@ -120,16 +120,16 @@ public class WifiButton extends PowerButton{ } @Override - protected void toggleState() { - sWifiState.toggleState(mView.getContext()); + protected void toggleState(Context context) { + sWifiState.toggleState(context); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.settings.WIFI_SETTINGS"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WimaxButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WimaxButton.java index f4f9f9d..6f065b5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WimaxButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/powerwidget/WimaxButton.java @@ -105,8 +105,8 @@ public class WimaxButton extends PowerButton { public WimaxButton() { mType = BUTTON_WIMAX; } @Override - protected void updateState() { - mState = sWimaxState.getTriState(mView.getContext()); + protected void updateState(Context context) { + mState = sWimaxState.getTriState(context); switch (mState) { case STATE_DISABLED: mIcon = R.drawable.stat_wimax_off; @@ -130,17 +130,17 @@ public class WimaxButton extends PowerButton { } @Override - protected void toggleState() { - sWimaxState.toggleState(mView.getContext()); + protected void toggleState(Context context) { + sWimaxState.toggleState(context); } @Override - protected boolean handleLongClick() { + protected boolean handleLongClick(Context context) { Intent intent = new Intent("android.intent.action.MAIN"); intent.setClassName("com.android.settings.wimax", "com.android.settings.wimax.WimaxSettings"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mView.getContext().startActivity(intent); + context.startActivity(intent); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java index d0f9449..0432ffa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java @@ -31,6 +31,8 @@ import android.widget.LinearLayout; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Switch; +import android.view.LayoutInflater; import com.android.systemui.R; import com.android.systemui.statusbar.policy.AirplaneModeController; @@ -51,7 +53,6 @@ public class SettingsView extends LinearLayout implements View.OnClickListener { static final String TAG = "SettingsView"; private static final String NO_TOGGLES = "no_toggles"; - private static final int[] TOGGLE_ID_ARRAY = new int[6]; private static final int AIRPLANE_ID = 0; private static final int ROTATE_ID = 1; private static final int BLUETOOTH_ID = 2; @@ -62,15 +63,6 @@ public class SettingsView extends LinearLayout implements View.OnClickListener { private static final int NETWORK_MODE_ID = 7; private static final int SOUND_ID = 8; - private static final int[] mToggleIds = new int[]{ - R.id.toggle_1, R.id.toggle_2, R.id.toggle_3, R.id.toggle_4, R.id.toggle_5, R.id.toggle_6}; - private static final int[] mToggleIcons = new int[]{ - R.id.toggle_1_icon, R.id.toggle_2_icon, R.id.toggle_3_icon, R.id.toggle_4_icon, R.id.toggle_5_icon, R.id.toggle_6_icon}; - private static final int[] mToggleLabels = new int[]{ - R.id.toggle_1_label, R.id.toggle_2_label, R.id.toggle_3_label, R.id.toggle_4_label, R.id.toggle_5_label, R.id.toggle_6_label}; - private static final int[] mToggleCheckBoxes = new int[]{ - R.id.toggle_1_checkbox, R.id.toggle_2_checkbox, R.id.toggle_3_checkbox, R.id.toggle_4_checkbox, R.id.toggle_5_checkbox, R.id.toggle_6_checkbox}; - private static final String[] KEY_TOGGLES = new String[]{"pref_airplane_toggle", "pref_rotate_toggle", "pref_bluetooth_toggle", "pref_gps_toggle", "pref_wifi_toggle", "pref_flashlight_toggle", "pref_mobile_data_toggle", "pref_network_mode_toggle", "pref_sound_toggle"}; private static final String BUTTON_DELIMITER = "\\|"; @@ -118,6 +110,13 @@ public class SettingsView extends LinearLayout implements View.OnClickListener { } } + private class ButtonTag { + public int toggleId; + public ButtonTag(int id) { + toggleId = id; + } + } + public SettingsView(Context context, AttributeSet attrs) { this(context, attrs, 0); } @@ -141,33 +140,46 @@ public class SettingsView extends LinearLayout implements View.OnClickListener { mToggleContainer = BUTTONS_DEFAULT; if(!mToggleContainer.equals(NO_TOGGLES)){ updateToggles(); - - int mLastVisible = mToggles.length; - for(int i=0; i<mToggleIds.length; i++){ - if(i<mLastVisible) - findViewById(mToggleIds[i]).setOnClickListener(this); - else - findViewById(mToggleIds[i]).setVisibility(View.GONE); - } - } else { - for(int i=0; i<mToggleIds.length; i++){ - findViewById(mToggleIds[i]).setVisibility(View.GONE); - } } findViewById(R.id.settings).setOnClickListener(this); } - private void updateToggles(){ + private void clearToggles() { + for (int i = getChildCount() - 1; i >= 0; i--) { + View v = getChildAt(i); + if (v.getTag() instanceof ButtonTag) + removeView(v); + } + } + + private void updateToggles(){ + clearToggleControllers(); + clearToggles(); mToggles = mToggleContainer.split("\\|"); - for(int i=0; i<mToggles.length; i++){ + for(int i=mToggles.length - 1; i>=0; i--){ String mToggleName = mToggles[i].replace("\\", ""); int[] resources = getResourcesById(mToggleName); - setToggleResources(mToggleIds[i], mToggleIcons[i], mToggleLabels[i], resources[0], resources[1]); - TOGGLE_ID_ARRAY[i] = resources[2]; - setToggleController(mToggleName, mToggleCheckBoxes[i]); + addToggle(resources, mToggleName); } } + private void addToggle(final int[] res, String name) { + LinearLayout toggle = (LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.status_bar_settings_button, this, false); + addView(toggle,0); + + ImageView icon = (ImageView)toggle.getChildAt(0); + icon.setImageResource(res[0]); + TextView label = (TextView)toggle.getChildAt(1); + label.setText(res[1]); + Switch checkbox = (Switch)toggle.getChildAt(2); + + toggle.setTag(new ButtonTag(res[2])); + toggle.setOnClickListener(this); + + setToggleController(name, (CompoundButton)checkbox); + } + + @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); @@ -180,25 +192,38 @@ public class SettingsView extends LinearLayout implements View.OnClickListener { mDoNotDisturb.release(); } - private void setToggleController(String id, int mCheckbox){ + + private void clearToggleControllers() { + mAirplane = null; + mRotate = null; + mBluetooth = null; + mFlashLight = null; + mGps = null; + mMobileData = null; + mNetworkMode = null; + mSound = null; + mWifi = null; + } + + private void setToggleController(String id, CompoundButton checkbox) { if(id.equals(KEY_TOGGLES[0])) - mAirplane = new AirplaneModeController(mContext, (CompoundButton)findViewById(mCheckbox)); + mAirplane = new AirplaneModeController(mContext, checkbox); else if(id.equals(KEY_TOGGLES[1])) - mRotate = new AutoRotateController(mContext, (CompoundButton)findViewById(mCheckbox)); + mRotate = new AutoRotateController(mContext, checkbox); else if(id.equals(KEY_TOGGLES[2])) - mBluetooth = new BluetoothController(mContext, (CompoundButton)findViewById(mCheckbox)); + mBluetooth = new BluetoothController(mContext, checkbox); else if(id.equals(KEY_TOGGLES[3])) - mGps = new LocationController(mContext, (CompoundButton)findViewById(mCheckbox)); + mGps = new LocationController(mContext, checkbox); else if(id.equals(KEY_TOGGLES[4])) - mWifi = new WifiController(mContext, (CompoundButton)findViewById(mCheckbox)); + mWifi = new WifiController(mContext, checkbox); else if(id.equals(KEY_TOGGLES[5])) - mFlashLight = new FlashlightController(mContext, (CompoundButton)findViewById(mCheckbox)); + mFlashLight = new FlashlightController(mContext, checkbox); else if(id.equals(KEY_TOGGLES[6])) - mMobileData = new MobileDataController(mContext, (CompoundButton)findViewById(mCheckbox)); + mMobileData = new MobileDataController(mContext, checkbox); else if(id.equals(KEY_TOGGLES[7])) - mNetworkMode = new NetworkModeController(mContext, (CompoundButton)findViewById(mCheckbox)); + mNetworkMode = new NetworkModeController(mContext, checkbox); else if(id.equals(KEY_TOGGLES[8])) - mSound = new SoundController(mContext, (CompoundButton)findViewById(mCheckbox)); + mSound = new SoundController(mContext, checkbox); } private int[] getResourcesById(String id){ @@ -224,41 +249,17 @@ public class SettingsView extends LinearLayout implements View.OnClickListener { return new int[]{0, 0}; } - private void setToggleResources(int resourceId, int resourceIcon, int resourceLabel, int newResourceIcon, int newResourceLabel){ - LinearLayout mToggle = (LinearLayout) findViewById(resourceId); - ImageView mToggleImageView = (ImageView) mToggle.findViewById(resourceIcon); - mToggleImageView.setImageResource(newResourceIcon); - TextView mToggleTextView = (TextView) mToggle.findViewById(resourceLabel); - mToggleTextView.setText(newResourceLabel); - } - private StatusBarManager getStatusBarManager() { return (StatusBarManager)getContext().getSystemService(Context.STATUS_BAR_SERVICE); } public void onClick(View v) { - switch (v.getId()) { - case R.id.toggle_1: - onClickToggle(TOGGLE_ID_ARRAY[0]); - break; - case R.id.toggle_2: - onClickToggle(TOGGLE_ID_ARRAY[1]); - break; - case R.id.toggle_3: - onClickToggle(TOGGLE_ID_ARRAY[2]); - break; - case R.id.toggle_4: - onClickToggle(TOGGLE_ID_ARRAY[3]); - break; - case R.id.toggle_5: - onClickToggle(TOGGLE_ID_ARRAY[4]); - break; - case R.id.toggle_6: - onClickToggle(TOGGLE_ID_ARRAY[5]); - break; - case R.id.settings: - onClickSettings(); - break; + if (v.getId() == R.id.settings) { + onClickSettings(); + } else { + Object tag = v.getTag(); + if (tag instanceof ButtonTag) + onClickToggle(((ButtonTag) tag).toggleId); } } diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index f03d93d..2078370 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -598,7 +598,13 @@ public class KeyguardViewMediator implements KeyguardViewCallback, * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet. */ public boolean isInputRestricted() { - return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned(); + if (mShowing) { + return true; + } + if (mExternallyEnabled && mNeedToReshowWhenReenabled) { + return true; + } + return !mUpdateMonitor.isDeviceProvisioned(); } /** @@ -623,22 +629,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback, * the keyguard to be shown. */ private void doKeyguardLocked() { - // if another app is disabling us, don't show - if (!mExternallyEnabled) { - if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); - - // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes - // for an occasional ugly flicker in this situation: - // 1) receive a call with the screen on (no keyguard) or make a call - // 2) screen times out - // 3) user hits key to turn screen back on - // instead, we reenable the keyguard when we know the screen is off and the call - // ends (see the broadcast receiver below) - // TODO: clean this up when we have better support at the window manager level - // for apps that wish to be on top of the keyguard - return; - } - // if the keyguard is already showing, don't bother if (mKeyguardViewManager.isShowing()) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing"); @@ -661,6 +651,22 @@ public class KeyguardViewMediator implements KeyguardViewCallback, return; } + // if another app is disabling us, don't show + if (!mExternallyEnabled && !lockedOrMissing) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); + + // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes + // for an occasional ugly flicker in this situation: + // 1) receive a call with the screen on (no keyguard) or make a call + // 2) screen times out + // 3) user hits key to turn screen back on + // instead, we reenable the keyguard when we know the screen is off and the call + // ends (see the broadcast receiver below) + // TODO: clean this up when we have better support at the window manager level + // for apps that wish to be on top of the keyguard + return; + } + if (mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off"); return; diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index e5c39b1..83d18ac 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -34,6 +34,10 @@ ifeq ($(BOARD_USE_MOTO_DOCK_HACK),true) LOCAL_CFLAGS += -DMOTO_DOCK_HACK endif +ifeq ($(BOARD_HAS_SAMSUNG_VOLUME_BUG),true) + LOCAL_CFLAGS += -DHAS_SAMSUNG_VOLUME_BUG +endif + ifeq ($(ARCH_ARM_HAVE_NEON),true) LOCAL_CFLAGS += -D__ARM_HAVE_NEON endif diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 0faf367..7c25380 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -95,6 +95,11 @@ static const uint32_t kMinThreadSleepTimeUs = 5000; // maximum divider applied to the active sleep time in the mixer thread loop static const uint32_t kMaxThreadSleepTimeShift = 2; +#ifdef HAS_SAMSUNG_VOLUME_BUG +float gPrevMusicStreamVolume = 0; +bool gMusicStreamIsMuted = false; +bool gMusicStreamNeedsPrevVolume = false; +#endif // ---------------------------------------------------------------------------- @@ -2527,9 +2532,41 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track track->setPaused(); } } else { +#ifdef HAS_SAMSUNG_VOLUME_BUG + if (track->type() == AUDIO_STREAM_MUSIC && !track->isMuted() && !track->isPausing()) { + if(mStreamTypes[AUDIO_STREAM_MUSIC].volume > 0 && !gMusicStreamNeedsPrevVolume) { + gPrevMusicStreamVolume = mStreamTypes[AUDIO_STREAM_MUSIC].volume; + } else { + gMusicStreamIsMuted = true; + } + } else if (track->type() == AUDIO_STREAM_MUSIC && (track->isMuted() || track->isPausing())) { + gMusicStreamIsMuted = true; + } + if (track->type() == AUDIO_STREAM_NOTIFICATION && gMusicStreamIsMuted) { + LOGD("Music stream needs volume restore!"); + LOGD("gPrevMusicStreamVolume = %f", gPrevMusicStreamVolume); + gMusicStreamNeedsPrevVolume = true; + } +#endif // read original volumes with volume control float typeVolume = mStreamTypes[track->type()].volume; + +#ifdef HAS_SAMSUNG_VOLUME_BUG + if (track->type() == AUDIO_STREAM_MUSIC && typeVolume > 0 && !track->isMuted() && + !track->isPausing() && gMusicStreamNeedsPrevVolume) { + LOGI("Restoring last known good volume value on music stream!"); + LOGI("gPrevMusicStreamVolume = %f", gPrevMusicStreamVolume); + mStreamTypes[AUDIO_STREAM_MUSIC].volume = gPrevMusicStreamVolume; + typeVolume = gPrevMusicStreamVolume; + gMusicStreamIsMuted = false; + gMusicStreamNeedsPrevVolume = false; + } else if (track->type() == AUDIO_STREAM_MUSIC && typeVolume > 0 + && !track->isMuted() && !track->isPausing()) { + gMusicStreamIsMuted = false; + } +#endif + float v = masterVolume * typeVolume; vl = (uint32_t)(v * cblk->volume[0]) << 12; vr = (uint32_t)(v * cblk->volume[1]) << 12; diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h index 57f923f..f787266 100644..100755 --- a/services/camera/libcameraservice/CameraHardwareInterface.h +++ b/services/camera/libcameraservice/CameraHardwareInterface.h @@ -115,6 +115,13 @@ public: LOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get()); if (mDevice->ops->set_preview_window) { +#ifdef QCOM_HARDWARE + LOGV("%s buf %p mPreviewWindow %p", __FUNCTION__, buf.get(), mPreviewWindow.get()); + if (mPreviewWindow.get() && (buf.get() != mPreviewWindow.get())) { + mDevice->ops->set_preview_window(mDevice, 0); + } +#endif + mPreviewWindow = buf; mHalPreviewWindow.user = this; LOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__, diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index f6825d7..e15a1b9 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -374,8 +374,11 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, (void *)cameraId); // Enable zoom, error, focus, and metadata messages by default - enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS | - CAMERA_MSG_PREVIEW_METADATA); + enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS +#ifndef QCOM_HARDWARE + | CAMERA_MSG_PREVIEW_METADATA +#endif + ); // Callback is disabled by default mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP; @@ -383,6 +386,9 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, mPlayShutterSound = true; cameraService->setCameraBusy(cameraId); cameraService->loadSound(); +#ifdef QCOM_HARDWARE + mFaceDetection = false; +#endif LOG1("Client::Client X (pid %d)", callingPid); } @@ -522,9 +528,11 @@ void CameraService::Client::disconnect() { // Release the held ANativeWindow resources. if (mPreviewWindow != 0) { +#ifdef QCOM_HARDWARE + mHardware->setPreviewWindow(0); +#endif disconnectWindow(mPreviewWindow); mPreviewWindow = 0; - mHardware->setPreviewWindow(mPreviewWindow); } mHardware.clear(); @@ -564,6 +572,10 @@ status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder, native_window_set_buffers_transform(window.get(), mOrientation); result = mHardware->setPreviewWindow(window); } +#ifdef QCOM_HARDWARE + } else { + result = mHardware->setPreviewWindow(window); +#endif } if (result == NO_ERROR) { @@ -623,7 +635,10 @@ void CameraService::Client::setPreviewCallbackFlag(int callback_flag) { // start preview mode status_t CameraService::Client::startPreview() { LOG1("startPreview (pid %d)", getCallingPid()); - enableMsgType(CAMERA_MSG_PREVIEW_METADATA); +#ifdef QCOM_HARDWARE + if (mFaceDetection) + enableMsgType(CAMERA_MSG_PREVIEW_METADATA); +#endif return startCameraMode(CAMERA_PREVIEW_MODE); } @@ -908,6 +923,14 @@ status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t a } else if (cmd == CAMERA_CMD_HISTOGRAM_OFF) { disableMsgType(CAMERA_MSG_STATS_DATA); +#ifdef QCOM_HARDWARE + } else if (cmd == CAMERA_CMD_START_FACE_DETECTION) { + mFaceDetection = true; + enableMsgType(CAMERA_MSG_PREVIEW_METADATA); + } else if (cmd == CAMERA_CMD_STOP_FACE_DETECTION) { + mFaceDetection = false; + disableMsgType(CAMERA_MSG_PREVIEW_METADATA); +#endif } @@ -1161,6 +1184,11 @@ void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) { if (!mburstCnt) { LOG1("mburstCnt = %d", mburstCnt); disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); +#ifdef QCOM_HARDWARE + if (mFaceDetection) { + enableMsgType(CAMERA_MSG_PREVIEW_METADATA); + } +#endif } sp<ICameraClient> c = mCameraClient; mLock.unlock(); diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 0d29105..33f7226 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -182,7 +182,9 @@ private: int mPreviewCallbackFlag; int mOrientation; // Current display orientation bool mPlayShutterSound; - +#ifdef QCOM_HARDWARE + bool mFaceDetection; +#endif // Ensures atomicity among the public methods mutable Mutex mLock; // This is a binder of Surface or SurfaceTexture. diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 652166d..0dad55a 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -265,7 +265,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { // Reset the key repeat timer whenever we disallow key events, even if the next event // is not a key. This is to ensure that we abort a key repeat if the device is just coming // out of sleep. - if (!mPolicy->isKeyRepeatEnabled()) { + if (!mPolicy->isKeyRepeatEnabled() || !mDispatchEnabled) { resetKeyRepeatLocked(); } diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index c66e7a1..d9290f4 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -4991,6 +4991,7 @@ void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) mPointerSimple.currentProperties.id = 0; mPointerSimple.currentProperties.toolType = mCurrentCookedPointerData.pointerProperties[index].toolType; + mLastStylusTime = when; } else { down = false; hovering = false; @@ -5073,6 +5074,11 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, } } + if (rejectPalm(when)) { // stylus is currently active + mPointerSimple.reset(); + return; + } + if (mPointerSimple.down && !down) { mPointerSimple.down = false; @@ -5183,6 +5189,9 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 const PointerProperties* properties, const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) { + + if (rejectPalm(when)) return; + PointerCoords pointerCoords[MAX_POINTERS]; PointerProperties pointerProperties[MAX_POINTERS]; uint32_t pointerCount = 0; @@ -5262,6 +5271,13 @@ void TouchInputMapper::unfadePointer(PointerControllerInterface::Transition tran } } +nsecs_t TouchInputMapper::mLastStylusTime = 0; + +bool TouchInputMapper::rejectPalm(nsecs_t when) { + return (when - mLastStylusTime < mConfig.stylusPalmRejectionTime) && + mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS; +} + bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue; diff --git a/services/input/InputReader.h b/services/input/InputReader.h index 379229f..6167508 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -152,6 +152,9 @@ struct InputReaderConfiguration { // True to show the pointer icon when a stylus is used. bool stylusIconEnabled; + // Ignore finger touches this long after the stylus has been used (including hover) + nsecs_t stylusPalmRejectionTime; + InputReaderConfiguration() : virtualKeyQuietTime(0), pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f), @@ -169,7 +172,9 @@ struct InputReaderConfiguration { pointerGestureMovementSpeedRatio(0.8f), pointerGestureZoomSpeedRatio(0.3f), showTouches(false), - stylusIconEnabled(false) { } + stylusIconEnabled(false), + stylusPalmRejectionTime(50 * 10000000LL) // 50 ms + { } bool getDisplayInfo(int32_t displayId, bool external, int32_t* width, int32_t* height, int32_t* orientation) const; @@ -1480,6 +1485,9 @@ private: VelocityControl mWheelXVelocityControl; VelocityControl mWheelYVelocityControl; + // The time the stylus event was processed by any TouchInputMapper + static nsecs_t mLastStylusTime; + void sync(nsecs_t when); bool consumeRawTouches(nsecs_t when, uint32_t policyFlags); @@ -1534,6 +1542,8 @@ private: void assignPointerIds(); void unfadePointer(PointerControllerInterface::Transition transition); + + bool rejectPalm(nsecs_t when); }; diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java index c9e533a..3312a9e 100644 --- a/services/java/com/android/server/BatteryService.java +++ b/services/java/com/android/server/BatteryService.java @@ -16,21 +16,20 @@ package com.android.server; -import com.android.internal.app.IBatteryStats; -import com.android.server.am.BatteryStatsService; - import android.app.ActivityManagerNative; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.database.ContentObserver; +import android.graphics.Color; import android.os.BatteryManager; import android.os.Binder; +import android.os.DropBoxManager; import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; -import android.os.DropBoxManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -39,14 +38,15 @@ import android.provider.Settings; import android.util.EventLog; import android.util.Slog; +import com.android.internal.app.IBatteryStats; +import com.android.server.am.BatteryStatsService; + import java.io.File; import java.io.FileDescriptor; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.util.Arrays; - +import java.util.Calendar; /** * <p>BatteryService monitors the charging status, and charge level of the device @@ -130,10 +130,21 @@ class BatteryService extends Binder { private int mDischargeStartLevel; private Led mLed; + private boolean mLightEnabled; private boolean mLedPulseEnabled; + private int mBatteryLowARGB; + private int mBatteryMediumARGB; + private int mBatteryFullARGB; + private boolean mMultiColorLed; private boolean mSentLowBatteryBroadcast = false; + // Quiet hours support + private boolean mQuietHoursEnabled = false; + private int mQuietHoursStart = 0; + private int mQuietHoursEnd = 0; + private boolean mQuietHoursDim = true; + public BatteryService(Context context, LightsService lights) { mContext = context; mLed = new Led(context, lights); @@ -571,9 +582,6 @@ class BatteryService extends Binder { private LightsService mLightsService; private LightsService.Light mBatteryLight; - private int mBatteryLowARGB; - private int mBatteryMediumARGB; - private int mBatteryFullARGB; private int mBatteryLedOn; private int mBatteryLedOff; @@ -582,15 +590,14 @@ class BatteryService extends Binder { private boolean mBatteryFull; Led(Context context, LightsService lights) { + mLightsService = lights; mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY); - mBatteryLowARGB = mContext.getResources().getInteger( - com.android.internal.R.integer.config_notificationsBatteryLowARGB); - mBatteryMediumARGB = mContext.getResources().getInteger( - com.android.internal.R.integer.config_notificationsBatteryMediumARGB); - mBatteryFullARGB = mContext.getResources().getInteger( - com.android.internal.R.integer.config_notificationsBatteryFullARGB); + // Does the Device support changing battery LED colors? + mMultiColorLed = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_multiColorBatteryLed); + mBatteryLedOn = mContext.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLedOn); mBatteryLedOff = mContext.getResources().getInteger( @@ -603,12 +610,27 @@ class BatteryService extends Binder { void updateLightsLocked() { final int level = mBatteryLevel; final int status = mBatteryStatus; - if (level < mLowBatteryWarningLevel) { + + if (!mLightEnabled) { + // No lights if explicitly disabled + mBatteryLight.turnOff(); + } else if (inQuietHours() && mQuietHoursDim) { + if (mLedPulseEnabled && level < mLowBatteryWarningLevel && + status != BatteryManager.BATTERY_STATUS_CHARGING) { + // The battery is low, the device is not charging and the low battery pulse + // is enabled - ignore Quiet Hours + mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED, + mBatteryLedOn, mBatteryLedOff); + } else { + // No lights if in Quiet Hours and battery not low + mBatteryLight.turnOff(); + } + } else if (level < mLowBatteryWarningLevel) { if (status == BatteryManager.BATTERY_STATUS_CHARGING) { - // Solid red when battery is charging + // Battery is charging and low mBatteryLight.setColor(mBatteryLowARGB); } else if (mLedPulseEnabled) { - // Flash red when battery is low and not charging + // Battery is low and not charging mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED, mBatteryLedOn, mBatteryLedOff); } else { @@ -616,16 +638,16 @@ class BatteryService extends Binder { mBatteryLight.turnOff(); } } else if (status == BatteryManager.BATTERY_STATUS_CHARGING - || status == BatteryManager.BATTERY_STATUS_FULL) { + || status == BatteryManager.BATTERY_STATUS_FULL) { if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) { - // Solid green when full or charging and nearly full + // Battery is full or charging and nearly full mBatteryLight.setColor(mBatteryFullARGB); } else { - // Solid orange when charging and halfway full + // Battery is charging and halfway full mBatteryLight.setColor(mBatteryMediumARGB); } } else { - // No lights if not charging and not low + //No lights if not charging and not low mBatteryLight.turnOff(); } } @@ -638,8 +660,36 @@ class BatteryService extends Binder { void observe() { ContentResolver resolver = mContext.getContentResolver(); + + // Battery light enabled + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.BATTERY_LIGHT_ENABLED), false, this); + + // Low battery pulse resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.BATTERY_LIGHT_PULSE), false, this); + + // Light colors + if (mMultiColorLed) { + // Register observer if we have a multi color led + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.BATTERY_LIGHT_LOW_COLOR), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.BATTERY_LIGHT_MEDIUM_COLOR), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.BATTERY_LIGHT_FULL_COLOR), false, this); + } + + // Quiet Hours + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.QUIET_HOURS_ENABLED), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.QUIET_HOURS_START), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.QUIET_HOURS_END), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.QUIET_HOURS_DIM), false, this); + update(); } @@ -649,13 +699,54 @@ class BatteryService extends Binder { public void update() { ContentResolver resolver = mContext.getContentResolver(); - boolean pulseEnabled = Settings.System.getInt(resolver, + Resources res = mContext.getResources(); + + // Battery light enabled + mLightEnabled = Settings.System.getInt(resolver, + Settings.System.BATTERY_LIGHT_ENABLED, 1) != 0; + + // Low battery pulse + mLedPulseEnabled = Settings.System.getInt(resolver, Settings.System.BATTERY_LIGHT_PULSE, 1) != 0; - if (mLedPulseEnabled != pulseEnabled) { - mLedPulseEnabled = pulseEnabled; - updateLedPulse(); + + // Light colors + mBatteryLowARGB = Settings.System.getInt(resolver, + Settings.System.BATTERY_LIGHT_LOW_COLOR, + res.getInteger(com.android.internal.R.integer.config_notificationsBatteryLowARGB)); + mBatteryMediumARGB = Settings.System.getInt(resolver, + Settings.System.BATTERY_LIGHT_MEDIUM_COLOR, + res.getInteger(com.android.internal.R.integer.config_notificationsBatteryMediumARGB)); + mBatteryFullARGB = Settings.System.getInt(resolver, + Settings.System.BATTERY_LIGHT_FULL_COLOR, + res.getInteger(com.android.internal.R.integer.config_notificationsBatteryFullARGB)); + + // Quiet Hours + mQuietHoursEnabled = Settings.System.getInt(resolver, + Settings.System.QUIET_HOURS_ENABLED, 0) != 0; + mQuietHoursStart = Settings.System.getInt(resolver, + Settings.System.QUIET_HOURS_START, 0); + mQuietHoursEnd = Settings.System.getInt(resolver, + Settings.System.QUIET_HOURS_END, 0); + mQuietHoursDim = Settings.System.getInt(resolver, + Settings.System.QUIET_HOURS_DIM, 0) != 0; + + updateLedPulse(); + } + } + + private boolean inQuietHours() { + if (mQuietHoursEnabled && (mQuietHoursStart != mQuietHoursEnd)) { + // Get the date in "quiet hours" format. + Calendar calendar = Calendar.getInstance(); + int minutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE); + if (mQuietHoursEnd < mQuietHoursStart) { + // Starts at night, ends in the morning. + return (minutes > mQuietHoursStart) || (minutes < mQuietHoursEnd); + } else { + return (minutes > mQuietHoursStart) && (minutes < mQuietHoursEnd); } } + return false; } -} +} diff --git a/services/java/com/android/server/RotationSwitchObserver.java b/services/java/com/android/server/RotationSwitchObserver.java new file mode 100644 index 0000000..a191433 --- /dev/null +++ b/services/java/com/android/server/RotationSwitchObserver.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2008 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. + * + */ + +package com.android.server; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.os.UEventObserver; +import android.provider.Settings; +import android.util.Log; +import android.util.Slog; + +import android.widget.Toast; +import android.view.IWindowManager; +import android.os.ServiceManager; +import android.os.RemoteException; +import android.os.AsyncTask; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; + +/** + * <p>RotationLockObserver monitors for rotation lock switch state + */ +class RotationSwitchObserver extends UEventObserver { + private static final String TAG = RotationSwitchObserver.class + .getSimpleName(); + private static final boolean LOG = true; + + private static final String LOCK_UEVENT_MATCH = + "DEVPATH=/devices/virtual/switch/rotationlock"; + private static final String LOCK_STATE_PATH = + "/sys/class/switch/rotationlock/state"; + + private static final int MSG_LOCK_STATE = 0; + + private int mLockState; + private int mPreviousLockState; + + private boolean mSystemReady; + + private final Context mContext; + + private boolean mAutoRotation; + + public RotationSwitchObserver(Context context) { + mContext = context; + init(); // set initial status + + startObserving(LOCK_UEVENT_MATCH); + } + + @Override + public void onUEvent(UEventObserver.UEvent event) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Slog.v(TAG, "Switch UEVENT: " + event.toString()); + } + + synchronized (this) { + try { + int newState = Integer.parseInt(event.get("SWITCH_STATE")); + if (newState != mLockState) { + mPreviousLockState = mLockState; + mLockState = newState; + if (mSystemReady) { + update(); + } + } + } catch (NumberFormatException e) { + Slog.e(TAG, "Could not parse switch state from event " + + event); + } + } + } + + private final void init() { + char[] buffer = new char[1024]; + + try { + FileReader file = new FileReader(LOCK_STATE_PATH); + int len = file.read(buffer, 0, 1024); + file.close(); + mPreviousLockState = mLockState = + Integer.valueOf((new String(buffer, 0, len)).trim()); + } catch (FileNotFoundException e) { + Slog.w(TAG, "This kernel does not have rotation switch support"); + } catch (NumberFormatException e) { + Slog.e(TAG, "" , e); + } catch (IOException e) { + Slog.e(TAG, "" , e); + } + } + + void systemReady() { + synchronized (this) { + mSystemReady = true; + } + } + + private final void update() { + mHandler.sendEmptyMessage(MSG_LOCK_STATE); + } + + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_LOCK_STATE: + synchronized (this) { + boolean autoRotate = mLockState == 0; + int toastId = autoRotate + ? com.android.internal.R.string.toast_rotation_unlocked + : com.android.internal.R.string.toast_rotation_locked; + + setAutoRotation(autoRotate); + + Toast.makeText(mContext, mContext.getString(toastId), + Toast.LENGTH_SHORT).show(); + break; + } + } + } + }; + + private void setAutoRotation(final boolean autorotate) { + mAutoRotation = autorotate; + AsyncTask.execute(new Runnable() { + public void run() { + try { + IWindowManager wm = IWindowManager.Stub.asInterface( + ServiceManager + .getService(Context.WINDOW_SERVICE)); + if (autorotate) { + wm.thawRotation(); + } else { + wm.freezeRotation(-1); + } + } catch (RemoteException exc) { + Log.w(TAG, "Unable to save auto-rotate setting"); + } + } + }); + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 17a4b5d..c13a3e2 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -144,6 +144,7 @@ class ServerThread extends Thread { BluetoothService bluetooth = null; BluetoothA2dpService bluetoothA2dp = null; DockObserver dock = null; + RotationSwitchObserver rotateSwitch = null; UsbService usb = null; UiModeManagerService uiMode = null; RecognitionManagerService recognition = null; @@ -282,6 +283,9 @@ class ServerThread extends Thread { Slog.e("System", "************ Failure starting core service", e); } + boolean hasRotationLock = context.getResources().getBoolean(com.android + .internal.R.bool.config_hasRotationLockSwitch); + DevicePolicyManagerService devicePolicy = null; StatusBarManagerService statusBar = null; InputMethodManagerService imm = null; @@ -531,6 +535,16 @@ class ServerThread extends Thread { } try { + if (hasRotationLock) { + Slog.i(TAG, "Rotation Switch Observer"); + // Listen for switch changes + rotateSwitch = new RotationSwitchObserver(context); + } + } catch (Throwable e) { + reportWtf("starting RotationSwitchObserver", e); + } + + try { Slog.i(TAG, "Wired Accessory Observer"); // Listen for wired headset changes new WiredAccessoryObserver(context); @@ -696,6 +710,7 @@ class ServerThread extends Thread { final NetworkPolicyManagerService networkPolicyF = networkPolicy; final ConnectivityService connectivityF = connectivity; final DockObserver dockF = dock; + final RotationSwitchObserver rotateSwitchF = rotateSwitch; final UsbService usbF = usb; final ThrottleService throttleF = throttle; final UiModeManagerService uiModeF = uiMode; @@ -750,6 +765,11 @@ class ServerThread extends Thread { reportWtf("making Dock Service ready", e); } try { + if (rotateSwitchF != null) rotateSwitchF.systemReady(); + } catch (Throwable e) { + reportWtf("making Rotation Switch Service ready", e); + } + try { if (usbF != null) usbF.systemReady(); } catch (Throwable e) { reportWtf("making USB Service ready", e); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 3bed489..a274891 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3004,7 +3004,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - final void logAppTooSlow(ProcessRecord app, long startTime, String msg) { + final void logAppTooSlow(int pid, long startTime, String msg) { if (IS_USER_BUILD) { return; } @@ -3037,7 +3037,7 @@ public final class ActivityManagerService extends ActivityManagerNative sb.append(msg); FileOutputStream fos = new FileOutputStream(tracesFile); fos.write(sb.toString().getBytes()); - if (app == null) { + if (pid <= 0) { fos.write("\n*** No application process!".getBytes()); } fos.close(); @@ -3047,9 +3047,9 @@ public final class ActivityManagerService extends ActivityManagerNative return; } - if (app != null) { + if (pid > 0) { ArrayList<Integer> firstPids = new ArrayList<Integer>(); - firstPids.add(app.pid); + firstPids.add(pid); dumpStackTraces(tracesPath, firstPids, null, null); } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 86d3a1a..d581d33 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -307,11 +307,18 @@ final class ActivityStack { // We don't at this point know if the activity is fullscreen, // so we need to be conservative and assume it isn't. Slog.w(TAG, "Activity pause timeout for " + r); + int pid = -1; + long pauseTime = 0; + String m = null; synchronized (mService) { if (r.app != null) { - mService.logAppTooSlow(r.app, r.pauseTime, - "pausing " + r); + pid = r.app.pid; } + pauseTime = r.pauseTime; + m = "pausing " + r; + } + if (pid > 0) { + mService.logAppTooSlow(pid, pauseTime, m); } activityPaused(r != null ? r.appToken : null, true); @@ -332,12 +339,21 @@ final class ActivityStack { } break; case LAUNCH_TICK_MSG: { ActivityRecord r = (ActivityRecord)msg.obj; + int pid = -1; + long launchTickTime = 0; + String m = null; synchronized (mService) { if (r.continueLaunchTickingLocked()) { - mService.logAppTooSlow(r.app, r.launchTickTime, - "launching " + r); + if (r.app != null) { + pid = r.app.pid; + } + launchTickTime = r.launchTickTime; + m = "launching " + r; } } + if (pid > 0) { + mService.logAppTooSlow(pid, launchTickTime, m); + } } break; case DESTROY_TIMEOUT_MSG: { ActivityRecord r = (ActivityRecord)msg.obj; diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java index 35503d3..4e4f851 100644 --- a/services/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java @@ -62,6 +62,7 @@ class ScreenRotationAnimation { public ScreenRotationAnimation(Context context, SurfaceSession session, boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) { + boolean isTegra = android.os.SystemProperties.get("ro.board.platform","").equals("tegra"); mContext = context; // Screenshot does NOT include rotation! @@ -99,7 +100,7 @@ class ScreenRotationAnimation { try { try { mSurface = new Surface(session, 0, "FreezeSurface", - -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN); + -1, mWidth, mHeight, PixelFormat.OPAQUE, isTegra ? 0 : (Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN)); if (mSurface == null || !mSurface.isValid()) { // Screenshot failed, punt. mSurface = null; @@ -116,6 +117,35 @@ class ScreenRotationAnimation { " FREEZE " + mSurface + ": CREATE"); setRotation(originalRotation); + + if (isTegra) { + Rect rect = new Rect(0, 0, mWidth, mHeight); + Canvas canvas = null; + + try { + canvas = mSurface.lockCanvas(rect); + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Unable to lock surface", e); + } catch (Surface.OutOfResourcesException e) { + Slog.w(TAG, "Unable to lock surface", e); + } + + Bitmap screenshot = Surface.screenshot(0, 0); + if (canvas == null || screenshot == null) { + Slog.w(TAG, "Null surface canvas"); + mSurface.destroy(); + mSurface = null; + return; + } + + Paint paint = new Paint(0); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); + + canvas.drawBitmap(screenshot, 0, 0, paint); + mSurface.unlockCanvasAndPost(canvas); + + } + } finally { if (!inTransaction) { Surface.closeTransaction(); diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java index abcee78..5b12e43 100644 --- a/telephony/java/com/android/internal/telephony/CommandsInterface.java +++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java @@ -1652,4 +1652,11 @@ public interface CommandsInterface { * CM-specific: Ask the RIL about the presence of back-compat flags */ public boolean needsOldRilFeature(String feature); + /** + * @hide + * samsung stk service implementation - set up registrant for sending + * sms send result from modem(RIL) to catService + */ + void setOnCatSendSmsResult(Handler h, int what, Object obj); + void unSetOnCatSendSmsResult(Handler h); } diff --git a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java index 9763265..d0da285 100644 --- a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java +++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java @@ -212,6 +212,19 @@ public abstract class IccSmsInterfaceManager extends ISms.Stub { return data; } + /** + * stk send sms Samsung way + * @param smsc + * @param pdu + * @param sentIntent + * @param deliveryIntent + */ + public void sendRawPduSat(byte[] smsc, byte[] pdu, PendingIntent sentIntent, + PendingIntent deliveryIntent) { + mPhone.getContext(); + mDispatcher.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent); + } + protected abstract void log(String msg); } diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index b8e7029..d4015ae 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -41,6 +41,7 @@ import android.os.Message; import android.os.Parcel; import android.os.PowerManager; import android.os.SystemProperties; +import android.os.Registrant; import android.os.PowerManager.WakeLock; import android.telephony.NeighboringCellInfo; import android.telephony.PhoneNumberUtils; @@ -267,6 +268,26 @@ public class RIL extends BaseCommands implements CommandsInterface { } }; + protected Registrant mCatSendSmsResultRegistrant; + /** + * samsung stk service implementation - set up registrant for sending + * sms send result from modem(RIL) to catService + * @param h + * @param what + * @param obj + */ + public void setOnCatSendSmsResult(Handler h, int what, Object obj) { + mCatSendSmsResultRegistrant = new Registrant(h, what, obj); + } + + /** + * + * @param h + */ + public void unSetOnCatSendSmsResult(Handler h) { + mCatSendSmsResultRegistrant.clear(); + } + class RILSender extends Handler implements Runnable { public RILSender(Looper looper) { super(looper); @@ -2467,6 +2488,8 @@ public class RIL extends BaseCommands implements CommandsInterface { case RIL_UNSOL_CDMA_PRL_CHANGED: ret = responseInts(p); break; case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break; case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break; + //samsung stk service implementation + case RIL_UNSOL_STK_SEND_SMS_RESULT: ret = responseInts(p); break; default: throw new RuntimeException("Unrecognized unsol response: " + response); @@ -2812,6 +2835,19 @@ public class RIL extends BaseCommands implements CommandsInterface { notifyRegistrantsRilConnectionChanged(((int[])ret)[0]); break; } + + //samsung stk service implementation + case RIL_UNSOL_STK_SEND_SMS_RESULT: + if (Resources.getSystem(). + getBoolean(com.android.internal.R.bool.config_samsung_stk)) { + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCatSendSmsResultRegistrant != null) { + mCatSendSmsResultRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + } + break; } } @@ -3608,6 +3644,7 @@ public class RIL extends BaseCommands implements CommandsInterface { case RIL_UNSOL_CDMA_PRL_CHANGED: return "UNSOL_CDMA_PRL_CHANGED"; case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE"; case RIL_UNSOL_RIL_CONNECTED: return "UNSOL_RIL_CONNECTED"; + case RIL_UNSOL_STK_SEND_SMS_RESULT: return "RIL_UNSOL_STK_SEND_SMS_RESULT"; default: return "<unknown response: "+request+">"; } } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 1bf2064..36c616a 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -300,4 +300,5 @@ cat include/telephony/ril.h | \ int RIL_UNSOL_CDMA_PRL_CHANGED = 1032; int RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE = 1033; int RIL_UNSOL_RIL_CONNECTED = 1034; + int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002; /* Samsung specific */ } diff --git a/telephony/java/com/android/internal/telephony/SamsungCDMAQualcommRIL.java b/telephony/java/com/android/internal/telephony/SamsungCDMAQualcommRIL.java new file mode 100644 index 0000000..6a5487f --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SamsungCDMAQualcommRIL.java @@ -0,0 +1,422 @@ +/* + * 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 android.telephony.PhoneNumberUtils; +import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; +import com.android.internal.telephony.cdma.CdmaInformationRecords; +import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec; +import com.android.internal.telephony.cdma.SignalToneUtil; + +import java.util.ArrayList; +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 + * + * {@hide} + */ +public class SamsungCDMAQualcommRIL extends QualcommSharedRIL implements CommandsInterface { + protected IccHandler mIccHandler; + private final int RIL_INT_RADIO_OFF = 0; + private final int RIL_INT_RADIO_UNAVALIABLE = 1; + private final int RIL_INT_RADIO_ON = 2; + private final int RIL_INT_RADIO_ON_NG = 10; + private final int RIL_INT_RADIO_ON_HTC = 13; + + public SamsungCDMAQualcommRIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + @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()); + p.readInt(); //remaining_count_pin1 + p.readInt(); //remaining_count_puk1 + p.readInt(); //remaining_count_pin2 + p.readInt(); //remaining_count_puk2 + status.addApplication(ca); + } + int appIndex = -1; + appIndex = status.getGsmUmtsSubscriptionAppIndex(); + Log.d(LOG_TAG, "This is a CDMA PHONE " + appIndex); + + + if (numApplications > 0) { + IccCardApplication application = status.getApplication(appIndex); + mAid = application.aid; + mUSIM = application.app_type + == IccCardApplication.AppType.APPTYPE_USIM; + mSetPreferredNetworkType = mPreferredNetworkType; + + if (TextUtils.isEmpty(mAid)) + mAid = ""; + Log.d(LOG_TAG, "mAid " + mAid); + } + + return status; + } + + 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: + case RIL_INT_RADIO_ON_NG: + case RIL_INT_RADIO_ON_HTC: + if (mIccHandler == null) { + handlerThread = new HandlerThread("IccHandler"); + mIccThread = handlerThread; + + mIccThread.start(); + + looper = mIccThread.getLooper(); + mIccHandler = new IccHandler(this,looper); + mIccHandler.run(); + } + radioState = CommandsInterface.RadioState.SIM_NOT_READY; + + setRadioState(radioState); + break; + default: + throw new RuntimeException("Unrecognized RIL_RadioState: " + stateCode); + } + + setRadioState (radioState); + } + @Override + protected Object + responseSignalStrength(Parcel p) { + int numInts = 12; + int response[]; + + // This is a mashup of algorithms used in + // SamsungQualcommUiccRIL.java + + // Get raw data + response = new int[numInts]; + for (int i = 0 ; i < numInts ; i++) { + response[i] = p.readInt(); + } + //Workaround: use cdmaecio and evdoecio to determine signal strength and it is better than no signal bars + //TODO: find a proper fix for it + response[2] = response[3]*4; // mutiply by 4 simulate dbm so the signal bars do not jump often to full bars + response[4] = response[5]*4; + // RIL_LTE_SignalStrength + if (response[7] == 99) { + // If LTE is not enabled, clear LTE results + // 7-11 must be -1 for GSM signal strength to be used (see frameworks/base/telephony/java/android/telephony/SignalStrength.java) + response[7] = -1; + response[8] = -1; + response[9] = -1; + response[10] = -1; + response[11] = -1; + } else { + response[8] *= -1; + } + + return response; + + } + + @Override + protected Object + responseCallList(Parcel p) { + int num; + int voiceSettings; + ArrayList<DriverCall> response; + DriverCall dc; + + num = p.readInt(); + response = new ArrayList<DriverCall>(num); + + for (int i = 0 ; i < num ; i++) { + 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(); + voiceSettings = p.readInt(); + dc.isVoice = (0 == voiceSettings) ? false : true; + dc.isVoicePrivacy = (0 != p.readInt()); + //Some Samsung magic data for Videocalls + // hack taken from smdk4210ril class + voiceSettings = p.readInt(); + //printing it to cosole for later investigation + Log.d(LOG_TAG, "Samsung magic = " + voiceSettings); + 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(); + 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); + riljLogv(String.format("Incoming UUS : type=%d, dcs=%d, length=%d", + dc.uusInfo.getType(), dc.uusInfo.getDcs(), + dc.uusInfo.getUserData().length)); + riljLogv("Incoming UUS : data (string)=" + + new String(dc.uusInfo.getUserData())); + riljLogv("Incoming UUS : data (hex): " + + IccUtils.bytesToHexString(dc.uusInfo.getUserData())); + } else { + riljLogv("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(); + riljLog("InCall VoicePrivacy is enabled"); + } else { + mVoicePrivacyOffRegistrants.notifyRegistrants(); + riljLog("InCall VoicePrivacy is disabled"); + } + } + + Collections.sort(response); + + 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); + } + + class IccHandler extends Handler implements Runnable { + private static final int EVENT_RADIO_ON = 1; + private static final int EVENT_ICC_STATUS_CHANGED = 2; + private static final int EVENT_GET_ICC_STATUS_DONE = 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; + } + mRil.setRadioState(CommandsInterface.RadioState.SIM_LOCKED_OR_ABSENT); + } else { + int appIndex = -1; + appIndex = status.getGsmUmtsSubscriptionAppIndex(); + Log.d(LOG_TAG, "This is a CDMA 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); + } + } + + +} diff --git a/telephony/java/com/android/internal/telephony/SamsungQualcommD2RIL.java b/telephony/java/com/android/internal/telephony/SamsungQualcommD2RIL.java new file mode 100644 index 0000000..bd7c1d5 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SamsungQualcommD2RIL.java @@ -0,0 +1,110 @@ +/* + * 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.Parcel; +import android.os.SystemProperties; +import android.util.Log; +import com.android.internal.telephony.RILConstants; +import java.util.Collections; +import android.telephony.PhoneNumberUtils; + +import java.util.ArrayList; + +/** + * Custom RIL to handle unique behavior of D2 radio + * + * {@hide} + */ +public class SamsungQualcommD2RIL extends SamsungQualcommUiccRIL implements CommandsInterface { + public SamsungQualcommD2RIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + @Override + protected Object + responseCallList(Parcel p) { + int num; + int voiceSettings; + ArrayList<DriverCall> response; + DriverCall dc; + + num = p.readInt(); + response = new ArrayList<DriverCall>(num); + + for (int i = 0 ; i < num ; i++) { + 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(); + voiceSettings = p.readInt(); + dc.isVoice = (0 == voiceSettings) ? false : true; + dc.isVoicePrivacy = (0 != p.readInt()); + //Some Samsung magic data for Videocalls + // hack taken from smdk4210ril class + voiceSettings = p.readInt(); + //printing it to cosole for later investigation + Log.d(LOG_TAG, "Samsung magic = " + voiceSettings); + 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(); + 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); + riljLogv(String.format("Incoming UUS : type=%d, dcs=%d, length=%d", + dc.uusInfo.getType(), dc.uusInfo.getDcs(), + dc.uusInfo.getUserData().length)); + riljLogv("Incoming UUS : data (string)=" + + new String(dc.uusInfo.getUserData())); + riljLogv("Incoming UUS : data (hex): " + + IccUtils.bytesToHexString(dc.uusInfo.getUserData())); + } else { + riljLogv("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(); + riljLog("InCall VoicePrivacy is enabled"); + } else { + mVoicePrivacyOffRegistrants.notifyRegistrants(); + riljLog("InCall VoicePrivacy is disabled"); + } + } + + Collections.sort(response); + + return response; + } +} diff --git a/telephony/java/com/android/internal/telephony/SamsungQualcommUiccRIL.java b/telephony/java/com/android/internal/telephony/SamsungQualcommUiccRIL.java index c45ab19..2c942ea 100644 --- a/telephony/java/com/android/internal/telephony/SamsungQualcommUiccRIL.java +++ b/telephony/java/com/android/internal/telephony/SamsungQualcommUiccRIL.java @@ -38,6 +38,9 @@ public class SamsungQualcommUiccRIL extends QualcommSharedRIL implements Command boolean RILJ_LOGV = true; boolean RILJ_LOGD = true; + public static final int INVALID_SNR = 0x7fffffff; + private boolean mSignalbarCount = SystemProperties.getBoolean("ro.telephony.sends_barcount", false); + public SamsungQualcommUiccRIL(Context context, int networkMode, int cdmaSubscription) { super(context, networkMode, cdmaSubscription); } @@ -225,18 +228,29 @@ public class SamsungQualcommUiccRIL extends QualcommSharedRIL implements Command for (int i = 0 ; i < numInts ; i++) { response[i] = p.readInt(); } + Log.d(LOG_TAG, "responseSignalStength BEFORE: mode=" + (mSignalbarCount ? "bars" : "raw") + + " gsmDbm=" + response[0] + " gsmEcio=" + response[1] + + " lteSignalStrength=" + response[7] + " lteRsrp=" + response[8] + " lteRsrq=" + response[9] + + " lteRssnr=" + response[10] + " lteCqi=" + response[11]); // RIL_GW_SignalStrength - boolean mSignalbarCount = SystemProperties.getBoolean("telephony.sends_barcount", true); - if(mSignalbarCount) { + if (mSignalbarCount) { //Samsung sends the count of bars that should be displayed instead of //a real signal strength - response[0] = ((response[0] & 0xFF00) >> 8) * 3; //gsmDbm - if ((response[0] > 0) && (response[0] != 99)) { - response[0]--; // correct down by 1 dBm to match stock's behavior + int num_bars = (response[0] & 0xff00) >> 8; + + // Translate number of bars into something SignalStrength.java can understand + switch (num_bars) { + case 0 : response[0] = 1; break; // map to 0 bars + case 1 : response[0] = 3; break; // map to 1 bar + case 2 : response[0] = 5; break; // map to 2 bars + case 3 : response[0] = 8; break; // map to 3 bars + case 4 : response[0] = 12; break; // map to 4 bars + case 5 : response[0] = 15; break; // map to 4 bars but give an extra 10 dBm + default : response[0] &= 0xff; break; // no idea; just pass value through } } else { - response[0] = response[0] & 0xFF; //gsmDbm + response[0] &= 0xff; //gsmDbm } response[1] = -1; // gsmEcio @@ -253,15 +267,35 @@ public class SamsungQualcommUiccRIL extends QualcommSharedRIL implements Command if (response[7] == 99) { // If LTE is not enabled, clear LTE results // 7-11 must be -1 for GSM signal strength to be used (see frameworks/base/telephony/java/android/telephony/SignalStrength.java) - response[7] = -1; - response[8] = -1; - response[9] = -1; - response[10] = -1; - response[11] = -1; + response[7] = -1; // lteSignalStrength + response[8] = -1; // lteRsrp + response[9] = -1; // lteRsrq + response[10] = -1; // lteRssnr + response[11] = -1; // lteCqi + } else if (mSignalbarCount) { + int num_bars = (response[7] & 0xff00) >> 8; + response[7] &= 0xff; // remove the Samsung number of bars field + response[10] = INVALID_SNR; // mark lteRssnr invalid so it doesn't get used + + // Translate number of bars into something SignalStrength.java can understand + switch (num_bars) { + case 0 : response[8] = -1; break; // map to 0 bars + case 1 : response[8] = -116; break; // map to 1 bar + case 2 : response[8] = -115; break; // map to 2 bars + case 3 : response[8] = -105; break; // map to 3 bars + case 4 : response[8] = -95; break; // map to 4 bars + case 5 : response[8] = -85; break; // map to 4 bars but give an extra 10 dBm + default : response[8] *= -1; break; // no idea; just pass value through + } } else { + response[7] &= 0xff; // remove the Samsung number of bars field response[8] *= -1; } + Log.d(LOG_TAG, "responseSignalStength AFTER: mode=" + (mSignalbarCount ? "bars" : "raw") + + " gsmDbm=" + response[0] + " gsmEcio=" + response[1] + + " lteSignalStrength=" + response[7] + " lteRsrp=" + response[8] + " lteRsrq=" + response[9] + + " lteRssnr=" + response[10] + " lteCqi=" + response[11]); return response; } } diff --git a/telephony/java/com/android/internal/telephony/SamsungRIL.java b/telephony/java/com/android/internal/telephony/SamsungRIL.java index 6851c52..fca571c 100644 --- a/telephony/java/com/android/internal/telephony/SamsungRIL.java +++ b/telephony/java/com/android/internal/telephony/SamsungRIL.java @@ -19,6 +19,8 @@ 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; @@ -386,7 +388,7 @@ public class SamsungRIL extends RIL implements CommandsInterface { case RIL_UNSOL_GPS_NOTI: ret = responseVoid(p); break; // Ignored in TW RIL. case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST: ret = responseVoid(p); break; case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_2: ret = responseVoid(p); break; - case RIL_UNSOL_AM: ret = responseVoid(p); break; + case RIL_UNSOL_AM: ret = responseString(p); break; default: throw new RuntimeException("Unrecognized unsol response: " + response); @@ -720,6 +722,18 @@ public class SamsungRIL extends RIL implements CommandsInterface { mResendIncallMuteRegistrants.notifyRegistrants( new AsyncResult (null, ret, null)); } + break; + 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; } } diff --git a/telephony/java/com/android/internal/telephony/Smdk4210RIL.java b/telephony/java/com/android/internal/telephony/Smdk4210RIL.java index 106e0f8..fa60598 100644 --- a/telephony/java/com/android/internal/telephony/Smdk4210RIL.java +++ b/telephony/java/com/android/internal/telephony/Smdk4210RIL.java @@ -30,6 +30,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; +import android.media.AudioManager; import android.net.ConnectivityManager; import android.net.LocalSocket; import android.net.LocalSocketAddress; @@ -59,25 +60,103 @@ import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.Runtime; import java.util.ArrayList; import java.util.Collections; public class Smdk4210RIL extends RIL implements CommandsInterface { - //SAMSUNG SMDK4210 STATES + //SAMSUNG STATES + static final int RIL_REQUEST_GET_CELL_BROADCAST_CONFIG = 10002; + + static final int RIL_REQUEST_SEND_ENCODED_USSD = 10005; + static final int RIL_REQUEST_SET_PDA_MEMORY_STATUS = 10006; + static final int RIL_REQUEST_GET_PHONEBOOK_STORAGE_INFO = 10007; + static final int RIL_REQUEST_GET_PHONEBOOK_ENTRY = 10008; + static final int RIL_REQUEST_ACCESS_PHONEBOOK_ENTRY = 10009; + static final int RIL_REQUEST_DIAL_VIDEO_CALL = 10010; + static final int RIL_REQUEST_CALL_DEFLECTION = 10011; + static final int RIL_REQUEST_READ_SMS_FROM_SIM = 10012; + static final int RIL_REQUEST_USIM_PB_CAPA = 10013; + static final int RIL_REQUEST_LOCK_INFO = 10014; + static final int RIL_REQUEST_DIAL_EMERGENCY = 10016; - static final int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002; + static final int RIL_REQUEST_GET_STOREAD_MSG_COUNT = 10017; + static final int RIL_REQUEST_STK_SIM_INIT_EVENT = 10018; + static final int RIL_REQUEST_GET_LINE_ID = 10019; + static final int RIL_REQUEST_SET_LINE_ID = 10020; + static final int RIL_REQUEST_GET_SERIAL_NUMBER = 10021; + static final int RIL_REQUEST_GET_MANUFACTURE_DATE_NUMBER = 10022; + static final int RIL_REQUEST_GET_BARCODE_NUMBER = 10023; + static final int RIL_REQUEST_UICC_GBA_AUTHENTICATE_BOOTSTRAP = 10024; + static final int RIL_REQUEST_UICC_GBA_AUTHENTICATE_NAF = 10025; + static final int RIL_REQUEST_SIM_TRANSMIT_BASIC = 10026; + static final int RIL_REQUEST_SIM_OPEN_CHANNEL = 10027; + static final int RIL_REQUEST_SIM_CLOSE_CHANNEL = 10028; + static final int RIL_REQUEST_SIM_TRANSMIT_CHANNEL = 10029; + static final int RIL_REQUEST_SIM_AUTH = 10030; + static final int RIL_REQUEST_PS_ATTACH = 10031; + static final int RIL_REQUEST_PS_DETACH = 10032; + static final int RIL_REQUEST_ACTIVATE_DATA_CALL = 10033; + static final int RIL_REQUEST_CHANGE_SIM_PERSO = 10034; + static final int RIL_REQUEST_ENTER_SIM_PERSO = 10035; + static final int RIL_REQUEST_GET_TIME_INFO = 10036; + static final int RIL_REQUEST_OMADM_SETUP_SESSION = 10037; + static final int RIL_REQUEST_OMADM_SERVER_START_SESSION = 10038; + static final int RIL_REQUEST_OMADM_CLIENT_START_SESSION = 10039; + static final int RIL_REQUEST_OMADM_SEND_DATA = 10040; + static final int RIL_REQUEST_CDMA_GET_DATAPROFILE = 10041; + static final int RIL_REQUEST_CDMA_SET_DATAPROFILE = 10042; + static final int RIL_REQUEST_CDMA_GET_SYSTEMPROPERTIES = 10043; + static final int RIL_REQUEST_CDMA_SET_SYSTEMPROPERTIES = 10044; + static final int RIL_REQUEST_SEND_SMS_COUNT = 10045; + static final int RIL_REQUEST_SEND_SMS_MSG = 10046; + static final int RIL_REQUEST_SEND_SMS_MSG_READ_STATUS = 10047; + static final int RIL_REQUEST_MODEM_HANGUP = 10048; + static final int RIL_REQUEST_SET_SIM_POWER = 10049; + static final int RIL_REQUEST_SET_PREFERRED_NETWORK_LIST = 10050; + static final int RIL_REQUEST_GET_PREFERRED_NETWORK_LIST = 10051; + static final int RIL_REQUEST_HANGUP_VT = 10052; + + static final int RIL_UNSOL_RELEASE_COMPLETE_MESSAGE = 11001; + //static final int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002; + static final int RIL_UNSOL_STK_CALL_CONTROL_RESULT = 11003; + static final int RIL_UNSOL_DUN_CALL_STATUS = 11004; + static final int RIL_UNSOL_O2_HOME_ZONE_INFO = 11007; static final int RIL_UNSOL_DEVICE_READY_NOTI = 11008; - static final int RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_1 = 11010; - static final int RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_2 = 11011; - static final int RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_3 = 11012; + static final int RIL_UNSOL_GPS_NOTI = 11009; + static final int RIL_UNSOL_AM = 11010; + static final int RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL = 11011; + static final int RIL_UNSOL_DATA_SUSPEND_RESUME = 11012; + static final int RIL_UNSOL_SAP = 11013; + + static final int RIL_UNSOL_SIM_SMS_STORAGE_AVAILALE = 11015; static final int RIL_UNSOL_HSDPA_STATE_CHANGED = 11016; + static final int RIL_UNSOL_WB_AMR_STATE = 11017; + static final int RIL_UNSOL_TWO_MIC_STATE = 11018; + static final int RIL_UNSOL_DHA_STATE = 11019; + static final int RIL_UNSOL_UART = 11020; + static final int RIL_UNSOL_RESPONSE_HANDOVER = 11021; + static final int RIL_UNSOL_IPV6_ADDR = 11022; + static final int RIL_UNSOL_NWK_INIT_DISC_REQUEST = 11023; + static final int RIL_UNSOL_RTS_INDICATION = 11024; + static final int RIL_UNSOL_OMADM_SEND_DATA = 11025; + static final int RIL_UNSOL_DUN = 11026; + static final int RIL_UNSOL_SYSTEM_REBOOT = 11027; + static final int RIL_UNSOL_VOICE_PRIVACY_CHANGED = 11028; + static final int RIL_UNSOL_UTS_GETSMSCOUNT = 11029; + static final int RIL_UNSOL_UTS_GETSMSMSG = 11030; + static final int RIL_UNSOL_UTS_GET_UNREAD_SMS_STATUS = 11031; + static final int RIL_UNSOL_MIP_CONNECT_STATUS = 11032; + protected HandlerThread mSmdk4210Thread; protected ConnectivityHandler mSmdk4210Handler; + private AudioManager audioManager; public Smdk4210RIL(Context context, int networkMode, int cdmaSubscription) { super(context, networkMode, cdmaSubscription); + audioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); } @Override @@ -422,9 +501,12 @@ public class Smdk4210RIL extends RIL implements CommandsInterface { case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: ret = responseString(p); break; case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break; // SAMSUNG STATES - case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_1: ret = responseVoid(p); break; - case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_2: ret = responseVoid(p); break; - case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_3: ret = responseVoid(p); break; + 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_STK_CALL_CONTROL_RESULT: ret = responseVoid(p); break; + case RIL_UNSOL_TWO_MIC_STATE: ret = responseInts(p); break; + case RIL_UNSOL_WB_AMR_STATE: ret = responseInts(p); break; default: // Rewind the Parcel @@ -454,13 +536,68 @@ public class Smdk4210RIL extends RIL implements CommandsInterface { notifyRegistrantsRilConnectionChanged(((int[])ret)[0]); break; // SAMSUNG STATES - case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_1: - case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_2: - case RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_3: + case RIL_UNSOL_AM: + if (RILJ_LOGD) samsungUnsljLogRet(response, ret); + 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; + case RIL_UNSOL_STK_CALL_CONTROL_RESULT: + if (RILJ_LOGD) samsungUnsljLogRet(response, ret); + break; + case RIL_UNSOL_TWO_MIC_STATE: + if (RILJ_LOGD) samsungUnsljLogRet(response, ret); + break; + case RIL_UNSOL_WB_AMR_STATE: + if (RILJ_LOGD) samsungUnsljLogRet(response, ret); + setWbAmr(((int[])ret)[0]); + break; + } + } + + 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"; + case RIL_UNSOL_STK_CALL_CONTROL_RESULT: return "RIL_UNSOL_STK_CALL_CONTROL_RESULT"; + case RIL_UNSOL_TWO_MIC_STATE: return "RIL_UNSOL_TWO_MIC_STATE"; + case RIL_UNSOL_WB_AMR_STATE: return "RIL_UNSOL_WB_AMR_STATE"; + default: return "<unknown response: "+request+">"; } } + protected void samsungUnsljLog(int response) { + riljLog("[UNSL]< " + samsungResponseToString(response)); + } + + protected void samsungUnsljLogMore(int response, String more) { + riljLog("[UNSL]< " + samsungResponseToString(response) + " " + more); + } + + protected void samsungUnsljLogRet(int response, Object ret) { + riljLog("[UNSL]< " + samsungResponseToString(response) + " " + retToString(response, ret)); + } + + protected void samsungUnsljLogvRet(int response, Object ret) { + riljLogv("[UNSL]< " + samsungResponseToString(response) + " " + retToString(response, ret)); + } + /** * Notifiy all registrants that the ril has connected or disconnected. * @@ -474,6 +611,21 @@ public class Smdk4210RIL extends RIL implements CommandsInterface { } } + /** + * Set audio parameter "wb_amr" for HD-Voice (Wideband AMR). + * + * @param state: 0 = unsupported, 1 = supported. + */ + private void setWbAmr(int state) { + if (state == 1) { + Log.d(LOG_TAG, "setWbAmr(): setting audio parameter - wb_amr=on"); + audioManager.setParameters("wb_amr=on"); + } else { + Log.d(LOG_TAG, "setWbAmr(): setting audio parameter - wb_amr=off"); + audioManager.setParameters("wb_amr=off"); + } + } + @Override protected Object responseCallList(Parcel p) { @@ -620,20 +772,29 @@ public class Smdk4210RIL extends RIL implements CommandsInterface { int numInts = 12; int response[]; - /* TODO: Add SignalStrength class to match RIL_SignalStrength */ + // Get raw data response = new int[numInts]; for (int i = 0 ; i < numInts ; i++) { response[i] = p.readInt(); } - // SamsungRIL is a v3 RIL, fill the rest with -1 - for (int i = 7; i < numInts; i++) { - response[i] = -1; + Log.d(LOG_TAG, "responseSignalStength BEFORE: gsmDbm=" + response[0]); + + //Samsung sends the count of bars that should be displayed instead of + //a real signal strength + int num_bars = (response[0] & 0xff00) >> 8; + + // Translate number of bars into something SignalStrength.java can understand + switch (num_bars) { + case 0 : response[0] = 1; break; // map to 0 bars + case 1 : response[0] = 3; break; // map to 1 bar + case 2 : response[0] = 5; break; // map to 2 bars + case 3 : response[0] = 8; break; // map to 3 bars + case 4 : response[0] = 12; break; // map to 4 bars + case 5 : response[0] = 15; break; // map to 4 bars but give an extra 10 dBm + default : response[0] &= 0xff; break; // no idea; just pass value through } - /* Matching Samsung signal strength to asu. - Method taken from Samsungs cdma/gsmSignalStateTracker */ - response[0] = ((response[0] & 0xFF00) >> 8) * 3; //gsmDbm response[1] = -1; //gsmEcio response[2] = (response[2] < 0)?-120:-response[2]; //cdmaDbm response[3] = (response[3] < 0)?-160:-response[3]; //cdmaEcio @@ -643,6 +804,8 @@ public class Smdk4210RIL extends RIL implements CommandsInterface { response[6] = -1; } + Log.d(LOG_TAG, "responseSignalStength AFTER: gsmDbm=" + response[0]); + return response; } } diff --git a/telephony/java/com/android/internal/telephony/cat/CallControlResult.java b/telephony/java/com/android/internal/telephony/cat/CallControlResult.java new file mode 100644 index 0000000..2dbc0d4 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/cat/CallControlResult.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2007 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. + */ + +package com.android.internal.telephony.cat; + + +public enum CallControlResult { + + CALL_CONTROL_NO_CONTROL(0x00), + CALL_CONTROL_ALLOWED_NO_MOD(0x01), + CALL_CONTROL_NOT_ALLOWED(0x02), + CALL_CONTROL_ALLOWED_WITH_MOD(0x03); + private int mValue; + + CallControlResult(int value) { + mValue = value; + } + + public static CallControlResult fromInt(int value) { + for (CallControlResult e : CallControlResult.values()) { + if (e.mValue == value) { + return e; + } + } + return null; + } + + public int value() { + return mValue; + } +} diff --git a/telephony/java/com/android/internal/telephony/cat/CatService.java b/telephony/java/com/android/internal/telephony/cat/CatService.java index 74af9fa..cd6f9b4 100644 --- a/telephony/java/com/android/internal/telephony/cat/CatService.java +++ b/telephony/java/com/android/internal/telephony/cat/CatService.java @@ -25,13 +25,14 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.os.SystemProperties; +import android.widget.Toast; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.IccCard; import com.android.internal.telephony.IccFileHandler; import com.android.internal.telephony.IccRecords; - +import com.android.internal.telephony.IccSmsInterfaceManager; import java.io.ByteArrayOutputStream; import java.util.List; @@ -73,6 +74,9 @@ public class CatService extends Handler implements AppInterface { private Context mContext; private CatCmdMessage mCurrntCmd = null; private CatCmdMessage mMenuCmd = null; + private IccSmsInterfaceManager mIccSms = null; + private int mTimeoutDest = 0; + private int mCallControlResultCode = 0; private RilMessageDecoder mMsgDecoder = null; private boolean mStkAppInstalled = false; @@ -85,8 +89,10 @@ public class CatService extends Handler implements AppInterface { static final int MSG_ID_REFRESH = 5; static final int MSG_ID_RESPONSE = 6; static final int MSG_ID_SIM_READY = 7; + static final int MSG_ID_TIMEOUT = 9; static final int MSG_ID_RIL_MSG_DECODED = 10; + static final int MSG_ID_SEND_SMS_RESULT = 12;//samsung ril response // Events to signal SIM presence or absent in the device. private static final int MSG_ID_ICC_RECORDS_LOADED = 20; @@ -100,17 +106,25 @@ public class CatService extends Handler implements AppInterface { static final String STK_DEFAULT = "Defualt Message"; + // Sms send result constants. + static final int SMS_SEND_OK = 0; + static final int SMS_SEND_FAIL = 32790; + static final int SMS_SEND_RETRY = 32810; + + static final int WAITING_SMS_RESULT = 2; + static final int WAITING_SMS_RESULT_TIME = 60000; + /* Intentionally private for singleton */ private CatService(CommandsInterface ci, IccRecords ir, Context context, - IccFileHandler fh, IccCard ic) { + IccFileHandler fh, IccCard ic, IccSmsInterfaceManager iccSmsInt) { if (ci == null || ir == null || context == null || fh == null - || ic == null) { + || ic == null || iccSmsInt == null) { throw new NullPointerException( "Service: Input parameters must not be null"); } mCmdIf = ci; mContext = context; - + mIccSms = iccSmsInt; // Get the RilMessagesDecoder for decoding the messages. mMsgDecoder = RilMessageDecoder.getInstance(this, fh); @@ -119,6 +133,8 @@ public class CatService extends Handler implements AppInterface { mCmdIf.setOnCatProactiveCmd(this, MSG_ID_PROACTIVE_COMMAND, null); mCmdIf.setOnCatEvent(this, MSG_ID_EVENT_NOTIFY, null); mCmdIf.setOnCatCallSetUp(this, MSG_ID_CALL_SETUP, null); + // samsung ril sms send result + mCmdIf.setOnCatSendSmsResult(this, MSG_ID_SEND_SMS_RESULT, null); //mCmdIf.setOnSimRefresh(this, MSG_ID_REFRESH, null); mIccRecords = ir; @@ -141,6 +157,7 @@ public class CatService extends Handler implements AppInterface { mCmdIf.unSetOnCatProactiveCmd(this); mCmdIf.unSetOnCatEvent(this); mCmdIf.unSetOnCatCallSetUp(this); + mCmdIf.unSetOnCatSendSmsResult(this); this.removeCallbacksAndMessages(null); } @@ -267,6 +284,19 @@ public class CatService extends Handler implements AppInterface { break; case SEND_DTMF: case SEND_SMS: + if (mContext.getResources(). + getBoolean(com.android.internal.R.bool.config_samsung_stk)) { + handleProactiveCommandSendSMS(cmdParams); + if (((DisplayTextParams)cmdParams).textMsg == null + || ((DisplayTextParams)cmdParams).textMsg.text == null) + break; + if (((DisplayTextParams)cmdParams).textMsg.text.equals(STK_DEFAULT)) { + message = mContext.getText(com.android.internal.R.string.sending); + ((DisplayTextParams)cmdParams).textMsg.text = message.toString(); + Toast.makeText(mContext, ((DisplayTextParams)cmdParams).textMsg.text, 1).show(); + } + } + break; case SEND_SS: case SEND_USSD: if ((((DisplayTextParams)cmdParams).textMsg.text != null) @@ -556,16 +586,16 @@ public class CatService extends Handler implements AppInterface { * @return The only Service object in the system */ public static CatService getInstance(CommandsInterface ci, IccRecords ir, - Context context, IccFileHandler fh, IccCard ic) { + Context context, IccFileHandler fh, IccCard ic, IccSmsInterfaceManager iccSmsInt) { synchronized (sInstanceLock) { if (sInstance == null) { if (ci == null || ir == null || context == null || fh == null - || ic == null) { + || ic == null || iccSmsInt == null) { return null; } HandlerThread thread = new HandlerThread("Cat Telephony service"); thread.start(); - sInstance = new CatService(ci, ir, context, fh, ic); + sInstance = new CatService(ci, ir, context, fh, ic, iccSmsInt); CatLog.d(sInstance, "NEW sInstance"); } else if ((ir != null) && (mIccRecords != ir)) { CatLog.d(sInstance, "Reinitialize the Service with SIMRecords"); @@ -587,7 +617,7 @@ public class CatService extends Handler implements AppInterface { * @return The only Service object in the system */ public static AppInterface getInstance() { - return getInstance(null, null, null, null, null); + return getInstance(null, null, null, null, null, null); } @Override @@ -627,6 +657,64 @@ public class CatService extends Handler implements AppInterface { CatLog.d(this, "SIM ready. Reporting STK service running now..."); mCmdIf.reportStkServiceIsRunning(null); break; + // Samsung ril sms send handling part + case MSG_ID_SEND_SMS_RESULT: + if (mContext.getResources(). + getBoolean(com.android.internal.R.bool.config_samsung_stk)) { + int[] sendResult; + AsyncResult ar; + CatLog.d(this, "handleMsg : MSG_ID_SEND_SMS_RESULT"); + cancelTimeOut(); + CatLog.d(this, "The Msg ID data:" + msg.what); + if (msg.obj == null) + break; + ar = (AsyncResult) msg.obj; + if (ar == null || ar.result == null || mCurrntCmd == null || mCurrntCmd.mCmdDet == null) + break; + sendResult = (int[]) ar.result; + switch (sendResult[0]) { + default: + CatLog.d(this, "SMS SEND GENERIC FAIL"); + if (CallControlResult.fromInt(mCallControlResultCode) == + CallControlResult.CALL_CONTROL_NOT_ALLOWED) + sendTerminalResponse(mCurrntCmd.mCmdDet, + ResultCode.USIM_CALL_CONTROL_PERMANENT, true, 1, null); + else + sendTerminalResponse(mCurrntCmd.mCmdDet, + ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS, false, 0, null); + break; + case SMS_SEND_OK: // '\0' + CatLog.d(this, "SMS SEND OK"); + if (CallControlResult.fromInt(mCallControlResultCode) == + CallControlResult.CALL_CONTROL_NOT_ALLOWED) + sendTerminalResponse(mCurrntCmd.mCmdDet, + ResultCode.USIM_CALL_CONTROL_PERMANENT, true, 1, null); + else + sendTerminalResponse(mCurrntCmd.mCmdDet, ResultCode.OK, false, 0, null); + break; + case SMS_SEND_FAIL: + CatLog.d(this, "SMS SEND FAIL - MEMORY NOT AVAILABLE"); + if (CallControlResult.fromInt(mCallControlResultCode) == + CallControlResult.CALL_CONTROL_NOT_ALLOWED) + sendTerminalResponse(mCurrntCmd.mCmdDet, + ResultCode.USIM_CALL_CONTROL_PERMANENT, true, 1, null); + else + sendTerminalResponse(mCurrntCmd.mCmdDet, + ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS, false, 0, null); + break; + case SMS_SEND_RETRY: + CatLog.d(this, "SMS SEND FAIL RETRY"); + if (CallControlResult.fromInt(mCallControlResultCode) == + CallControlResult.CALL_CONTROL_NOT_ALLOWED) + sendTerminalResponse(mCurrntCmd.mCmdDet, + ResultCode.USIM_CALL_CONTROL_PERMANENT, true, 1, null); + else + sendTerminalResponse(mCurrntCmd.mCmdDet, + ResultCode.NETWORK_CRNTLY_UNABLE_TO_PROCESS, false, 0, null); + break; + } + } + break; default: throw new AssertionError("Unrecognized CAT command: " + msg.what); } @@ -749,4 +837,27 @@ public class CatService extends Handler implements AppInterface { return (numReceiver > 0); } + + /** + * samsung send sms + * @param cmdPar + */ + private void handleProactiveCommandSendSMS(CommandParams cmdPar) { + CatLog.d(this, "The smscaddress is: " + ((SendSMSParams)cmdPar).smscAddress); + CatLog.d(this, "The SMS tpdu is: " + ((SendSMSParams)cmdPar).pdu); + mIccSms.sendRawPduSat(IccUtils.hexStringToBytes(((SendSMSParams)cmdPar).smscAddress), + IccUtils.hexStringToBytes(((SendSMSParams)cmdPar).pdu), null, null); + startTimeOut(WAITING_SMS_RESULT, WAITING_SMS_RESULT_TIME); + } + + private void cancelTimeOut() { + removeMessages(MSG_ID_TIMEOUT); + mTimeoutDest = 0; + } + + private void startTimeOut(int timeout, int delay) { + cancelTimeOut(); + mTimeoutDest = timeout; + sendMessageDelayed(obtainMessage(MSG_ID_TIMEOUT), delay); + } } diff --git a/telephony/java/com/android/internal/telephony/cat/CommandParams.java b/telephony/java/com/android/internal/telephony/cat/CommandParams.java index 959c9e2..31e8bbdb 100644 --- a/telephony/java/com/android/internal/telephony/cat/CommandParams.java +++ b/telephony/java/com/android/internal/telephony/cat/CommandParams.java @@ -192,3 +192,14 @@ class BIPClientParams extends CommandParams { return false; } } + +class SendSMSParams extends DisplayTextParams { + String pdu; + String smscAddress; + + SendSMSParams(CommandDetails cmdDet, TextMessage textmessage, String smscaddress, String smsPdu) { + super(cmdDet, textmessage); + smscAddress = smscaddress; + pdu = smsPdu; + } +} diff --git a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java index 89c1329..5b8ec5b 100644 --- a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java +++ b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java @@ -16,6 +16,7 @@ package com.android.internal.telephony.cat; +import android.content.res.Resources; import android.graphics.Bitmap; import android.os.Handler; import android.os.Message; @@ -134,43 +135,43 @@ class CommandParamsFactory extends Handler { case DISPLAY_TEXT: cmdPending = processDisplayText(cmdDet, ctlvs); break; - case SET_UP_IDLE_MODE_TEXT: - cmdPending = processSetUpIdleModeText(cmdDet, ctlvs); - break; - case GET_INKEY: + case SET_UP_IDLE_MODE_TEXT: + cmdPending = processSetUpIdleModeText(cmdDet, ctlvs); + break; + case GET_INKEY: cmdPending = processGetInkey(cmdDet, ctlvs); break; - case GET_INPUT: - cmdPending = processGetInput(cmdDet, ctlvs); - break; - case SEND_DTMF: - case SEND_SMS: - case SEND_SS: - case SEND_USSD: - cmdPending = processEventNotify(cmdDet, ctlvs); - break; - case SET_UP_CALL: - cmdPending = processSetupCall(cmdDet, ctlvs); - break; - case REFRESH: + case GET_INPUT: + cmdPending = processGetInput(cmdDet, ctlvs); + break; + case SEND_DTMF: + case SEND_SMS: + case SEND_SS: + case SEND_USSD: + cmdPending = processEventNotify(cmdDet, ctlvs); + break; + case SET_UP_CALL: + cmdPending = processSetupCall(cmdDet, ctlvs); + break; + case REFRESH: processRefresh(cmdDet, ctlvs); cmdPending = false; break; - case LAUNCH_BROWSER: - cmdPending = processLaunchBrowser(cmdDet, ctlvs); - break; - case PLAY_TONE: + case LAUNCH_BROWSER: + cmdPending = processLaunchBrowser(cmdDet, ctlvs); + break; + case PLAY_TONE: cmdPending = processPlayTone(cmdDet, ctlvs); break; - case PROVIDE_LOCAL_INFORMATION: + case PROVIDE_LOCAL_INFORMATION: cmdPending = processProvideLocalInfo(cmdDet, ctlvs); break; - case OPEN_CHANNEL: - case CLOSE_CHANNEL: - case RECEIVE_DATA: - case SEND_DATA: - cmdPending = processBIPClient(cmdDet, ctlvs); - break; + case OPEN_CHANNEL: + case CLOSE_CHANNEL: + case RECEIVE_DATA: + case SEND_DATA: + cmdPending = processBIPClient(cmdDet, ctlvs); + break; default: // unsupported proactive commands mCmdParams = new CommandParams(cmdDet); @@ -641,7 +642,34 @@ class CommandParamsFactory extends Handler { } textMsg.responseNeeded = false; - mCmdParams = new DisplayTextParams(cmdDet, textMsg); + + // samsung stk overlay + if (Resources.getSystem().getBoolean(com.android.internal.R.bool.config_samsung_stk)) { + String smscAddress = null; + String pdu = null; + + ctlv = searchForTag(ComprehensionTlvTag.ADDRESS, ctlvs); + if (ctlv != null) { + smscAddress = ValueParser.retrieveSMSCaddress(ctlv); + CatLog.d(this, "The smsc address is " + smscAddress); + } + else { + CatLog.d(this, "The smsc address is null"); + } + + ctlv = searchForTag(ComprehensionTlvTag.SMS_TPDU, ctlvs); + if (ctlv != null) { + pdu = ValueParser.retrieveSMSTPDU(ctlv); + CatLog.d(this, "The SMS tpdu is " + pdu); + } + else { + CatLog.d(this, "The SMS tpdu is null"); + } + mCmdParams = new SendSMSParams(cmdDet, textMsg, smscAddress, pdu); + } + else { + mCmdParams = new DisplayTextParams(cmdDet, textMsg); + } if (iconId != null) { mIconLoadState = LOAD_SINGLE_ICON; diff --git a/telephony/java/com/android/internal/telephony/cat/ValueParser.java b/telephony/java/com/android/internal/telephony/cat/ValueParser.java index 584d96c..66c0c67 100644 --- a/telephony/java/com/android/internal/telephony/cat/ValueParser.java +++ b/telephony/java/com/android/internal/telephony/cat/ValueParser.java @@ -338,4 +338,71 @@ abstract class ValueParser { throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); } } + + /** + * samsung part for converting byte[] to hexstring + * @param ctlv + * @return + * @throws ResultException + */ + static String retrieveSMSCaddress(ComprehensionTlv ctlv) + throws ResultException { + byte[] rawValue = ctlv.getRawValue(); + int valueIndex = ctlv.getValueIndex(); + int length = ctlv.getLength(); + byte[] outputValue = new byte[length + 1]; + + for (int k = 0; k <= length; k++) { + try { + outputValue[k] = rawValue[k + (valueIndex - 1)]; + } + catch (IndexOutOfBoundsException indexoutofboundsexception) { + throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); + } + } + if (length != 0) + return IccUtils.bytesToHexString(outputValue); + else + throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); + } + + /** + * + * @param ctlv + * @return + * @throws ResultException + */ + static String retrieveSMSTPDU(ComprehensionTlv ctlv) + throws ResultException { + byte[] rawValue = ctlv.getRawValue(); + int valueIndex = ctlv.getValueIndex(); + int pduLength = ctlv.getLength(); + byte[] outputValue; + int k; + String result; + if (rawValue[valueIndex + 2] % 2 == 0) + k = rawValue[valueIndex + 2] / 2; + else + k = (1 + rawValue[valueIndex + 2]) / 2; + + if (pduLength == k + 6) + outputValue = new byte[pduLength + 1]; + else + outputValue = new byte[pduLength]; + + for (int l = 0; l < pduLength; l++) { + try { + outputValue[l] = rawValue[valueIndex + l]; + } + catch (IndexOutOfBoundsException ex) { + throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); + } + } + if (pduLength != 0) + result = IccUtils.bytesToHexString(outputValue); + else + throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); + + return result; + } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index 58e3e5f..276c6c5 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -165,7 +165,7 @@ public class CDMAPhone extends PhoneBase { mSubInfo = new PhoneSubInfo(this); mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML); mCcatService = CatService.getInstance(mCM, mIccRecords, mContext, - mIccFileHandler, mIccCard); + mIccFileHandler, mIccCard, mRuimSmsInterfaceManager); mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null); diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java index bd80ca9..3a30f9c 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java +++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java @@ -147,7 +147,8 @@ public class GSMPhone extends PhoneBase { mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS); mSubInfo = new PhoneSubInfo(this); } - mStkService = CatService.getInstance(mCM, mIccRecords, mContext, mIccFileHandler, mIccCard); + mStkService = CatService.getInstance(mCM, mIccRecords, mContext, mIccFileHandler, mIccCard, + mSimSmsIntManager); mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index 21167a9..8e31e5a 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -1356,8 +1356,10 @@ final class GsmServiceStateTracker extends ServiceStateTracker { // As a special extension, the Android emulator appends the name of // the host computer's timezone to the nitz string. this is zoneinfo // timezone name of the form Area!Location or Area!Location!SubLocation - // so we need to convert the ! into / - if (nitzSubs.length >= 9) { + // so we need to convert the ! into /. If there's no "!", then maybe + // the carrier is appending something extra (as AT&T does) and it + // should be ignored + if ((nitzSubs.length >= 9) && (nitzSubs[8].indexOf('!') != -1)) { String tzname = nitzSubs[8].replace('!','/'); zone = TimeZone.getTimeZone( tzname ); } diff --git a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java index 583b1a5..e2ba8bf 100644 --- a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java +++ b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java @@ -414,4 +414,16 @@ class SipCommandInterface extends BaseCommands implements CommandsInterface { } public boolean needsOldRilFeature(String feature) { return false; } + + /** + * added samsung part to command interface + * @param h + * @param what + * @param obj + */ + public void setOnCatSendSmsResult(Handler h, int what, Object obj) { + } + + public void unSetOnCatSendSmsResult(Handler h) { + } } diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java index 710faa6..e662cd3 100644 --- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java +++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java @@ -17,6 +17,7 @@ package com.android.internal.telephony.test; import android.os.AsyncResult; +import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; @@ -1519,4 +1520,20 @@ public final class SimulatedCommands extends BaseCommands } public boolean needsOldRilFeature(String feature) { return false; } + + /** + * added samsung part to command interface + * @param h + * @param what + * @param obj + */ + public void setOnCatSendSmsResult(Handler h, int what, Object obj) { + } + + /** + * + * @param h + */ + public void unSetOnCatSendSmsResult(Handler h) { + } } diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java index 44aee91..4f77473 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java @@ -18,6 +18,7 @@ package com.android.internal.telephony.gsm; import android.content.Context; import android.os.AsyncResult; +import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.Log; @@ -611,4 +612,12 @@ class UsimDataDownloadCommands extends BaseCommands { @Override public boolean needsOldRilFeature(String feature) { return false; } + + @Override + public void setOnCatSendSmsResult(Handler h, int what, Object obj) { + } + + @Override + public void unSetOnCatSendSmsResult(Handler h) { + } } |