Fix bug 2040024 phone rings only once sometimes.

The phone only rang once on rings that did't loop. In the GSM phones
the vendor ril sends a RIL_UNSOL_CALL_RING event to cause the phone
to properly play non-looping ring tones. To reproduce select a non-looping
ring tone such as "Digital Phone" and call it from another phone, the
phone will only ring once.

Three solutions were discussed:

*) Have all ring tones loop; rejected because to more space would be taken
by the silence.

*) Require all vendor RIL's to send RIL_UNSOL_CALL_RING; rejected because
it is inefficient to send a notification from the bottom of the stack.

*) Modify the PhoneApp or the audio layer; rejected because it would be
to big of change.

*) Modify the framework; this is the solution accepted.

The framework was modified to use two now properties to control the
call ring notification.

ro.telephony.multiple_call_ring: a boolean that if true the vendor ril
is assumed to send multiple RIL_UNSOL_CALL_RING messages. If false
only one is assumed and the framework will generate additional events.
(The default if absent is true).

ro.telephony.call_ring_delay: the delay in milli-seconds between
the generated events. (default if absent is 3000)

To minimize code duplication this change does some reorganization
of the PhoneBase class hierarchy and PhoneBase becomes a handler
and implements a default handleMessage method handles events associated
with call ring notification. This handler is overridden by derived
classes, CDMAPhone and GSMPhone which will pass unknown events
to PhoneBase.handleMessage and thus handle call notification for any
derived class.

Change-Id: I5b147b2b69b647d9987052f16ada41c9b66e4bf1
This commit is contained in:
Wink Saville
2009-08-28 11:10:09 -07:00
parent 6d45accc71
commit a3659232ba
7 changed files with 428 additions and 389 deletions

View File

@ -1388,7 +1388,7 @@ public interface Phone {
*/
String getIccSerialNumber();
//***** CDMA support methods
/* CDMA support methods */
/*
* TODO(Moto) TODO(Teleca): can getCdmaMin, getEsn, getMeid use more generic calls

View File

@ -31,7 +31,6 @@ import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.text.TextUtils;
import android.util.Log;
@ -55,7 +54,7 @@ import java.util.Locale;
*
*/
public abstract class PhoneBase implements Phone {
public abstract class PhoneBase extends Handler implements Phone {
private static final String LOG_TAG = "PHONE";
private static final boolean LOCAL_DEBUG = true;
@ -68,7 +67,7 @@ public abstract class PhoneBase implements Phone {
// Key used to read/write "disable data connection on boot" pref (used for testing)
public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
//***** Event Constants
/* Event Constants */
protected static final int EVENT_RADIO_AVAILABLE = 1;
/** Supplementary Service Notification received. */
protected static final int EVENT_SSN = 2;
@ -84,20 +83,22 @@ public abstract class PhoneBase implements Phone {
protected static final int EVENT_SET_CALL_FORWARD_DONE = 12;
protected static final int EVENT_GET_CALL_FORWARD_DONE = 13;
protected static final int EVENT_CALL_RING = 14;
protected static final int EVENT_CALL_RING_CONTINUE = 15;
// Used to intercept the carrier selection calls so that
// we can save the values.
protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE = 15;
protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 16;
protected static final int EVENT_SET_CLIR_COMPLETE = 17;
protected static final int EVENT_REGISTERED_TO_NETWORK = 18;
protected static final int EVENT_SET_VM_NUMBER_DONE = 19;
protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE = 16;
protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 17;
protected static final int EVENT_SET_CLIR_COMPLETE = 18;
protected static final int EVENT_REGISTERED_TO_NETWORK = 19;
protected static final int EVENT_SET_VM_NUMBER_DONE = 20;
// Events for CDMA support
protected static final int EVENT_GET_DEVICE_IDENTITY_DONE = 20;
protected static final int EVENT_RUIM_RECORDS_LOADED = 21;
protected static final int EVENT_NV_READY = 22;
protected static final int EVENT_SET_ENHANCED_VP = 23;
protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER = 24;
protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 25;
protected static final int EVENT_GET_DEVICE_IDENTITY_DONE = 21;
protected static final int EVENT_RUIM_RECORDS_LOADED = 22;
protected static final int EVENT_NV_READY = 23;
protected static final int EVENT_SET_ENHANCED_VP = 24;
protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER = 25;
protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
// Key used to read/write current CLIR setting
public static final String CLIR_KEY = "clir_key";
@ -105,11 +106,14 @@ public abstract class PhoneBase implements Phone {
// Key used to read/write "disable DNS server check" pref (used for testing)
public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
//***** Instance Variables
/* Instance Variables */
public CommandsInterface mCM;
protected IccFileHandler mIccFileHandler;
boolean mDnsCheckDisabled = false;
public DataConnectionTracker mDataConnection;
boolean mDoesRilSendMultipleCallRing;
int mCallRingContinueToken = 0;
int mCallRingDelay;
/**
* Set a system property, unless we're in unit test mode
@ -172,8 +176,8 @@ public abstract class PhoneBase implements Phone {
* @param notifier An instance of DefaultPhoneNotifier,
* unless unit testing.
*/
protected PhoneBase(PhoneNotifier notifier, Context context) {
this(notifier, context, false);
protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci) {
this(notifier, context, ci, false);
}
/**
@ -185,11 +189,12 @@ public abstract class PhoneBase implements Phone {
* @param unitTestMode when true, prevents notifications
* of state change events
*/
protected PhoneBase(PhoneNotifier notifier, Context context,
protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
boolean unitTestMode) {
this.mNotifier = notifier;
this.mContext = context;
mLooper = Looper.myLooper();
mCM = ci;
setPropertiesByCarrier();
@ -197,6 +202,70 @@ public abstract class PhoneBase implements Phone {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
mCM.setOnCallRing(this, EVENT_CALL_RING, null);
/**
* Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
* to be generated locally. Ideally all ring tones should be loops
* and this wouldn't be necessary. But to minimize changes to upper
* layers it is requested that it be generated by lower layers.
*
* By default old phones won't have the property set but do generate
* the RIL_UNSOL_CALL_RING so the default if there is no property is
* true.
*/
mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
Log.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
mCallRingDelay = SystemProperties.getInt(
TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
Log.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
}
public void dispose() {
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
mCM.unSetOnCallRing(this);
}
}
/**
* When overridden the derived class needs to call
* super.handleMessage(msg) so this method has a
* a chance to process the message.
*
* @param msg
*/
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
switch(msg.what) {
case EVENT_CALL_RING:
Log.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
Phone.State state = getState();
if ((!mDoesRilSendMultipleCallRing)
&& ((state == Phone.State.RINGING) || (state == Phone.State.IDLE))) {
mCallRingContinueToken += 1;
sendIncomingCallRingNotification(mCallRingContinueToken);
} else {
notifyIncomingRing();
}
}
break;
case EVENT_CALL_RING_CONTINUE:
Log.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received stat=" + getState());
if (getState() == Phone.State.RINGING) {
sendIncomingCallRingNotification(msg.arg1);
}
break;
default:
throw new RuntimeException("unexpected event not handled");
}
}
// Inherited documentation suffices.
@ -290,16 +359,6 @@ public abstract class PhoneBase implements Phone {
mCM.unregisterForInCallVoicePrivacyOff(h);
}
/**
* Notifiy registrants of a new ringing Connection.
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
protected void notifyNewRingingConnectionP(Connection cn) {
AsyncResult ar = new AsyncResult(null, cn, null);
mNewRingingConnectionRegistrants.notifyRegistrants(ar);
}
// Inherited documentation suffices.
public void registerForIncomingRing(
Handler h, int what, Object obj) {
@ -553,16 +612,22 @@ public abstract class PhoneBase implements Phone {
}
}
/*
* Retrieves the Handler of the Phone instance
/**
* Get state
*/
public abstract Handler getHandler();
public abstract Phone.State getState();
/**
* Retrieves the IccFileHandler of the Phone instance
*/
public abstract IccFileHandler getIccFileHandler();
/*
* Retrieves the Handler of the Phone instance
*/
public Handler getHandler() {
return this;
}
/**
* Query the status of the CDMA roaming preference
@ -902,4 +967,39 @@ public abstract class PhoneBase implements Phone {
mDataConnection.setState(dcState);
notifyDataConnection(null);
}
/**
* Notifiy registrants of a new ringing Connection.
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
protected void notifyNewRingingConnectionP(Connection cn) {
AsyncResult ar = new AsyncResult(null, cn, null);
mNewRingingConnectionRegistrants.notifyRegistrants(ar);
}
/**
* Notify registrants of a RING event.
*/
private void notifyIncomingRing() {
AsyncResult ar = new AsyncResult(null, this, null);
mIncomingRingRegistrants.notifyRegistrants(ar);
}
/**
* Send the incoming call Ring notification if conditions are right.
*/
private void sendIncomingCallRingNotification(int token) {
if (!mDoesRilSendMultipleCallRing && (token == mCallRingContinueToken)) {
Log.d(LOG_TAG, "Sending notifyIncomingRing");
notifyIncomingRing();
sendMessageDelayed(
obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
} else {
Log.d(LOG_TAG, "Ignoring ring notification request,"
+ " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
+ " token=" + token
+ " mCallRingContinueToken=" + mCallRingContinueToken);
}
}
}

View File

@ -120,4 +120,14 @@ public interface TelephonyProperties
*/
static final String PROPERTY_DISABLE_CALL = "ro.telephony.disable-call";
/**
* Set to true for vendor RIL's that send multiple UNSOL_CALL_RING notifications.
*/
static final String PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING =
"ro.telephony.call_ring.multiple";
/**
* The number of milli-seconds between CALL_RING notifications.
*/
static final String PROPERTY_CALL_RING_DELAY = "ro.telephony.call_ring.delay";
}

View File

@ -26,7 +26,6 @@ import android.database.SQLException;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
@ -35,7 +34,6 @@ import android.os.RegistrantList;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Telephony;
import android.telephony.CellLocation;
import android.telephony.PhoneNumberUtils;
@ -96,20 +94,20 @@ public class CDMAPhone extends PhoneBase {
static final int RESTART_ECM_TIMER = 0; // restart Ecm timer
static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer
//***** Instance Variables
// Instance Variables
CdmaCallTracker mCT;
CdmaSMSDispatcher mSMS;
CdmaServiceStateTracker mSST;
RuimFileHandler mRuimFileHandler;
RuimRecords mRuimRecords;
RuimCard mRuimCard;
MyHandler h;
RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
RuimSmsInterfaceManager mRuimSmsInterfaceManager;
PhoneSubInfo mSubInfo;
EriManager mEriManager;
WakeLock mWakeLock;
// mNvLoadedRegistrants are informed after the EVENT_NV_READY
private RegistrantList mNvLoadedRegistrants = new RegistrantList();
@ -139,17 +137,14 @@ public class CDMAPhone extends PhoneBase {
Registrant mPostDialHandler;
//***** Constructors
// Constructors
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
this(context,ci,notifier, false);
}
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode) {
super(notifier, context, unitTestMode);
h = new MyHandler();
mCM = ci;
super(notifier, context, ci, unitTestMode);
mCM.setPhoneType(RILConstants.CDMA_PHONE);
mCT = new CdmaCallTracker(this);
@ -164,15 +159,14 @@ public class CDMAPhone extends PhoneBase {
mSubInfo = new PhoneSubInfo(this);
mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null);
mRuimRecords.registerForRecordsLoaded(h, EVENT_RUIM_RECORDS_LOADED, null);
mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCM.registerForOn(h, EVENT_RADIO_ON, null);
mCM.setOnSuppServiceNotification(h, EVENT_SSN, null);
mCM.setOnCallRing(h, EVENT_CALL_RING, null);
mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null);
mCM.registerForNVReady(h, EVENT_NV_READY, null);
mCM.setEmergencyCallbackMode(h, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
mRuimRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCM.registerForOn(this, EVENT_RADIO_ON, null);
mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
mSST.registerForNetworkAttach(this, EVENT_REGISTERED_TO_NETWORK, null);
mCM.registerForNVReady(this, EVENT_NV_READY, null);
mCM.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
PowerManager pm
= (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@ -207,23 +201,23 @@ public class CDMAPhone extends PhoneBase {
// Updates MCC MNC device configuration information
updateMccMncConfiguration(operatorNumeric);
// Notify voicemails.
notifier.notifyMessageWaitingChanged(this);
}
public void dispose() {
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
super.dispose();
//Unregister from all former registered events
mRuimRecords.unregisterForRecordsLoaded(h); //EVENT_RUIM_RECORDS_LOADED
mCM.unregisterForAvailable(h); //EVENT_RADIO_AVAILABLE
mCM.unregisterForOffOrNotAvailable(h); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
mCM.unregisterForOn(h); //EVENT_RADIO_ON
mCM.unregisterForNVReady(h); //EVENT_NV_READY
mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnSuppServiceNotification(h);
mCM.unSetOnCallRing(h);
mRuimRecords.unregisterForRecordsLoaded(this); //EVENT_RUIM_RECORDS_LOADED
mCM.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE
mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
mCM.unregisterForOn(this); //EVENT_RADIO_ON
mCM.unregisterForNVReady(this); //EVENT_NV_READY
mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnSuppServiceNotification(this);
//Force all referenced classes to unregister their former registered events
mCT.dispose();
@ -262,8 +256,6 @@ public class CDMAPhone extends PhoneBase {
}
}
//***** Overridden from Phone
public ServiceState getServiceState() {
return mSST.ss;
}
@ -701,7 +693,7 @@ public class CDMAPhone extends PhoneBase {
Message onComplete) {
Message resp;
mVmNumber = voiceMailNumber;
resp = h.obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
mRuimRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
}
@ -826,14 +818,6 @@ public class CDMAPhone extends PhoneBase {
super.notifyNewRingingConnectionP(c);
}
/**
* Notifiy registrants of a RING event.
*/
void notifyIncomingRing() {
AsyncResult ar = new AsyncResult(null, this, null);
mIncomingRingRegistrants.notifyRegistrants(ar);
}
/*package*/ void notifyDisconnect(Connection cn) {
mDisconnectRegistrants.notifyResult(cn);
}
@ -883,7 +867,7 @@ public class CDMAPhone extends PhoneBase {
mWakeLock.release();
}
// Send a message which will invoke handleExitEmergencyCallbackMode
mCM.exitEmergencyCallbackMode(h.obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
mCM.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
}
private void handleEnterEmergencyCallbackMode(Message msg) {
@ -902,7 +886,7 @@ public class CDMAPhone extends PhoneBase {
// if no one invokes exitEmergencyCallbackMode() directly.
long delayInMillis = SystemProperties.getLong(
TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
h.postDelayed(mExitEcmRunnable, delayInMillis);
postDelayed(mExitEcmRunnable, delayInMillis);
// We don't want to go to sleep while in Ecm
mWakeLock.acquire();
}
@ -915,7 +899,7 @@ public class CDMAPhone extends PhoneBase {
+ ar.exception + mIsPhoneInEcmState);
}
// Remove pending exit Ecm runnable, if any
h.removeCallbacks(mExitEcmRunnable);
removeCallbacks(mExitEcmRunnable);
if (mEcmExitRespRegistrant != null) {
mEcmExitRespRegistrant.notifyRegistrant(ar);
@ -941,13 +925,13 @@ public class CDMAPhone extends PhoneBase {
void handleTimerInEmergencyCallbackMode(int action) {
switch(action) {
case CANCEL_ECM_TIMER:
h.removeCallbacks(mExitEcmRunnable);
removeCallbacks(mExitEcmRunnable);
mEcmTimerResetRegistrants.notifyResult(new Boolean(true));
break;
case RESTART_ECM_TIMER:
long delayInMillis = SystemProperties.getLong(
TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
h.postDelayed(mExitEcmRunnable, delayInMillis);
postDelayed(mExitEcmRunnable, delayInMillis);
mEcmTimerResetRegistrants.notifyResult(new Boolean(false));
break;
default:
@ -969,123 +953,108 @@ public class CDMAPhone extends PhoneBase {
mEcmTimerResetRegistrants.remove(h);
}
//***** Inner Classes
class MyHandler extends Handler {
MyHandler() {
}
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
Message onComplete;
MyHandler(Looper l) {
super(l);
}
switch(msg.what) {
case EVENT_RADIO_AVAILABLE: {
mCM.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
Message onComplete;
mCM.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
}
break;
switch(msg.what) {
case EVENT_RADIO_AVAILABLE: {
mCM.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
case EVENT_GET_BASEBAND_VERSION_DONE:{
ar = (AsyncResult)msg.obj;
mCM.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
if (ar.exception != null) {
break;
}
break;
case EVENT_GET_BASEBAND_VERSION_DONE:{
ar = (AsyncResult)msg.obj;
if (DBG) Log.d(LOG_TAG, "Baseband version: " + ar.result);
setSystemProperty(TelephonyProperties.PROPERTY_BASEBAND_VERSION, (String)ar.result);
}
break;
if (ar.exception != null) {
break;
}
case EVENT_GET_DEVICE_IDENTITY_DONE:{
ar = (AsyncResult)msg.obj;
if (DBG) Log.d(LOG_TAG, "Baseband version: " + ar.result);
setSystemProperty(TelephonyProperties.PROPERTY_BASEBAND_VERSION, (String)ar.result);
if (ar.exception != null) {
break;
}
break;
String[] respId = (String[])ar.result;
mEsn = respId[2];
mMeid = respId[3];
}
break;
case EVENT_GET_DEVICE_IDENTITY_DONE:{
ar = (AsyncResult)msg.obj;
case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{
handleEnterEmergencyCallbackMode(msg);
}
break;
if (ar.exception != null) {
break;
}
String[] respId = (String[])ar.result;
mEsn = respId[2];
mMeid = respId[3];
case EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{
handleExitEmergencyCallbackMode(msg);
}
break;
case EVENT_RUIM_RECORDS_LOADED:{
Log.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received");
}
break;
case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{
Log.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
}
break;
case EVENT_RADIO_ON:{
Log.d(LOG_TAG, "Event EVENT_RADIO_ON Received");
}
break;
case EVENT_SSN:{
Log.d(LOG_TAG, "Event EVENT_SSN Received");
}
break;
case EVENT_REGISTERED_TO_NETWORK:{
Log.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received");
}
break;
case EVENT_NV_READY:{
Log.d(LOG_TAG, "Event EVENT_NV_READY Received");
//Inform the Service State Tracker
mEriManager.loadEriFile();
mNvLoadedRegistrants.notifyRegistrants();
if(mEriManager.isEriFileLoaded()) {
// when the ERI file is loaded
Log.d(LOG_TAG, "ERI read, notify registrants");
mEriFileLoadedRegistrants.notifyRegistrants();
}
break;
setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE,"false");
}
break;
case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{
handleEnterEmergencyCallbackMode(msg);
case EVENT_SET_VM_NUMBER_DONE:{
ar = (AsyncResult)msg.obj;
if (IccException.class.isInstance(ar.exception)) {
storeVoiceMailNumber(mVmNumber);
ar.exception = null;
}
break;
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
}
break;
case EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{
handleExitEmergencyCallbackMode(msg);
}
break;
case EVENT_RUIM_RECORDS_LOADED:{
Log.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received");
}
break;
case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{
Log.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
}
break;
case EVENT_RADIO_ON:{
Log.d(LOG_TAG, "Event EVENT_RADIO_ON Received");
}
break;
case EVENT_SSN:{
Log.d(LOG_TAG, "Event EVENT_SSN Received");
}
break;
case EVENT_CALL_RING:{
Log.d(LOG_TAG, "Event EVENT_CALL_RING Received");
}
break;
case EVENT_REGISTERED_TO_NETWORK:{
Log.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received");
}
break;
case EVENT_NV_READY:{
Log.d(LOG_TAG, "Event EVENT_NV_READY Received");
//Inform the Service State Tracker
mEriManager.loadEriFile();
mNvLoadedRegistrants.notifyRegistrants();
if(mEriManager.isEriFileLoaded()) {
// when the ERI file is loaded
Log.d(LOG_TAG, "ERI read, notify registrants");
mEriFileLoadedRegistrants.notifyRegistrants();
}
setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE,"false");
}
break;
case EVENT_SET_VM_NUMBER_DONE:{
ar = (AsyncResult)msg.obj;
if (IccException.class.isInstance(ar.exception)) {
storeVoiceMailNumber(mVmNumber);
ar.exception = null;
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
}
break;
default:{
throw new RuntimeException("unexpected event not handled");
}
default:{
super.handleMessage(msg);
}
}
}
@ -1137,13 +1106,6 @@ public class CDMAPhone extends PhoneBase {
super.setSystemProperty(property, value);
}
/**
* {@inheritDoc}
*/
public Handler getHandler() {
return h;
}
/**
* {@inheritDoc}
*/

View File

@ -146,7 +146,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
};
//***** Constructor
/* Constructor */
CdmaDataConnectionTracker(CDMAPhone p) {
super(p);
@ -174,7 +174,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
p.getContext().registerReceiver(mIntentReceiver, filter, null, p.h);
// TODO: Why is this registering the phone as the receiver of the intent
// and not its own handler?
p.getContext().registerReceiver(mIntentReceiver, filter, null, p);
mDataConnectionTracker = this;

View File

@ -23,13 +23,11 @@ import android.database.SQLException;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Telephony;
import android.telephony.CellLocation;
import android.telephony.PhoneNumberUtils;
@ -98,14 +96,13 @@ public class GSMPhone extends PhoneBase {
// Key used to read/write the SIM IMSI used for storing the voice mail
public static final String VM_SIM_IMSI = "vm_sim_imsi_key";
//***** Instance Variables
// Instance Variables
GsmCallTracker mCT;
GsmServiceStateTracker mSST;
GsmSMSDispatcher mSMS;
SIMRecords mSIMRecords;
SimCard mSimCard;
StkService mStkService;
MyHandler h;
ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>();
SimPhoneBookInterfaceManager mSimPhoneBookIntManager;
SimSmsInterfaceManager mSimSmsIntManager;
@ -129,7 +126,7 @@ public class GSMPhone extends PhoneBase {
private String mVmNumber;
//***** Constructors
// Constructors
public
GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier) {
@ -138,9 +135,7 @@ public class GSMPhone extends PhoneBase {
public
GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {
super(notifier, context, unitTestMode);
h = new MyHandler();
mCM = ci;
super(notifier, context, ci, unitTestMode);
if (ci instanceof SimulatedRadioControl) {
mSimulatedRadioControl = (SimulatedRadioControl) ci;
@ -162,14 +157,13 @@ public class GSMPhone extends PhoneBase {
mStkService = StkService.getInstance(mCM, mSIMRecords, mContext,
(SIMFileHandler)mIccFileHandler, mSimCard);
mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null);
mSIMRecords.registerForRecordsLoaded(h, EVENT_SIM_RECORDS_LOADED, null);
mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCM.registerForOn(h, EVENT_RADIO_ON, null);
mCM.setOnUSSD(h, EVENT_USSD, null);
mCM.setOnSuppServiceNotification(h, EVENT_SSN, null);
mCM.setOnCallRing(h, EVENT_CALL_RING, null);
mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null);
mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
mSIMRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCM.registerForOn(this, EVENT_RADIO_ON, null);
mCM.setOnUSSD(this, EVENT_USSD, null);
mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
mSST.registerForNetworkAttach(this, EVENT_REGISTERED_TO_NETWORK, null);
if (false) {
try {
@ -212,15 +206,16 @@ public class GSMPhone extends PhoneBase {
public void dispose() {
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
super.dispose();
//Unregister from all former registered events
mCM.unregisterForAvailable(h); //EVENT_RADIO_AVAILABLE
mSIMRecords.unregisterForRecordsLoaded(h); //EVENT_SIM_RECORDS_LOADED
mCM.unregisterForOffOrNotAvailable(h); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
mCM.unregisterForOn(h); //EVENT_RADIO_ON
mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnUSSD(h);
mCM.unSetOnSuppServiceNotification(h);
mCM.unSetOnCallRing(h);
mCM.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE
mSIMRecords.unregisterForRecordsLoaded(this); //EVENT_SIM_RECORDS_LOADED
mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
mCM.unregisterForOn(this); //EVENT_RADIO_ON
mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnUSSD(this);
mCM.unSetOnSuppServiceNotification(this);
mPendingMMIs.clear();
@ -258,8 +253,6 @@ public class GSMPhone extends PhoneBase {
}
//***** Overridden from Phone
public ServiceState
getServiceState() {
return mSST.ss;
@ -391,14 +384,6 @@ public class GSMPhone extends PhoneBase {
super.notifyNewRingingConnectionP(c);
}
/**
* Notifiy registrants of a RING event.
*/
void notifyIncomingRing() {
AsyncResult ar = new AsyncResult(null, this, null);
mIncomingRingRegistrants.notifyRegistrants(ar);
}
/*package*/ void
notifyDisconnect(Connection cn) {
mDisconnectRegistrants.notifyResult(cn);
@ -917,7 +902,7 @@ public class GSMPhone extends PhoneBase {
Message resp;
mVmNumber = voiceMailNumber;
resp = h.obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
mSIMRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
}
@ -956,7 +941,7 @@ public class GSMPhone extends PhoneBase {
if (LOCAL_DEBUG) Log.d(LOG_TAG, "requesting call forwarding query.");
Message resp;
if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
resp = h.obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete);
resp = obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete);
} else {
resp = onComplete;
}
@ -974,7 +959,7 @@ public class GSMPhone extends PhoneBase {
Message resp;
if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
resp = h.obtainMessage(EVENT_SET_CALL_FORWARD_DONE,
resp = obtainMessage(EVENT_SET_CALL_FORWARD_DONE,
isCfEnable(commandInterfaceCFAction) ? 1 : 0, 0, onComplete);
} else {
resp = onComplete;
@ -995,7 +980,7 @@ public class GSMPhone extends PhoneBase {
public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
Message onComplete) {
mCM.setCLIR(commandInterfaceCLIRMode,
h.obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete));
obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete));
}
public void getCallWaiting(Message onComplete) {
@ -1043,7 +1028,7 @@ public class GSMPhone extends PhoneBase {
nsm.operatorAlphaLong = "";
// get the message
Message msg = h.obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
Message msg = obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
if (LOCAL_DEBUG)
Log.d(LOG_TAG, "wrapping and sending message to connect automatically");
@ -1061,7 +1046,7 @@ public class GSMPhone extends PhoneBase {
nsm.operatorAlphaLong = network.operatorAlphaLong;
// get the message
Message msg = h.obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
mCM.setNetworkSelectionModeManual(network.operatorNumeric, msg);
}
@ -1247,178 +1232,163 @@ public class GSMPhone extends PhoneBase {
}
}
//***** Inner Classes
@Override
public void handleMessage (Message msg) {
AsyncResult ar;
Message onComplete;
class MyHandler extends Handler {
MyHandler() {
}
switch (msg.what) {
case EVENT_RADIO_AVAILABLE: {
mCM.getBasebandVersion(
obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
MyHandler(Looper l) {
super(l);
}
mCM.getIMEI(obtainMessage(EVENT_GET_IMEI_DONE));
mCM.getIMEISV(obtainMessage(EVENT_GET_IMEISV_DONE));
}
break;
public void
handleMessage (Message msg) {
AsyncResult ar;
Message onComplete;
case EVENT_RADIO_ON:
break;
switch (msg.what) {
case EVENT_RADIO_AVAILABLE: {
mCM.getBasebandVersion(
obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
case EVENT_REGISTERED_TO_NETWORK:
syncClirSetting();
break;
mCM.getIMEI(obtainMessage(EVENT_GET_IMEI_DONE));
mCM.getIMEISV(obtainMessage(EVENT_GET_IMEISV_DONE));
case EVENT_SIM_RECORDS_LOADED:
updateCurrentCarrierInProvider();
// Check if this is a different SIM than the previous one. If so unset the
// voice mail number.
String imsi = getVmSimImsi();
if (imsi != null && !getSubscriberId().equals(imsi)) {
storeVoiceMailNumber(null);
setVmSimImsi(null);
}
break;
case EVENT_GET_BASEBAND_VERSION_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
break;
}
if (LOCAL_DEBUG) Log.d(LOG_TAG, "Baseband version: " + ar.result);
setSystemProperty(PROPERTY_BASEBAND_VERSION, (String)ar.result);
break;
case EVENT_GET_IMEI_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
break;
}
mImei = (String)ar.result;
break;
case EVENT_GET_IMEISV_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
break;
}
mImeiSv = (String)ar.result;
break;
case EVENT_USSD:
ar = (AsyncResult)msg.obj;
String[] ussdResult = (String[]) ar.result;
if (ussdResult.length > 1) {
try {
onIncomingUSSD(Integer.parseInt(ussdResult[0]), ussdResult[1]);
} catch (NumberFormatException e) {
Log.w(LOG_TAG, "error parsing USSD");
}
}
break;
case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
// Some MMI requests (eg USSD) are not completed
// within the course of a CommandsInterface request
// If the radio shuts off or resets while one of these
// is pending, we need to clean up.
for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) {
if (mPendingMMIs.get(i).isPendingUSSD()) {
mPendingMMIs.get(i).onUssdFinishedError();
}
}
break;
case EVENT_SSN:
ar = (AsyncResult)msg.obj;
SuppServiceNotification not = (SuppServiceNotification) ar.result;
mSsnRegistrants.notifyRegistrants(ar);
break;
case EVENT_SET_CALL_FORWARD_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
mSIMRecords.setVoiceCallForwardingFlag(1, msg.arg1 == 1);
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
break;
case EVENT_RADIO_ON:
case EVENT_SET_VM_NUMBER_DONE:
ar = (AsyncResult)msg.obj;
if (IccVmNotSupportedException.class.isInstance(ar.exception)) {
storeVoiceMailNumber(mVmNumber);
ar.exception = null;
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
break;
case EVENT_REGISTERED_TO_NETWORK:
syncClirSetting();
break;
case EVENT_SIM_RECORDS_LOADED:
updateCurrentCarrierInProvider();
// Check if this is a different SIM than the previous one. If so unset the
// voice mail number.
String imsi = getVmSimImsi();
if (imsi != null && !getSubscriberId().equals(imsi)) {
storeVoiceMailNumber(null);
setVmSimImsi(null);
}
case EVENT_GET_CALL_FORWARD_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
handleCfuQueryResult((CallForwardInfo[])ar.result);
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
break;
case EVENT_GET_BASEBAND_VERSION_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
break;
}
if (LOCAL_DEBUG) Log.d(LOG_TAG, "Baseband version: " + ar.result);
setSystemProperty(PROPERTY_BASEBAND_VERSION, (String)ar.result);
// handle the select network completion callbacks.
case EVENT_SET_NETWORK_MANUAL_COMPLETE:
case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
handleSetSelectNetwork((AsyncResult) msg.obj);
break;
case EVENT_GET_IMEI_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
break;
}
mImei = (String)ar.result;
case EVENT_SET_CLIR_COMPLETE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
saveClirSetting(msg.arg1);
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
break;
case EVENT_GET_IMEISV_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
break;
}
mImeiSv = (String)ar.result;
break;
case EVENT_USSD:
ar = (AsyncResult)msg.obj;
String[] ussdResult = (String[]) ar.result;
if (ussdResult.length > 1) {
try {
onIncomingUSSD(Integer.parseInt(ussdResult[0]), ussdResult[1]);
} catch (NumberFormatException e) {
Log.w(LOG_TAG, "error parsing USSD");
}
}
break;
case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
// Some MMI requests (eg USSD) are not completed
// within the course of a CommandsInterface request
// If the radio shuts off or resets while one of these
// is pending, we need to clean up.
for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) {
if (mPendingMMIs.get(i).isPendingUSSD()) {
mPendingMMIs.get(i).onUssdFinishedError();
}
}
break;
case EVENT_SSN:
ar = (AsyncResult)msg.obj;
SuppServiceNotification not = (SuppServiceNotification) ar.result;
mSsnRegistrants.notifyRegistrants(ar);
break;
case EVENT_SET_CALL_FORWARD_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
mSIMRecords.setVoiceCallForwardingFlag(1, msg.arg1 == 1);
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
break;
case EVENT_SET_VM_NUMBER_DONE:
ar = (AsyncResult)msg.obj;
if (IccVmNotSupportedException.class.isInstance(ar.exception)) {
storeVoiceMailNumber(mVmNumber);
ar.exception = null;
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
break;
case EVENT_GET_CALL_FORWARD_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
handleCfuQueryResult((CallForwardInfo[])ar.result);
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
break;
case EVENT_CALL_RING:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
notifyIncomingRing();
}
break;
// handle the select network completion callbacks.
case EVENT_SET_NETWORK_MANUAL_COMPLETE:
case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
handleSetSelectNetwork((AsyncResult) msg.obj);
break;
case EVENT_SET_CLIR_COMPLETE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
saveClirSetting(msg.arg1);
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
break;
}
default:
super.handleMessage(msg);
}
}
@ -1530,13 +1500,6 @@ public class GSMPhone extends PhoneBase {
return mSimPhoneBookIntManager;
}
/**
* {@inheritDoc}
*/
public Handler getHandler(){
return h;
}
/**
* {@inheritDoc}
*/

View File

@ -222,7 +222,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
p.getContext().registerReceiver(mIntentReceiver, filter, null, p.h);
// TODO: Why is this registering the phone as the receiver of the intent
// and not its own handler?
p.getContext().registerReceiver(mIntentReceiver, filter, null, p);
mDataConnectionTracker = this;