Merge "Fixed a race when slot-to-sub mapping table is rebuilding"
diff --git a/Android.mk b/Android.mk
index 915ad01..6e4e43e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -29,6 +29,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android.hardware.radio-V1.0-java \
android.hardware.radio-V1.1-java \
+ android.hardware.radio-V1.2-java \
android.hardware.radio.deprecated-V1.0-java \
android.hidl.base-V1.0-java
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 59195f8..391de50 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -158,6 +158,17 @@
/** New SMS received as an AsyncResult. */
public static final int EVENT_INJECT_SMS = 8;
+ /** Update tracker object; used only in waiting state */
+ private static final int EVENT_UPDATE_TRACKER = 9;
+
+ /** Timeout in case state machine is stuck in a state for too long; used only in waiting
+ * state */
+ private static final int EVENT_STATE_TIMEOUT = 10;
+
+ /** Timeout duration for EVENT_STATE_TIMEOUT */
+ @VisibleForTesting
+ public static final int STATE_TIMEOUT = 30000;
+
/** Wakelock release delay when returning to idle state. */
private static final int WAKELOCK_TIMEOUT = 3000;
@@ -450,6 +461,7 @@
// if any broadcasts were sent, transition to waiting state
InboundSmsTracker inboundSmsTracker = (InboundSmsTracker) msg.obj;
if (processMessagePart(inboundSmsTracker)) {
+ sendMessage(EVENT_UPDATE_TRACKER, inboundSmsTracker);
transitionTo(mWaitingState);
} else {
// if event is sent from SmsBroadcastUndelivered.broadcastSms(), and
@@ -493,18 +505,41 @@
* {@link IdleState} after any deferred {@link #EVENT_BROADCAST_SMS} messages are handled.
*/
private class WaitingState extends State {
+ private InboundSmsTracker mTracker;
+
+ @Override
+ public void enter() {
+ if (DBG) log("entering Waiting state");
+ mTracker = null;
+ sendMessageDelayed(EVENT_STATE_TIMEOUT, STATE_TIMEOUT);
+ }
+
@Override
public void exit() {
if (DBG) log("exiting Waiting state");
// Before moving to idle state, set wakelock timeout to WAKE_LOCK_TIMEOUT milliseconds
// to give any receivers time to take their own wake locks
setWakeLockTimeout(WAKELOCK_TIMEOUT);
+ if (VDBG) {
+ if (hasMessages(EVENT_STATE_TIMEOUT)) {
+ log("exiting Waiting state: removing EVENT_STATE_TIMEOUT from message queue");
+ }
+ if (hasMessages(EVENT_UPDATE_TRACKER)) {
+ log("exiting Waiting state: removing EVENT_UPDATE_TRACKER from message queue");
+ }
+ }
+ removeMessages(EVENT_STATE_TIMEOUT);
+ removeMessages(EVENT_UPDATE_TRACKER);
}
@Override
public boolean processMessage(Message msg) {
log("WaitingState.processMessage:" + msg.what);
switch (msg.what) {
+ case EVENT_UPDATE_TRACKER:
+ mTracker = (InboundSmsTracker) msg.obj;
+ return HANDLED;
+
case EVENT_BROADCAST_SMS:
// defer until the current broadcast completes
deferMessage(msg);
@@ -520,6 +555,18 @@
// not ready to return to idle; ignore
return HANDLED;
+ case EVENT_STATE_TIMEOUT:
+ // stuck in WaitingState for too long; drop the message and exit this state
+ if (mTracker != null) {
+ log("WaitingState.processMessage: EVENT_STATE_TIMEOUT; dropping message");
+ dropSms(new SmsBroadcastReceiver(mTracker));
+ } else {
+ log("WaitingState.processMessage: EVENT_STATE_TIMEOUT; mTracker is null "
+ + "- sending EVENT_BROADCAST_COMPLETE");
+ sendMessage(EVENT_BROADCAST_COMPLETE);
+ }
+ return HANDLED;
+
default:
// parent state handles the other message types
return NOT_HANDLED;
diff --git a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
index 14c6810..46b1eef 100644
--- a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
+++ b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
@@ -125,6 +125,34 @@
return false;
}
}
+
+ if ((nsri.mRequest.searchPeriodicity < NetworkScanRequest.MIN_SEARCH_PERIODICITY_SEC)
+ || (nsri.mRequest.searchPeriodicity
+ > NetworkScanRequest.MAX_SEARCH_PERIODICITY_SEC)) {
+ return false;
+ }
+
+ if ((nsri.mRequest.maxSearchTime < NetworkScanRequest.MIN_SEARCH_MAX_SEC)
+ || (nsri.mRequest.maxSearchTime > NetworkScanRequest.MAX_SEARCH_MAX_SEC)) {
+ return false;
+ }
+
+ if ((nsri.mRequest.incrementalResultsPeriodicity
+ < NetworkScanRequest.MIN_INCREMENTAL_PERIODICITY_SEC)
+ || (nsri.mRequest.incrementalResultsPeriodicity
+ > NetworkScanRequest.MAX_INCREMENTAL_PERIODICITY_SEC)) {
+ return false;
+ }
+
+ if ((nsri.mRequest.searchPeriodicity > nsri.mRequest.maxSearchTime)
+ || (nsri.mRequest.incrementalResultsPeriodicity > nsri.mRequest.maxSearchTime)) {
+ return false;
+ }
+
+ if ((nsri.mRequest.mccMncs != null)
+ && (nsri.mRequest.mccMncs.size() > NetworkScanRequest.MAX_MCC_MNC_LIST_SIZE)) {
+ return false;
+ }
return true;
}
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 3ed591f..78fbd77 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -1809,56 +1809,69 @@
}
}
+ private android.hardware.radio.V1_1.RadioAccessSpecifier convertRadioAccessSpecifierToRadioHAL(
+ RadioAccessSpecifier ras) {
+ android.hardware.radio.V1_1.RadioAccessSpecifier rasInHalFormat =
+ new android.hardware.radio.V1_1.RadioAccessSpecifier();
+ rasInHalFormat.radioAccessNetwork = ras.radioAccessNetwork;
+ List<Integer> bands = null;
+ switch (ras.radioAccessNetwork) {
+ case RadioAccessNetworks.GERAN:
+ bands = rasInHalFormat.geranBands;
+ break;
+ case RadioAccessNetworks.UTRAN:
+ bands = rasInHalFormat.utranBands;
+ break;
+ case RadioAccessNetworks.EUTRAN:
+ bands = rasInHalFormat.eutranBands;
+ break;
+ default:
+ Log.wtf(RILJ_LOG_TAG, "radioAccessNetwork " + ras.radioAccessNetwork
+ + " not supported!");
+ return null;
+ }
+
+ if (ras.bands != null) {
+ for (int band : ras.bands) {
+ bands.add(band);
+ }
+ }
+ if (ras.channels != null) {
+ for (int channel : ras.channels) {
+ rasInHalFormat.channels.add(channel);
+ }
+ }
+
+ return rasInHalFormat;
+ }
+
@Override
public void startNetworkScan(NetworkScanRequest nsr, Message result) {
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
- android.hardware.radio.V1_1.IRadio radioProxy11 =
- android.hardware.radio.V1_1.IRadio.castFrom(radioProxy);
- if (radioProxy11 == null) {
- if (result != null) {
- AsyncResult.forMessage(result, null,
- CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
- result.sendToTarget();
- }
- } else {
- android.hardware.radio.V1_1.NetworkScanRequest request =
- new android.hardware.radio.V1_1.NetworkScanRequest();
+ android.hardware.radio.V1_2.IRadio radioProxy12 =
+ android.hardware.radio.V1_2.IRadio.castFrom(radioProxy);
+ if (radioProxy12 != null) {
+ android.hardware.radio.V1_2.NetworkScanRequest request =
+ new android.hardware.radio.V1_2.NetworkScanRequest();
request.type = nsr.scanType;
- request.interval = 60;
+ request.interval = nsr.searchPeriodicity;
+ request.maxSearchTime = nsr.maxSearchTime;
+ request.incrementalResultsPeriodicity = nsr.incrementalResultsPeriodicity;
+ request.incrementalResults = nsr.incrementalResults;
+
for (RadioAccessSpecifier ras : nsr.specifiers) {
- android.hardware.radio.V1_1.RadioAccessSpecifier s =
- new android.hardware.radio.V1_1.RadioAccessSpecifier();
- s.radioAccessNetwork = ras.radioAccessNetwork;
- List<Integer> bands = null;
- switch (ras.radioAccessNetwork) {
- case RadioAccessNetworks.GERAN:
- bands = s.geranBands;
- break;
- case RadioAccessNetworks.UTRAN:
- bands = s.utranBands;
- break;
- case RadioAccessNetworks.EUTRAN:
- bands = s.eutranBands;
- break;
- default:
- Log.wtf(RILJ_LOG_TAG, "radioAccessNetwork " + ras.radioAccessNetwork
- + " not supported!");
- return;
+
+ android.hardware.radio.V1_1.RadioAccessSpecifier rasInHalFormat =
+ convertRadioAccessSpecifierToRadioHAL(ras);
+ if (rasInHalFormat == null) {
+ return;
}
- if (ras.bands != null) {
- for (int band : ras.bands) {
- bands.add(band);
- }
- }
- if (ras.channels != null) {
- for (int channel : ras.channels) {
- s.channels.add(channel);
- }
- }
- request.specifiers.add(s);
+
+ request.specifiers.add(rasInHalFormat);
}
+ request.mccMncs.addAll(nsr.mccMncs);
RILRequest rr = obtainRequest(RIL_REQUEST_START_NETWORK_SCAN, result,
mRILDefaultWorkSource);
@@ -1867,10 +1880,47 @@
}
try {
- radioProxy11.startNetworkScan(rr.mSerial, request);
+ radioProxy12.startNetworkScan_1_2(rr.mSerial, request);
} catch (RemoteException | RuntimeException e) {
handleRadioProxyExceptionForRR(rr, "startNetworkScan", e);
}
+ } else {
+ android.hardware.radio.V1_1.IRadio radioProxy11 =
+ android.hardware.radio.V1_1.IRadio.castFrom(radioProxy);
+ if (radioProxy11 == null) {
+ if (result != null) {
+ AsyncResult.forMessage(result, null,
+ CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+ result.sendToTarget();
+ }
+ } else {
+ android.hardware.radio.V1_1.NetworkScanRequest request =
+ new android.hardware.radio.V1_1.NetworkScanRequest();
+ request.type = nsr.scanType;
+ request.interval = nsr.searchPeriodicity;
+ for (RadioAccessSpecifier ras : nsr.specifiers) {
+ android.hardware.radio.V1_1.RadioAccessSpecifier rasInHalFormat =
+ convertRadioAccessSpecifierToRadioHAL(ras);
+ if (rasInHalFormat == null) {
+ return;
+ }
+
+ request.specifiers.add(rasInHalFormat);
+ }
+
+ RILRequest rr = obtainRequest(RIL_REQUEST_START_NETWORK_SCAN, result,
+ mRILDefaultWorkSource);
+
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ }
+
+ try {
+ radioProxy11.startNetworkScan(rr.mSerial, request);
+ } catch (RemoteException | RuntimeException e) {
+ handleRadioProxyExceptionForRR(rr, "startNetworkScan", e);
+ }
+ }
}
}
}
diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java
index cd7a756..802944d 100755
--- a/src/java/com/android/internal/telephony/cat/CatService.java
+++ b/src/java/com/android/internal/telephony/cat/CatService.java
@@ -1071,6 +1071,13 @@
}
break;
case NO_RESPONSE_FROM_USER:
+ // No need to send terminal response for SET UP CALL on user timeout,
+ // instead use dedicated API
+ if (type == CommandType.SET_UP_CALL) {
+ mCmdIf.handleCallSetupRequestFromSim(false, null);
+ mCurrntCmd = null;
+ return;
+ }
case UICC_SESSION_TERM_BY_USER:
resp = null;
break;
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
index e2904df..fa6bc3a 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
@@ -382,11 +382,8 @@
case EVENT_CHANGE_PIN2_DONE:
// a PIN/PUK/PIN2/PUK2 complete
// request has completed. ar.userObj is the response Message
- int attemptsRemaining = -1;
ar = (AsyncResult)msg.obj;
- if ((ar.exception != null) && (ar.result != null)) {
- attemptsRemaining = parsePinPukErrorResult(ar);
- }
+ int attemptsRemaining = parsePinPukErrorResult(ar);
Message response = (Message)ar.userObj;
AsyncResult.forMessage(response).exception = ar.exception;
response.arg1 = attemptsRemaining;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkScanRequestTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkScanRequestTest.java
index fe75088..7284083 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkScanRequestTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkScanRequestTest.java
@@ -28,6 +28,8 @@
import org.junit.Test;
+import java.util.ArrayList;
+
/** Unit tests for {@link NetworkScanRequest}. */
public class NetworkScanRequestTest {
@@ -44,7 +46,16 @@
int[] lteChannels = {5, 6, 7, 8};
RadioAccessSpecifier lte = new RadioAccessSpecifier(ranLte, lteBands, lteChannels);
RadioAccessSpecifier[] ras = {gsm, lte};
- NetworkScanRequest nsq = new NetworkScanRequest(NetworkScanRequest.SCAN_TYPE_ONE_SHOT, ras);
+ int searchPeriodicity = 70;
+ int maxSearchTime = 200;
+ boolean incrementalResults = true;
+ int incrementalResultsPeriodicity = 7;
+ ArrayList<String> mccmncs = new ArrayList<String>();
+ mccmncs.add("310480");
+ mccmncs.add("21002");
+ NetworkScanRequest nsq = new NetworkScanRequest(NetworkScanRequest.SCAN_TYPE_ONE_SHOT, ras,
+ searchPeriodicity, maxSearchTime, incrementalResults,
+ incrementalResultsPeriodicity, mccmncs);
Parcel p = Parcel.obtain();
nsq.writeToParcel(p, 0);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
index e9a16bf..22070a2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
@@ -47,8 +47,8 @@
import android.os.UserManager;
import android.provider.Telephony;
import android.support.test.filters.FlakyTest;
+import android.support.test.filters.MediumTest;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.MediumTest;
import com.android.internal.telephony.FakeSmsContentProvider;
import com.android.internal.telephony.InboundSmsHandler;
@@ -777,4 +777,28 @@
verifySmsIntentBroadcasts(0);
}
+
+ @FlakyTest
+ @Ignore
+ @Test
+ @MediumTest
+ public void testWaitingStateTimeout() throws Exception {
+ transitionFromStartupToIdle();
+
+ // send new SMS to state machine and verify that triggers SMS_DELIVER_ACTION
+ mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS,
+ new AsyncResult(null, mSmsMessage, null));
+ waitForMs(100);
+
+ ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext, times(1)).sendBroadcast(
+ intentArgumentCaptor.capture());
+ assertEquals(Telephony.Sms.Intents.SMS_DELIVER_ACTION,
+ intentArgumentCaptor.getAllValues().get(0).getAction());
+ assertEquals("WaitingState", getCurrentState().getName());
+
+ waitForMs(InboundSmsHandler.STATE_TIMEOUT + 300);
+
+ assertEquals("IdleState", getCurrentState().getName());
+ }
}