summaryrefslogtreecommitdiffstats
path: root/src/java
diff options
context:
space:
mode:
authorPawit Pornkitprasan <p.pawit@gmail.com>2012-11-24 08:34:56 +0700
committerChirayu Desai <cdesai@cyanogenmod.org>2012-11-24 18:45:21 +0530
commit301196aad4bd2efea2d8423e1ceb1c6414b8c74d (patch)
treeec8b1e39dc98e3f86a062a3c9ce15d8ffc43d017 /src/java
parent6db524cbc46a96464a4c807596b7ec4b909a24d7 (diff)
downloadframeworks_opt_telephony-301196aad4bd2efea2d8423e1ceb1c6414b8c74d.zip
frameworks_opt_telephony-301196aad4bd2efea2d8423e1ceb1c6414b8c74d.tar.gz
frameworks_opt_telephony-301196aad4bd2efea2d8423e1ceb1c6414b8c74d.tar.bz2
telephony: add SamsungExynos3RIL
forward ported from CM10 SamsungRIL commit 9cfdf50438f603196cd3c75b92ae5346968c2b6d Author: Pawit Pornkitprasan <p.pawit@gmail.com> Date: Thu Aug 2 20:24:38 2012 +0700 SamsungRIL: Fix data connection after pin unlock If the user has PIN-locked his phone, data connectivity will not work because the RIL sends APPSTATE_UNKNOWN and does not update it to APPSTATE_READY. We inject the state update if there's a signal change. Change-Id: Id64e95ebcadd1d7ff181f8d9c2ee4f18e6ae48f1 commit 7e06e52d2c23443a28c8ad756fe7ac9b883e6ba9 Author: Pawit Pornkitprasan <p.pawit@gmail.com> Date: Tue Jul 24 22:43:02 2012 +0700 SamsungRIL: Update HSDPA checking for jellybean Jellybean no longer publish network type id to prop, don't check for it Change-Id: I689aa448853677a8719af963bf3370abaefdaf23 commit caa215a26a958962b3e24b0f193698547ac7e317 Author: Pawit Pornkitprasan <p.pawit@gmail.com> Date: Wed Jul 18 10:54:08 2012 +0700 SamsungRIL: cleanup Removed unneeded states and forward them to RIL. In ics, this had the side-effect of allowing STK to work due to the Samsung STK implementation already in place cherry-picked from ics stk functionality for SamsungRIL * Implemented SMS based SIM application functionality * PatchSet 3: Added fix so unknown unsolicited response are sent to super class * PatchSet 4: Removed "import android.content.resources" - not needed any more * PatchSet 5: processUnsolicited cleanup, using super class standard states where possible * Patchset 6: Rebased Change-Id: I9bf844da1480fe442f851fb20d99b530b96cfa4c commit 3f876005b1c6c39a62c4eee3d5e54a3bc36e7faa Author: Daniel Bateman <jetison.24@gmail.com> Date: Sat Jul 14 11:27:07 2012 +0200 samsung ril: add UNSOL_AM implementation * The Samsung RIL will sometimes send up an UNSOL_AM request which is to be handled by the "am" service. (For example when the RIL resets) Change-Id: Ifc8ead91f2dbc39456c4a502b9623c608c796224 commit acdff5c2f175127fd2fdfc6ef4ae511b0f4bc329 Author: sbrissen <sbrissen@Hotmail.com> Date: Fri May 25 09:27:31 2012 -0400 Fix for Signal bars on Samsung devices Sometimes the CDMA ecio value is sent as a negative integer where we would expect a positive. This causes SignalStrength.java to mark ecio as -160 (Unknown_Signal_Strength) and making signal bar s clear out. This "fix" checks the ecio value and takes it absolute value if it is negative. Confirmed working on SCH-I500 and SPH-D710 Change-Id: Ic515dd6c92193cd5db75adf5bef93ecd617a5c6a commit 6308cb5329de73292665d8c8d538b09b4fe97fb3 Author: Daniel Bateman <jetison.24@gmail.com> Date: Mon Apr 23 22:24:01 2012 -0500 telephony: SamsungRIL cleanup == RIL == * remove unused "found" boolean in processSolicited * make requestToString/repsonseToString append the request ID on unknown requests. == Samsung RIL == * add CM copyright header to file * SAMSUNG_UNKNOWN_MAGIC_REQUEST_3 is actually UNSOL_AM * add DIAL_EMERGENCY to a SamsungRIL::requestToString * add DIAL_EMERGENCY response to processSolicited * move emergency dialing into dialEmergencyCall() * dialEmergencyCall() also ditches UUS info like on stock. * cleanup and improve readibility of responseCallList() * move isVideo before isVoicePrivacy, as it is in stock: ref "stock" code: http://pastebin.com/WePMyXDi ref "stock" order: isMpty then isMT then als then isVoice then isVideo then isVoicePrivacy ref cm code: http://pastebin.com/UU105gNr ref cm order: isMpty then isMT then als then isVoice then isVoicePrivacy then "videoMagic" * general cleanup Change-Id: Ic4ada0a3d6ac1bf580b3930a2599a91e822540ef Conflicts: telephony/java/com/android/internal/telephony/RIL.java commit e96b94500359b13fbbc186bf8b03418d82449f09 Author: Daniel Bateman <jetison.24@gmail.com> Date: Tue Apr 17 03:01:20 2012 -0500 SamsungRIL: clean up and re-organization Clean up some messy code in the Samsung RIL. Change-Id: If8bc9c0e4264de5919be1b6a858896076c879708 commit 7a3d8a991067e957ccd6b0159951f4b98d6d98f5 Author: Mike Kasick <mike@kasick.org> Date: Sat Mar 3 13:16:42 2012 -0500 SamsungRIL: Fixes for CDMA data reconnection failures due to stale pppd Occasionally the CDMA data connection fails to reconnect after various radio events, which is fixed neither by toggling mobile data nor airplane mode, but only by a reboot. One known cause of this problem is that the pppd_cdma service is occasionally left running after the radio event, which causes all subsequent "setup data call" operations to fail. These two fixes address the stale pppd_cdma service issue: - Move the pppd_cdma service shutdown (set ril.cdma.data_state=0) from the "deactivate data call" response to its request. This avoids the issue where the response never comes (radio crash?), and thus, the service is never stopped. - Force pppd_cdma service shutdown on a "setup data call" failure. This allows subsequent setup attempts to succeed in the event that the "deactivate" request was never made (unexpected radio poweroff). commit 3f647c94c54e8861cfe1b75120903c303a423ddb Author: Mike Kasick <mike@kasick.org> Date: Fri Feb 3 16:23:03 2012 -0500 Add more CDMA SamsungRIL fixes. Adds a collection of CDMA device fixes to SamsungRIL. They include: - Overriding ERROR_UNSPECIFIED fail cause with NORMAL_CLEARING, to prevent far-end hangups from displaying the "Call Lost" dialog. - Adding, and ignoring the RIL_UNSOL_GPS_NOTI request, which is also ignored in the TW RIL, to keep the radio log clean of exceptions when the GPS is active. - Workaround for Samsung CDMA "ring of death" bug. See source comments for details on this problem. Change-Id: Ida4797718ad3463d073a6fc27246cc916526d487 commit 65d22c288fec6a82d3350c68da0a76163bade668 Author: Mike Kasick <mike@kasick.org> Date: Sun Jan 29 17:32:13 2012 -0500 Fix support for CDMA devices in SamsungRIL. These fixes are ported from jt1134's fascinatemtd patches and CM7. For CM9, the fixes are applied to SamsungRIL directly instead of elsewhere in the telephony framework. They include: - Signal strength reporting: pass raw integer values. - Voice registration: convert base station values from hex to dec. - Data call setup/deactivate: start/stop pppd_cdma service and pull network parameters from pppd ip-up script. - CDMA subscription: add missing PRL version from system properties. Changes from CM7: Note use of "ril.cdma.data_state" property instead of "ril.cdma.data_ready". This property has three states: - Disconnect(ed): ril.cdma.data_state=0: stop pppd_cdma service. - Connecting: ril.cdma.data_state=1: (re)start pppd_cdma. - Connected: ril.cdma.data_state=2: pppd_cdma has responded. The disconnect (0) and connecting (1) states are set by SamsungRIL on the deactivation and setup, respectively, of a data call. Prior to setting the connecting (1) state, SamsungRIL sets the "net.cdma.datalinkinterface" for pppd_runner's use. After setting to the connecting (1) state, SamsungRIL waits for pppd_cdma to respond by (itself) setting the connected (2) state. This should be done at the end of a /system/etc/ppp/ip-up script, after that script sets the following interface values, which SamsungRIL uses to complete the data call state: - net.cdma.ppp.interface: $IFNAME (typically "ppp0") - net.$IFNAME.local-ip: pppd's local IPv4 address - net.$IFNAME.remote-ip: pppd's remote IPv4 address - net.$IFNAME.dns1: pppd's primary DNS address - net.$IFNAME.dns2: pppd's secondary DNS address commit 0b4354118b72c23d5ce003b065b42a1d9e3c5155 Author: Pawit Pornkitprasan <p.pawit@gmail.com> Date: Sat Jan 14 13:47:19 2012 +0700 telephony: Add SamsungRIL Patch Set 2: Fix Emergency calling for Samsung CDMA Patch Set 3: Do not extraneously send RIL poll requests due to extraneous HSDPA update Patch Set 4: Remove extraneous import accidentally added in Patch Set 3 commit 91cb0a82f785539986ee4f6ef95ccd8c789121d5 Author: Pawit Pornkitprasan <p.pawit@gmail.com> Date: Mon Dec 19 17:53:40 2011 +0700 SamsungRIL: ignore setCurrentPreferredNetworkType Change-Id: Ifa87949da3d807803db932e31c6c2dd053040c9c commit b578cdb7bf0222a05af65cb09cdfc53aa7457328 Author: Daniel Hillenbrand <info@codeworkx.de> Date: Mon Dec 12 18:32:35 2011 +0100 SamsungRIL: added unknown unsol request 11010 commit 259ccc34d53a0067c730c616814c0ec5fc788d95 Author: Pawit Pornkitprasan <p.pawit@gmail.com> Date: Sun Nov 27 12:06:34 2011 +0700 SamsungRIL: Always use v3 signal strength Our signal processing wouldn't make sense without it anyway. Change-Id: Ie101d6b220b00383aa18a9ac2c66e2ef786b7467 commit 1f5730d26e7e0dece905192b4dab6340336a8a21 Author: Pawit Pornkitprasan <p.pawit@gmail.com> Date: Fri Nov 18 21:15:34 2011 +0700 SamsungRIL: Fix datacall commit 1838b577a899a1f5259327361d95fe64f706c8e8 Author: Pawit Pornkitprasan <p.pawit@gmail.com> Date: Fri Nov 18 13:50:39 2011 +0700 SamsungRIL: Fix signal strength commit 1e23a1d363e7514b32703f604bdc96411cc35330 Author: Pawit Pornkitprasan <p.pawit@gmail.com> Date: Thu Nov 17 17:40:56 2011 +0700 Brings back SamsungRIL Change-Id: Ice09e25c8657aad0ddb345d240829789f28d18fb Change-Id: I06ee05b590e603413106a9a20ab85d65d4eb33cf
Diffstat (limited to 'src/java')
-rw-r--r--src/java/com/android/internal/telephony/SamsungExynos3RIL.java965
1 files changed, 965 insertions, 0 deletions
diff --git a/src/java/com/android/internal/telephony/SamsungExynos3RIL.java b/src/java/com/android/internal/telephony/SamsungExynos3RIL.java
new file mode 100644
index 0000000..5cf1933
--- /dev/null
+++ b/src/java/com/android/internal/telephony/SamsungExynos3RIL.java
@@ -0,0 +1,965 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2011, 2012 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.lang.Runtime;
+import java.io.IOException;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.os.Handler;
+import android.os.Message;
+import android.os.AsyncResult;
+import android.os.Parcel;
+import android.os.SystemProperties;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.SignalStrength;
+import android.telephony.SmsManager;
+import android.telephony.SmsMessage;
+import static com.android.internal.telephony.RILConstants.*;
+
+import com.android.internal.telephony.CallForwardInfo;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.DataCallState;
+import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
+import com.android.internal.telephony.gsm.SuppServiceNotification;
+import com.android.internal.telephony.IccCardApplicationStatus;
+import com.android.internal.telephony.IccCardStatus;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.SmsResponse;
+import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
+import com.android.internal.telephony.cdma.CdmaInformationRecords;
+import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec;
+import com.android.internal.telephony.cdma.SignalToneUtil;
+
+import android.util.Log;
+
+public class SamsungExynos3RIL extends RIL implements CommandsInterface {
+
+ private boolean mSignalbarCount = SystemProperties.getInt("ro.telephony.sends_barcount", 0) == 1 ? true : false;
+ private boolean mIsSamsungCdma = SystemProperties.getBoolean("ro.ril.samsung_cdma", false);
+
+ public SamsungExynos3RIL(Context context, int networkMode, int cdmaSubscription) {
+ super(context, networkMode, cdmaSubscription);
+ }
+
+ // SAMSUNG SGS STATES
+ static final int RIL_UNSOL_O2_HOME_ZONE_INFO = 11007;
+ static final int RIL_UNSOL_DEVICE_READY_NOTI = 11008;
+ static final int RIL_UNSOL_GPS_NOTI = 11009;
+ static final int RIL_UNSOL_AM = 11010;
+ static final int RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST = 11012;
+ static final int RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_2 = 11011;
+ static final int RIL_UNSOL_HSDPA_STATE_CHANGED = 11016;
+ static final int RIL_REQUEST_DIAL_EMERGENCY = 10016;
+
+ static String
+ requestToString(int request) {
+ switch (request) {
+ case RIL_REQUEST_DIAL_EMERGENCY: return "DIAL_EMERGENCY";
+ default: return RIL.requestToString(request);
+ }
+ }
+
+ @Override
+ public void
+ setRadioPower(boolean on, Message result) {
+ RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
+
+ if (on) {
+ rr.mp.writeInt(1);
+ rr.mp.writeInt(1);
+ } else {
+ rr.mp.writeInt(2);
+ rr.mp.writeInt(0);
+ rr.mp.writeInt(0);
+ }
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ send(rr);
+ }
+
+ @Override
+ protected void
+ processSolicited (Parcel p) {
+ int serial, error;
+
+ serial = p.readInt();
+ error = p.readInt();
+
+ Log.d(LOG_TAG, "Serial: " + serial);
+ Log.d(LOG_TAG, "Error: " + error);
+
+ RILRequest rr;
+
+ rr = findAndRemoveRequestFromList(serial);
+
+ if (rr == null) {
+ Log.w(LOG_TAG, "Unexpected solicited response! sn: "
+ + serial + " error: " + error);
+ return;
+ }
+
+ Object ret = null;
+
+ if (error == 0 || p.dataAvail() > 0) {
+ // either command succeeds or command fails but with data payload
+ try {switch (rr.mRequest) {
+ /*
+ cat libs/telephony/ril_commands.h \
+ | egrep "^ *{RIL_" \
+ | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: ret = \2(p); break;/'
+ */
+ case RIL_REQUEST_GET_SIM_STATUS: ret = responseIccCardStatus(p); break;
+ case RIL_REQUEST_ENTER_SIM_PIN: ret = responseInts(p); break;
+ case RIL_REQUEST_ENTER_SIM_PUK: ret = responseInts(p); break;
+ case RIL_REQUEST_ENTER_SIM_PIN2: ret = responseInts(p); break;
+ case RIL_REQUEST_ENTER_SIM_PUK2: ret = responseInts(p); break;
+ case RIL_REQUEST_CHANGE_SIM_PIN: ret = responseInts(p); break;
+ case RIL_REQUEST_CHANGE_SIM_PIN2: ret = responseInts(p); break;
+ case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: ret = responseInts(p); break;
+ case RIL_REQUEST_GET_CURRENT_CALLS: ret = responseCallList(p); break;
+ case RIL_REQUEST_DIAL: ret = responseVoid(p); break;
+ case RIL_REQUEST_GET_IMSI: ret = responseString(p); break;
+ case RIL_REQUEST_HANGUP: ret = responseVoid(p); break;
+ case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: ret = responseVoid(p); break;
+ case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: ret = responseVoid(p); break;
+ case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: ret = responseVoid(p); break;
+ case RIL_REQUEST_CONFERENCE: ret = responseVoid(p); break;
+ case RIL_REQUEST_UDUB: ret = responseVoid(p); break;
+ case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: ret = responseLastCallFailCause(p); break;
+ case RIL_REQUEST_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;
+ case RIL_REQUEST_VOICE_REGISTRATION_STATE: ret = responseVoiceRegistrationState(p); break;
+ case RIL_REQUEST_DATA_REGISTRATION_STATE: ret = responseStrings(p); break;
+ case RIL_REQUEST_OPERATOR: ret = responseStrings(p); break;
+ case RIL_REQUEST_RADIO_POWER: ret = responseVoid(p); break;
+ case RIL_REQUEST_DTMF: ret = responseVoid(p); break;
+ case RIL_REQUEST_SEND_SMS: ret = responseSMS(p); break;
+ case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret = responseSMS(p); break;
+ case RIL_REQUEST_SETUP_DATA_CALL: ret = responseSetupDataCall(p); break;
+ case RIL_REQUEST_SIM_IO: ret = responseICC_IO(p); break;
+ case RIL_REQUEST_SEND_USSD: ret = responseVoid(p); break;
+ case RIL_REQUEST_CANCEL_USSD: ret = responseVoid(p); break;
+ case RIL_REQUEST_GET_CLIR: ret = responseInts(p); break;
+ case RIL_REQUEST_SET_CLIR: ret = responseVoid(p); break;
+ case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS: ret = responseCallForward(p); break;
+ case RIL_REQUEST_SET_CALL_FORWARD: ret = responseVoid(p); break;
+ case RIL_REQUEST_QUERY_CALL_WAITING: ret = responseInts(p); break;
+ case RIL_REQUEST_SET_CALL_WAITING: ret = responseVoid(p); break;
+ case RIL_REQUEST_SMS_ACKNOWLEDGE: ret = responseVoid(p); break;
+ case RIL_REQUEST_GET_IMEI: ret = responseString(p); break;
+ case RIL_REQUEST_GET_IMEISV: ret = responseString(p); break;
+ case RIL_REQUEST_ANSWER: ret = responseVoid(p); break;
+ case RIL_REQUEST_DEACTIVATE_DATA_CALL: ret = responseVoid(p); break;
+ case RIL_REQUEST_QUERY_FACILITY_LOCK: ret = responseInts(p); break;
+ case RIL_REQUEST_SET_FACILITY_LOCK: ret = responseInts(p); break;
+ case RIL_REQUEST_CHANGE_BARRING_PASSWORD: ret = responseVoid(p); break;
+ case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: ret = responseInts(p); break;
+ case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: ret = responseVoid(p); break;
+ case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: ret = responseVoid(p); break;
+ case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS : ret = responseOperatorInfos(p); break;
+ case RIL_REQUEST_DTMF_START: ret = responseVoid(p); break;
+ case RIL_REQUEST_DTMF_STOP: ret = responseVoid(p); break;
+ case RIL_REQUEST_BASEBAND_VERSION: ret = responseString(p); break;
+ case RIL_REQUEST_SEPARATE_CONNECTION: ret = responseVoid(p); break;
+ case RIL_REQUEST_SET_MUTE: ret = responseVoid(p); break;
+ case RIL_REQUEST_GET_MUTE: ret = responseInts(p); break;
+ case RIL_REQUEST_QUERY_CLIP: ret = responseInts(p); break;
+ case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: ret = responseInts(p); break;
+ case RIL_REQUEST_DATA_CALL_LIST: ret = responseDataCallList(p); break;
+ case RIL_REQUEST_RESET_RADIO: ret = responseVoid(p); break;
+ case RIL_REQUEST_OEM_HOOK_RAW: ret = responseRaw(p); break;
+ case RIL_REQUEST_OEM_HOOK_STRINGS: ret = responseStrings(p); break;
+ case RIL_REQUEST_SCREEN_STATE: ret = responseVoid(p); break;
+ case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: ret = responseVoid(p); break;
+ case RIL_REQUEST_WRITE_SMS_TO_SIM: ret = responseInts(p); break;
+ case RIL_REQUEST_DELETE_SMS_ON_SIM: ret = responseVoid(p); break;
+ case RIL_REQUEST_SET_BAND_MODE: ret = responseVoid(p); break;
+ case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: ret = responseInts(p); break;
+ case RIL_REQUEST_STK_GET_PROFILE: ret = responseString(p); break;
+ case RIL_REQUEST_STK_SET_PROFILE: ret = responseVoid(p); break;
+ case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: ret = responseString(p); break;
+ case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: ret = responseVoid(p); break;
+ case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: ret = responseInts(p); break;
+ case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret = responseVoid(p); break;
+ case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret = responseVoid(p); break;
+ case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret = responseNetworkType(p); break;
+ case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: ret = responseCellList(p); break;
+ case RIL_REQUEST_SET_LOCATION_UPDATES: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE: ret = responseInts(p); break;
+ case RIL_REQUEST_SET_TTY_MODE: ret = responseVoid(p); break;
+ case RIL_REQUEST_QUERY_TTY_MODE: ret = responseInts(p); break;
+ case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: ret = responseInts(p); break;
+ case RIL_REQUEST_CDMA_FLASH: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_BURST_DTMF: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_SEND_SMS: ret = responseSMS(p); break;
+ case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: ret = responseVoid(p); break;
+ case RIL_REQUEST_GSM_GET_BROADCAST_CONFIG: ret = responseGmsBroadcastConfig(p); break;
+ case RIL_REQUEST_GSM_SET_BROADCAST_CONFIG: ret = responseVoid(p); break;
+ case RIL_REQUEST_GSM_BROADCAST_ACTIVATION: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG: ret = responseCdmaBroadcastConfig(p); break;
+ case RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_BROADCAST_ACTIVATION: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY: ret = responseVoid(p); break;
+ case RIL_REQUEST_CDMA_SUBSCRIPTION: ret = responseCdmaSubscription(p); break;
+ case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: ret = responseInts(p); break;
+ case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: ret = responseVoid(p); break;
+ case RIL_REQUEST_DEVICE_IDENTITY: ret = responseStrings(p); break;
+ case RIL_REQUEST_GET_SMSC_ADDRESS: ret = responseString(p); break;
+ case RIL_REQUEST_SET_SMSC_ADDRESS: ret = responseVoid(p); break;
+ case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
+ case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: ret = responseVoid(p); break;
+ case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: ret = responseVoid(p); break;
+ case RIL_REQUEST_DIAL_EMERGENCY: ret = responseVoid(p); break;
+ default:
+ throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
+ //break;
+ }} catch (Throwable tr) {
+ // Exceptions here usually mean invalid RIL responses
+
+ Log.w(LOG_TAG, rr.serialString() + "< "
+ + requestToString(rr.mRequest)
+ + " exception, possible invalid RIL response", tr);
+
+ if (rr.mResult != null) {
+ AsyncResult.forMessage(rr.mResult, null, tr);
+ rr.mResult.sendToTarget();
+ }
+ rr.release();
+ return;
+ }
+ }
+
+ if (error != 0) {
+ // Ugly fix for Samsung messing up SMS_SEND request fail in binary RIL
+ if (error == -1 && rr.mRequest == RIL_REQUEST_SEND_SMS)
+ {
+ try
+ {
+ ret = responseSMS(p);
+ } catch (Throwable tr) {
+ Log.w(LOG_TAG, rr.serialString() + "< "
+ + requestToString(rr.mRequest)
+ + " exception, Processing Samsung SMS fix ", tr);
+ rr.onError(error, ret);
+ rr.release();
+ return;
+ }
+ } else {
+ rr.onError(error, ret);
+ rr.release();
+ return;
+ }
+ }
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest)
+ + " " + retToString(rr.mRequest, ret));
+
+ if (rr.mResult != null) {
+ AsyncResult.forMessage(rr.mResult, ret, null);
+ rr.mResult.sendToTarget();
+ }
+
+ rr.release();
+ }
+
+ @Override
+ public void
+ dial(String address, int clirMode, UUSInfo uusInfo, Message result) {
+ RILRequest rr;
+ if (!mIsSamsungCdma && PhoneNumberUtils.isEmergencyNumber(address)) {
+ dialEmergencyCall(address, clirMode, result);
+ return;
+ }
+
+ rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
+ rr.mp.writeString(address);
+ rr.mp.writeInt(clirMode);
+ rr.mp.writeInt(0); // UUS information is absent
+
+ if (uusInfo == null) {
+ rr.mp.writeInt(0); // UUS information is absent
+ } else {
+ rr.mp.writeInt(1); // UUS information is present
+ rr.mp.writeInt(uusInfo.getType());
+ rr.mp.writeInt(uusInfo.getDcs());
+ rr.mp.writeByteArray(uusInfo.getUserData());
+ }
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+ send(rr);
+ }
+
+ public void
+ dialEmergencyCall(String address, int clirMode, Message result) {
+ RILRequest rr;
+ Log.v(LOG_TAG, "Emergency dial: " + address);
+
+ rr = RILRequest.obtain(RIL_REQUEST_DIAL_EMERGENCY, result);
+ rr.mp.writeString(address + "/");
+ rr.mp.writeInt(clirMode);
+ rr.mp.writeInt(0);
+ rr.mp.writeInt(0);
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+ send(rr);
+ }
+
+ @Override
+ protected void
+ processUnsolicited (Parcel p) {
+ int response;
+ Object ret;
+ int dataPosition = p.dataPosition();
+
+ response = p.readInt();
+
+ switch(response) {
+ /*
+ cat libs/telephony/ril_unsol_commands.h \
+ | egrep "^ *{RIL_" \
+ | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: \2(rr, p); break;/'
+ */
+
+ case RIL_UNSOL_NITZ_TIME_RECEIVED: ret = responseString(p); break;
+ case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;
+ case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break;
+ case RIL_UNSOL_HSDPA_STATE_CHANGED: ret = responseInts(p); break;
+
+ //fixing anoying Exceptions caused by the new Samsung states
+ //FIXME figure out what the states mean an what data is in the parcel
+
+ case RIL_UNSOL_O2_HOME_ZONE_INFO: ret = responseVoid(p); break;
+ case RIL_UNSOL_DEVICE_READY_NOTI: ret = responseVoid(p); break;
+ case RIL_UNSOL_GPS_NOTI: ret = responseVoid(p); break; // Ignored in TW RIL.
+ 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 = responseString(p); break;
+
+ default:
+ // Rewind the Parcel
+ p.setDataPosition(dataPosition);
+
+ // Forward responses that we are not overriding to the super class
+ super.processUnsolicited(p);
+ return;
+ }
+
+ switch(response) {
+ case RIL_UNSOL_HSDPA_STATE_CHANGED:
+ if (RILJ_LOGD) unsljLog(response);
+
+ boolean newHsdpa = ((int[])ret)[0] == 1;
+ String curState = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE);
+ boolean curHsdpa = false;
+
+ if (curState.startsWith("HSDPA")) {
+ curHsdpa = true;
+ } else if (!curState.startsWith("UMTS")) {
+ // Don't send poll request if not on 3g
+ break;
+ }
+
+ if (curHsdpa != newHsdpa) {
+ mVoiceNetworkStateRegistrants
+ .notifyRegistrants(new AsyncResult(null, null, null));
+ }
+ break;
+
+ case RIL_UNSOL_NITZ_TIME_RECEIVED:
+ if (RILJ_LOGD) unsljLogRet(response, ret);
+
+ // has bonus long containing milliseconds since boot that the NITZ
+ // time was received
+ long nitzReceiveTime = p.readLong();
+
+ Object[] result = new Object[2];
+
+ String nitz = (String)ret;
+ if (RILJ_LOGD) riljLog(" RIL_UNSOL_NITZ_TIME_RECEIVED length = "
+ + nitz.split("[/:,+-]").length);
+
+ // remove the tailing information that samsung added to the string
+ if(nitz.split("[/:,+-]").length >= 9)
+ nitz = nitz.substring(0,(nitz.lastIndexOf(",")));
+
+ if (RILJ_LOGD) riljLog(" RIL_UNSOL_NITZ_TIME_RECEIVED striped nitz = "
+ + nitz);
+
+ result[0] = nitz;
+ result[1] = Long.valueOf(nitzReceiveTime);
+
+ if (mNITZTimeRegistrant != null) {
+
+ mNITZTimeRegistrant
+ .notifyRegistrant(new AsyncResult (null, result, null));
+ } else {
+ // in case NITZ time registrant isnt registered yet
+ mLastNITZTimeInfo = nitz;
+ }
+ break;
+
+ case RIL_UNSOL_SIGNAL_STRENGTH:
+ // Note this is set to "verbose" because it happens
+ // frequently
+ if (RILJ_LOGV) unsljLogvRet(response, ret);
+
+ if (mSignalStrengthRegistrant != null) {
+ mSignalStrengthRegistrant.notifyRegistrant(
+ new AsyncResult (null, ret, null));
+ }
+ break;
+
+ case RIL_UNSOL_CDMA_INFO_REC:
+ ArrayList<CdmaInformationRecords> listInfoRecs;
+
+ try {
+ listInfoRecs = (ArrayList<CdmaInformationRecords>)ret;
+ } catch (ClassCastException e) {
+ Log.e(LOG_TAG, "Unexpected exception casting to listInfoRecs", e);
+ break;
+ }
+
+ for (CdmaInformationRecords rec : listInfoRecs) {
+ if (RILJ_LOGD) unsljLogRet(response, rec);
+ notifyRegistrantsCdmaInfoRec(rec);
+ }
+ break;
+
+ case RIL_UNSOL_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;
+ }
+ }
+
+ @Override
+ protected Object
+ responseCallList(Parcel p) {
+ int num;
+ boolean isVideo;
+ ArrayList<DriverCall> response;
+ DriverCall dc;
+ int dataAvail = p.dataAvail();
+ int pos = p.dataPosition();
+ int size = p.dataSize();
+
+ Log.d(LOG_TAG, "Parcel size = " + size);
+ Log.d(LOG_TAG, "Parcel pos = " + pos);
+ Log.d(LOG_TAG, "Parcel dataAvail = " + dataAvail);
+
+ num = p.readInt();
+ response = new ArrayList<DriverCall>(num);
+
+ for (int i = 0 ; i < num ; i++) {
+ if (mIsSamsungCdma)
+ dc = new SamsungDriverCall();
+ else
+ dc = new DriverCall();
+
+ dc.state = DriverCall.stateFromCLCC(p.readInt());
+ dc.index = p.readInt();
+ dc.TOA = p.readInt();
+ dc.isMpty = (0 != p.readInt());
+ dc.isMT = (0 != p.readInt());
+ dc.als = p.readInt();
+ dc.isVoice = (0 != p.readInt());
+ isVideo = (0 != p.readInt());
+ dc.isVoicePrivacy = (0 != p.readInt());
+ dc.number = p.readString();
+ int np = p.readInt();
+ dc.numberPresentation = DriverCall.presentationFromCLIP(np);
+ dc.name = p.readString();
+ dc.namePresentation = p.readInt();
+ int uusInfoPresent = p.readInt();
+
+ Log.d(LOG_TAG, "state = " + dc.state);
+ Log.d(LOG_TAG, "index = " + dc.index);
+ Log.d(LOG_TAG, "state = " + dc.TOA);
+ Log.d(LOG_TAG, "isMpty = " + dc.isMpty);
+ Log.d(LOG_TAG, "isMT = " + dc.isMT);
+ Log.d(LOG_TAG, "als = " + dc.als);
+ Log.d(LOG_TAG, "isVoice = " + dc.isVoice);
+ Log.d(LOG_TAG, "isVideo = " + isVideo);
+ Log.d(LOG_TAG, "number = " + dc.number);
+ Log.d(LOG_TAG, "numberPresentation = " + np);
+ Log.d(LOG_TAG, "name = " + dc.name);
+ Log.d(LOG_TAG, "namePresentation = " + dc.namePresentation);
+ Log.d(LOG_TAG, "uusInfoPresent = " + uusInfoPresent);
+
+ if (uusInfoPresent == 1) {
+ dc.uusInfo = new UUSInfo();
+ dc.uusInfo.setType(p.readInt());
+ dc.uusInfo.setDcs(p.readInt());
+ byte[] userData = p.createByteArray();
+ dc.uusInfo.setUserData(userData);
+ Log
+ .v(LOG_TAG, String.format("Incoming UUS : type=%d, dcs=%d, length=%d",
+ dc.uusInfo.getType(), dc.uusInfo.getDcs(),
+ dc.uusInfo.getUserData().length));
+ Log.v(LOG_TAG, "Incoming UUS : data (string)="
+ + new String(dc.uusInfo.getUserData()));
+ Log.v(LOG_TAG, "Incoming UUS : data (hex): "
+ + IccUtils.bytesToHexString(dc.uusInfo.getUserData()));
+ } else {
+ Log.v(LOG_TAG, "Incoming UUS : NOT present!");
+ }
+
+ // Make sure there's a leading + on addresses with a TOA of 145
+ dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA);
+
+ response.add(dc);
+
+ if (dc.isVoicePrivacy) {
+ mVoicePrivacyOnRegistrants.notifyRegistrants();
+ Log.d(LOG_TAG, "InCall VoicePrivacy is enabled");
+ } else {
+ mVoicePrivacyOffRegistrants.notifyRegistrants();
+ Log.d(LOG_TAG, "InCall VoicePrivacy is disabled");
+ }
+ }
+
+ Collections.sort(response);
+
+ return response;
+ }
+
+ protected Object
+ responseLastCallFailCause(Parcel p) {
+ int response[] = (int[])responseInts(p);
+
+ if (mIsSamsungCdma && response.length > 0 &&
+ response[0] == com.android.internal.telephony.cdma.CallFailCause.ERROR_UNSPECIFIED) {
+
+ // Far-end hangup returns ERROR_UNSPECIFIED, which shows "Call Lost" dialog.
+ Log.d(LOG_TAG, "Overriding ERROR_UNSPECIFIED fail cause with NORMAL_CLEARING.");
+ response[0] = com.android.internal.telephony.cdma.CallFailCause.NORMAL_CLEARING;
+ }
+
+ return response;
+ }
+
+ @Override
+ protected Object
+ responseSignalStrength(Parcel p) {
+ // When SIM is PIN-unlocked, the RIL responds with APPSTATE_UNKNOWN and
+ // does not follow up with RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED. We
+ // notify the system here.
+ String state = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE);
+ if (!"READY".equals(state) && mIccStatusChangedRegistrants != null) {
+ mIccStatusChangedRegistrants.notifyRegistrants();
+ }
+
+ int[] response = new int[7];
+ for (int i = 0 ; i < 7 ; i++) {
+ response[i] = p.readInt();
+ }
+
+ if (mIsSamsungCdma){
+ if(response[3] < 0){
+ response[3] = -response[3];
+ }
+ // Framework takes care of the rest for us.
+ }
+ else {
+ /* Matching Samsung signal strength to asu.
+ Method taken from Samsungs cdma/gsmSignalStateTracker */
+ 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
+ } else {
+ response[0] = response[0] & 0xFF; // gsmDbm
+ }
+ response[1] = -1; // gsmEcio
+ response[2] = (response[2] < 0)?-120:-response[2]; // cdmaDbm
+ response[3] = (response[3] < 0)?-160:-response[3]; // cdmaEcio
+ response[4] = (response[4] < 0)?-120:-response[4]; // evdoRssi
+ response[5] = (response[5] < 0)?-1:-response[5]; // evdoEcio
+ if(response[6] < 0 || response[6] > 8)
+ response[6] = -1;
+ }
+
+ SignalStrength signalStrength = new SignalStrength(
+ response[0], response[1], response[2], response[3], response[4],
+ response[5], response[6], !mIsSamsungCdma);
+ return signalStrength;
+ }
+
+ protected Object
+ responseVoiceRegistrationState(Parcel p) {
+ String response[] = (String[])responseStrings(p);
+
+ if (mIsSamsungCdma && response.length > 6) {
+ // These values are provided in hex, convert to dec.
+ response[4] = Integer.toString(Integer.parseInt(response[4], 16)); // baseStationId
+ response[5] = Integer.toString(Integer.parseInt(response[5], 16)); // baseStationLatitude
+ response[6] = Integer.toString(Integer.parseInt(response[6], 16)); // baseStationLongitude
+ }
+
+ return response;
+ }
+
+ protected Object
+ responseNetworkType(Parcel p) {
+ int response[] = (int[]) responseInts(p);
+
+ // When the modem responds Phone.NT_MODE_GLOBAL, it means Phone.NT_MODE_WCDMA_PREF
+ if (!mIsSamsungCdma && response[0] == Phone.NT_MODE_GLOBAL) {
+ Log.d(LOG_TAG, "Overriding network type response from global to WCDMA preferred");
+ response[0] = Phone.NT_MODE_WCDMA_PREF;
+ }
+
+ return response;
+ }
+
+ @Override
+ protected Object
+ responseSetupDataCall(Parcel p) {
+ DataCallState dataCall = new DataCallState();
+ String strings[] = (String []) responseStrings(p);
+
+ if (strings.length >= 2) {
+ dataCall.cid = Integer.parseInt(strings[0]);
+
+ if (mIsSamsungCdma) {
+ // We're responsible for starting/stopping the pppd_cdma service.
+ if (!startPppdCdmaService(strings[1])) {
+ // pppd_cdma service didn't respond timely.
+ dataCall.status = FailCause.ERROR_UNSPECIFIED.getErrorCode();
+ return dataCall;
+ }
+
+ // pppd_cdma service responded, pull network parameters set by ip-up script.
+ dataCall.ifname = SystemProperties.get("net.cdma.ppp.interface");
+ String ifprop = "net." + dataCall.ifname;
+
+ dataCall.addresses = new String[] {SystemProperties.get(ifprop + ".local-ip")};
+ dataCall.gateways = new String[] {SystemProperties.get(ifprop + ".remote-ip")};
+ dataCall.dnses = new String[] {SystemProperties.get(ifprop + ".dns1"),
+ SystemProperties.get(ifprop + ".dns2")};
+ } else {
+ dataCall.ifname = strings[1];
+
+ if (strings.length >= 3) {
+ dataCall.addresses = strings[2].split(" ");
+ }
+ }
+ } else {
+ if (mIsSamsungCdma) {
+ // On rare occasion the pppd_cdma service is left active from a stale
+ // session, causing the data call setup to fail. Make sure that pppd_cdma
+ // is stopped now, so that the next setup attempt may succeed.
+ Log.d(LOG_TAG, "Set ril.cdma.data_state=0 to make sure pppd_cdma is stopped.");
+ SystemProperties.set("ril.cdma.data_state", "0");
+ }
+
+ dataCall.status = FailCause.ERROR_UNSPECIFIED.getErrorCode(); // Who knows?
+ }
+
+ return dataCall;
+ }
+
+ private boolean startPppdCdmaService(String ttyname) {
+ SystemProperties.set("net.cdma.datalinkinterface", ttyname);
+
+ // Connecting: Set ril.cdma.data_state=1 to (re)start pppd_cdma service,
+ // which responds by setting ril.cdma.data_state=2 once connection is up.
+ SystemProperties.set("ril.cdma.data_state", "1");
+ Log.d(LOG_TAG, "Set ril.cdma.data_state=1, waiting for ril.cdma.data_state=2.");
+
+ // Typically takes < 200 ms on my Epic, so sleep in 100 ms intervals.
+ for (int i = 0; i < 10; i++) {
+ try {Thread.sleep(100);} catch (InterruptedException e) {}
+
+ if (SystemProperties.getInt("ril.cdma.data_state", 1) == 2) {
+ Log.d(LOG_TAG, "Got ril.cdma.data_state=2, connected.");
+ return true;
+ }
+ }
+
+ // Taking > 1 s here, try up to 10 s, which is hopefully long enough.
+ for (int i = 1; i < 10; i++) {
+ try {Thread.sleep(1000);} catch (InterruptedException e) {}
+
+ if (SystemProperties.getInt("ril.cdma.data_state", 1) == 2) {
+ Log.d(LOG_TAG, "Got ril.cdma.data_state=2, connected.");
+ return true;
+ }
+ }
+
+ // Disconnect: Set ril.cdma.data_state=0 to stop pppd_cdma service.
+ Log.d(LOG_TAG, "Didn't get ril.cdma.data_state=2 timely, aborting.");
+ SystemProperties.set("ril.cdma.data_state", "0");
+
+ return false;
+ }
+
+ @Override
+ public void
+ deactivateDataCall(int cid, int reason, Message result) {
+ if (mIsSamsungCdma) {
+ // Disconnect: Set ril.cdma.data_state=0 to stop pppd_cdma service.
+ Log.d(LOG_TAG, "Set ril.cdma.data_state=0.");
+ SystemProperties.set("ril.cdma.data_state", "0");
+ }
+
+ super.deactivateDataCall(cid, reason, result);
+ }
+
+ protected Object
+ responseCdmaSubscription(Parcel p) {
+ String response[] = (String[])responseStrings(p);
+
+ if (/* mIsSamsungCdma && */ response.length == 4) {
+ // PRL version is missing in subscription parcel, add it from properties.
+ String prlVersion = SystemProperties.get("ril.prl_ver_1").split(":")[1];
+ response = new String[] {response[0], response[1], response[2],
+ response[3], prlVersion};
+ }
+
+ return response;
+ }
+
+ // Workaround for Samsung CDMA "ring of death" bug:
+ //
+ // Symptom: As soon as the phone receives notice of an incoming call, an
+ // audible "old fashioned ring" is emitted through the earpiece and
+ // persists through the duration of the call, or until reboot if the call
+ // isn't answered.
+ //
+ // Background: The CDMA telephony stack implements a number of "signal info
+ // tones" that are locally generated by ToneGenerator and mixed into the
+ // voice call path in response to radio RIL_UNSOL_CDMA_INFO_REC requests.
+ // One of these tones, IS95_CONST_IR_SIG_IS54B_L, is requested by the
+ // radio just prior to notice of an incoming call when the voice call
+ // path is muted. CallNotifier is responsible for stopping all signal
+ // tones (by "playing" the TONE_CDMA_SIGNAL_OFF tone) upon receipt of a
+ // "new ringing connection", prior to unmuting the voice call path.
+ //
+ // Problem: CallNotifier's incoming call path is designed to minimize
+ // latency to notify users of incoming calls ASAP. Thus,
+ // SignalInfoTonePlayer requests are handled asynchronously by spawning a
+ // one-shot thread for each. Unfortunately the ToneGenerator API does
+ // not provide a mechanism to specify an ordering on requests, and thus,
+ // unexpected thread interleaving may result in ToneGenerator processing
+ // them in the opposite order that CallNotifier intended. In this case,
+ // playing the "signal off" tone first, followed by playing the "old
+ // fashioned ring" indefinitely.
+ //
+ // Solution: An API change to ToneGenerator is required to enable
+ // SignalInfoTonePlayer to impose an ordering on requests (i.e., drop any
+ // request that's older than the most recent observed). Such a change,
+ // or another appropriate fix should be implemented in AOSP first.
+ //
+ // Workaround: Intercept RIL_UNSOL_CDMA_INFO_REC requests from the radio,
+ // check for a signal info record matching IS95_CONST_IR_SIG_IS54B_L, and
+ // drop it so it's never seen by CallNotifier. If other signal tones are
+ // observed to cause this problem, they should be dropped here as well.
+ @Override
+ protected void
+ notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) {
+ final int response = RIL_UNSOL_CDMA_INFO_REC;
+
+ if (/* mIsSamsungCdma && */ infoRec.record instanceof CdmaSignalInfoRec) {
+ CdmaSignalInfoRec sir = (CdmaSignalInfoRec)infoRec.record;
+ if (sir != null && sir.isPresent &&
+ sir.signalType == SignalToneUtil.IS95_CONST_IR_SIGNAL_IS54B &&
+ sir.alertPitch == SignalToneUtil.IS95_CONST_IR_ALERT_MED &&
+ sir.signal == SignalToneUtil.IS95_CONST_IR_SIG_IS54B_L) {
+
+ Log.d(LOG_TAG, "Dropping \"" + responseToString(response) + " " +
+ retToString(response, sir) + "\" to prevent \"ring of death\" bug.");
+ return;
+ }
+ }
+
+ super.notifyRegistrantsCdmaInfoRec(infoRec);
+ }
+
+ protected class SamsungDriverCall extends DriverCall {
+ @Override
+ public String
+ toString() {
+ // Samsung CDMA devices' call parcel is formatted differently
+ // fake unused data for video calls, and fix formatting
+ // so that voice calls' information can be correctly parsed
+ return "id=" + index + ","
+ + state + ","
+ + "toa=" + TOA + ","
+ + (isMpty ? "conf" : "norm") + ","
+ + (isMT ? "mt" : "mo") + ","
+ + "als=" + als + ","
+ + (isVoice ? "voc" : "nonvoc") + ","
+ + "nonvid" + ","
+ + number + ","
+ + "cli=" + numberPresentation + ","
+ + "name=" + name + ","
+ + namePresentation;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setCurrentPreferredNetworkType() {
+ if (RILJ_LOGD) riljLog("setCurrentPreferredNetworkType IGNORED");
+ /* Google added this as a fix for crespo loosing network type after
+ * taking an OTA. This messes up the data connection state for us
+ * due to the way we handle network type change (disable data
+ * then change then re-enable).
+ */
+ }
+
+ @Override
+ public void setPreferredNetworkType(int networkType , Message response) {
+ /* Samsung modem implementation does bad things when a datacall is running
+ * while switching the preferred networktype.
+ */
+ ConnectivityManager cm =
+ (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+ if(cm.getMobileDataEnabled())
+ {
+ ConnectivityHandler handler = new ConnectivityHandler(mContext);
+ handler.setPreferedNetworkType(networkType, response);
+ } else {
+ sendPreferedNetworktype(networkType, response);
+ }
+ }
+
+
+ //Sends the real RIL request to the modem.
+ private void sendPreferedNetworktype(int networkType, Message response) {
+ RILRequest rr = RILRequest.obtain(
+ RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response);
+
+ rr.mp.writeInt(1);
+ rr.mp.writeInt(networkType);
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ + " : " + networkType);
+
+ send(rr);
+ }
+ /* private class that does the handling for the dataconnection
+ * dataconnection is done async, so we send the request for disabling it,
+ * wait for the response, set the prefered networktype and notify the
+ * real sender with its result.
+ */
+ private class ConnectivityHandler extends Handler{
+
+ private static final int MESSAGE_SET_PREFERRED_NETWORK_TYPE = 30;
+ private Context mContext;
+ private int mDesiredNetworkType;
+ //the original message, we need it for calling back the original caller when done
+ private Message mNetworktypeResponse;
+ private ConnectivityBroadcastReceiver mConnectivityReceiver = new ConnectivityBroadcastReceiver();
+
+ public ConnectivityHandler(Context context)
+ {
+ mContext = context;
+ }
+
+ private void startListening() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ mContext.registerReceiver(mConnectivityReceiver, filter);
+ }
+
+ private synchronized void stopListening() {
+ mContext.unregisterReceiver(mConnectivityReceiver);
+ }
+
+ public void setPreferedNetworkType(int networkType, Message response)
+ {
+ Log.d(LOG_TAG, "Mobile Dataconnection is online setting it down");
+ mDesiredNetworkType = networkType;
+ mNetworktypeResponse = response;
+ ConnectivityManager cm =
+ (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ //start listening for the connectivity change broadcast
+ startListening();
+ cm.setMobileDataEnabled(false);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ //networktype was set, now we can enable the dataconnection again
+ case MESSAGE_SET_PREFERRED_NETWORK_TYPE:
+ ConnectivityManager cm =
+ (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+ Log.d(LOG_TAG, "preferred NetworkType set upping Mobile Dataconnection");
+
+ cm.setMobileDataEnabled(true);
+ //everything done now call back that we have set the networktype
+ AsyncResult.forMessage(mNetworktypeResponse, null, null);
+ mNetworktypeResponse.sendToTarget();
+ mNetworktypeResponse = null;
+ break;
+ default:
+ throw new RuntimeException("unexpected event not handled");
+ }
+ }
+
+ private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ Log.w(LOG_TAG, "onReceived() called with " + intent);
+ return;
+ }
+ boolean noConnectivity =
+ intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
+
+ if (noConnectivity) {
+ //Ok dataconnection is down, now set the networktype
+ Log.w(LOG_TAG, "Mobile Dataconnection is now down setting preferred NetworkType");
+ stopListening();
+ sendPreferedNetworktype(mDesiredNetworkType, obtainMessage(MESSAGE_SET_PREFERRED_NETWORK_TYPE));
+ mDesiredNetworkType = -1;
+ }
+ }
+ }
+ }
+}