/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.telephony.test; import android.hardware.radio.V1_0.DataRegStateResult; import android.hardware.radio.V1_0.VoiceRegStateResult; import android.os.AsyncResult; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.SystemClock; import android.os.WorkSource; import android.service.carrier.CarrierIdentifier; import android.telephony.CellInfo; import android.telephony.CellInfoGsm; import android.telephony.IccOpenLogicalChannelResponse; import android.telephony.ImsiEncryptionInfo; import android.telephony.NetworkScanRequest; import android.telephony.Rlog; import android.telephony.ServiceState; import android.telephony.SignalStrength; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.BaseCommands; import com.android.internal.telephony.CallFailCause; import com.android.internal.telephony.CommandException; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.LastCallFailCause; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.RadioCapability; import com.android.internal.telephony.SmsResponse; import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo; import com.android.internal.telephony.dataconnection.DataCallResponse; import com.android.internal.telephony.dataconnection.DataProfile; import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; import com.android.internal.telephony.gsm.SuppServiceNotification; import com.android.internal.telephony.uicc.IccCardStatus; import com.android.internal.telephony.uicc.IccIoResult; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; public class SimulatedCommands extends BaseCommands implements CommandsInterface, SimulatedRadioControl { private final static String LOG_TAG = "SimulatedCommands"; private enum SimLockState { NONE, REQUIRE_PIN, REQUIRE_PUK, SIM_PERM_LOCKED } private enum SimFdnState { NONE, REQUIRE_PIN2, REQUIRE_PUK2, SIM_PERM_LOCKED } private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE; public final static String DEFAULT_SIM_PIN_CODE = "1234"; private final static String SIM_PUK_CODE = "12345678"; private final static SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE; public final static String DEFAULT_SIM_PIN2_CODE = "5678"; private final static String SIM_PUK2_CODE = "87654321"; public final static String FAKE_LONG_NAME = "Fake long name"; public final static String FAKE_SHORT_NAME = "Fake short name"; public final static String FAKE_MCC_MNC = "310260"; public final static String FAKE_IMEI = "012345678901234"; public final static String FAKE_IMEISV = "99"; public final static String FAKE_ESN = "1234"; public final static String FAKE_MEID = "1234"; public final static int DEFAULT_PIN1_ATTEMPT = 5; public final static int DEFAULT_PIN2_ATTEMPT = 5; private String mImei; private String mImeiSv; //***** Instance Variables SimulatedGsmCallState simulatedCallState; HandlerThread mHandlerThread; SimLockState mSimLockedState; boolean mSimLockEnabled; int mPinUnlockAttempts; int mPukUnlockAttempts; String mPinCode; int mPin1attemptsRemaining = DEFAULT_PIN1_ATTEMPT; SimFdnState mSimFdnEnabledState; boolean mSimFdnEnabled; int mPin2UnlockAttempts; int mPuk2UnlockAttempts; int mNetworkType; String mPin2Code; boolean mSsnNotifyOn = false; private int mVoiceRegState = ServiceState.RIL_REG_STATE_HOME; private int mVoiceRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_UMTS; private int mDataRegState = ServiceState.RIL_REG_STATE_HOME; private int mDataRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_UMTS; private SignalStrength mSignalStrength; private List mCellInfoList; private int[] mImsRegState; private IccCardStatus mIccCardStatus; private IccIoResult mIccIoResultForApduLogicalChannel; private int mChannelId = IccOpenLogicalChannelResponse.INVALID_CHANNEL; int mPausedResponseCount; ArrayList mPausedResponses = new ArrayList(); int mNextCallFailCause = CallFailCause.NORMAL_CLEARING; private boolean mDcSuccess = true; private DataCallResponse mDcResponse; //***** Constructor public SimulatedCommands() { super(null); // Don't log statistics mHandlerThread = new HandlerThread("SimulatedCommands"); mHandlerThread.start(); Looper looper = mHandlerThread.getLooper(); simulatedCallState = new SimulatedGsmCallState(looper); setRadioState(RadioState.RADIO_ON); mSimLockedState = INITIAL_LOCK_STATE; mSimLockEnabled = (mSimLockedState != SimLockState.NONE); mPinCode = DEFAULT_SIM_PIN_CODE; mSimFdnEnabledState = INITIAL_FDN_STATE; mSimFdnEnabled = (mSimFdnEnabledState != SimFdnState.NONE); mPin2Code = DEFAULT_SIM_PIN2_CODE; } public void dispose() { if (mHandlerThread != null) { mHandlerThread.quit(); } } private void log(String str) { Rlog.d(LOG_TAG, str); } //***** CommandsInterface implementation @Override public void getIccCardStatus(Message result) { if(mIccCardStatus!=null) { resultSuccess(result, mIccCardStatus); } else { resultFail(result, null, new RuntimeException("IccCardStatus not set")); } } @Override public void supplyIccPin(String pin, Message result) { if (mSimLockedState != SimLockState.REQUIRE_PIN) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: wrong state, state=" + mSimLockedState); CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); return; } if (pin != null && pin.equals(mPinCode)) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: success!"); mPinUnlockAttempts = 0; mSimLockedState = SimLockState.NONE; mIccStatusChangedRegistrants.notifyRegistrants(); resultSuccess(result, null); return; } if (result != null) { mPinUnlockAttempts ++; Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: failed! attempt=" + mPinUnlockAttempts); if (mPinUnlockAttempts >= DEFAULT_PIN1_ATTEMPT) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: set state to REQUIRE_PUK"); mSimLockedState = SimLockState.REQUIRE_PUK; } CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); } } @Override public void supplyIccPuk(String puk, String newPin, Message result) { if (mSimLockedState != SimLockState.REQUIRE_PUK) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: wrong state, state=" + mSimLockedState); CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); return; } if (puk != null && puk.equals(SIM_PUK_CODE)) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: success!"); mSimLockedState = SimLockState.NONE; mPukUnlockAttempts = 0; mIccStatusChangedRegistrants.notifyRegistrants(); resultSuccess(result, null); return; } if (result != null) { mPukUnlockAttempts ++; Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: failed! attempt=" + mPukUnlockAttempts); if (mPukUnlockAttempts >= 10) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: set state to SIM_PERM_LOCKED"); mSimLockedState = SimLockState.SIM_PERM_LOCKED; } CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); } } @Override public void supplyIccPin2(String pin2, Message result) { if (mSimFdnEnabledState != SimFdnState.REQUIRE_PIN2) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: wrong state, state=" + mSimFdnEnabledState); CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); return; } if (pin2 != null && pin2.equals(mPin2Code)) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: success!"); mPin2UnlockAttempts = 0; mSimFdnEnabledState = SimFdnState.NONE; resultSuccess(result, null); return; } if (result != null) { mPin2UnlockAttempts ++; Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: failed! attempt=" + mPin2UnlockAttempts); if (mPin2UnlockAttempts >= DEFAULT_PIN2_ATTEMPT) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: set state to REQUIRE_PUK2"); mSimFdnEnabledState = SimFdnState.REQUIRE_PUK2; } CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); } } @Override public void supplyIccPuk2(String puk2, String newPin2, Message result) { if (mSimFdnEnabledState != SimFdnState.REQUIRE_PUK2) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: wrong state, state=" + mSimLockedState); CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); return; } if (puk2 != null && puk2.equals(SIM_PUK2_CODE)) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: success!"); mSimFdnEnabledState = SimFdnState.NONE; mPuk2UnlockAttempts = 0; resultSuccess(result, null); return; } if (result != null) { mPuk2UnlockAttempts ++; Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: failed! attempt=" + mPuk2UnlockAttempts); if (mPuk2UnlockAttempts >= 10) { Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: set state to SIM_PERM_LOCKED"); mSimFdnEnabledState = SimFdnState.SIM_PERM_LOCKED; } CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); } } @Override public void changeIccPin(String oldPin, String newPin, Message result) { if (oldPin != null && oldPin.equals(mPinCode)) { mPinCode = newPin; resultSuccess(result, null); return; } Rlog.i(LOG_TAG, "[SimCmd] changeIccPin: pin failed!"); CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); } @Override public void changeIccPin2(String oldPin2, String newPin2, Message result) { if (oldPin2 != null && oldPin2.equals(mPin2Code)) { mPin2Code = newPin2; resultSuccess(result, null); return; } Rlog.i(LOG_TAG, "[SimCmd] changeIccPin2: pin2 failed!"); CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(result, null, ex); } @Override public void changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) { unimplemented(result); } @Override public void setSuppServiceNotifications(boolean enable, Message result) { resultSuccess(result, null); if (enable && mSsnNotifyOn) { Rlog.w(LOG_TAG, "Supp Service Notifications already enabled!"); } mSsnNotifyOn = enable; } @Override public void queryFacilityLock(String facility, String pin, int serviceClass, Message result) { queryFacilityLockForApp(facility, pin, serviceClass, null, result); } @Override public void queryFacilityLockForApp(String facility, String pin, int serviceClass, String appId, Message result) { if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) { if (result != null) { int[] r = new int[1]; r[0] = (mSimLockEnabled ? 1 : 0); Rlog.i(LOG_TAG, "[SimCmd] queryFacilityLock: SIM is " + (r[0] == 0 ? "unlocked" : "locked")); resultSuccess(result, r); } return; } else if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) { if (result != null) { int[] r = new int[1]; r[0] = (mSimFdnEnabled ? 1 : 0); Rlog.i(LOG_TAG, "[SimCmd] queryFacilityLock: FDN is " + (r[0] == 0 ? "disabled" : "enabled")); resultSuccess(result, r); } return; } unimplemented(result); } @Override public void setFacilityLock(String facility, boolean lockEnabled, String pin, int serviceClass, Message result) { setFacilityLockForApp(facility, lockEnabled, pin, serviceClass, null, result); } @Override public void setFacilityLockForApp(String facility, boolean lockEnabled, String pin, int serviceClass, String appId, Message result) { if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) { if (pin != null && pin.equals(mPinCode)) { Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin is valid"); mSimLockEnabled = lockEnabled; resultSuccess(result, null); return; } Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin failed!"); CommandException ex = new CommandException( CommandException.Error.GENERIC_FAILURE); resultFail(result, null, ex); return; } else if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) { if (pin != null && pin.equals(mPin2Code)) { Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 is valid"); mSimFdnEnabled = lockEnabled; resultSuccess(result, null); return; } Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 failed!"); CommandException ex = new CommandException( CommandException.Error.GENERIC_FAILURE); resultFail(result, null, ex); return; } unimplemented(result); } @Override public void supplyNetworkDepersonalization(String netpin, Message result) { unimplemented(result); } /** * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result contains a List of DriverCall * The ar.result List is sorted by DriverCall.index */ @Override public void getCurrentCalls (Message result) { SimulatedCommandsVerifier.getInstance().getCurrentCalls(result); if ((mState == RadioState.RADIO_ON) && !isSimLocked()) { //Rlog.i("GSM", "[SimCmds] getCurrentCalls"); resultSuccess(result, simulatedCallState.getDriverCalls()); } else { //Rlog.i("GSM", "[SimCmds] getCurrentCalls: RADIO_OFF or SIM not ready!"); resultFail(result, null, new CommandException(CommandException.Error.RADIO_NOT_AVAILABLE)); } } /** * @deprecated */ @Deprecated @Override public void getPDPContextList(Message result) { getDataCallList(result); } /** * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result contains a List of DataCallResponse */ @Override public void getDataCallList(Message result) { resultSuccess(result, new ArrayList(0)); } /** * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure * * CLIR_DEFAULT == on "use subscription default value" * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) */ @Override public void dial (String address, int clirMode, Message result) { SimulatedCommandsVerifier.getInstance().dial(address, clirMode, result); simulatedCallState.onDial(address); resultSuccess(result, null); } /** * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure * * CLIR_DEFAULT == on "use subscription default value" * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) */ @Override public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) { SimulatedCommandsVerifier.getInstance().dial(address, clirMode, uusInfo, result); simulatedCallState.onDial(address); resultSuccess(result, null); } @Override public void getIMSI(Message result) { getIMSIForApp(null, result); } /** * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is String containing IMSI on success */ @Override public void getIMSIForApp(String aid, Message result) { resultSuccess(result, "012345678901234"); } public void setIMEI(String imei) { mImei = imei; } /** * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is String containing IMEI on success */ @Override public void getIMEI(Message result) { SimulatedCommandsVerifier.getInstance().getIMEI(result); resultSuccess(result, mImei != null ? mImei : FAKE_IMEI); } public void setIMEISV(String imeisv) { mImeiSv = imeisv; } /** * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is String containing IMEISV on success */ @Override public void getIMEISV(Message result) { SimulatedCommandsVerifier.getInstance().getIMEISV(result); resultSuccess(result, mImeiSv != null ? mImeiSv : FAKE_IMEISV); } /** * Hang up one individual connection. * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure * * 3GPP 22.030 6.5.5 * "Releases a specific active call X" */ @Override public void hangupConnection (int gsmIndex, Message result) { boolean success; success = simulatedCallState.onChld('1', (char)('0'+gsmIndex)); if (!success){ Rlog.i("GSM", "[SimCmd] hangupConnection: resultFail"); resultFail(result, null, new RuntimeException("Hangup Error")); } else { Rlog.i("GSM", "[SimCmd] hangupConnection: resultSuccess"); resultSuccess(result, null); } } /** * 3GPP 22.030 6.5.5 * "Releases all held calls or sets User Determined User Busy (UDUB) * for a waiting call." * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void hangupWaitingOrBackground (Message result) { boolean success; success = simulatedCallState.onChld('0', '\0'); if (!success){ resultFail(result, null, new RuntimeException("Hangup Error")); } else { resultSuccess(result, null); } } /** * 3GPP 22.030 6.5.5 * "Releases all active calls (if any exist) and accepts * the other (held or waiting) call." * * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void hangupForegroundResumeBackground (Message result) { boolean success; success = simulatedCallState.onChld('1', '\0'); if (!success){ resultFail(result, null, new RuntimeException("Hangup Error")); } else { resultSuccess(result, null); } } /** * 3GPP 22.030 6.5.5 * "Places all active calls (if any exist) on hold and accepts * the other (held or waiting) call." * * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void switchWaitingOrHoldingAndActive (Message result) { boolean success; success = simulatedCallState.onChld('2', '\0'); if (!success){ resultFail(result, null, new RuntimeException("Hangup Error")); } else { resultSuccess(result, null); } } /** * 3GPP 22.030 6.5.5 * "Adds a held call to the conversation" * * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void conference (Message result) { boolean success; success = simulatedCallState.onChld('3', '\0'); if (!success){ resultFail(result, null, new RuntimeException("Hangup Error")); } else { resultSuccess(result, null); } } /** * 3GPP 22.030 6.5.5 * "Connects the two calls and disconnects the subscriber from both calls" * * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void explicitCallTransfer (Message result) { boolean success; success = simulatedCallState.onChld('4', '\0'); if (!success){ resultFail(result, null, new RuntimeException("Hangup Error")); } else { resultSuccess(result, null); } } /** * 3GPP 22.030 6.5.5 * "Places all active calls on hold except call X with which * communication shall be supported." */ @Override public void separateConnection (int gsmIndex, Message result) { boolean success; char ch = (char)(gsmIndex + '0'); success = simulatedCallState.onChld('2', ch); if (!success){ resultFail(result, null, new RuntimeException("Hangup Error")); } else { resultSuccess(result, null); } } /** * * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void acceptCall (Message result) { boolean success; SimulatedCommandsVerifier.getInstance().acceptCall(result); success = simulatedCallState.onAnswer(); if (!success){ resultFail(result, null, new RuntimeException("Hangup Error")); } else { resultSuccess(result, null); } } /** * also known as UDUB * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void rejectCall (Message result) { boolean success; success = simulatedCallState.onChld('0', '\0'); if (!success){ resultFail(result, null, new RuntimeException("Hangup Error")); } else { resultSuccess(result, null); } } /** * cause code returned as Integer in Message.obj.response * Returns integer cause code defined in TS 24.008 * Annex H or closest approximation. * Most significant codes: * - Any defined in 22.001 F.4 (for generating busy/congestion) * - Cause 68: ACM >= ACMMax */ @Override public void getLastCallFailCause (Message result) { LastCallFailCause mFailCause = new LastCallFailCause(); mFailCause.causeCode = mNextCallFailCause; resultSuccess(result, mFailCause); } /** * @deprecated */ @Deprecated @Override public void getLastPdpFailCause (Message result) { unimplemented(result); } @Override public void getLastDataCallFailCause(Message result) { // unimplemented(result); } @Override public void setMute (boolean enableMute, Message result) {unimplemented(result);} @Override public void getMute (Message result) {unimplemented(result);} public void setSignalStrength(SignalStrength signalStrength) { mSignalStrength = signalStrength; } @Override public void getSignalStrength (Message result) { if (mSignalStrength == null) { mSignalStrength = new SignalStrength( 20, // gsmSignalStrength 0, // gsmBitErrorRate -1, // cdmaDbm -1, // cdmaEcio -1, // evdoDbm -1, // evdoEcio -1, // evdoSnr 99, // lteSignalStrength SignalStrength.INVALID, // lteRsrp SignalStrength.INVALID, // lteRsrq SignalStrength.INVALID, // lteRssnr SignalStrength.INVALID, // lteCqi SignalStrength.INVALID, // tdScdmaRscp true // gsmFlag ); } resultSuccess(result, mSignalStrength); } /** * Assign a specified band for RF configuration. * * @param bandMode one of BM_*_BAND * @param result is callback message */ @Override public void setBandMode (int bandMode, Message result) { resultSuccess(result, null); } /** * Query the list of band mode supported by RF. * * @param result is callback message * ((AsyncResult)response.obj).result is an int[] where int[0] is * the size of the array and the rest of each element representing * one available BM_*_BAND */ @Override public void queryAvailableBandMode (Message result) { int ret[] = new int [4]; ret[0] = 4; ret[1] = Phone.BM_US_BAND; ret[2] = Phone.BM_JPN_BAND; ret[3] = Phone.BM_AUS_BAND; resultSuccess(result, ret); } /** * {@inheritDoc} */ @Override public void sendTerminalResponse(String contents, Message response) { resultSuccess(response, null); } /** * {@inheritDoc} */ @Override public void sendEnvelope(String contents, Message response) { resultSuccess(response, null); } /** * {@inheritDoc} */ @Override public void sendEnvelopeWithStatus(String contents, Message response) { resultSuccess(response, null); } /** * {@inheritDoc} */ @Override public void handleCallSetupRequestFromSim( boolean accept, Message response) { resultSuccess(response, null); } public void setVoiceRadioTech(int voiceRadioTech) { mVoiceRadioTech = voiceRadioTech; } public void setVoiceRegState(int voiceRegState) { mVoiceRegState = voiceRegState; } /** * response.obj.result is an String[14] * See ril.h for details * * Please note that registration state 4 ("unknown") is treated * as "out of service" above */ @Override public void getVoiceRegistrationState(Message result) { mGetVoiceRegistrationStateCallCount.incrementAndGet(); VoiceRegStateResult ret = new VoiceRegStateResult(); ret.regState = mVoiceRegState; ret.rat = mVoiceRadioTech; resultSuccess(result, ret); } private final AtomicInteger mGetVoiceRegistrationStateCallCount = new AtomicInteger(0); @VisibleForTesting public int getGetVoiceRegistrationStateCallCount() { return mGetVoiceRegistrationStateCallCount.get(); } public void setDataRadioTech(int radioTech) { mDataRadioTech = radioTech; } public void setDataRegState(int dataRegState) { mDataRegState = dataRegState; } @Override public void getDataRegistrationState (Message result) { mGetDataRegistrationStateCallCount.incrementAndGet(); DataRegStateResult ret = new DataRegStateResult(); ret.regState = mDataRegState; ret.rat = mDataRadioTech; resultSuccess(result, ret); } private final AtomicInteger mGetDataRegistrationStateCallCount = new AtomicInteger(0); @VisibleForTesting public int getGetDataRegistrationStateCallCount() { return mGetDataRegistrationStateCallCount.get(); } /** * response.obj.result is a String[3] * response.obj.result[0] is long alpha or null if unregistered * response.obj.result[1] is short alpha or null if unregistered * response.obj.result[2] is numeric or null if unregistered */ @Override public void getOperator(Message result) { mGetOperatorCallCount.incrementAndGet(); String[] ret = new String[3]; ret[0] = FAKE_LONG_NAME; ret[1] = FAKE_SHORT_NAME; ret[2] = FAKE_MCC_MNC; resultSuccess(result, ret); } private final AtomicInteger mGetOperatorCallCount = new AtomicInteger(0); @VisibleForTesting public int getGetOperatorCallCount() { final int count = mGetOperatorCallCount.get(); return mGetOperatorCallCount.get(); } /** * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void sendDtmf(char c, Message result) { resultSuccess(result, null); } /** * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void startDtmf(char c, Message result) { resultSuccess(result, null); } /** * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void stopDtmf(Message result) { resultSuccess(result, null); } /** * ar.exception carries exception on failure * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ @Override public void sendBurstDtmf(String dtmfString, int on, int off, Message result) { SimulatedCommandsVerifier.getInstance().sendBurstDtmf(dtmfString, on, off, result); resultSuccess(result, null); } /** * smscPDU is smsc address in PDU form GSM BCD format prefixed * by a length byte (as expected by TS 27.005) or NULL for default SMSC * pdu is SMS in PDU format as an ASCII hex string * less the SMSC address */ @Override public void sendSMS (String smscPDU, String pdu, Message result) { SimulatedCommandsVerifier.getInstance().sendSMS(smscPDU, pdu, result); resultSuccess(result, new SmsResponse(0 /*messageRef*/, null, 0)); } /** * Send an SMS message, Identical to sendSMS, * except that more messages are expected to be sent soon * smscPDU is smsc address in PDU form GSM BCD format prefixed * by a length byte (as expected by TS 27.005) or NULL for default SMSC * pdu is SMS in PDU format as an ASCII hex string * less the SMSC address */ @Override public void sendSMSExpectMore (String smscPDU, String pdu, Message result) { unimplemented(result); } @Override public void deleteSmsOnSim(int index, Message response) { Rlog.d(LOG_TAG, "Delete message at index " + index); unimplemented(response); } @Override public void deleteSmsOnRuim(int index, Message response) { Rlog.d(LOG_TAG, "Delete RUIM message at index " + index); unimplemented(response); } @Override public void writeSmsToSim(int status, String smsc, String pdu, Message response) { Rlog.d(LOG_TAG, "Write SMS to SIM with status " + status); unimplemented(response); } @Override public void writeSmsToRuim(int status, String pdu, Message response) { Rlog.d(LOG_TAG, "Write SMS to RUIM with status " + status); unimplemented(response); } public void setDataCallResponse(final boolean success, final DataCallResponse dcResponse) { mDcResponse = dcResponse; mDcSuccess = success; } public void triggerNITZupdate(String NITZStr) { if (NITZStr != null) { mNITZTimeRegistrant.notifyRegistrant(new AsyncResult (null, new Object[]{NITZStr, SystemClock.elapsedRealtime()}, null)); } } @Override public void setupDataCall(int radioTechnology, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, Message result) { SimulatedCommandsVerifier.getInstance().setupDataCall(radioTechnology, dataProfile, isRoaming, allowRoaming, result); if (mDcResponse == null) { mDcResponse = new DataCallResponse(0, -1, 1, 2, "IP", "rmnet_data7", "12.34.56.78", "98.76.54.32", "11.22.33.44", "", 1440); } if (mDcSuccess) { resultSuccess(result, mDcResponse); } else { resultFail(result, mDcResponse, new RuntimeException("Setup data call failed!")); } } @Override public void deactivateDataCall(int cid, int reason, Message result) { SimulatedCommandsVerifier.getInstance().deactivateDataCall(cid, reason, result); resultSuccess(result, null); } @Override public void setPreferredNetworkType(int networkType , Message result) { SimulatedCommandsVerifier.getInstance().setPreferredNetworkType(networkType, result); mNetworkType = networkType; resultSuccess(result, null); } @Override public void getPreferredNetworkType(Message result) { SimulatedCommandsVerifier.getInstance().getPreferredNetworkType(result); int ret[] = new int[1]; ret[0] = mNetworkType; resultSuccess(result, ret); } @Override public void getNeighboringCids(Message result, WorkSource workSource) { int ret[] = new int[7]; ret[0] = 6; for (int i = 1; i<7; i++) { ret[i] = i; } resultSuccess(result, ret); } @Override public void setLocationUpdates(boolean enable, Message response) { SimulatedCommandsVerifier.getInstance().setLocationUpdates(enable, response); resultSuccess(response, null); } @Override public void getSmscAddress(Message result) { unimplemented(result); } @Override public void setSmscAddress(String address, Message result) { unimplemented(result); } @Override public void reportSmsMemoryStatus(boolean available, Message result) { resultSuccess(result, null); SimulatedCommandsVerifier.getInstance().reportSmsMemoryStatus(available, result); } @Override public void reportStkServiceIsRunning(Message result) { resultSuccess(result, null); } @Override public void getCdmaSubscriptionSource(Message result) { unimplemented(result); } private boolean isSimLocked() { if (mSimLockedState != SimLockState.NONE) { return true; } return false; } @Override public void setRadioPower(boolean on, Message result) { if(on) { setRadioState(RadioState.RADIO_ON); } else { setRadioState(RadioState.RADIO_OFF); } } @Override public void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) { unimplemented(result); SimulatedCommandsVerifier.getInstance(). acknowledgeLastIncomingGsmSms(success, cause, result); } @Override public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) { unimplemented(result); } @Override public void acknowledgeIncomingGsmSmsWithPdu(boolean success, String ackPdu, Message result) { unimplemented(result); } @Override public void iccIO(int command, int fileid, String path, int p1, int p2, int p3, String data, String pin2, Message response) { iccIOForApp(command, fileid, path, p1, p2, p3, data, pin2, null, response); } /** * parameters equivalent to 27.007 AT+CRSM command * response.obj will be an AsyncResult * response.obj.userObj will be a SimIoResult on success */ @Override public void iccIOForApp (int command, int fileid, String path, int p1, int p2, int p3, String data, String pin2, String aid, Message result) { unimplemented(result); } /** * (AsyncResult)response.obj).result is an int[] with element [0] set to * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned". * * @param response is callback message */ @Override public void queryCLIP(Message response) { unimplemented(response); } /** * response.obj will be a an int[2] * * response.obj[0] will be TS 27.007 +CLIR parameter 'n' * 0 presentation indicator is used according to the subscription of the CLIR service * 1 CLIR invocation * 2 CLIR suppression * * response.obj[1] will be TS 27.007 +CLIR parameter 'm' * 0 CLIR not provisioned * 1 CLIR provisioned in permanent mode * 2 unknown (e.g. no network, etc.) * 3 CLIR temporary mode presentation restricted * 4 CLIR temporary mode presentation allowed */ @Override public void getCLIR(Message result) {unimplemented(result);} /** * clirMode is one of the CLIR_* constants above * * response.obj is null */ @Override public void setCLIR(int clirMode, Message result) {unimplemented(result);} /** * (AsyncResult)response.obj).result is an int[] with element [0] set to * 0 for disabled, 1 for enabled. * * @param serviceClass is a sum of SERVICE_CLASS_* * @param response is callback message */ @Override public void queryCallWaiting(int serviceClass, Message response) { unimplemented(response); } /** * @param enable is true to enable, false to disable * @param serviceClass is a sum of SERVICE_CLASS_* * @param response is callback message */ @Override public void setCallWaiting(boolean enable, int serviceClass, Message response) { unimplemented(response); } /** * @param action is one of CF_ACTION_* * @param cfReason is one of CF_REASON_* * @param serviceClass is a sum of SERVICE_CLASSS_* */ @Override public void setCallForward(int action, int cfReason, int serviceClass, String number, int timeSeconds, Message result) { SimulatedCommandsVerifier.getInstance().setCallForward(action, cfReason, serviceClass, number, timeSeconds, result); resultSuccess(result, null); } /** * cfReason is one of CF_REASON_* * * ((AsyncResult)response.obj).result will be an array of * CallForwardInfo's * * An array of length 0 means "disabled for all codes" */ @Override public void queryCallForwardStatus(int cfReason, int serviceClass, String number, Message result) { SimulatedCommandsVerifier.getInstance().queryCallForwardStatus(cfReason, serviceClass, number, result); resultSuccess(result, null); } @Override public void setNetworkSelectionModeAutomatic(Message result) {unimplemented(result);} @Override public void exitEmergencyCallbackMode(Message result) {unimplemented(result);} @Override public void setNetworkSelectionModeManual( String operatorNumeric, Message result) {unimplemented(result);} /** * Queries whether the current network selection mode is automatic * or manual * * ((AsyncResult)response.obj).result is an int[] with element [0] being * a 0 for automatic selection and a 1 for manual selection */ @Override public void getNetworkSelectionMode(Message result) { SimulatedCommandsVerifier.getInstance().getNetworkSelectionMode(result); getNetworkSelectionModeCallCount.incrementAndGet(); int ret[] = new int[1]; ret[0] = 0; resultSuccess(result, ret); } private final AtomicInteger getNetworkSelectionModeCallCount = new AtomicInteger(0); @VisibleForTesting public int getGetNetworkSelectionModeCallCount() { return getNetworkSelectionModeCallCount.get(); } /** * Queries the currently available networks * * ((AsyncResult)response.obj).result is a List of NetworkInfo objects */ @Override public void getAvailableNetworks(Message result) { unimplemented(result); } /** * Starts a network scan */ @Override public void startNetworkScan(NetworkScanRequest nsr, Message result) { unimplemented(result); } /** * Stops an ongoing network scan */ @Override public void stopNetworkScan(Message result) { unimplemented(result); } @Override public void getBasebandVersion (Message result) { SimulatedCommandsVerifier.getInstance().getBasebandVersion(result); resultSuccess(result, "SimulatedCommands"); } /** * Simulates an Stk Call Control Alpha message * @param alphaString Alpha string to send. */ public void triggerIncomingStkCcAlpha(String alphaString) { if (mCatCcAlphaRegistrant != null) { mCatCcAlphaRegistrant.notifyResult(alphaString); } } public void sendStkCcAplha(String alphaString) { triggerIncomingStkCcAlpha(alphaString); } /** * Simulates an incoming USSD message * @param statusCode Status code string. See setOnUSSD * in CommandsInterface.java * @param message Message text to send or null if none */ @Override public void triggerIncomingUssd(String statusCode, String message) { if (mUSSDRegistrant != null) { String[] result = {statusCode, message}; mUSSDRegistrant.notifyResult(result); } } @Override public void sendUSSD (String ussdString, Message result) { // We simulate this particular sequence if (ussdString.equals("#646#")) { resultSuccess(result, null); // 0 == USSD-Notify triggerIncomingUssd("0", "You have NNN minutes remaining."); } else { resultSuccess(result, null); triggerIncomingUssd("0", "All Done"); } } // inherited javadoc suffices @Override public void cancelPendingUssd (Message response) { resultSuccess(response, null); } @Override public void resetRadio(Message result) { unimplemented(result); } @Override public void invokeOemRilRequestRaw(byte[] data, Message response) { // Just echo back data if (response != null) { AsyncResult.forMessage(response).result = data; response.sendToTarget(); } } @Override public void setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo, Message response) { // Just echo back data if (response != null) { AsyncResult.forMessage(response).result = imsiEncryptionInfo; response.sendToTarget(); } } @Override public void invokeOemRilRequestStrings(String[] strings, Message response) { // Just echo back data if (response != null) { AsyncResult.forMessage(response).result = strings; response.sendToTarget(); } } //***** SimulatedRadioControl /** Start the simulated phone ringing */ @Override public void triggerRing(String number) { simulatedCallState.triggerRing(number); mCallStateRegistrants.notifyRegistrants(); } @Override public void progressConnectingCallState() { simulatedCallState.progressConnectingCallState(); mCallStateRegistrants.notifyRegistrants(); } /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */ @Override public void progressConnectingToActive() { simulatedCallState.progressConnectingToActive(); mCallStateRegistrants.notifyRegistrants(); } /** automatically progress mobile originated calls to ACTIVE. * default to true */ @Override public void setAutoProgressConnectingCall(boolean b) { simulatedCallState.setAutoProgressConnectingCall(b); } @Override public void setNextDialFailImmediately(boolean b) { simulatedCallState.setNextDialFailImmediately(b); } @Override public void setNextCallFailCause(int gsmCause) { mNextCallFailCause = gsmCause; } @Override public void triggerHangupForeground() { simulatedCallState.triggerHangupForeground(); mCallStateRegistrants.notifyRegistrants(); } /** hangup holding calls */ @Override public void triggerHangupBackground() { simulatedCallState.triggerHangupBackground(); mCallStateRegistrants.notifyRegistrants(); } @Override public void triggerSsn(int type, int code) { SuppServiceNotification not = new SuppServiceNotification(); not.notificationType = type; not.code = code; mSsnRegistrant.notifyRegistrant(new AsyncResult(null, not, null)); } @Override public void shutdown() { setRadioState(RadioState.RADIO_UNAVAILABLE); Looper looper = mHandlerThread.getLooper(); if (looper != null) { looper.quit(); } } /** hangup all */ @Override public void triggerHangupAll() { simulatedCallState.triggerHangupAll(); mCallStateRegistrants.notifyRegistrants(); } @Override public void triggerIncomingSMS(String message) { //TODO } @Override public void pauseResponses() { mPausedResponseCount++; } @Override public void resumeResponses() { mPausedResponseCount--; if (mPausedResponseCount == 0) { for (int i = 0, s = mPausedResponses.size(); i < s ; i++) { mPausedResponses.get(i).sendToTarget(); } mPausedResponses.clear(); } else { Rlog.e("GSM", "SimulatedCommands.resumeResponses < 0"); } } //***** Private Methods private void unimplemented(Message result) { if (result != null) { AsyncResult.forMessage(result).exception = new RuntimeException("Unimplemented"); if (mPausedResponseCount > 0) { mPausedResponses.add(result); } else { result.sendToTarget(); } } } private void resultSuccess(Message result, Object ret) { if (result != null) { AsyncResult.forMessage(result).result = ret; if (mPausedResponseCount > 0) { mPausedResponses.add(result); } else { result.sendToTarget(); } } } private void resultFail(Message result, Object ret, Throwable tr) { if (result != null) { AsyncResult.forMessage(result, ret, tr); if (mPausedResponseCount > 0) { mPausedResponses.add(result); } else { result.sendToTarget(); } } } // ***** Methods for CDMA support @Override public void getDeviceIdentity(Message response) { SimulatedCommandsVerifier.getInstance().getDeviceIdentity(response); resultSuccess(response, new String[] {FAKE_IMEI, FAKE_IMEISV, FAKE_ESN, FAKE_MEID}); } @Override public void getCDMASubscription(Message result) { String ret[] = new String[5]; ret[0] = "123"; ret[1] = "456"; ret[2] = "789"; ret[3] = "234"; ret[4] = "345"; resultSuccess(result, ret); } @Override public void setCdmaSubscriptionSource(int cdmaSubscriptionType, Message response) { unimplemented(response); } @Override public void queryCdmaRoamingPreference(Message response) { unimplemented(response); } @Override public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) { unimplemented(response); } @Override public void setPhoneType(int phoneType) { } @Override public void getPreferredVoicePrivacy(Message result) { unimplemented(result); } @Override public void setPreferredVoicePrivacy(boolean enable, Message result) { unimplemented(result); } /** * Set the TTY mode * * @param ttyMode is one of the following: * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} * @param response is callback message */ @Override public void setTTYMode(int ttyMode, Message response) { Rlog.w(LOG_TAG, "Not implemented in SimulatedCommands"); unimplemented(response); } /** * Query the TTY mode * (AsyncResult)response.obj).result is an int[] with element [0] set to * tty mode: * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} * @param response is callback message */ @Override public void queryTTYMode(Message response) { unimplemented(response); } /** * {@inheritDoc} */ @Override public void sendCDMAFeatureCode(String FeatureCode, Message response) { unimplemented(response); } /** * {@inheritDoc} */ @Override public void sendCdmaSms(byte[] pdu, Message response){ SimulatedCommandsVerifier.getInstance().sendCdmaSms(pdu, response); resultSuccess(response, null); } @Override public void setCdmaBroadcastActivation(boolean activate, Message response) { unimplemented(response); } @Override public void getCdmaBroadcastConfig(Message response) { unimplemented(response); } @Override public void setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs, Message response) { unimplemented(response); } public void forceDataDormancy(Message response) { unimplemented(response); } @Override public void setGsmBroadcastActivation(boolean activate, Message response) { unimplemented(response); } @Override public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message response) { unimplemented(response); } @Override public void getGsmBroadcastConfig(Message response) { unimplemented(response); } @Override public void supplyIccPinForApp(String pin, String aid, Message response) { SimulatedCommandsVerifier.getInstance().supplyIccPinForApp(pin, aid, response); if (mPinCode != null && mPinCode.equals(pin)) { resultSuccess(response, null); return; } Rlog.i(LOG_TAG, "[SimCmd] supplyIccPinForApp: pin failed!"); CommandException ex = new CommandException( CommandException.Error.PASSWORD_INCORRECT); resultFail(response, new int[]{ (--mPin1attemptsRemaining < 0) ? 0 : mPin1attemptsRemaining}, ex); } @Override public void supplyIccPukForApp(String puk, String newPin, String aid, Message response) { unimplemented(response); } @Override public void supplyIccPin2ForApp(String pin2, String aid, Message response) { unimplemented(response); } @Override public void supplyIccPuk2ForApp(String puk2, String newPin2, String aid, Message response) { unimplemented(response); } @Override public void changeIccPinForApp(String oldPin, String newPin, String aidPtr, Message response) { SimulatedCommandsVerifier.getInstance().changeIccPinForApp(oldPin, newPin, aidPtr, response); changeIccPin(oldPin, newPin, response); } @Override public void changeIccPin2ForApp(String oldPin2, String newPin2, String aidPtr, Message response) { unimplemented(response); } @Override public void requestIsimAuthentication(String nonce, Message response) { unimplemented(response); } @Override public void requestIccSimAuthentication(int authContext, String data, String aid, Message response) { unimplemented(response); } @Override public void getVoiceRadioTechnology(Message response) { SimulatedCommandsVerifier.getInstance().getVoiceRadioTechnology(response); int ret[] = new int[1]; ret[0] = mVoiceRadioTech; resultSuccess(response, ret); } public void setCellInfoList(List list) { mCellInfoList = list; } @Override public void getCellInfoList(Message response, WorkSource WorkSource) { if (mCellInfoList == null) { Parcel p = Parcel.obtain(); p.writeInt(1); p.writeInt(1); p.writeInt(2); p.writeLong(1453510289108L); p.writeInt(310); p.writeInt(260); p.writeInt(123); p.writeInt(456); p.writeInt(99); p.writeInt(3); p.setDataPosition(0); CellInfoGsm cellInfo = CellInfoGsm.CREATOR.createFromParcel(p); ArrayList mCellInfoList = new ArrayList(); mCellInfoList.add(cellInfo); } resultSuccess(response, mCellInfoList); } @Override public int getRilVersion() { return 11; } @Override public void setCellInfoListRate(int rateInMillis, Message response, WorkSource workSource) { unimplemented(response); } @Override public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, Message result) { } @Override public void setDataProfile(DataProfile[] dps, boolean isRoaming, Message result) { } public void setImsRegistrationState(int[] regState) { mImsRegState = regState; } @Override public void getImsRegistrationState(Message response) { if (mImsRegState == null) { mImsRegState = new int[]{1, PhoneConstants.PHONE_TYPE_NONE}; } resultSuccess(response, mImsRegState); } @Override public void sendImsCdmaSms(byte[] pdu, int retry, int messageRef, Message response){ SimulatedCommandsVerifier.getInstance().sendImsCdmaSms(pdu, retry, messageRef, response); resultSuccess(response, new SmsResponse(0 /*messageRef*/, null, 0)); } @Override public void sendImsGsmSms(String smscPDU, String pdu, int retry, int messageRef, Message response){ SimulatedCommandsVerifier.getInstance().sendImsGsmSms(smscPDU, pdu, retry, messageRef, response); resultSuccess(response, new SmsResponse(0 /*messageRef*/, null, 0)); } @Override public void iccOpenLogicalChannel(String AID, int p2, Message response) { SimulatedCommandsVerifier.getInstance().iccOpenLogicalChannel(AID, p2, response); Object result = new int[]{mChannelId}; resultSuccess(response, result); } @Override public void iccCloseLogicalChannel(int channel, Message response) { unimplemented(response); } @Override public void iccTransmitApduLogicalChannel(int channel, int cla, int instruction, int p1, int p2, int p3, String data, Message response) { SimulatedCommandsVerifier.getInstance().iccTransmitApduLogicalChannel(channel, cla, instruction, p1, p2, p3, data, response); if(mIccIoResultForApduLogicalChannel!=null) { resultSuccess(response, mIccIoResultForApduLogicalChannel); }else { resultFail(response, null, new RuntimeException("IccIoResult not set")); } } @Override public void iccTransmitApduBasicChannel(int cla, int instruction, int p1, int p2, int p3, String data, Message response) { unimplemented(response); } @Override public void nvReadItem(int itemID, Message response) { unimplemented(response); } @Override public void nvWriteItem(int itemID, String itemValue, Message response) { unimplemented(response); } @Override public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message response) { unimplemented(response); } @Override public void nvResetConfig(int resetType, Message response) { unimplemented(response); } @Override public void getHardwareConfig(Message result) { unimplemented(result); } @Override public void requestShutdown(Message result) { setRadioState(RadioState.RADIO_UNAVAILABLE); } @Override public void startLceService(int report_interval_ms, boolean pullMode, Message result) { SimulatedCommandsVerifier.getInstance().startLceService(report_interval_ms, pullMode, result); unimplemented(result); } @Override public void stopLceService(Message result) { unimplemented(result); } @Override public void pullLceData(Message result) { unimplemented(result); } @Override public void getModemActivityInfo(Message result) { unimplemented(result); } @Override public void setAllowedCarriers(List carriers, Message result) { unimplemented(result); } @Override public void getAllowedCarriers(Message result) { unimplemented(result); } @Override public void getRadioCapability(Message result) { SimulatedCommandsVerifier.getInstance().getRadioCapability(result); resultSuccess(result, new RadioCapability(0, 0, 0, 0xFFFF, null, 0)); } public void notifySmsStatus(Object result) { if (mSmsStatusRegistrant != null) { mSmsStatusRegistrant.notifyRegistrant(new AsyncResult(null, result, null)); } } public void notifyGsmBroadcastSms(Object result) { if (mGsmBroadcastSmsRegistrant != null) { mGsmBroadcastSmsRegistrant.notifyRegistrant(new AsyncResult(null, result, null)); } } public void notifyIccSmsFull() { if (mIccSmsFullRegistrant != null) { mIccSmsFullRegistrant.notifyRegistrant(); } } public void notifyEmergencyCallbackMode() { if (mEmergencyCallbackModeRegistrant != null) { mEmergencyCallbackModeRegistrant.notifyRegistrant(); } } @Override public void setEmergencyCallbackMode(Handler h, int what, Object obj) { SimulatedCommandsVerifier.getInstance().setEmergencyCallbackMode(h, what, obj); super.setEmergencyCallbackMode(h, what, obj); } public void notifyExitEmergencyCallbackMode() { if (mExitEmergencyCallbackModeRegistrants != null) { mExitEmergencyCallbackModeRegistrants.notifyRegistrants( new AsyncResult (null, null, null)); } } public void notifyImsNetworkStateChanged() { if(mImsNetworkStateChangedRegistrants != null) { mImsNetworkStateChangedRegistrants.notifyRegistrants(); } } public void notifyModemReset() { if (mModemResetRegistrants != null) { mModemResetRegistrants.notifyRegistrants(new AsyncResult(null, "Test", null)); } } @Override public void registerForExitEmergencyCallbackMode(Handler h, int what, Object obj) { SimulatedCommandsVerifier.getInstance().registerForExitEmergencyCallbackMode(h, what, obj); super.registerForExitEmergencyCallbackMode(h, what, obj); } public void notifyRadioOn() { mOnRegistrants.notifyRegistrants(); } @VisibleForTesting public void notifyNetworkStateChanged() { mNetworkStateRegistrants.notifyRegistrants(); } @VisibleForTesting public void notifyOtaProvisionStatusChanged() { if (mOtaProvisionRegistrants != null) { int ret[] = new int[1]; ret[0] = Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED; mOtaProvisionRegistrants.notifyRegistrants(new AsyncResult(null, ret, null)); } } public void notifySignalStrength() { if (mSignalStrength == null) { mSignalStrength = new SignalStrength( 20, // gsmSignalStrength 0, // gsmBitErrorRate -1, // cdmaDbm -1, // cdmaEcio -1, // evdoDbm -1, // evdoEcio -1, // evdoSnr 99, // lteSignalStrength SignalStrength.INVALID, // lteRsrp SignalStrength.INVALID, // lteRsrq SignalStrength.INVALID, // lteRssnr SignalStrength.INVALID, // lteCqi SignalStrength.INVALID, // tdScdmaRscp true // gsmFlag ); } if (mSignalStrengthRegistrant != null) { mSignalStrengthRegistrant.notifyRegistrant( new AsyncResult (null, mSignalStrength, null)); } } public void setIccCardStatus(IccCardStatus iccCardStatus){ mIccCardStatus = iccCardStatus; } public void setIccIoResultForApduLogicalChannel(IccIoResult iccIoResult) { mIccIoResultForApduLogicalChannel = iccIoResult; } public void setOpenChannelId(int channelId) { mChannelId = channelId; } public void setPin1RemainingAttempt(int pin1attemptsRemaining) { mPin1attemptsRemaining = pin1attemptsRemaining; } private AtomicBoolean mAllowed = new AtomicBoolean(false); @Override public void setDataAllowed(boolean allowed, Message result) { log("setDataAllowed = " + allowed); mAllowed.set(allowed); resultSuccess(result, null); } @VisibleForTesting public boolean isDataAllowed() { return mAllowed.get(); } @Override public void registerForPcoData(Handler h, int what, Object obj) { } @Override public void unregisterForPcoData(Handler h) { } @Override public void registerForModemReset(Handler h, int what, Object obj) { SimulatedCommandsVerifier.getInstance().registerForModemReset(h, what, obj); super.registerForModemReset(h, what, obj); } @Override public void sendDeviceState(int stateType, boolean state, Message result) { SimulatedCommandsVerifier.getInstance().sendDeviceState(stateType, state, result); resultSuccess(result, null); } @Override public void setUnsolResponseFilter(int filter, Message result) { SimulatedCommandsVerifier.getInstance().setUnsolResponseFilter(filter, result); resultSuccess(result, null); } @Override public void setSimCardPower(int state, Message result) { } @VisibleForTesting public void triggerRestrictedStateChanged(int restrictedState) { if (mRestrictedStateRegistrant != null) { mRestrictedStateRegistrant.notifyRegistrant( new AsyncResult(null, restrictedState, null)); } } @Override public void setOnRestrictedStateChanged(Handler h, int what, Object obj) { super.setOnRestrictedStateChanged(h, what, obj); SimulatedCommandsVerifier.getInstance().setOnRestrictedStateChanged(h, what, obj); } }