Loading telephony/java/com/android/internal/telephony/SamsungRIL.java +77 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ 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; Loading @@ -47,6 +49,7 @@ public class SamsungRIL extends RIL implements CommandsInterface { static final int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002; 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_SAMSUNG_UNKNOWN_MAGIC_REQUEST_3 = 11010; static final int RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_2 = 11011; static final int RIL_UNSOL_HSDPA_STATE_CHANGED = 11016; Loading Loading @@ -121,7 +124,7 @@ public class SamsungRIL extends RIL implements CommandsInterface { 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 = responseInts(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; Loading Loading @@ -343,6 +346,7 @@ public class SamsungRIL extends RIL implements CommandsInterface { case RIL_UNSOL_O2_HOME_ZONE_INFO: ret = responseVoid(p); break; case RIL_UNSOL_STK_SEND_SMS_RESULT: 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_SAMSUNG_UNKNOWN_MAGIC_REQUEST_3: ret = responseVoid(p); break; Loading Loading @@ -776,6 +780,22 @@ public class SamsungRIL extends RIL implements CommandsInterface { 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) { Loading Loading @@ -943,6 +963,62 @@ public class SamsungRIL extends RIL implements CommandsInterface { 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 Loading Loading
telephony/java/com/android/internal/telephony/SamsungRIL.java +77 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ 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; Loading @@ -47,6 +49,7 @@ public class SamsungRIL extends RIL implements CommandsInterface { static final int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002; 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_SAMSUNG_UNKNOWN_MAGIC_REQUEST_3 = 11010; static final int RIL_UNSOL_SAMSUNG_UNKNOWN_MAGIC_REQUEST_2 = 11011; static final int RIL_UNSOL_HSDPA_STATE_CHANGED = 11016; Loading Loading @@ -121,7 +124,7 @@ public class SamsungRIL extends RIL implements CommandsInterface { 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 = responseInts(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; Loading Loading @@ -343,6 +346,7 @@ public class SamsungRIL extends RIL implements CommandsInterface { case RIL_UNSOL_O2_HOME_ZONE_INFO: ret = responseVoid(p); break; case RIL_UNSOL_STK_SEND_SMS_RESULT: 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_SAMSUNG_UNKNOWN_MAGIC_REQUEST_3: ret = responseVoid(p); break; Loading Loading @@ -776,6 +780,22 @@ public class SamsungRIL extends RIL implements CommandsInterface { 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) { Loading Loading @@ -943,6 +963,62 @@ public class SamsungRIL extends RIL implements CommandsInterface { 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 Loading