Message.obj
.
* AsyncResult.userData will be set to the obj argument here.
* The h parameter is held only by a weak reference.
*/
public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
checkCorrectThread(h);
mPreciseCallStateRegistrants.addUnique(h, what, obj);
}
/**
* Unregisters for voice call state change notifications.
* Extraneous calls are tolerated silently.
*/
public void unregisterForPreciseCallStateChanged(Handler h) {
mPreciseCallStateRegistrants.remove(h);
}
/**
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
protected void notifyPreciseCallStateChangedP() {
AsyncResult ar = new AsyncResult(null, this, null);
mPreciseCallStateRegistrants.notifyRegistrants(ar);
mNotifier.notifyPreciseCallState(this);
}
/**
* Notifies when a Handover happens due to SRVCC or Silent Redial
*/
public void registerForHandoverStateChanged(Handler h, int what, Object obj) {
checkCorrectThread(h);
mHandoverRegistrants.addUnique(h, what, obj);
}
/**
* Unregisters for handover state notifications
*/
public void unregisterForHandoverStateChanged(Handler h) {
mHandoverRegistrants.remove(h);
}
/**
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
public void notifyHandoverStateChanged(Connection cn) {
AsyncResult ar = new AsyncResult(null, cn, null);
mHandoverRegistrants.notifyRegistrants(ar);
}
protected void setIsInEmergencyCall() {
}
protected void migrateFrom(Phone from) {
migrate(mHandoverRegistrants, from.mHandoverRegistrants);
migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
migrate(mNewRingingConnectionRegistrants, from.mNewRingingConnectionRegistrants);
migrate(mIncomingRingRegistrants, from.mIncomingRingRegistrants);
migrate(mDisconnectRegistrants, from.mDisconnectRegistrants);
migrate(mServiceStateRegistrants, from.mServiceStateRegistrants);
migrate(mMmiCompleteRegistrants, from.mMmiCompleteRegistrants);
migrate(mMmiRegistrants, from.mMmiRegistrants);
migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
if (from.isInEmergencyCall()) {
setIsInEmergencyCall();
}
}
protected void migrate(RegistrantList to, RegistrantList from) {
from.removeCleared();
for (int i = 0, n = from.size(); i < n; i++) {
Registrant r = (Registrant) from.get(i);
Message msg = r.messageForRegistrant();
// Since CallManager has already registered with both CS and IMS phones,
// the migrate should happen only for those registrants which are not
// registered with CallManager.Hence the below check is needed to add
// only those registrants to the registrant list which are not
// coming from the CallManager.
if (msg != null) {
if (msg.obj == CallManager.getInstance().getRegistrantIdentifier()) {
continue;
} else {
to.add((Registrant) from.get(i));
}
} else {
Rlog.d(LOG_TAG, "msg is null");
}
}
}
/**
* Notifies when a previously untracked non-ringing/waiting connection has appeared.
* This is likely due to some other entity (eg, SIM card application) initiating a call.
*/
public void registerForUnknownConnection(Handler h, int what, Object obj) {
checkCorrectThread(h);
mUnknownConnectionRegistrants.addUnique(h, what, obj);
}
/**
* Unregisters for unknown connection notifications.
*/
public void unregisterForUnknownConnection(Handler h) {
mUnknownConnectionRegistrants.remove(h);
}
/**
* Notifies when a new ringing or waiting connection has appeared.* * Messages received from this: * Message.obj will be an AsyncResult * AsyncResult.userObj = obj * AsyncResult.result = a Connection.
* Please check Connection.isRinging() to make sure the Connection * has not dropped since this message was posted. * If Connection.isRinging() is true, then * Connection.getCall() == Phone.getRingingCall() */ public void registerForNewRingingConnection( Handler h, int what, Object obj) { checkCorrectThread(h); mNewRingingConnectionRegistrants.addUnique(h, what, obj); } /** * Unregisters for new ringing connection notification. * Extraneous calls are tolerated silently */ public void unregisterForNewRingingConnection(Handler h) { mNewRingingConnectionRegistrants.remove(h); } /** * Notifies when phone's video capabilities changes
* * Messages received from this: * Message.obj will be an AsyncResult * AsyncResult.userObj = obj * AsyncResult.result = true if phone supports video calling
*/ public void registerForVideoCapabilityChanged( Handler h, int what, Object obj) { checkCorrectThread(h); mVideoCapabilityChangedRegistrants.addUnique(h, what, obj); // Notify any registrants of the cached video capability as soon as they register. notifyForVideoCapabilityChanged(mIsVideoCapable); } /** * Unregisters for video capability changed notification. * Extraneous calls are tolerated silently */ public void unregisterForVideoCapabilityChanged(Handler h) { mVideoCapabilityChangedRegistrants.remove(h); } /** * Register for notifications when a sInCall VoicePrivacy is enabled * * @param h Handler that receives the notification message. * @param what User-defined message code. * @param obj User object. */ public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){ mCi.registerForInCallVoicePrivacyOn(h, what, obj); } /** * Unegister for notifications when a sInCall VoicePrivacy is enabled * * @param h Handler to be removed from the registrant list. */ public void unregisterForInCallVoicePrivacyOn(Handler h){ mCi.unregisterForInCallVoicePrivacyOn(h); } /** * Register for notifications when a sInCall VoicePrivacy is disabled * * @param h Handler that receives the notification message. * @param what User-defined message code. * @param obj User object. */ public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){ mCi.registerForInCallVoicePrivacyOff(h, what, obj); } /** * Unregister for notifications when a sInCall VoicePrivacy is disabled * * @param h Handler to be removed from the registrant list. */ public void unregisterForInCallVoicePrivacyOff(Handler h){ mCi.unregisterForInCallVoicePrivacyOff(h); } /** * Notifies when an incoming call rings.
* * Messages received from this: * Message.obj will be an AsyncResult * AsyncResult.userObj = obj * AsyncResult.result = a Connection.
*/ public void registerForIncomingRing( Handler h, int what, Object obj) { checkCorrectThread(h); mIncomingRingRegistrants.addUnique(h, what, obj); } /** * Unregisters for ring notification. * Extraneous calls are tolerated silently */ public void unregisterForIncomingRing(Handler h) { mIncomingRingRegistrants.remove(h); } /** * Notifies when a voice connection has disconnected, either due to local * or remote hangup or error. * * Messages received from this will have the following members:
*
* * Example: If Phone.dial is called with "*#31#", then the app will * be notified here.
*
* The returned Message.obj
will contain an AsyncResult.
*
* obj.result
will be an "MmiCode" object.
*/
public void registerForMmiInitiate(Handler h, int what, Object obj) {
checkCorrectThread(h);
mMmiRegistrants.addUnique(h, what, obj);
}
/**
* Unregisters for new MMI initiate notification.
* Extraneous calls are tolerated silently
*/
public void unregisterForMmiInitiate(Handler h) {
mMmiRegistrants.remove(h);
}
/**
* Register for notifications that an MMI request has completed
* its network activity and is in its final state. This may mean a state
* of COMPLETE, FAILED, or CANCELLED.
*
* Message.obj
will contain an AsyncResult.
* obj.result
will be an "MmiCode" object
*/
public void registerForMmiComplete(Handler h, int what, Object obj) {
checkCorrectThread(h);
mMmiCompleteRegistrants.addUnique(h, what, obj);
}
/**
* Unregisters for MMI complete notification.
* Extraneous calls are tolerated silently
*/
public void unregisterForMmiComplete(Handler h) {
checkCorrectThread(h);
mMmiCompleteRegistrants.remove(h);
}
/**
* Registration point for Sim records loaded
* @param h handler to notify
* @param what what code of message when delivered
* @param obj placed in Message.obj
*/
public void registerForSimRecordsLoaded(Handler h, int what, Object obj) {
}
/**
* Unregister for notifications for Sim records loaded
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForSimRecordsLoaded(Handler h) {
}
/**
* Register for TTY mode change notifications from the network.
* Message.obj will contain an AsyncResult.
* AsyncResult.result will be an Integer containing new mode.
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
public void registerForTtyModeReceived(Handler h, int what, Object obj) {
}
/**
* Unregisters for TTY mode change notifications.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForTtyModeReceived(Handler h) {
}
/**
* Switches network selection mode to "automatic", re-scanning and
* re-selecting a network if appropriate.
*
* @param response The message to dispatch when the network selection
* is complete.
*
* @see #selectNetworkManually(OperatorInfo, boolean, android.os.Message)
*/
public void setNetworkSelectionModeAutomatic(Message response) {
Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic, querying current mode");
// we don't want to do this unecesarily - it acutally causes
// the radio to repeate network selection and is costly
// first check if we're already in automatic mode
Message msg = obtainMessage(EVENT_CHECK_FOR_NETWORK_AUTOMATIC);
msg.obj = response;
mCi.getNetworkSelectionMode(msg);
}
private void onCheckForNetworkSelectionModeAutomatic(Message fromRil) {
AsyncResult ar = (AsyncResult)fromRil.obj;
Message response = (Message)ar.userObj;
boolean doAutomatic = true;
if (ar.exception == null && ar.result != null) {
try {
int[] modes = (int[])ar.result;
if (modes[0] == 0) {
// already confirmed to be in automatic mode - don't resend
doAutomatic = false;
}
} catch (Exception e) {
// send the setting on error
}
}
// wrap the response message in our own message along with
// an empty string (to indicate automatic selection) for the
// operator's id.
NetworkSelectMessage nsm = new NetworkSelectMessage();
nsm.message = response;
nsm.operatorNumeric = "";
nsm.operatorAlphaLong = "";
nsm.operatorAlphaShort = "";
if (doAutomatic) {
Message msg = obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
mCi.setNetworkSelectionModeAutomatic(msg);
} else {
Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic - already auto, ignoring");
ar.userObj = nsm;
handleSetSelectNetwork(ar);
}
updateSavedNetworkOperator(nsm);
}
/**
* Query the radio for the current network selection mode.
*
* Return values:
* 0 - automatic.
* 1 - manual.
*/
public void getNetworkSelectionMode(Message message) {
mCi.getNetworkSelectionMode(message);
}
/**
* Manually selects a network. response
is
* dispatched when this is complete. response.obj
will be
* an AsyncResult, and response.obj.exception
will be non-null
* on failure.
*
* @see #setNetworkSelectionModeAutomatic(Message)
*/
public void selectNetworkManually(OperatorInfo network, boolean persistSelection,
Message response) {
// wrap the response message in our own message along with
// the operator's id.
NetworkSelectMessage nsm = new NetworkSelectMessage();
nsm.message = response;
nsm.operatorNumeric = network.getOperatorNumeric();
nsm.operatorAlphaLong = network.getOperatorAlphaLong();
nsm.operatorAlphaShort = network.getOperatorAlphaShort();
Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg);
if (persistSelection) {
updateSavedNetworkOperator(nsm);
} else {
clearSavedNetworkSelection();
}
}
/**
* Registration point for emergency call/callback mode start. Message.obj is AsyncResult and
* Message.obj.result will be Integer indicating start of call by value 1 or end of call by
* value 0
* @param h handler to notify
* @param what what code of message when delivered
* @param obj placed in Message.obj.userObj
*/
public void registerForEmergencyCallToggle(Handler h, int what, Object obj) {
Registrant r = new Registrant(h, what, obj);
mEmergencyCallToggledRegistrants.add(r);
}
public void unregisterForEmergencyCallToggle(Handler h) {
mEmergencyCallToggledRegistrants.remove(h);
}
private void updateSavedNetworkOperator(NetworkSelectMessage nsm) {
int subId = getSubId();
if (SubscriptionManager.isValidSubscriptionId(subId)) {
// open the shared preferences editor, and write the value.
// nsm.operatorNumeric is "" if we're in automatic.selection.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sp.edit();
editor.putString(NETWORK_SELECTION_KEY + subId, nsm.operatorNumeric);
editor.putString(NETWORK_SELECTION_NAME_KEY + subId, nsm.operatorAlphaLong);
editor.putString(NETWORK_SELECTION_SHORT_KEY + subId, nsm.operatorAlphaShort);
// commit and log the result.
if (!editor.commit()) {
Rlog.e(LOG_TAG, "failed to commit network selection preference");
}
} else {
Rlog.e(LOG_TAG, "Cannot update network selection preference due to invalid subId " +
subId);
}
}
/**
* Used to track the settings upon completion of the network change.
*/
private void handleSetSelectNetwork(AsyncResult ar) {
// look for our wrapper within the asyncresult, skip the rest if it
// is null.
if (!(ar.userObj instanceof NetworkSelectMessage)) {
Rlog.e(LOG_TAG, "unexpected result from user object.");
return;
}
NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj;
// found the object, now we send off the message we had originally
// attached to the request.
if (nsm.message != null) {
AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
nsm.message.sendToTarget();
}
}
/**
* Method to retrieve the saved operator from the Shared Preferences
*/
private OperatorInfo getSavedNetworkSelection() {
// open the shared preferences and search with our key.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
String numeric = sp.getString(NETWORK_SELECTION_KEY + getSubId(), "");
String name = sp.getString(NETWORK_SELECTION_NAME_KEY + getSubId(), "");
String shrt = sp.getString(NETWORK_SELECTION_SHORT_KEY + getSubId(), "");
return new OperatorInfo(name, shrt, numeric);
}
/**
* Clears the saved network selection.
*/
private void clearSavedNetworkSelection() {
// open the shared preferences and search with our key.
PreferenceManager.getDefaultSharedPreferences(getContext()).edit().
remove(NETWORK_SELECTION_KEY + getSubId()).
remove(NETWORK_SELECTION_NAME_KEY + getSubId()).
remove(NETWORK_SELECTION_SHORT_KEY + getSubId()).commit();
}
/**
* Method to restore the previously saved operator id, or reset to
* automatic selection, all depending upon the value in the shared
* preferences.
*/
private void restoreSavedNetworkSelection(Message response) {
// retrieve the operator
OperatorInfo networkSelection = getSavedNetworkSelection();
// set to auto if the id is empty, otherwise select the network.
if (networkSelection == null || TextUtils.isEmpty(networkSelection.getOperatorNumeric())) {
setNetworkSelectionModeAutomatic(response);
} else {
selectNetworkManually(networkSelection, true, response);
}
}
/**
* Saves CLIR setting so that we can re-apply it as necessary
* (in case the RIL resets it across reboots).
*/
public void saveClirSetting(int commandInterfaceCLIRMode) {
// Open the shared preferences editor, and write the value.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sp.edit();
editor.putInt(CLIR_KEY + getPhoneId(), commandInterfaceCLIRMode);
// Commit and log the result.
if (!editor.commit()) {
Rlog.e(LOG_TAG, "Failed to commit CLIR preference");
}
}
/**
* For unit tests; don't send notifications to "Phone"
* mailbox registrants if true.
*/
private void setUnitTestMode(boolean f) {
mUnitTestMode = f;
}
/**
* @return true If unit test mode is enabled
*/
public boolean getUnitTestMode() {
return mUnitTestMode;
}
/**
* To be invoked when a voice call Connection disconnects.
*
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
protected void notifyDisconnectP(Connection cn) {
AsyncResult ar = new AsyncResult(null, cn, null);
mDisconnectRegistrants.notifyRegistrants(ar);
}
/**
* Register for ServiceState changed.
* Message.obj will contain an AsyncResult.
* AsyncResult.result will be a ServiceState instance
*/
public void registerForServiceStateChanged(
Handler h, int what, Object obj) {
checkCorrectThread(h);
mServiceStateRegistrants.add(h, what, obj);
}
/**
* Unregisters for ServiceStateChange notification.
* Extraneous calls are tolerated silently
*/
public void unregisterForServiceStateChanged(Handler h) {
mServiceStateRegistrants.remove(h);
}
/**
* Notifies when out-band ringback tone is needed.
* * Messages received from this: * Message.obj will be an AsyncResult * AsyncResult.userObj = obj * AsyncResult.result = boolean, true to start play ringback tone * and false to stop.
*/ public void registerForRingbackTone(Handler h, int what, Object obj) { mCi.registerForRingbackTone(h, what, obj); } /** * Unregisters for ringback tone notification. */ public void unregisterForRingbackTone(Handler h) { mCi.unregisterForRingbackTone(h); } /** * Notifies when out-band on-hold tone is needed.
* * Messages received from this: * Message.obj will be an AsyncResult * AsyncResult.userObj = obj * AsyncResult.result = boolean, true to start play on-hold tone * and false to stop.
*/ public void registerForOnHoldTone(Handler h, int what, Object obj) { } /** * Unregisters for on-hold tone notification. */ public void unregisterForOnHoldTone(Handler h) { } /** * Registers the handler to reset the uplink mute state to get * uplink audio. */ public void registerForResendIncallMute(Handler h, int what, Object obj) { mCi.registerForResendIncallMute(h, what, obj); } /** * Unregisters for resend incall mute notifications. */ public void unregisterForResendIncallMute(Handler h) { mCi.unregisterForResendIncallMute(h); } /** * Enables or disables echo suppression. */ public void setEchoSuppressionEnabled() { // no need for regular phone } /** * Subclasses of Phone probably want to replace this with a * version scoped to their packages */ protected void notifyServiceStateChangedP(ServiceState ss) { AsyncResult ar = new AsyncResult(null, ss, null); mServiceStateRegistrants.notifyRegistrants(ar); mNotifier.notifyServiceState(this); } /** * If this is a simulated phone interface, returns a SimulatedRadioControl. * @return SimulatedRadioControl if this is a simulated interface; * otherwise, null. */ public SimulatedRadioControl getSimulatedRadioControl() { return mSimulatedRadioControl; } /** * Verifies the current thread is the same as the thread originally * used in the initialization of this instance. Throws RuntimeException * if not. * * @exception RuntimeException if the current thread is not * the thread that originally obtained this Phone instance. */ private void checkCorrectThread(Handler h) { if (h.getLooper() != mLooper) { throw new RuntimeException( "com.android.internal.telephony.Phone must be used from within one thread"); } } /** * Set the properties by matching the carrier string in * a string-array resource */ private static Locale getLocaleFromCarrierProperties(Context ctx) { String carrier = SystemProperties.get("ro.carrier"); if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) { return null; } CharSequence[] carrierLocales = ctx.getResources().getTextArray(R.array.carrier_properties); for (int i = 0; i < carrierLocales.length; i+=3) { String c = carrierLocales[i].toString(); if (carrier.equals(c)) { return Locale.forLanguageTag(carrierLocales[i + 1].toString().replace('_', '-')); } } return null; } /** * Get current coarse-grained voice call state. * Use {@link #registerForPreciseCallStateChanged(Handler, int, Object) * registerForPreciseCallStateChanged()} for change notification.
* If the phone has an active call and call waiting occurs, * then the phone state is RINGING not OFFHOOK * Note: * This registration point provides notification of finer-grained * changes.
*/
public abstract PhoneConstants.State getState();
/**
* Retrieves the IccFileHandler of the Phone instance
*/
public IccFileHandler getIccFileHandler(){
UiccCardApplication uiccApplication = mUiccApplication.get();
IccFileHandler fh;
if (uiccApplication == null) {
Rlog.d(LOG_TAG, "getIccFileHandler: uiccApplication == null, return null");
fh = null;
} else {
fh = uiccApplication.getIccFileHandler();
}
Rlog.d(LOG_TAG, "getIccFileHandler: fh=" + fh);
return fh;
}
/*
* Retrieves the Handler of the Phone instance
*/
public Handler getHandler() {
return this;
}
/**
* Update the phone object if the voice radio technology has changed
*
* @param voiceRadioTech The new voice radio technology
*/
public void updatePhoneObject(int voiceRadioTech) {
}
/**
* Retrieves the ServiceStateTracker of the phone instance.
*/
public ServiceStateTracker getServiceStateTracker() {
return null;
}
/**
* Get call tracker
*/
public CallTracker getCallTracker() {
return null;
}
/**
* Update voice mail count related fields and notify listeners
*/
public void updateVoiceMail() {
Rlog.e(LOG_TAG, "updateVoiceMail() should be overridden");
}
public AppType getCurrentUiccAppType() {
UiccCardApplication currentApp = mUiccApplication.get();
if (currentApp != null) {
return currentApp.getType();
}
return AppType.APPTYPE_UNKNOWN;
}
/**
* Returns the ICC card interface for this phone, or null
* if not applicable to underlying technology.
*/
public IccCard getIccCard() {
return null;
//throw new Exception("getIccCard Shouldn't be called from Phone");
}
/**
* Retrieves the serial number of the ICC, if applicable. Returns only the decimal digits before
* the first hex digit in the ICC ID.
*/
public String getIccSerialNumber() {
IccRecords r = mIccRecords.get();
return (r != null) ? r.getIccId() : null;
}
/**
* Retrieves the full serial number of the ICC (including hex digits), if applicable.
*/
public String getFullIccSerialNumber() {
IccRecords r = mIccRecords.get();
return (r != null) ? r.getFullIccId() : null;
}
/**
* Returns SIM record load state. Use
* getSimCard().registerForReady()
for change notification.
*
* @return true if records from the SIM have been loaded and are
* available (if applicable). If not applicable to the underlying
* technology, returns true as well.
*/
public boolean getIccRecordsLoaded() {
IccRecords r = mIccRecords.get();
return (r != null) ? r.getRecordsLoaded() : false;
}
/**
* @return all available cell information or null if none.
*/
public ListPhoneStateNotifier
or an equivalent.
* An ASU is 0-31 or -1 if unknown (for GSM, dBm = -113 - 2 * asu).
* The following special values are defined:
*/ public int getVoiceMessageCount(){ return mVmCount; } /** sets the voice mail count of the phone and notifies listeners. */ public void setVoiceMessageCount(int countWaiting) { mVmCount = countWaiting; int subId = getSubId(); if (SubscriptionManager.isValidSubscriptionId(subId)) { Rlog.d(LOG_TAG, "setVoiceMessageCount: Storing Voice Mail Count = " + countWaiting + " for mVmCountKey = " + VM_COUNT + subId + " in preferences."); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); SharedPreferences.Editor editor = sp.edit(); editor.putInt(VM_COUNT + subId, countWaiting); editor.apply(); } else { Rlog.e(LOG_TAG, "setVoiceMessageCount in sharedPreference: invalid subId " + subId); } // notify listeners of voice mail notifyMessageWaitingIndicator(); } /** gets the voice mail count from preferences */ protected int getStoredVoiceMessageCount() { int countVoiceMessages = 0; int subId = getSubId(); if (SubscriptionManager.isValidSubscriptionId(subId)) { int invalidCount = -2; //-1 is not really invalid. It is used for unknown number of vm SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); int countFromSP = sp.getInt(VM_COUNT + subId, invalidCount); if (countFromSP != invalidCount) { countVoiceMessages = countFromSP; Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: from preference for subId " + subId + "= " + countVoiceMessages); } else { // Check for old preference if count not found for current subId. This part of the // code is needed only when upgrading from M to N. String subscriberId = sp.getString(VM_ID, null); if (subscriberId != null) { String currentSubscriberId = getSubscriberId(); if (currentSubscriberId != null && currentSubscriberId.equals(subscriberId)) { // get voice mail count from preferences countVoiceMessages = sp.getInt(VM_COUNT, 0); setVoiceMessageCount(countVoiceMessages); Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: from preference = " + countVoiceMessages); } else { Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: returning 0 as count for " + "matching subscriberId not found"); } // get rid of old preferences. SharedPreferences.Editor editor = sp.edit(); editor.remove(VM_ID); editor.remove(VM_COUNT); editor.apply(); } } } else { Rlog.e(LOG_TAG, "getStoredVoiceMessageCount: invalid subId " + subId); } return countVoiceMessages; } /** * Returns the CDMA ERI icon index to display */ public int getCdmaEriIconIndex() { return -1; } /** * Returns the CDMA ERI icon mode, * 0 - ON * 1 - FLASHING */ public int getCdmaEriIconMode() { return -1; } /** * Returns the CDMA ERI text, */ public String getCdmaEriText() { return "GSM nw, no ERI"; } /** * Retrieves the MIN for CDMA phones. */ public String getCdmaMin() { return null; } /** * Check if subscription data has been assigned to mMin * * return true if MIN info is ready; false otherwise. */ public boolean isMinInfoReady() { return false; } /** * Retrieves PRL Version for CDMA phones */ public String getCdmaPrlVersion(){ return null; } /** * send burst DTMF tone, it can send the string as single character or multiple character * ignore if there is no active call or not valid digits string. * Valid digit means only includes characters ISO-LATIN characters 0-9, *, # * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character, * this api can send single character and multiple character, also, this api has response * back to caller. * * @param dtmfString is string representing the dialing digit(s) in the active call * @param on the DTMF ON length in milliseconds, or 0 for default * @param off the DTMF OFF length in milliseconds, or 0 for default * @param onComplete is the callback message when the action is processed by BP * */ public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { } /** * Sets an event to be fired when the telephony system processes * a post-dial character on an outgoing call.
*
* Messages of type what
will be sent to h
.
* The obj
field of these Message's will be instances of
* AsyncResult
. Message.obj.result
will be
* a Connection object.
* * Message.arg1 will be the post dial character being processed, * or 0 ('\0') if end of string.
* * If Connection.getPostDialState() == WAIT, * the application must call * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar() * Connection.proceedAfterWaitChar()} or * {@link com.android.internal.telephony.Connection#cancelPostDial() * Connection.cancelPostDial()} * for the telephony system to continue playing the post-dial * DTMF sequence.
* * If Connection.getPostDialState() == WILD, * the application must call * {@link com.android.internal.telephony.Connection#proceedAfterWildChar * Connection.proceedAfterWildChar()} * or * {@link com.android.internal.telephony.Connection#cancelPostDial() * Connection.cancelPostDial()} * for the telephony system to continue playing the * post-dial DTMF sequence.
* * Only one post dial character handler may be set.
* Calling this method with "h" equal to null unsets this handler.
*/
public void setOnPostDialCharacter(Handler h, int what, Object obj) {
mPostDialHandler = new Registrant(h, what, obj);
}
public Registrant getPostDialHandler() {
return mPostDialHandler;
}
/**
* request to exit emergency call back mode
* the caller should use setOnECMModeExitResponse
* to receive the emergency callback mode exit response
*/
public void exitEmergencyCallbackMode() {
}
/**
* Register for notifications when CDMA OTA Provision status change
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
}
/**
* Unregister for notifications when CDMA OTA Provision status change
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForCdmaOtaStatusChange(Handler h) {
}
/**
* Registration point for subscription info ready
* @param h handler to notify
* @param what what code of message when delivered
* @param obj placed in Message.obj
*/
public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
}
/**
* Unregister for notifications for subscription info
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForSubscriptionInfoReady(Handler h) {
}
/**
* Returns true if OTA Service Provisioning needs to be performed.
*/
public boolean needsOtaServiceProvisioning() {
return false;
}
/**
* this decides if the dial number is OTA(Over the air provision) number or not
* @param dialStr is string representing the dialing digit(s)
* @return true means the dialStr is OTA number, and false means the dialStr is not OTA number
*/
public boolean isOtaSpNumber(String dialStr) {
return false;
}
/**
* Register for notifications when CDMA call waiting comes
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
public void registerForCallWaiting(Handler h, int what, Object obj){
}
/**
* Unegister for notifications when CDMA Call waiting comes
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForCallWaiting(Handler h){
}
/**
* Registration point for Ecm timer reset
* @param h handler to notify
* @param what user-defined message code
* @param obj placed in Message.obj
*/
public void registerForEcmTimerReset(Handler h, int what, Object obj) {
}
/**
* Unregister for notification for Ecm timer reset
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForEcmTimerReset(Handler h) {
}
/**
* Register for signal information notifications from the network.
* Message.obj will contain an AsyncResult.
* AsyncResult.result will be a SuppServiceNotification instance.
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
public void registerForSignalInfo(Handler h, int what, Object obj) {
mCi.registerForSignalInfo(h, what, obj);
}
/**
* Unregisters for signal information notifications.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForSignalInfo(Handler h) {
mCi.unregisterForSignalInfo(h);
}
/**
* Register for display information notifications from the network.
* Message.obj will contain an AsyncResult.
* AsyncResult.result will be a SuppServiceNotification instance.
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
public void registerForDisplayInfo(Handler h, int what, Object obj) {
mCi.registerForDisplayInfo(h, what, obj);
}
/**
* Unregisters for display information notifications.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForDisplayInfo(Handler h) {
mCi.unregisterForDisplayInfo(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.
*/
public void registerForNumberInfo(Handler h, int what, Object obj) {
mCi.registerForNumberInfo(h, what, obj);
}
/**
* Unregisters for number information record notifications.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForNumberInfo(Handler h) {
mCi.unregisterForNumberInfo(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.
*/
public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
mCi.registerForRedirectedNumberInfo(h, what, obj);
}
/**
* Unregisters for redirected number information record notification.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForRedirectedNumberInfo(Handler h) {
mCi.unregisterForRedirectedNumberInfo(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.
*/
public void registerForLineControlInfo(Handler h, int what, Object obj) {
mCi.registerForLineControlInfo(h, what, obj);
}
/**
* Unregisters for line control information notifications.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForLineControlInfo(Handler h) {
mCi.unregisterForLineControlInfo(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.
*/
public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
mCi.registerFoT53ClirlInfo(h, what, obj);
}
/**
* Unregisters for T53 CLIR information record notification
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForT53ClirInfo(Handler h) {
mCi.unregisterForT53ClirInfo(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.
*/
public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
mCi.registerForT53AudioControlInfo(h, what, obj);
}
/**
* Unregisters for T53 audio control information record notifications.
* Extraneous calls are tolerated silently
*
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForT53AudioControlInfo(Handler h) {
mCi.unregisterForT53AudioControlInfo(h);
}
/**
* registers for exit emergency call back mode request response
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
}
/**
* Unregisters for exit emergency call back mode request response
*
* @param h Handler to be removed from the registrant list.
*/
public void unsetOnEcbModeExitResponse(Handler h){
}
/**
* Register for radio off or not available
*
* @param h Handler that receives the notification message.
* @param what User-defined message code.
* @param obj User object.
*/
public void registerForRadioOffOrNotAvailable(Handler h, int what, Object obj) {
mRadioOffOrNotAvailableRegistrants.addUnique(h, what, obj);
}
/**
* Unregisters for radio off or not available
*
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForRadioOffOrNotAvailable(Handler h) {
mRadioOffOrNotAvailableRegistrants.remove(h);
}
/**
* Returns an array of string identifiers for the APN types serviced by the
* currently active.
* @return The string array will always return at least one entry, Phone.APN_TYPE_DEFAULT.
* TODO: Revisit if we always should return at least one entry.
*/
public String[] getActiveApnTypes() {
if (mDcTracker == null) {
return null;
}
return mDcTracker.getActiveApnTypes();
}
/**
* Check if TETHER_DUN_APN setting or config_tether_apndata includes APN that matches
* current operator.
* @return true if there is a matching DUN APN.
*/
public boolean hasMatchedTetherApnSetting() {
return mDcTracker.hasMatchedTetherApnSetting();
}
/**
* Returns string for the active APN host.
* @return type as a string or null if none.
*/
public String getActiveApnHost(String apnType) {
return mDcTracker.getActiveApnString(apnType);
}
/**
* Return the LinkProperties for the named apn or null if not available
*/
public LinkProperties getLinkProperties(String apnType) {
return mDcTracker.getLinkProperties(apnType);
}
/**
* Return the NetworkCapabilities
*/
public NetworkCapabilities getNetworkCapabilities(String apnType) {
return mDcTracker.getNetworkCapabilities(apnType);
}
/**
* Report on whether data connectivity is allowed.
*/
public boolean isDataConnectivityPossible() {
return isDataConnectivityPossible(PhoneConstants.APN_TYPE_DEFAULT);
}
/**
* Report on whether data connectivity is allowed for an APN.
*/
public boolean isDataConnectivityPossible(String apnType) {
return ((mDcTracker != null) &&
(mDcTracker.isDataPossible(apnType)));
}
/**
* Action set from carrier signalling broadcast receivers to enable/disable metered apns.
*/
public void carrierActionSetMeteredApnsEnabled(boolean enabled) {
if(mDcTracker != null) {
mDcTracker.setApnsEnabledByCarrier(enabled);
}
}
/**
* Action set from carrier signalling broadcast receivers to enable/disable radio
*/
public void carrierActionSetRadioEnabled(boolean enabled) {
if(mDcTracker != null) {
mDcTracker.carrierActionSetRadioEnabled(enabled);
}
}
/**
* Notify registrants of a new ringing Connection.
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
public void notifyNewRingingConnectionP(Connection cn) {
if (!mIsVoiceCapable)
return;
AsyncResult ar = new AsyncResult(null, cn, null);
mNewRingingConnectionRegistrants.notifyRegistrants(ar);
}
/**
* Notify registrants of a new unknown connection.
*/
public void notifyUnknownConnectionP(Connection cn) {
mUnknownConnectionRegistrants.notifyResult(cn);
}
/**
* Notify registrants if phone is video capable.
*/
public void notifyForVideoCapabilityChanged(boolean isVideoCallCapable) {
// Cache the current video capability so that we don't lose the information.
mIsVideoCapable = isVideoCallCapable;
AsyncResult ar = new AsyncResult(null, isVideoCallCapable, null);
mVideoCapabilityChangedRegistrants.notifyRegistrants(ar);
}
/**
* Notify registrants of a RING event.
*/
private void notifyIncomingRing() {
if (!mIsVoiceCapable)
return;
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 (mIsVoiceCapable && !mDoesRilSendMultipleCallRing &&
(token == mCallRingContinueToken)) {
Rlog.d(LOG_TAG, "Sending notifyIncomingRing");
notifyIncomingRing();
sendMessageDelayed(
obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
} else {
Rlog.d(LOG_TAG, "Ignoring ring notification request,"
+ " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
+ " token=" + token
+ " mCallRingContinueToken=" + mCallRingContinueToken
+ " mIsVoiceCapable=" + mIsVoiceCapable);
}
}
/**
* TODO: Adding a function for each property is not good.
* A fucntion of type getPhoneProp(propType) where propType is an
* enum of GSM+CDMA+LTE props would be a better approach.
*
* Get "Restriction of menu options for manual PLMN selection" bit
* status from EF_CSP data, this belongs to "Value Added Services Group".
* @return true if this bit is set or EF_CSP data is unavailable,
* false otherwise
*/
public boolean isCspPlmnEnabled() {
return false;
}
/**
* Return an interface to retrieve the ISIM records for IMS, if available.
* @return the interface to retrieve the ISIM records, or null if not supported
*/
public IsimRecords getIsimRecords() {
Rlog.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices");
return null;
}
/**
* Retrieves the MSISDN from the UICC. For GSM/UMTS phones, this is equivalent to
* {@link #getLine1Number()}. For CDMA phones, {@link #getLine1Number()} returns
* the MDN, so this method is provided to return the MSISDN on CDMA/LTE phones.
*/
public String getMsisdn() {
return null;
}
/**
* Get the current for the default apn DataState. No change notification
* exists at this interface -- use
* {@link android.telephony.PhoneStateListener} instead.
*/
public PhoneConstants.DataState getDataConnectionState() {
return getDataConnectionState(PhoneConstants.APN_TYPE_DEFAULT);
}
public void notifyCallForwardingIndicator() {
}
public void notifyDataConnectionFailed(String reason, String apnType) {
mNotifier.notifyDataConnectionFailed(this, reason, apnType);
}
public void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
String failCause) {
mNotifier.notifyPreciseDataConnectionFailed(this, reason, apnType, apn, failCause);
}
/**
* Return if the current radio is LTE on CDMA. This
* is a tri-state return value as for a period of time
* the mode may be unknown.
*
* @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}
* or {@link PhoneConstants#LTE_ON_CDMA_TRUE}
*/
public int getLteOnCdmaMode() {
return mCi.getLteOnCdmaMode();
}
/**
* Sets the SIM voice message waiting indicator records.
* @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
* @param countWaiting The number of messages waiting, if known. Use
* -1 to indicate that an unknown number of
* messages are waiting
*/
public void setVoiceMessageWaiting(int line, int countWaiting) {
// This function should be overridden by class GsmCdmaPhone.
Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive Phone.");
}
/**
* Gets the USIM service table from the UICC, if present and available.
* @return an interface to the UsimServiceTable record, or null if not available
*/
public UsimServiceTable getUsimServiceTable() {
IccRecords r = mIccRecords.get();
return (r != null) ? r.getUsimServiceTable() : null;
}
/**
* Gets the Uicc card corresponding to this phone.
* @return the UiccCard object corresponding to the phone ID.
*/
public UiccCard getUiccCard() {
return mUiccController.getUiccCard(mPhoneId);
}
/**
* Get P-CSCF address from PCO after data connection is established or modified.
* @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
*/
public String[] getPcscfAddress(String apnType) {
return mDcTracker.getPcscfAddress(apnType);
}
/**
* Set IMS registration state
*/
public void setImsRegistrationState(boolean registered) {
}
/**
* Return an instance of a IMS phone
*/
public Phone getImsPhone() {
return mImsPhone;
}
/**
* Return if UT capability of ImsPhone is enabled or not
*/
public boolean isUtEnabled() {
if (mImsPhone != null) {
return mImsPhone.isUtEnabled();
}
return false;
}
public void dispose() {
}
private void updateImsPhone() {
Rlog.d(LOG_TAG, "updateImsPhone"
+ " mImsServiceReady=" + mImsServiceReady);
if (mImsServiceReady && (mImsPhone == null)) {
mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this);
CallManager.getInstance().registerPhone(mImsPhone);
mImsPhone.registerForSilentRedial(
this, EVENT_INITIATE_SILENT_REDIAL, null);
} else if (!mImsServiceReady && (mImsPhone != null)) {
CallManager.getInstance().unregisterPhone(mImsPhone);
mImsPhone.unregisterForSilentRedial(this);
mImsPhone.dispose();
// Potential GC issue if someone keeps a reference to ImsPhone.
// However: this change will make sure that such a reference does
// not access functions through NULL pointer.
//mImsPhone.removeReferences();
mImsPhone = null;
}
}
/**
* Dials a number.
*
* @param dialString The number to dial.
* @param uusInfo The UUSInfo.
* @param videoState The video state for the call.
* @param intentExtras Extras from the original CALL intent.
* @return The Connection.
* @throws CallStateException
*/
protected Connection dialInternal(
String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)
throws CallStateException {
// dialInternal shall be overriden by GsmCdmaPhone
return null;
}
/*
* Returns the subscription id.
*/
public int getSubId() {
return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhoneId);
}
/**
* Returns the phone id.
*/
public int getPhoneId() {
return mPhoneId;
}
/**
* Return the service state of mImsPhone if it is STATE_IN_SERVICE
* otherwise return the current voice service state
*/
public int getVoicePhoneServiceState() {
Phone imsPhone = mImsPhone;
if (imsPhone != null
&& imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
return ServiceState.STATE_IN_SERVICE;
}
return getServiceState().getState();
}
/**
* Override the service provider name and the operator name for the current ICCID.
*/
public boolean setOperatorBrandOverride(String brand) {
return false;
}
/**
* Override the roaming indicator for the current ICCID.
*/
public boolean setRoamingOverride(List