Merge change 3107 into donut

* changes:
  Motorola changes from 090602 through 090605
This commit is contained in:
Android (Google) Code Review
2009-06-07 22:48:29 -07:00
20 changed files with 1099 additions and 394 deletions

View File

@@ -59,6 +59,12 @@ public abstract class BaseCommands implements CommandsInterface {
protected RegistrantList mCallWaitingInfoRegistrants = new RegistrantList(); protected RegistrantList mCallWaitingInfoRegistrants = new RegistrantList();
protected RegistrantList mDisplayInfoRegistrants = new RegistrantList(); protected RegistrantList mDisplayInfoRegistrants = new RegistrantList();
protected RegistrantList mSignalInfoRegistrants = new RegistrantList(); protected RegistrantList mSignalInfoRegistrants = new RegistrantList();
protected RegistrantList mNumberInfoRegistrants = new RegistrantList();
protected RegistrantList mRedirNumInfoRegistrants = new RegistrantList();
protected RegistrantList mLineControlInfoRegistrants = new RegistrantList();
protected RegistrantList mT53ClirInfoRegistrants = new RegistrantList();
protected RegistrantList mT53AudCntrlInfoRegistrants = new RegistrantList();
protected Registrant mSMSRegistrant; protected Registrant mSMSRegistrant;
protected Registrant mNITZTimeRegistrant; protected Registrant mNITZTimeRegistrant;
protected Registrant mSignalStrengthRegistrant; protected Registrant mSignalStrengthRegistrant;
@@ -509,6 +515,50 @@ public abstract class BaseCommands implements CommandsInterface {
mOtaProvisionRegistrants.remove(h); mOtaProvisionRegistrants.remove(h);
} }
public void registerForNumberInfo(Handler h,int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
mNumberInfoRegistrants.add(r);
}
public void unregisterForNumberInfo(Handler h){
mNumberInfoRegistrants.remove(h);
}
public void registerForRedirectedNumberInfo(Handler h,int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
mRedirNumInfoRegistrants.add(r);
}
public void unregisterForRedirectedNumberInfo(Handler h) {
mRedirNumInfoRegistrants.remove(h);
}
public void registerForLineControlInfo(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
mLineControlInfoRegistrants.add(r);
}
public void unregisterForLineControlInfo(Handler h) {
mLineControlInfoRegistrants.remove(h);
}
public void registerFoT53ClirlInfo(Handler h,int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
mT53ClirInfoRegistrants.add(r);
}
public void unregisterForT53ClirInfo(Handler h) {
mT53ClirInfoRegistrants.remove(h);
}
public void registerForT53AudioControlInfo(Handler h,int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
mT53AudCntrlInfoRegistrants.add(r);
}
public void unregisterForT53AudioControlInfo(Handler h) {
mT53AudCntrlInfoRegistrants.remove(h);
}
//***** Protected Methods //***** Protected Methods
/** /**

View File

@@ -46,6 +46,13 @@ public abstract class Call {
public State state = State.IDLE; public State state = State.IDLE;
// Flag to indicate if the current calling/caller information
// is accurate. If false the information is known to be accurate.
//
// For CDMA, during call waiting/3 way, there is no network response
// if call waiting is answered, network timed out, dropped, 3 way
// merged, etc.
protected boolean isGeneric = false;
/* Instance Methods */ /* Instance Methods */
@@ -126,6 +133,7 @@ public abstract class Call {
if (t < time) { if (t < time) {
earliest = c; earliest = c;
time = t;
} }
} }
@@ -157,10 +165,8 @@ public abstract class Call {
public long public long
getEarliestConnectTime() { getEarliestConnectTime() {
List l;
long time = Long.MAX_VALUE; long time = Long.MAX_VALUE;
List l = getConnections();
l = getConnections();
if (l.size() == 0) { if (l.size() == 0) {
return 0; return 0;
@@ -189,4 +195,44 @@ public abstract class Call {
return getState().isRinging(); return getState().isRinging();
} }
/**
* Returns the Connection associated with this Call that was created
* last, or null if there are no Connections in this Call
*/
public Connection
getLatestConnection() {
List l = getConnections();
if (l.size() == 0) {
return null;
}
long time = 0;
Connection latest = null;
for (int i = 0, s = l.size() ; i < s ; i++) {
Connection c = (Connection) l.get(i);
long t = c.getCreateTime();
if (t > time) {
latest = c;
time = t;
}
}
return latest;
}
/**
* To indicate if the connection information is accurate
* or not. false means accurate. Only used for CDMA.
*/
public boolean isGeneric() {
return isGeneric;
}
/**
* Set the generic instance variable
*/
public void setGeneric(boolean generic) {
isGeneric = generic;
}
} }

View File

@@ -57,7 +57,8 @@ public abstract class CallTracker extends Handler {
protected static final int EVENT_SEPARATE_RESULT = 12; protected static final int EVENT_SEPARATE_RESULT = 12;
protected static final int EVENT_ECT_RESULT = 13; protected static final int EVENT_ECT_RESULT = 13;
protected static final int EVENT_EXIT_ECM_RESPONSE_CDMA = 14; protected static final int EVENT_EXIT_ECM_RESPONSE_CDMA = 14;
protected static final int EVENT_CALL_WAITING_INFO_CDMA = 15;
protected static final int EVENT_THREE_WAY_DIAL_L2_RESULT_CDMA = 16;
protected void pollCallsWhenSafe() { protected void pollCallsWhenSafe() {
needsPoll = true; needsPoll = true;

View File

@@ -465,6 +465,61 @@ public interface CommandsInterface {
void registerForSignalInfo(Handler h, int what, Object obj); void registerForSignalInfo(Handler h, int what, Object obj);
void unregisterForSignalInfo(Handler h); void unregisterForSignalInfo(Handler h);
/**
* Registers the handler for CDMA number information record
* Unlike the register* methods, there's only one notification handler
*
* @param h Handler for notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerForNumberInfo(Handler h, int what, Object obj);
void unregisterForNumberInfo(Handler h);
/**
* Registers the handler for CDMA redirected number Information record
* Unlike the register* methods, there's only one notification handler
*
* @param h Handler for notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerForRedirectedNumberInfo(Handler h, int what, Object obj);
void unregisterForRedirectedNumberInfo(Handler h);
/**
* Registers the handler for CDMA line control information record
* Unlike the register* methods, there's only one notification handler
*
* @param h Handler for notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerForLineControlInfo(Handler h, int what, Object obj);
void unregisterForLineControlInfo(Handler h);
/**
* Registers the handler for CDMA T53 CLIR information record
* Unlike the register* methods, there's only one notification handler
*
* @param h Handler for notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerFoT53ClirlInfo(Handler h, int what, Object obj);
void unregisterForT53ClirInfo(Handler h);
/**
* Registers the handler for CDMA T53 audio control information record
* Unlike the register* methods, there's only one notification handler
*
* @param h Handler for notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerForT53AudioControlInfo(Handler h, int what, Object obj);
void unregisterForT53AudioControlInfo(Handler h);
/** /**
* Fires on if Modem enters Emergency Callback mode * Fires on if Modem enters Emergency Callback mode
*/ */

View File

@@ -1350,9 +1350,13 @@ public interface Phone {
/** /**
* Retrieves the MIN for CDMA phones. * Retrieves the MIN for CDMA phones.
*/ */
String getCdmaMin(); String getCdmaMin();
/**
* Retrieves PRL Version for CDMA phones
*/
String getCdmaPrlVersion();
/** /**
* Retrieves the ESN for CDMA phones. * Retrieves the ESN for CDMA phones.
*/ */
@@ -1464,14 +1468,12 @@ public interface Phone {
* @param what User-defined message code. * @param what User-defined message code.
* @param obj User object. * @param obj User object.
*/ */
// TODO(Moto) TODO: Remove when generic implemented
void registerForCallWaiting(Handler h, int what, Object obj); void registerForCallWaiting(Handler h, int what, Object obj);
/** /**
* Unegister for notifications when CDMA Call waiting comes * Unegister for notifications when CDMA Call waiting comes
* @param h Handler to be removed from the registrant list. * @param h Handler to be removed from the registrant list.
*/ */
// TODO(Moto): Remove when generic implemented
void unregisterForCallWaiting(Handler h); void unregisterForCallWaiting(Handler h);
@@ -1513,6 +1515,109 @@ public interface Phone {
*/ */
void unregisterForDisplayInfo(Handler h) ; void unregisterForDisplayInfo(Handler h) ;
/**
* Register for CDMA number information record notification from the network.
* Message.obj will contain an AsyncResult.
* AsyncResult.result will be a CdmaInformationRecords.CdmaNumberInfoRec
* instance.
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerForNumberInfo(Handler h, int what, Object obj);
/**
* Unregisters for number information record notifications.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
void unregisterForNumberInfo(Handler h);
/**
* Register for CDMA redirected number information record notification
* from the network.
* Message.obj will contain an AsyncResult.
* AsyncResult.result will be a CdmaInformationRecords.CdmaRedirectingNumberInfoRec
* instance.
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerForRedirectedNumberInfo(Handler h, int what, Object obj);
/**
* Unregisters for redirected number information record notification.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
void unregisterForRedirectedNumberInfo(Handler h);
/**
* Register for CDMA line control information record notification
* from the network.
* Message.obj will contain an AsyncResult.
* AsyncResult.result will be a CdmaInformationRecords.CdmaLineControlInfoRec
* instance.
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerForLineControlInfo(Handler h, int what, Object obj);
/**
* Unregisters for line control information notifications.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
void unregisterForLineControlInfo(Handler h);
/**
* Register for CDMA T53 CLIR information record notifications
* from the network.
* Message.obj will contain an AsyncResult.
* AsyncResult.result will be a CdmaInformationRecords.CdmaT53ClirInfoRec
* instance.
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerFoT53ClirlInfo(Handler h, int what, Object obj);
/**
* Unregisters for T53 CLIR information record notification
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
void unregisterForT53ClirInfo(Handler h);
/**
* Register for CDMA T53 audio control information record notifications
* from the network.
* Message.obj will contain an AsyncResult.
* AsyncResult.result will be a CdmaInformationRecords.CdmaT53AudioControlInfoRec
* instance.
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
void registerForT53AudioControlInfo(Handler h, int what, Object obj);
/**
* Unregisters for T53 audio control information record notifications.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
void unregisterForT53AudioControlInfo(Handler h);
/** /**
* registers for exit emergency call back mode request response * registers for exit emergency call back mode request response

View File

@@ -674,6 +674,12 @@ public abstract class PhoneBase implements Phone {
return null; return null;
} }
public String getCdmaPrlVersion(){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
return null;
}
public void sendBurstDtmf(String dtmfString, Message onComplete) { public void sendBurstDtmf(String dtmfString, Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
@@ -726,6 +732,46 @@ public abstract class PhoneBase implements Phone {
mCM.unregisterForDisplayInfo(h); mCM.unregisterForDisplayInfo(h);
} }
public void registerForNumberInfo(Handler h, int what, Object obj) {
mCM.registerForNumberInfo(h, what, obj);
}
public void unregisterForNumberInfo(Handler h) {
mCM.unregisterForNumberInfo(h);
}
public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
mCM.registerForRedirectedNumberInfo(h, what, obj);
}
public void unregisterForRedirectedNumberInfo(Handler h) {
mCM.unregisterForRedirectedNumberInfo(h);
}
public void registerForLineControlInfo(Handler h, int what, Object obj) {
mCM.registerForLineControlInfo( h, what, obj);
}
public void unregisterForLineControlInfo(Handler h) {
mCM.unregisterForLineControlInfo(h);
}
public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
mCM.registerFoT53ClirlInfo(h, what, obj);
}
public void unregisterForT53ClirInfo(Handler h) {
mCM.unregisterForT53ClirInfo(h);
}
public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
mCM.registerForT53AudioControlInfo( h, what, obj);
}
public void unregisterForT53AudioControlInfo(Handler h) {
mCM.unregisterForT53AudioControlInfo(h);
}
public void setOnEcbModeExitResponse(Handler h, int what, Object obj){ public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");

View File

@@ -418,6 +418,10 @@ public class PhoneProxy extends Handler implements Phone {
return mActivePhone.getCdmaMin(); return mActivePhone.getCdmaMin();
} }
public String getCdmaPrlVersion() {
return mActivePhone.getCdmaPrlVersion();
}
public String getLine1AlphaTag() { public String getLine1AlphaTag() {
return mActivePhone.getLine1AlphaTag(); return mActivePhone.getLine1AlphaTag();
} }
@@ -745,6 +749,46 @@ public class PhoneProxy extends Handler implements Phone {
mActivePhone.unregisterForDisplayInfo(h); mActivePhone.unregisterForDisplayInfo(h);
} }
public void registerForNumberInfo(Handler h, int what, Object obj) {
mActivePhone.registerForNumberInfo(h, what, obj);
}
public void unregisterForNumberInfo(Handler h) {
mActivePhone.unregisterForNumberInfo(h);
}
public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
mActivePhone.registerForRedirectedNumberInfo(h, what, obj);
}
public void unregisterForRedirectedNumberInfo(Handler h) {
mActivePhone.unregisterForRedirectedNumberInfo(h);
}
public void registerForLineControlInfo(Handler h, int what, Object obj) {
mActivePhone.registerForLineControlInfo( h, what, obj);
}
public void unregisterForLineControlInfo(Handler h) {
mActivePhone.unregisterForLineControlInfo(h);
}
public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
mActivePhone.registerFoT53ClirlInfo(h, what, obj);
}
public void unregisterForT53ClirInfo(Handler h) {
mActivePhone.unregisterForT53ClirInfo(h);
}
public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
mActivePhone.registerForT53AudioControlInfo( h, what, obj);
}
public void unregisterForT53AudioControlInfo(Handler h) {
mActivePhone.unregisterForT53AudioControlInfo(h);
}
public void setOnEcbModeExitResponse(Handler h, int what, Object obj){ public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
mActivePhone.setOnEcbModeExitResponse(h,what,obj); mActivePhone.setOnEcbModeExitResponse(h,what,obj);
} }

View File

@@ -2233,7 +2233,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break; case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break; case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break;
case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break; case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break;
case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInfoRec(p); break; case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break;
case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break; case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break;
default: default:
@@ -2490,23 +2490,18 @@ public final class RIL extends BaseCommands implements CommandsInterface {
break; break;
case RIL_UNSOL_CDMA_INFO_REC: case RIL_UNSOL_CDMA_INFO_REC:
if (RILJ_LOGD) unsljLog(response); ArrayList<CdmaInformationRecords> listInfoRecs;
CdmaInformationRecords infoRec = (CdmaInformationRecords) ret; try {
if (infoRec.isDispInfo) { listInfoRecs = (ArrayList<CdmaInformationRecords>)ret;
if (mDisplayInfoRegistrants != null) { } catch (ClassCastException e) {
if (RILJ_LOGD) unsljLogRet(response, infoRec.cdmaDisplayInfoRecord); Log.e(LOG_TAG, "Unexpected exception casting to listInfoRecs", e);
break;
}
mDisplayInfoRegistrants.notifyRegistrants( for (CdmaInformationRecords rec : listInfoRecs) {
new AsyncResult (null, infoRec.cdmaDisplayInfoRecord, null)); if (RILJ_LOGD) unsljLogRet(response, rec);
} notifyRegistrantsCdmaInfoRec(rec);
}
if (infoRec.isSignInfo) {
if (mSignalInfoRegistrants != null) {
if (RILJ_LOGD) unsljLogRet(response, infoRec.cdmaSignalInfoRecord);
mSignalInfoRegistrants.notifyRegistrants(
new AsyncResult (null, infoRec.cdmaSignalInfoRecord, null));
}
} }
break; break;
@@ -2764,30 +2759,24 @@ public final class RIL extends BaseCommands implements CommandsInterface {
dc.als = p.readInt(); dc.als = p.readInt();
voiceSettings = p.readInt(); voiceSettings = p.readInt();
dc.isVoice = (0 == voiceSettings) ? false : true; dc.isVoice = (0 == voiceSettings) ? false : true;
int voicePrivacy = p.readInt(); dc.isVoicePrivacy = (0 != p.readInt());
dc.isVoicePrivacy = (0 != voicePrivacy);
dc.number = p.readString(); dc.number = p.readString();
int np = p.readInt(); int np = p.readInt();
dc.numberPresentation = DriverCall.presentationFromCLIP(np); dc.numberPresentation = DriverCall.presentationFromCLIP(np);
dc.name = p.readString(); dc.name = p.readString();
dc.namePresentation = p.readInt(); dc.namePresentation = p.readInt();
// Make sure there's a leading + on addresses with a TOA // Make sure there's a leading + on addresses with a TOA of 145
// of 145 dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA);
dc.number = PhoneNumberUtils.stringFromStringAndTOA(
dc.number, dc.TOA);
response.add(dc); response.add(dc);
if ( RILConstants.CDMA_VOICE_PRIVACY == voicePrivacy ) { if (dc.isVoicePrivacy) {
mVoicePrivacyOnRegistrants.notifyRegistrants(); mVoicePrivacyOnRegistrants.notifyRegistrants();
Log.d(LOG_TAG, "InCall VoicePrivacy is enabled: " + Log.d(LOG_TAG, "InCall VoicePrivacy is enabled");
Integer.toString(voicePrivacy));
} else { } else {
mVoicePrivacyOffRegistrants.notifyRegistrants(); mVoicePrivacyOffRegistrants.notifyRegistrants();
Log.d(LOG_TAG, "InCall VoicePrivacy is disabled: " + Log.d(LOG_TAG, "InCall VoicePrivacy is disabled");
Integer.toString(voicePrivacy));
} }
} }
@@ -2880,15 +2869,19 @@ public final class RIL extends BaseCommands implements CommandsInterface {
numServiceCategories = p.readInt(); numServiceCategories = p.readInt();
if (numServiceCategories == 0) { if (numServiceCategories == 0) {
// TODO(Teleca) TODO(Moto): The logic of providing default
// values should not be done by this transport layer. And
// needs to be done by the vendor ril or application logic.
// TODO(Google): Remove ASAP
int numInts; int numInts;
numInts = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES * CDMA_BSI_NO_OF_INTS_STRUCT + 1; numInts = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES * CDMA_BSI_NO_OF_INTS_STRUCT + 1;
response = new int[numInts]; response = new int[numInts];
// Indicate that a zero length table was received // Faking a default record for all possible records.
response[0] = 0; // TODO(Moto): This is very strange, please explain why. response[0] = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES;
// Loop over CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES set 'english' as // Loop over CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES set 'english' as
// default language and selection status to false // default language and selection status to false for all.
for (int i = 1; i < numInts; i += CDMA_BSI_NO_OF_INTS_STRUCT ) { for (int i = 1; i < numInts; i += CDMA_BSI_NO_OF_INTS_STRUCT ) {
response[i + 0] = i / CDMA_BSI_NO_OF_INTS_STRUCT; response[i + 0] = i / CDMA_BSI_NO_OF_INTS_STRUCT;
response[i + 1] = 1; response[i + 1] = 1;
@@ -2922,66 +2915,24 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response; return response;
} }
private Object private ArrayList<CdmaInformationRecords>
responseCdmaInfoRec(Parcel p) { responseCdmaInformationRecord(Parcel p) {
int infoRecordName; int numberOfInfoRecs;
CdmaInformationRecords records = new CdmaInformationRecords(); ArrayList<CdmaInformationRecords> response;
/**
* Loop through all of the information records unmarshalling them
* and converting them to Java Objects.
*/
numberOfInfoRecs = p.readInt();
response = new ArrayList<CdmaInformationRecords>(numberOfInfoRecs);
int numberOfInfoRecs = p.readInt();
for (int i = 0; i < numberOfInfoRecs; i++) { for (int i = 0; i < numberOfInfoRecs; i++) {
infoRecordName = p.readInt(); CdmaInformationRecords InfoRec = new CdmaInformationRecords(p);
switch(infoRecordName) { response.add(InfoRec);
case CdmaInformationRecords.RIL_CDMA_DISPLAY_INFO_REC:
case CdmaInformationRecords.RIL_CDMA_EXTENDED_DISPLAY_INFO_REC:
records.setDispInfo(p.readString());
break;
case CdmaInformationRecords.RIL_CDMA_SIGNAL_INFO_REC:
records.setSignInfo(p.readInt(), p.readInt(), p.readInt(), p.readInt());
break;
// InfoReocords with names as below aren't supported in AFW yet
case CdmaInformationRecords.RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC:
case CdmaInformationRecords.RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC:
case CdmaInformationRecords.RIL_CDMA_CONNECTED_NUMBER_INFO_REC:
// TODO(Moto) implement
p.readString(); // number
p.readInt(); // number_type
p.readInt(); // number_plan
p.readInt(); // pi
p.readInt(); // si
break;
case CdmaInformationRecords.RIL_CDMA_REDIRECTING_NUMBER_INFO_REC:
// TODO(Moto) implement
p.readString(); // redirecting number
p.readInt(); // number_type
p.readInt(); // number_plan
p.readInt(); // pi
p.readInt(); // si
p.readInt(); // reason
break;
case CdmaInformationRecords.RIL_CDMA_LINE_CONTROL_INFO_REC:
// TODO(Moto) implement
p.readInt(); // PolarityIncluded
p.readInt(); // Toggle
p.readInt(); // Reverse
p.readInt(); // PowerDenial
break;
case CdmaInformationRecords.RIL_CDMA_T53_CLIR_INFO_REC:
// TODO(Moto) implement
p.readInt(); // Cause
break;
case CdmaInformationRecords.RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC:
// TODO(Moto) implement
p.readInt(); // upLink
p.readInt(); // downLink
break;
case CdmaInformationRecords.RIL_CDMA_T53_RELEASE_INFO_REC:
// TODO(Moto) implement unknown fall through
default:
throw new RuntimeException("RIL_UNSOL_CDMA_INFO_REC: unsupported record. Got "
+ records.recordToString(infoRecordName) + " ");
} }
}
return records; return response;
} }
private Object private Object
@@ -3012,6 +2963,54 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response; return response;
} }
private void
notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) {
int response = RIL_UNSOL_CDMA_INFO_REC;
if (infoRec.record instanceof CdmaInformationRecords.CdmaDisplayInfoRec) {
if (mDisplayInfoRegistrants != null) {
if (RILJ_LOGD) unsljLogRet(response, infoRec.record);
mDisplayInfoRegistrants.notifyRegistrants(
new AsyncResult (null, infoRec.record, null));
}
} else if (infoRec.record instanceof CdmaInformationRecords.CdmaSignalInfoRec) {
if (mSignalInfoRegistrants != null) {
if (RILJ_LOGD) unsljLogRet(response, infoRec.record);
mSignalInfoRegistrants.notifyRegistrants(
new AsyncResult (null, infoRec.record, null));
}
} else if (infoRec.record instanceof CdmaInformationRecords.CdmaNumberInfoRec) {
if (mNumberInfoRegistrants != null) {
if (RILJ_LOGD) unsljLogRet(response, infoRec.record);
mNumberInfoRegistrants.notifyRegistrants(
new AsyncResult (null, infoRec.record, null));
}
} else if (infoRec.record instanceof CdmaInformationRecords.CdmaRedirectingNumberInfoRec) {
if (mRedirNumInfoRegistrants != null) {
if (RILJ_LOGD) unsljLogRet(response, infoRec.record);
mRedirNumInfoRegistrants.notifyRegistrants(
new AsyncResult (null, infoRec.record, null));
}
} else if (infoRec.record instanceof CdmaInformationRecords.CdmaLineControlInfoRec) {
if (mLineControlInfoRegistrants != null) {
if (RILJ_LOGD) unsljLogRet(response, infoRec.record);
mLineControlInfoRegistrants.notifyRegistrants(
new AsyncResult (null, infoRec.record, null));
}
} else if (infoRec.record instanceof CdmaInformationRecords.CdmaT53ClirInfoRec) {
if (mT53ClirInfoRegistrants != null) {
if (RILJ_LOGD) unsljLogRet(response, infoRec.record);
mT53ClirInfoRegistrants.notifyRegistrants(
new AsyncResult (null, infoRec.record, null));
}
} else if (infoRec.record instanceof CdmaInformationRecords.CdmaT53AudioControlInfoRec) {
if (mT53AudCntrlInfoRegistrants != null) {
if (RILJ_LOGD) unsljLogRet(response, infoRec.record);
mT53AudCntrlInfoRegistrants.notifyRegistrants(
new AsyncResult (null, infoRec.record, null));
}
}
}
static String static String
requestToString(int request) { requestToString(int request) {
/* /*

View File

@@ -78,9 +78,6 @@ public interface RILConstants {
int CDM_TTY_HCO_MODE = 2; int CDM_TTY_HCO_MODE = 2;
int CDM_TTY_VCO_MODE = 3; int CDM_TTY_VCO_MODE = 3;
byte CDMA_VOICE_PRIVACY = 0x70; /* "p" value used in Ril_Call.isVoice if Privacy
is active */
/* /*
cat include/telephony/ril.h | \ cat include/telephony/ril.h | \
egrep '^#define' | \ egrep '^#define' | \

View File

@@ -185,8 +185,9 @@ public class TelephonyIntents {
/** /**
* <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms * <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms
* <p class="note">. * <p class="note">.
* This is to pop up a notice to show user that the phone is in emergency callback mode
* and atacalls and outgoing sms are blocked.
*/ */
// TODO(Moto): What is the use case, who is interested in this?
public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS
= "android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS"; = "android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS";
@@ -202,6 +203,11 @@ public class TelephonyIntents {
// TODO(Moto): Generally broadcast intents are for use to allow entities which // TODO(Moto): Generally broadcast intents are for use to allow entities which
// may not know about each other to "communicate". This seems quite specific // may not know about each other to "communicate". This seems quite specific
// and maybe using the registrant style would be better. // and maybe using the registrant style would be better.
// Moto: Since this is used for apps not in the same process of phone, can the
// registrant style be used? (Ling Li says: Maybe the "app" can request rather
// than save the MDN each time and this intent would not be necessary?)
// Moto response: Moto internal discussion is on-going.
public static final String ACTION_CDMA_OTA_MDN_CHANGED public static final String ACTION_CDMA_OTA_MDN_CHANGED
= "android.intent.action.ACTION_MDN_STATE_CHANGED"; = "android.intent.action.ACTION_MDN_STATE_CHANGED";

View File

@@ -101,4 +101,9 @@ public interface TelephonyProperties
/** Indicate if phone is in emergency callback mode */ /** Indicate if phone is in emergency callback mode */
static final String PROPERTY_INECM_MODE = "ril.cdma.inecmmode"; static final String PROPERTY_INECM_MODE = "ril.cdma.inecmmode";
/** Indicate the timer value for exiting emergency callback mode */
static final String PROPERTY_ECM_EXIT_TIMER = "ro.cdma.ecmexittimer";
/** The international dialing prefix conversion string */
static final String PROPERTY_IDP_STRING = "ro.cdma.idpstring";
} }

View File

@@ -34,9 +34,6 @@ import android.telephony.SignalStrength;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_INECM_MODE;
import com.android.internal.telephony.CallStateException; import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.CommandException; import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.CommandsInterface;
@@ -66,6 +63,9 @@ public class CDMAPhone extends PhoneBase {
static final String LOG_TAG = "CDMA"; static final String LOG_TAG = "CDMA";
private static final boolean LOCAL_DEBUG = true; private static final boolean LOCAL_DEBUG = true;
// Default Emergency Callback Mode exit timer
private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 30000;
//***** Instance Variables //***** Instance Variables
CdmaCallTracker mCT; CdmaCallTracker mCT;
CdmaSMSDispatcher mSMS; CdmaSMSDispatcher mSMS;
@@ -144,8 +144,8 @@ public class CDMAPhone extends PhoneBase {
SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE, SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE,
new Integer(RILConstants.CDMA_PHONE).toString()); new Integer(RILConstants.CDMA_PHONE).toString());
// TODO(Moto): Is this needed to handle phone crashes and/or power cycling? // This is needed to handle phone process crashes
String inEcm=SystemProperties.get(PROPERTY_INECM_MODE, "false"); String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
mIsPhoneInECMState = inEcm.equals("true"); mIsPhoneInECMState = inEcm.equals("true");
} }
@@ -288,17 +288,11 @@ public class CDMAPhone extends PhoneBase {
if (fc != null) { if (fc != null) {
//mMmiRegistrants.notifyRegistrants(new AsyncResult(null, fc, null)); //mMmiRegistrants.notifyRegistrants(new AsyncResult(null, fc, null));
fc.processCode(); fc.processCode();
} else {
FeatureCode digits = new FeatureCode(this);
// use dial number as poundString
digits.poundString = newDialString;
digits.processCode();
}
return null; return null;
} else {
return mCT.dial(newDialString);
} }
} }
return mCT.dial(newDialString);
}
public SignalStrength getSignalStrength() { public SignalStrength getSignalStrength() {
return mSST.mSignalStrength; return mSST.mSignalStrength;
@@ -388,6 +382,10 @@ public class CDMAPhone extends PhoneBase {
return mSST.getMdnNumber(); return mSST.getMdnNumber();
} }
public String getCdmaPrlVersion(){
return mRuimRecords.getPrlVersion();
}
public String getCdmaMIN() { public String getCdmaMIN() {
return mSST.getCdmaMin(); return mSST.getCdmaMin();
} }
@@ -420,9 +418,14 @@ public class CDMAPhone extends PhoneBase {
} }
public String getSubscriberId() { public String getSubscriberId() {
Log.e(LOG_TAG, "method getSubscriberId for IMSI is NOT supported in CDMA!"); // Subscriber ID is the combination of MCC+MNC+MIN as CDMA IMSI
// TODO(Moto): Replace with call to mRuimRecords.getIMSI_M() when implemented.
if ((getServiceState().getOperatorNumeric() != null) && (getCdmaMIN() != null)) {
return (getServiceState().getOperatorNumeric() + getCdmaMIN());
} else {
return null; return null;
} }
}
public boolean canConference() { public boolean canConference() {
Log.e(LOG_TAG, "canConference: not possible in CDMA"); Log.e(LOG_TAG, "canConference: not possible in CDMA");
@@ -513,11 +516,11 @@ public class CDMAPhone extends PhoneBase {
} }
public void registerForCallWaiting(Handler h, int what, Object obj) { public void registerForCallWaiting(Handler h, int what, Object obj) {
Log.e(LOG_TAG, "method registerForCallWaiting is NOT yet supported in CDMA"); mCT.registerForCallWaiting(h, what, obj);
} }
public void unregisterForCallWaiting(Handler h) { public void unregisterForCallWaiting(Handler h) {
Log.e(LOG_TAG, "method unregisterForCallWaiting is NOT yet supported in CDMA"); mCT.unregisterForCallWaiting(h);
} }
public String getIpAddress(String apnType) { public String getIpAddress(String apnType) {
@@ -850,12 +853,12 @@ public class CDMAPhone extends PhoneBase {
mIsPhoneInECMState = true; mIsPhoneInECMState = true;
// notify change // notify change
sendEmergencyCallbackModeChange(); sendEmergencyCallbackModeChange();
setSystemProperty(PROPERTY_INECM_MODE, "true"); setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "true");
// Post this runnable so we will automatically exit // Post this runnable so we will automatically exit
// if no one invokes exitEmergencyCallbackMode() directly. // if no one invokes exitEmergencyCallbackMode() directly.
// TODO(Moto): Get the delay a property so it can be adjusted long delayInMillis = SystemProperties.getLong(
long delayInMillis = 300000; // 30,000 millis == 5 minutes TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
h.postDelayed(mExitEcmRunnable, delayInMillis); h.postDelayed(mExitEcmRunnable, delayInMillis);
} }
} }
@@ -874,7 +877,7 @@ public class CDMAPhone extends PhoneBase {
if (ar.exception == null) { if (ar.exception == null) {
if (mIsPhoneInECMState) { if (mIsPhoneInECMState) {
mIsPhoneInECMState = false; mIsPhoneInECMState = false;
setSystemProperty(PROPERTY_INECM_MODE, "false"); setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "false");
} }
// send an Intent // send an Intent
sendEmergencyCallbackModeChange(); sendEmergencyCallbackModeChange();
@@ -911,7 +914,7 @@ public class CDMAPhone extends PhoneBase {
} }
if (LOCAL_DEBUG) Log.d(LOG_TAG, "Baseband version: " + ar.result); if (LOCAL_DEBUG) Log.d(LOG_TAG, "Baseband version: " + ar.result);
setSystemProperty(PROPERTY_BASEBAND_VERSION, (String)ar.result); setSystemProperty(TelephonyProperties.PROPERTY_BASEBAND_VERSION, (String)ar.result);
} }
break; break;
@@ -977,7 +980,7 @@ public class CDMAPhone extends PhoneBase {
Log.d(LOG_TAG, "ERI read, notify registrants"); Log.d(LOG_TAG, "ERI read, notify registrants");
mEriFileLoadedRegistrants.notifyRegistrants(); mEriFileLoadedRegistrants.notifyRegistrants();
} }
setSystemProperty(PROPERTY_INECM_MODE,"false"); setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE,"false");
} }
break; break;

View File

@@ -181,9 +181,7 @@ public final class CdmaCall extends Call {
*/ */
void void
onHangupLocal() { onHangupLocal() {
for (int i = 0, s = connections.size() for (int i = 0, s = connections.size(); i < s; i++) {
; i < s; i++
) {
CdmaConnection cn = (CdmaConnection)connections.get(i); CdmaConnection cn = (CdmaConnection)connections.get(i);
cn.onHangupLocal(); cn.onHangupLocal();

View File

@@ -58,6 +58,7 @@ public final class CdmaCallTracker extends CallTracker {
CdmaConnection connections[] = new CdmaConnection[MAX_CONNECTIONS]; CdmaConnection connections[] = new CdmaConnection[MAX_CONNECTIONS];
RegistrantList voiceCallEndedRegistrants = new RegistrantList(); RegistrantList voiceCallEndedRegistrants = new RegistrantList();
RegistrantList voiceCallStartedRegistrants = new RegistrantList(); RegistrantList voiceCallStartedRegistrants = new RegistrantList();
RegistrantList callWaitingRegistrants = new RegistrantList();
// connections dropped durin last poll // connections dropped durin last poll
@@ -93,13 +94,15 @@ public final class CdmaCallTracker extends CallTracker {
cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null); cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null); cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null);
cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null); cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
cm.registerForCallWaitingInfo(this, EVENT_CALL_WAITING_INFO_CDMA, null);
foregroundCall.setGeneric(false);
} }
public void dispose() { public void dispose() {
cm.unregisterForCallStateChanged(this); cm.unregisterForCallStateChanged(this);
cm.unregisterForOn(this); cm.unregisterForOn(this);
cm.unregisterForNotAvailable(this); cm.unregisterForNotAvailable(this);
cm.unregisterForCallWaitingInfo(this);
for(CdmaConnection c : connections) { for(CdmaConnection c : connections) {
try { try {
if(c != null) hangup(c); if(c != null) hangup(c);
@@ -143,6 +146,15 @@ public final class CdmaCallTracker extends CallTracker {
voiceCallEndedRegistrants.remove(h); voiceCallEndedRegistrants.remove(h);
} }
public void registerForCallWaiting(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
callWaitingRegistrants.add(r);
}
public void unregisterForCallWaiting(Handler h) {
callWaitingRegistrants.remove(h);
}
private void private void
fakeHoldForegroundBeforeDial() { fakeHoldForegroundBeforeDial() {
List<Connection> connCopy; List<Connection> connCopy;
@@ -170,34 +182,24 @@ public final class CdmaCallTracker extends CallTracker {
throw new CallStateException("cannot dial in current state"); throw new CallStateException("cannot dial in current state");
} }
// We are initiating a call therefore even if we previously
// didn't know the state (i.e. Generic was true) we now know
// and therefore can set Generic to false.
foregroundCall.setGeneric(false);
// The new call must be assigned to the foreground call. // The new call must be assigned to the foreground call.
// That call must be idle, so place anything that's // That call must be idle, so place anything that's
// there on hold // there on hold
if (foregroundCall.getState() == CdmaCall.State.ACTIVE) { if (foregroundCall.getState() == CdmaCall.State.ACTIVE) {
// this will probably be done by the radio anyway return dialThreeWay(dialString);
// but the dial might fail before this happens
// and we need to make sure the foreground call is clear
// for the newly dialed connection
switchWaitingOrHoldingAndActive();
// Fake local state so that
// a) foregroundCall is empty for the newly dialed connection
// b) hasNonHangupStateChanged remains false in the
// next poll, so that we don't clear a failed dialing call
fakeHoldForegroundBeforeDial();
}
if (foregroundCall.getState() != CdmaCall.State.IDLE) {
//we should have failed in !canDial() above before we get here
throw new CallStateException("cannot dial in current state");
} }
pendingMO = new CdmaConnection(phone.getContext(), dialString, this, foregroundCall); pendingMO = new CdmaConnection(phone.getContext(), dialString, this, foregroundCall);
hangupPendingMO = false; hangupPendingMO = false;
if (pendingMO.address == null || pendingMO.address.length() == 0 if (pendingMO.address == null || pendingMO.address.length() == 0
|| pendingMO.address.indexOf(PhoneNumberUtils.WILD) >= 0 || pendingMO.address.indexOf(PhoneNumberUtils.WILD) >= 0) {
) {
// Phone number is invalid // Phone number is invalid
pendingMO.cause = Connection.DisconnectCause.INVALID_NUMBER; pendingMO.cause = Connection.DisconnectCause.INVALID_NUMBER;
@@ -231,19 +233,39 @@ public final class CdmaCallTracker extends CallTracker {
return dial(dialString, CommandsInterface.CLIR_DEFAULT); return dial(dialString, CommandsInterface.CLIR_DEFAULT);
} }
private Connection
dialThreeWay (String dialString) {
if (!foregroundCall.isIdle()) {
// Attach the new connection to foregroundCall
pendingMO = new CdmaConnection(phone.getContext(),
dialString, this, foregroundCall);
cm.sendCDMAFeatureCode(pendingMO.address,
obtainMessage(EVENT_THREE_WAY_DIAL_L2_RESULT_CDMA));
return pendingMO;
}
return null;
}
void void
acceptCall() throws CallStateException { acceptCall() throws CallStateException {
// FIXME if SWITCH fails, should retry with ANSWER
// in case the active/holding call disappeared and this
// is no longer call waiting
if (ringingCall.getState() == CdmaCall.State.INCOMING) { if (ringingCall.getState() == CdmaCall.State.INCOMING) {
Log.i("phone", "acceptCall: incoming..."); Log.i("phone", "acceptCall: incoming...");
// Always unmute when answering a new call // Always unmute when answering a new call
setMute(false); setMute(false);
cm.acceptCall(obtainCompleteMessage()); cm.acceptCall(obtainCompleteMessage());
} else if (ringingCall.getState() == CdmaCall.State.WAITING) { } else if ((foregroundCall.connections.size() > 0) &&
setMute(false); (ringingCall.getState() == CdmaCall.State.WAITING)) {
// TODO(Moto): jsh asks, "Is this check necessary? I don't think it should be
// possible to have no fg connection and a WAITING call, but if we should hit
// this situation, is a CallStateExcetion appropriate?"
CdmaConnection cwConn = (CdmaConnection)(ringingCall.getLatestConnection());
// Since there is no network response for supplimentary
// service for CDMA, we assume call waiting is answered.
// ringing Call state change to idle is in CdmaCall.detach
// triggered by updateParent.
cwConn.updateParent(ringingCall, foregroundCall);
cwConn.onConnectedInOrOut();
switchWaitingOrHoldingAndActive(); switchWaitingOrHoldingAndActive();
} else { } else {
throw new CallStateException("phone not ringing"); throw new CallStateException("phone not ringing");
@@ -267,14 +289,14 @@ public final class CdmaCallTracker extends CallTracker {
if (ringingCall.getState() == CdmaCall.State.INCOMING) { if (ringingCall.getState() == CdmaCall.State.INCOMING) {
throw new CallStateException("cannot be in the incoming state"); throw new CallStateException("cannot be in the incoming state");
} else { } else {
cm.sendCDMAFeatureCode("", obtainCompleteMessage(EVENT_SWITCH_RESULT)); flashAndSetGenericTrue();
} }
} }
void void
conference() throws CallStateException { conference() throws CallStateException {
// three way calls in CDMA will be handled by feature codes // Should we be checking state?
Log.e(LOG_TAG, "conference: not possible in CDMA"); flashAndSetGenericTrue();
} }
void void
@@ -307,6 +329,7 @@ public final class CdmaCallTracker extends CallTracker {
pendingMO == null pendingMO == null
&& !ringingCall.isRinging() && !ringingCall.isRinging()
&& (!foregroundCall.getState().isAlive() && (!foregroundCall.getState().isAlive()
|| (foregroundCall.getState() == CdmaCall.State.ACTIVE)
|| !backgroundCall.getState().isAlive()); || !backgroundCall.getState().isAlive());
return ret; return ret;
@@ -495,9 +518,24 @@ public final class CdmaCallTracker extends CallTracker {
} }
hasNonHangupStateChanged = true; hasNonHangupStateChanged = true;
} else if (conn != null && dc == null) { } else if (conn != null && dc == null) {
// Connection missing in CLCC response that we were int count = foregroundCall.connections.size();
// tracking. if (count == 0) {
// Handle an unanswered MO/MT call, there is no
// foregroundCall connections at this time.
droppedDuringPoll.add(conn); droppedDuringPoll.add(conn);
} else {
// Loop through foreground call connections as
// it contains the known logical connections.
for (int n = 0; n < count; n++) {
CdmaConnection cn = (CdmaConnection)foregroundCall.connections.get(n);
droppedDuringPoll.add(cn);
}
// TODO(Moto): jsh asks, "Are we sure we don't need to do this for
// ringingCall as well? What if there's a WAITING call (ie, UI timer
// hasn't expired, moving it to DISCONNECTED)? How/when will it
// transition to DISCONNECTED?"
}
foregroundCall.setGeneric(false);
// Dropped connections are removed from the CallTracker // Dropped connections are removed from the CallTracker
// list but kept in the Call list // list but kept in the Call list
connections[i] = null; connections[i] = null;
@@ -634,6 +672,18 @@ public final class CdmaCallTracker extends CallTracker {
if (Phone.DEBUG_PHONE) log("hangup: set hangupPendingMO to true"); if (Phone.DEBUG_PHONE) log("hangup: set hangupPendingMO to true");
hangupPendingMO = true; hangupPendingMO = true;
} else if ((conn.getCall() == ringingCall)
&& (ringingCall.getState() == CdmaCall.State.WAITING)) {
// Handle call waiting hang up case.
//
// The ringingCall state will change to IDLE in CdmaCall.detach
// if the ringing call connection size is 0. We don't specifically
// set the ringing call state to IDLE here to avoid a race condition
// where a new call waiting could get a hang up from an old call
// waiting ringingCall.
// TODO(Moto): jsh asks, "Should we call conn.ondisconnect() here or Somewhere?"
ringingCall.detach(conn);
return;
} else { } else {
try { try {
cm.hangupConnection (conn.getCDMAIndex(), obtainCompleteMessage()); cm.hangupConnection (conn.getCDMAIndex(), obtainCompleteMessage());
@@ -768,6 +818,16 @@ public final class CdmaCallTracker extends CallTracker {
return null; return null;
} }
private void flashAndSetGenericTrue() throws CallStateException {
cm.sendCDMAFeatureCode("", obtainMessage(EVENT_SWITCH_RESULT));
// Set generic to true because in CDMA it is not known what
// the status of the call is after a call waiting is answered,
// 3 way call merged or a switch between calls.
foregroundCall.setGeneric(true);
phone.notifyCallStateChanged();
}
private Phone.SuppService getFailedService(int what) { private Phone.SuppService getFailedService(int what) {
switch (what) { switch (what) {
case EVENT_SWITCH_RESULT: case EVENT_SWITCH_RESULT:
@@ -789,6 +849,30 @@ public final class CdmaCallTracker extends CallTracker {
pollCallsWhenSafe(); pollCallsWhenSafe();
} }
private void notifyCallWaitingInfo(CdmaCallWaitingNotification obj) {
if (callWaitingRegistrants != null) {
callWaitingRegistrants.notifyRegistrants(new AsyncResult(null, obj, null));
}
}
private void handleCallWaitingInfo (CdmaCallWaitingNotification cw) {
// Check how many connections in foregroundCall.
// If the connection in foregroundCall is more
// than one, then the connection information is
// not reliable anymore since it means either
// call waiting is connected or 3 way call is
// dialed before, so set generic.
if (foregroundCall.connections.size() > 1 ) {
foregroundCall.setGeneric(true);
}
// Create a new CdmaConnection which attaches itself to ringingCall.
ringingCall.setGeneric(false);
new CdmaConnection(phone.getContext(), cw, this, ringingCall);
// Finally notify application
notifyCallWaitingInfo(cw);
}
//****** Overridden from Handler //****** Overridden from Handler
public void public void
@@ -811,13 +895,13 @@ public final class CdmaCallTracker extends CallTracker {
break; break;
case EVENT_OPERATION_COMPLETE: case EVENT_OPERATION_COMPLETE:
ar = (AsyncResult)msg.obj;
operationComplete(); operationComplete();
break; break;
case EVENT_SWITCH_RESULT: case EVENT_SWITCH_RESULT:
ar = (AsyncResult)msg.obj; // In GSM call operationComplete() here which gets the
operationComplete(); // current call list. But in CDMA there is no list so
// there is nothing to do.
break; break;
case EVENT_GET_LAST_CALL_FAIL_CAUSE: case EVENT_GET_LAST_CALL_FAIL_CAUSE:
@@ -871,6 +955,22 @@ public final class CdmaCallTracker extends CallTracker {
phone.unsetOnEcbModeExitResponse(this); phone.unsetOnEcbModeExitResponse(this);
break; break;
case EVENT_CALL_WAITING_INFO_CDMA:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
handleCallWaitingInfo((CdmaCallWaitingNotification)ar.result);
Log.d(LOG_TAG, "Event EVENT_CALL_WAITING_INFO_CDMA Received");
}
break;
case EVENT_THREE_WAY_DIAL_L2_RESULT_CDMA:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
// Assume 3 way call is connected
pendingMO.onConnectedInOrOut();
}
break;
default:{ default:{
throw new RuntimeException("unexpected event not handled"); throw new RuntimeException("unexpected event not handled");
} }

View File

@@ -25,11 +25,14 @@ import android.os.Message;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.Registrant; import android.os.Registrant;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Config; import android.util.Config;
import android.util.Log; import android.util.Log;
import android.text.TextUtils;
import android.telephony.PhoneNumberUtils; import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState; import android.telephony.ServiceState;
import com.android.internal.telephony.TelephonyProperties;
/** /**
* {@hide} * {@hide}
@@ -91,16 +94,6 @@ public class CdmaConnection extends Connection {
static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000; static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000;
static final int PAUSE_DELAY_MILLIS = 2 * 1000; static final int PAUSE_DELAY_MILLIS = 2 * 1000;
// TODO(Moto): These should be come from a resourse file
// at a minimum as different carriers may want to use
// different characters and our general default is "," & ";".
// Furthermore Android supports contacts that have phone
// numbers entered as strings so '1-800-164flowers' would not
// be handled as expected. Both issues need to be resolved.
static final char CUSTOMERIZED_WAIT_CHAR_UPPER ='W';
static final char CUSTOMERIZED_WAIT_CHAR_LOWER ='w';
static final char CUSTOMERIZED_PAUSE_CHAR_UPPER ='P';
static final char CUSTOMERIZED_PAUSE_CHAR_LOWER ='p';
//***** Inner Classes //***** Inner Classes
class MyHandler extends Handler { class MyHandler extends Handler {
@@ -147,17 +140,7 @@ public class CdmaConnection extends Connection {
parent.attach(this, dc); parent.attach(this, dc);
} }
CdmaConnection () { /** This is an MO call/three way call, created when dialing */
owner = null;
h = null;
address = null;
index = -1;
parent = null;
isIncoming = true;
createTime = System.currentTimeMillis();
}
/** This is an MO call, created when dialing */
/*package*/ /*package*/
CdmaConnection(Context context, String dialString, CdmaCallTracker ct, CdmaCall parent) { CdmaConnection(Context context, String dialString, CdmaCallTracker ct, CdmaCall parent) {
createWakeLock(context); createWakeLock(context);
@@ -184,9 +167,35 @@ public class CdmaConnection extends Connection {
if (parent != null) { if (parent != null) {
this.parent = parent; this.parent = parent;
//for the three way call case, not change parent state
if (parent.state == CdmaCall.State.ACTIVE) {
parent.attachFake(this, CdmaCall.State.ACTIVE);
} else {
parent.attachFake(this, CdmaCall.State.DIALING); parent.attachFake(this, CdmaCall.State.DIALING);
} }
} }
}
/** This is a Call waiting call*/
CdmaConnection(Context context, CdmaCallWaitingNotification cw, CdmaCallTracker ct,
CdmaCall parent) {
createWakeLock(context);
acquireWakeLock();
owner = ct;
h = new MyHandler(owner.getLooper());
address = cw.number;
numberPresentation = cw.numberPresentation;
cnapName = cw.name;
cnapNamePresentation = cw.namePresentation;
index = -1;
isIncoming = true;
createTime = System.currentTimeMillis();
connectTime = 0;
this.parent = parent;
parent.attachFake(this, CdmaCall.State.WAITING);
}
public void dispose() { public void dispose() {
} }
@@ -363,16 +372,6 @@ public class CdmaConnection extends Connection {
} }
} }
/**
* Used for 3way call only
*/
void update (CdmaConnection c) {
address = c.address;
cnapName = c.cnapName;
cnapNamePresentation = c.cnapNamePresentation;
numberPresentation = c.numberPresentation;
}
public void cancelPostDial() { public void cancelPostDial() {
setPostDialState(PostDialState.CANCELLED); setPostDialState(PostDialState.CANCELLED);
} }
@@ -408,7 +407,7 @@ public class CdmaConnection extends Connection {
case CallFailCause.CDMA_LOCKED_UNTIL_POWER_CYCLE: case CallFailCause.CDMA_LOCKED_UNTIL_POWER_CYCLE:
return DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE; return DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE;
case CallFailCause.CDMA_DROP: case CallFailCause.CDMA_DROP:
return DisconnectCause.LOST_SIGNAL; // TODO(Moto): wink/dave changed from CDMA_DROP; return DisconnectCause.CDMA_DROP;
case CallFailCause.CDMA_INTERCEPT: case CallFailCause.CDMA_INTERCEPT:
return DisconnectCause.CDMA_INTERCEPT; return DisconnectCause.CDMA_INTERCEPT;
case CallFailCause.CDMA_REORDER: case CallFailCause.CDMA_REORDER:
@@ -488,15 +487,14 @@ public class CdmaConnection extends Connection {
} }
// A null cnapName should be the same as "" // A null cnapName should be the same as ""
if (null != dc.name) { if (TextUtils.isEmpty(dc.name) && !TextUtils.isEmpty(cnapName)) {
if (cnapName != dc.name) {
cnapName = dc.name;
changed = true; changed = true;
}
} else {
cnapName = ""; cnapName = "";
// TODO(Moto): Should changed = true if cnapName wasn't previously "" } else if (dc.name.equals(cnapName) == false) {
changed = true;
cnapName = dc.name;
} }
log("--dssds----"+cnapName); log("--dssds----"+cnapName);
cnapNamePresentation = dc.namePresentation; cnapNamePresentation = dc.namePresentation;
numberPresentation = dc.numberPresentation; numberPresentation = dc.numberPresentation;
@@ -631,21 +629,7 @@ public class CdmaConnection extends Connection {
int wIndex = subStr.indexOf(PhoneNumberUtils.WAIT); int wIndex = subStr.indexOf(PhoneNumberUtils.WAIT);
int pIndex = subStr.indexOf(PhoneNumberUtils.PAUSE); int pIndex = subStr.indexOf(PhoneNumberUtils.PAUSE);
// TODO(Moto): Courtesy of jsh; is this simpler expression equivalent? if (wIndex > 0 && (wIndex < pIndex || pIndex <= 0)) {
//
// if (wIndex > 0 && (wIndex < pIndex || pIndex <= 0)) {
// subStr = subStr.substring(0, wIndex);
// } else if (pIndex > 0) {
// subStr = subStr.substring(0, pIndex);
// }
if (wIndex > 0 && pIndex > 0) {
if (wIndex > pIndex) {
subStr = subStr.substring(0, pIndex);
} else {
subStr = subStr.substring(0, wIndex);
}
} else if (wIndex > 0) {
subStr = subStr.substring(0, wIndex); subStr = subStr.substring(0, wIndex);
} else if (pIndex > 0) { } else if (pIndex > 0) {
subStr = subStr.substring(0, pIndex); subStr = subStr.substring(0, pIndex);
@@ -654,6 +638,16 @@ public class CdmaConnection extends Connection {
return subStr; return subStr;
} }
public void updateParent(CdmaCall oldParent, CdmaCall newParent){
if (newParent != oldParent) {
if (oldParent != null) {
oldParent.detach(this);
}
newParent.attachFake(this, CdmaCall.State.ACTIVE);
parent = newParent;
}
}
@Override @Override
protected void finalize() protected void finalize()
{ {
@@ -795,62 +789,25 @@ public class CdmaConnection extends Connection {
} }
private static boolean isPause(char c) { private static boolean isPause(char c) {
if (c == CUSTOMERIZED_PAUSE_CHAR_UPPER || c == CUSTOMERIZED_PAUSE_CHAR_LOWER return c == PhoneNumberUtils.PAUSE;
|| c == PhoneNumberUtils.PAUSE) {
return true;
} else {
return false;
}
} }
private static boolean isWait(char c) { private static boolean isWait(char c) {
if (c == CUSTOMERIZED_WAIT_CHAR_LOWER || c == CUSTOMERIZED_WAIT_CHAR_UPPER return c == PhoneNumberUtils.WAIT;
|| c == PhoneNumberUtils.WAIT) {
return true;
} else {
return false;
}
} }
/**
* format string
* convert "+" to "011"
* handle corner cases for PAUSE/WAIT
* If PAUSE/WAIT sequence at the end,ignore them
* If PAUSE/WAIT sequence in the middle, then if there is any WAIT
* in PAUSE/WAIT sequence, treat them like WAIT
* If PAUSE followed by WAIT or WAIT followed by PAUSE in the middle,
* treat them like just PAUSE or WAIT
*/
private static String formatDialString(String phoneNumber) {
if (phoneNumber == null) {
return null;
}
int length = phoneNumber.length();
StringBuilder ret = new StringBuilder();
// TODO(Moto): Modifying the for loop index is confusing, a
// while loop is probably better and overall this code is
// hard to follow. If this was routine was refactored and
// used several private methods with good names to make it
// easier to follow.
for (int i = 0; i < length; i++) {
char c = phoneNumber.charAt(i);
if (PhoneNumberUtils.isDialable(c)) {
if (c == '+') { // This function is to find the next PAUSE character index if
// TODO(Moto): Is this valid for "all" countries???? // multiple pauses in a row. Otherwise it finds the next non PAUSE or
// should probably be pulled from a resource based // non WAIT character index.
// on current contry code (MCC). private static int
ret.append("011"); findNextPCharOrNonPOrNonWCharIndex(String phoneNumber, int currIndex) {
} else {
ret.append(c);
}
} else if (isPause(c) || isWait(c)) {
if (i < length - 1) { // if PAUSE/WAIT not at the end
int index = 0;
boolean wMatched = false; boolean wMatched = false;
for (index = i + 1; index < length; index++) { int index = currIndex + 1;
int length = phoneNumber.length();
while (index < length) {
char cNext = phoneNumber.charAt(index); char cNext = phoneNumber.charAt(index);
// if there is any W inside P/W sequence,mark it // if there is any W inside P/W sequence,mark it
if (isWait(cNext)) { if (isWait(cNext)) {
@@ -861,48 +818,92 @@ public class CdmaConnection extends Connection {
if (!isWait(cNext) && !isPause(cNext)) { if (!isWait(cNext) && !isPause(cNext)) {
break; break;
} }
} index++;
if (index == length) {
// it means there is no dialable character after PAUSE/WAIT
i = length - 1;
break;
} else {// means index <length
if (isPause(c)) {
c = PhoneNumberUtils.PAUSE;
} else if (isWait(c)) {
c = PhoneNumberUtils.WAIT;
} }
if (index == i + 1) { // It means the PAUSE character(s) is in the middle of dial string
ret.append(c); // and it needs to be handled one by one.
} else if (isWait(c)) { if ((index < length) && (index > (currIndex + 1)) &&
// for case like 123WP456 =123P456 ((wMatched == false) && isPause(phoneNumber.charAt(currIndex)))) {
if ((index == i + 2) && isPause(phoneNumber.charAt(index - 1))) { return (currIndex + 1);
// skip W,append P }
ret.append(PhoneNumberUtils.PAUSE); return index;
} else {
// append W
ret.append(c);
} }
i = index - 1;
} else if (isPause(c)) {
// for case like 123PW456 =123W456, skip p, append W // This function returns either PAUSE or WAIT character to append.
// or there is 1 W in between, treat the whole PW // It is based on the next non PAUSE/WAIT character in the phoneNumber and the
// sequence as W // index for the current PAUSE/WAIT character
if (wMatched == true) { private static char
// skip P,append W findPOrWCharToAppend(String phoneNumber, int currPwIndex, int nextNonPwCharIndex) {
ret.append(PhoneNumberUtils.WAIT); char c = phoneNumber.charAt(currPwIndex);
i = index - 1; char ret;
// Append the PW char
ret = (isPause(c)) ? PhoneNumberUtils.PAUSE : PhoneNumberUtils.WAIT;
// if there is a PAUSE in at the begining of PW character sequences, and this
// PW character sequences has more than 2 PAUSE and WAIT Characters,skip P, append W
if (isPause(c) && (nextNonPwCharIndex > (currPwIndex + 1))) {
ret = PhoneNumberUtils.WAIT;
}
return ret;
}
/**
* format orignal dial string
* 1) convert international dialing prefix "+" to
* string specified per region
*
* 2) handle corner cases for PAUSE/WAIT dialing:
*
* If PAUSE/WAIT sequence at the end, ignore them.
*
* If consecutive PAUSE/WAIT sequence in the middle of the string,
* and if there is any WAIT in PAUSE/WAIT sequence, treat them like WAIT.
*/
public static String formatDialString(String phoneNumber) {
if (phoneNumber == null) {
return null;
}
int length = phoneNumber.length();
StringBuilder ret = new StringBuilder();
char c;
int currIndex = 0;
while (currIndex < length) {
c = phoneNumber.charAt(currIndex);
if (PhoneNumberUtils.isDialable(c)) {
if (c == '+') {
String ps = null;
SystemProperties.get(TelephonyProperties.PROPERTY_IDP_STRING, ps);
if (TextUtils.isEmpty(ps)) {
ps = "011";
}
ret.append(ps);
} else { } else {
ret.append(c); ret.append(c);
} }
} // end of pause case } else if (isPause(c) || isWait(c)) {
} // end of index <length, it means dialable characters after P/W if (currIndex < length - 1) {
// if PW not at the end
int nextIndex = findNextPCharOrNonPOrNonWCharIndex(phoneNumber, currIndex);
// If there is non PW char following PW sequence
if (nextIndex < length) {
char pC = findPOrWCharToAppend(phoneNumber, currIndex, nextIndex);
ret.append(pC);
// If PW char is immediately followed by non-PW char
if (nextIndex > (currIndex + 1)) {
currIndex = nextIndex - 1;
} }
} else { // if it's characters other than P/W } else if (nextIndex == length) {
// It means PW characters at the end, ignore
currIndex = length - 1;
}
}
} else {
ret.append(c); ret.append(c);
} }
currIndex++;
} }
return ret.toString(); return ret.toString();
} }

View File

@@ -16,8 +16,14 @@
package com.android.internal.telephony.cdma; package com.android.internal.telephony.cdma;
import static com.android.internal.telephony.RILConstants.*; import static com.android.internal.telephony.RILConstants.*;
import android.os.Parcel;
public final class CdmaInformationRecords { public final class CdmaInformationRecords {
public Object record;
/**
* Record type identifier
*/
public static final int RIL_CDMA_DISPLAY_INFO_REC = 0; public static final int RIL_CDMA_DISPLAY_INFO_REC = 0;
public static final int RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC = 1; public static final int RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC = 1;
public static final int RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC = 2; public static final int RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC = 2;
@@ -30,34 +36,54 @@ public final class CdmaInformationRecords {
public static final int RIL_CDMA_T53_RELEASE_INFO_REC = 9; public static final int RIL_CDMA_T53_RELEASE_INFO_REC = 9;
public static final int RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC = 10; public static final int RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC = 10;
public boolean isDispInfo; public CdmaInformationRecords(Parcel p) {
public boolean isSignInfo; int id = p.readInt();
public String cdmaDisplayInfoRecord; switch (id) {
public int[] cdmaSignalInfoRecord; case RIL_CDMA_DISPLAY_INFO_REC:
case RIL_CDMA_EXTENDED_DISPLAY_INFO_REC:
record = new CdmaDisplayInfoRec(id, p.readString());
break;
private static final int ALPHA_LEN_FOR_DISPLAY_INFO = 64; case RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC:
case RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC:
case RIL_CDMA_CONNECTED_NUMBER_INFO_REC:
record = new CdmaNumberInfoRec(id, p.readString(), p.readInt(), p.readInt(),
p.readInt(), p.readInt());
break;
public CdmaInformationRecords() { case RIL_CDMA_SIGNAL_INFO_REC:
isDispInfo = false; record = new CdmaSignalInfoRec(p.readInt(), p.readInt(), p.readInt(), p.readInt());
isSignInfo = false; break;
case RIL_CDMA_REDIRECTING_NUMBER_INFO_REC:
record = new CdmaRedirectingNumberInfoRec(p.readString(), p.readInt(), p.readInt(),
p.readInt(), p.readInt(), p.readInt());
break;
case RIL_CDMA_LINE_CONTROL_INFO_REC:
record = new CdmaLineControlInfoRec(p.readInt(), p.readInt(), p.readInt(),
p.readInt());
break;
case RIL_CDMA_T53_CLIR_INFO_REC:
record = new CdmaT53ClirInfoRec(p.readInt());
break;
case RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC:
record = new CdmaT53AudioControlInfoRec(p.readInt(), p.readInt());
break;
case RIL_CDMA_T53_RELEASE_INFO_REC:
// TODO(Moto): WHAT to do, for now fall through and throw exception
default:
throw new RuntimeException("RIL_UNSOL_CDMA_INFO_REC: unsupported record. Got "
+ CdmaInformationRecords.idToString(id) + " ");
}
} }
public void setDispInfo(String resString) { public static String idToString(int id) {
isDispInfo = true; switch(id) {
cdmaDisplayInfoRecord = resString;
}
public void setSignInfo(int isPresent, int signalType, int alertPitch, int signal) {
isSignInfo = true;
cdmaSignalInfoRecord = new int[4];
cdmaSignalInfoRecord[0] = isPresent;
cdmaSignalInfoRecord[1] = signalType;
cdmaSignalInfoRecord[2] = alertPitch;
cdmaSignalInfoRecord[3] = signal;
}
public String recordToString (int record) {
switch(record) {
case RIL_CDMA_DISPLAY_INFO_REC: return "RIL_CDMA_DISPLAY_INFO_REC"; case RIL_CDMA_DISPLAY_INFO_REC: return "RIL_CDMA_DISPLAY_INFO_REC";
case RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC: return "RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC"; case RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC: return "RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC";
case RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC: return "RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC"; case RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC: return "RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC";
@@ -72,4 +98,166 @@ public final class CdmaInformationRecords {
default: return "<unknown record>"; default: return "<unknown record>";
} }
} }
/**
* Signal Information record from 3GPP2 C.S005 3.7.5.5
*/
public static class CdmaSignalInfoRec {
public boolean isPresent; /* non-zero if signal information record is present */
public int signalType;
public int alertPitch;
public int signal;
public CdmaSignalInfoRec() {}
public CdmaSignalInfoRec(int isPresent, int signalType, int alertPitch, int signal) {
this.isPresent = isPresent != 0;
this.signalType = signalType;
this.alertPitch = alertPitch;
this.signal = signal;
}
@Override
public String toString() {
return "CdmaSignalInfo: {" +
" isPresent: " + isPresent +
", signalType: " + signalType +
", alertPitch: " + alertPitch +
", signal: " + signal +
" }";
}
}
public static class CdmaDisplayInfoRec {
public int id;
public String alpha;
public CdmaDisplayInfoRec(int id, String alpha) {
this.id = id;
this.alpha = alpha;
}
@Override
public String toString() {
return "CdmaDisplayInfoRec: {" +
" id: " + CdmaInformationRecords.idToString(id) +
", alpha: " + alpha +
" }";
}
}
public static class CdmaNumberInfoRec {
public int id;
public String number;
public byte numberType;
public byte numberPlan;
public byte pi;
public byte si;
public CdmaNumberInfoRec(int id, String number, int numberType, int numberPlan, int pi,
int si) {
this.number = number;
this.numberType = (byte)numberType;
this.numberPlan = (byte)numberPlan;
this.pi = (byte)pi;
this.si = (byte)si;
}
@Override
public String toString() {
return "CdmaNumberInfoRec: {" +
" id: " + CdmaInformationRecords.idToString(id) +
", number: " + number +
", numberType: " + numberType +
", numberPlan: " + numberPlan +
", pi: " + pi +
", si: " + si +
" }";
}
}
public static class CdmaRedirectingNumberInfoRec {
public static final int REASON_UNKNOWN = 0;
public static final int REASON_CALL_FORWARDING_BUSY = 1;
public static final int REASON_CALL_FORWARDING_NO_REPLY = 2;
public static final int REASON_CALLED_DTE_OUT_OF_ORDER = 9;
public static final int REASON_CALL_FORWARDING_BY_THE_CALLED_DTE = 10;
public static final int REASON_CALL_FORWARDING_UNCONDITIONAL = 15;
public CdmaNumberInfoRec numberInfoRec;
public int redirectingReason;
public CdmaRedirectingNumberInfoRec(String number, int numberType, int numberPlan,
int pi, int si, int reason) {
numberInfoRec = new CdmaNumberInfoRec(RIL_CDMA_REDIRECTING_NUMBER_INFO_REC,
number, numberType, numberPlan, pi, si);
redirectingReason = reason;
}
@Override
public String toString() {
return "CdmaNumberInfoRec: {" +
" numberInfoRec: " + numberInfoRec +
", redirectingReason: " + redirectingReason +
" }";
}
}
public static class CdmaLineControlInfoRec {
public byte lineCtrlPolarityIncluded;
public byte lineCtrlToggle;
public byte lineCtrlReverse;
public byte lineCtrlPowerDenial;
public CdmaLineControlInfoRec(int lineCtrlPolarityIncluded, int lineCtrlToggle,
int lineCtrlReverse, int lineCtrlPowerDenial) {
this.lineCtrlPolarityIncluded = (byte)lineCtrlPolarityIncluded;
this.lineCtrlToggle = (byte)lineCtrlToggle;
this.lineCtrlReverse = (byte)lineCtrlReverse;
this.lineCtrlPowerDenial = (byte)lineCtrlPowerDenial;
}
@Override
public String toString() {
return "CdmaLineControlInfoRec: {" +
" lineCtrlPolarityIncluded: " + lineCtrlPolarityIncluded +
" lineCtrlToggle: " + lineCtrlToggle +
" lineCtrlReverse: " + lineCtrlReverse +
" lineCtrlPowerDenial: " + lineCtrlPowerDenial +
" }";
}
}
public static class CdmaT53ClirInfoRec {
public byte cause;
public CdmaT53ClirInfoRec(int cause) {
this.cause = (byte)cause;
}
@Override
public String toString() {
return "CdmaT53ClirInfoRec: {" +
" cause: " + cause +
" }";
}
}
public static class CdmaT53AudioControlInfoRec {
public byte uplink;
public byte downlink;
public CdmaT53AudioControlInfoRec(int uplink, int downlink) {
this.uplink = (byte) uplink;
this.downlink = (byte) downlink;
}
@Override
public String toString() {
return "CdmaT53AudioControlInfoRec: {" +
" uplink: " + uplink +
" downlink: " + downlink +
" }";
}
}
} }

View File

@@ -19,8 +19,11 @@ package com.android.internal.telephony.cdma;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.ContentValues;
import android.content.Intent; import android.content.Intent;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.SQLException;
import android.net.Uri;
import android.os.AsyncResult; import android.os.AsyncResult;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
@@ -32,6 +35,7 @@ import android.os.SystemProperties;
import android.provider.Checkin; import android.provider.Checkin;
import android.provider.Settings; import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException; import android.provider.Settings.SettingNotFoundException;
import android.provider.Telephony;
import android.provider.Telephony.Intents; import android.provider.Telephony.Intents;
import android.telephony.ServiceState; import android.telephony.ServiceState;
import android.telephony.SignalStrength; import android.telephony.SignalStrength;
@@ -134,6 +138,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
static final String LOG_TAG = "CDMA"; static final String LOG_TAG = "CDMA";
private ContentResolver cr; private ContentResolver cr;
private String currentCarrier = null;
private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) { private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
@Override @Override
@@ -203,6 +208,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
cr.unregisterContentObserver(this.mAutoTimeObserver); cr.unregisterContentObserver(this.mAutoTimeObserver);
} }
@Override
protected void finalize() { protected void finalize() {
if (DBG) log("CdmaServiceStateTracker finalized"); if (DBG) log("CdmaServiceStateTracker finalized");
} }
@@ -265,10 +271,8 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
EVENT_GET_LOC_DONE_CDMA, onComplete)); EVENT_GET_LOC_DONE_CDMA, onComplete));
} }
@Override
//***** Overridden from ServiceStateTracker public void handleMessage (Message msg) {
public void
handleMessage (Message msg) {
AsyncResult ar; AsyncResult ar;
int[] ints; int[] ints;
String[] strings; String[] strings;
@@ -434,8 +438,8 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
//***** Private Instance Methods //***** Private Instance Methods
protected void setPowerStateToDesired() @Override
{ protected void setPowerStateToDesired() {
// If we want it on and it's off, turn it on // If we want it on and it's off, turn it on
if (mDesiredPowerState if (mDesiredPowerState
&& cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) { && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
@@ -470,6 +474,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
} // Otherwise, we're in the desired state } // Otherwise, we're in the desired state
} }
@Override
protected void updateSpnDisplay() { protected void updateSpnDisplay() {
String spn = ""; String spn = "";
boolean showSpn = false; boolean showSpn = false;
@@ -511,8 +516,8 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
* Handle the result of one of the pollState()-related requests * Handle the result of one of the pollState()-related requests
*/ */
protected void @Override
handlePollStateResult (int what, AsyncResult ar) { protected void handlePollStateResult (int what, AsyncResult ar) {
int ints[]; int ints[];
String states[]; String states[];
@@ -624,11 +629,32 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (opNames != null && opNames.length >= 3) { if (opNames != null && opNames.length >= 3) {
if (cm.getRadioState().isNVReady()) { if (cm.getRadioState().isNVReady()) {
// In CDMA in case on NV the ss.mOperatorAlphaLong is set later with the // In CDMA in case on NV the ss.mOperatorAlphaLong is set later with the
// ERI text, so here is ignored what is coming from the modem // ERI text, so here it is ignored what is coming from the modem
newSS.setOperatorName(null, opNames[1], opNames[2]); newSS.setOperatorName(null, opNames[1], opNames[2]);
} else { } else {
newSS.setOperatorName(opNames[0], opNames[1], opNames[2]); newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
} }
if (!(opNames[2].equals(currentCarrier))) {
// TODO(Moto): jsh asks, "This uses the MCC+MNC of the current registered
// network to set the "current" entry in the APN table. But the correct
// entry should be the MCC+MNC that matches the subscribed operator
// (eg, phone issuer). These can be different when roaming."
try {
// Set the current field of the telephony provider according to
// the CDMA's operator
Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
ContentValues map = new ContentValues();
map.put(Telephony.Carriers.NUMERIC, opNames[2]);
cr.insert(uri, map);
// save current carrier for the next time check
currentCarrier = opNames[2];
} catch (SQLException e) {
Log.e(LOG_TAG, "Can't store current operator", e);
}
} else {
Log.i(LOG_TAG, "current carrier is not changed");
}
} else { } else {
Log.w(LOG_TAG, "error parsing opNames"); Log.w(LOG_TAG, "error parsing opNames");
} }

View File

@@ -84,7 +84,6 @@ public final class FeatureCode extends Handler implements MmiCode {
CDMAPhone phone; CDMAPhone phone;
Context context; Context context;
CdmaConnection suppConn;
String action; // '*' in CDMA String action; // '*' in CDMA
String sc; // Service Code String sc; // Service Code
String poundString; // Entire Flash string String poundString; // Entire Flash string
@@ -239,15 +238,7 @@ public final class FeatureCode extends Handler implements MmiCode {
/** Process a Flash Code...anything that isn't a dialing number */ /** Process a Flash Code...anything that isn't a dialing number */
void processCode() { void processCode() {
Log.d(LOG_TAG, "send feature code..."); Log.d(LOG_TAG, "send feature code...");
if (this.poundString != null) { phone.mCM.sendCDMAFeatureCode(this.poundString, obtainMessage(EVENT_CDMA_FLASH_COMPLETED));
// TODO(Moto): Is suppConn going away?
suppConn = new CdmaConnection(phone.getContext(), this.poundString, phone.mCT, null);
phone.mCM.sendCDMAFeatureCode(suppConn.address,
obtainMessage(EVENT_CDMA_FLASH_COMPLETED));
} else {
phone.mCM.sendCDMAFeatureCode(this.poundString,
obtainMessage(EVENT_CDMA_FLASH_COMPLETED));
}
} }
/** Called from CDMAPhone.handleMessage; not a Handler subclass */ /** Called from CDMAPhone.handleMessage; not a Handler subclass */
@@ -268,7 +259,6 @@ public final class FeatureCode extends Handler implements MmiCode {
} else { } else {
state = State.COMPLETE; state = State.COMPLETE;
message = context.getText(com.android.internal.R.string.fcComplete); message = context.getText(com.android.internal.R.string.fcComplete);
suppConn.processNextPostDialChar();
} }
phone.onFeatureCodeDone(this); phone.onFeatureCodeDone(this);
break; break;

View File

@@ -16,19 +16,17 @@
package com.android.internal.telephony.cdma; package com.android.internal.telephony.cdma;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
import android.os.AsyncResult; import android.os.AsyncResult;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.Registrant; import android.os.Registrant;
import android.util.Log; import android.util.Log;
import static com.android.internal.telephony.TelephonyProperties.*;
import com.android.internal.telephony.AdnRecord; import com.android.internal.telephony.AdnRecord;
import com.android.internal.telephony.AdnRecordCache; import com.android.internal.telephony.AdnRecordCache;
import com.android.internal.telephony.AdnRecordLoader; import com.android.internal.telephony.AdnRecordLoader;
import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.cdma.RuimCard; import com.android.internal.telephony.cdma.RuimCard;
import com.android.internal.telephony.gsm.MccTable; import com.android.internal.telephony.gsm.MccTable;
@@ -55,8 +53,13 @@ public final class RuimRecords extends IccRecords {
//***** Instance Variables //***** Instance Variables
String spn; private String mImsi;
int spnDisplayCondition; private String mMyMobileNumber;
private String mSid;
private String mNid;
private String mMin2Min1;
private String mPrlVersion;
//***** Event Constants //***** Event Constants
@@ -122,8 +125,8 @@ public final class RuimRecords extends IccRecords {
adnCache.reset(); adnCache.reset();
phone.setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, null); phone.setSystemProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, null);
phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null); phone.setSystemProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null);
// recordsRequested is set to false indicating that the SIM // recordsRequested is set to false indicating that the SIM
// read requests made so far are not valid. This is set to // read requests made so far are not valid. This is set to
@@ -131,6 +134,25 @@ public final class RuimRecords extends IccRecords {
recordsRequested = false; recordsRequested = false;
} }
/** Returns null if RUIM is not yet ready */
public String getIMSI_M() {
// TODO(Moto): mImsi is not initialized, fix.
return mImsi;
}
public String getMdnNumber() {
return mMyMobileNumber;
}
public String getCdmaMin() {
return mMin2Min1;
}
/** Returns null if RUIM is not yet ready */
public String getPrlVersion() {
return mPrlVersion;
}
@Override @Override
public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){ public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){
// In CDMA this is Operator/OEM dependent // In CDMA this is Operator/OEM dependent
@@ -155,6 +177,30 @@ public final class RuimRecords extends IccRecords {
} }
} }
/**
* Returns the 5 or 6 digit MCC/MNC of the operator that
* provided the RUIM card. Returns null of RUIM is not yet ready
*/
public String getRUIMOperatorNumeric() {
if (mImsi == null) {
return null;
}
// TODO(Moto): mncLength is not set anywhere.
if (mncLength != 0) {
// Length = length of MCC + length of MNC
// TODO: change spec name
// length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
return mImsi.substring(0, 3 + mncLength);
}
// Guess the MNC length based on the MCC if we don't
// have a valid value in ef[ad]
int mcc = Integer.parseInt(mImsi.substring(0,3));
return mImsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
}
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
AsyncResult ar; AsyncResult ar;
@@ -181,35 +227,27 @@ public final class RuimRecords extends IccRecords {
/* IO events */ /* IO events */
case EVENT_GET_CDMA_SUBSCRIPTION_DONE: case EVENT_GET_CDMA_SUBSCRIPTION_DONE:
// TODO(Moto):TODO(Teleca): This event was removed by Teleca/QCT
// I've left it as it's needed to complete EVENT_OTA_PROVISION_STATUS_CHANGE.
// But since various instance variables are removed I've commented
// out code that references them. I'm sure this is wrong so
// Moto/Teleca/QCT need to come to an agreement. Also see onRuimReady
// and onVnReady.
ar = (AsyncResult)msg.obj; ar = (AsyncResult)msg.obj;
String localTemp[] = (String[])ar.result; String localTemp[] = (String[])ar.result;
if (ar.exception != null) { if (ar.exception != null) {
break; break;
} }
if (m_ota_commited) { if (m_ota_commited) {
//if(mMyMobileNumber != localTemp[0]) { if (mMyMobileNumber != localTemp[0]) {
Intent intent = new Intent(TelephonyIntents.ACTION_CDMA_OTA_MDN_CHANGED); Intent intent = new Intent(TelephonyIntents.ACTION_CDMA_OTA_MDN_CHANGED);
intent.putExtra("mdn", localTemp[0]); intent.putExtra("mdn", localTemp[0]);
Log.d(LOG_TAG,"Broadcasting intent MDN Change in OTA "); Log.d(LOG_TAG,"Broadcasting intent MDN Change in OTA ");
ActivityManagerNative.broadcastStickyIntent(intent, null); ActivityManagerNative.broadcastStickyIntent(intent, null);
//} }
m_ota_commited = false; m_ota_commited = false;
} }
//mMyMobileNumber = localTemp[0]; mMyMobileNumber = localTemp[0];
//mSid = localTemp[1]; mSid = localTemp[1];
//mNid = localTemp[2]; mNid = localTemp[2];
//if (localTemp.length >= 3) { // TODO(Moto): remove when new ril always returns min2_min1 mMin2Min1 = localTemp[3];
// mMin2Min1 = localTemp[3]; mPrlVersion = localTemp[4];
//}
//Log.d(LOG_TAG, "MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1); Log.d(LOG_TAG, "MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1);
break; break;
@@ -265,6 +303,8 @@ public final class RuimRecords extends IccRecords {
if (otaStatus == phone.CDMA_OTA_PROVISION_STATUS_COMMITTED) { if (otaStatus == phone.CDMA_OTA_PROVISION_STATUS_COMMITTED) {
m_ota_commited=true; m_ota_commited=true;
phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE)); phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
} else if (otaStatus == phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED) {
phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
} }
} }
break; break;
@@ -316,13 +356,13 @@ public final class RuimRecords extends IccRecords {
fetchRuimRecords(); fetchRuimRecords();
// TODO(Moto): TODO(Teleca): Work out how to do CDMA subscription phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
// phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
} }
private void onNvReady() { private void onNvReady() {
// TODO(Moto): TODO(Teleca): Work out how to do CDMA subscription phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
// phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
} }
private void fetchRuimRecords() { private void fetchRuimRecords() {

View File

@@ -74,13 +74,18 @@ public class SignalToneUtil {
static private HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>(); static private HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
private static Integer signalParamHash(int signalType, int alertPitch, int signal) { private static Integer signalParamHash(int signalType, int alertPitch, int signal) {
// TODO(Moto): The input should get checked before usage if ((signalType < 0) || (signalType > 256) || (alertPitch > 256) ||
(alertPitch < 0) || (signal > 256) || (signal < 0)) {
return new Integer(ToneGenerator.TONE_CDMA_INVALID);
}
return new Integer(signalType * 256 * 256 + alertPitch * 256 + signal); return new Integer(signalType * 256 * 256 + alertPitch * 256 + signal);
} }
public static int getAudioToneFromSignalInfo(int signalType, int alertPitch, int signal) { public static int getAudioToneFromSignalInfo(int signalType, int alertPitch, int signal) {
int result = ToneGenerator.TONE_CDMA_INVALID; Integer result = hm.get(signalParamHash(signalType, alertPitch, signal));
result = hm.get(signalParamHash(signalType, alertPitch, signal)); if (result == null) {
return ToneGenerator.TONE_CDMA_INVALID;
}
return result; return result;
} }