Snap for 6664195 from 5e66fb77205bbf1d7426e94254577c307f334400 to rvc-d1-release
Change-Id: If0241e23a49228327bc52826816260169e07fa3c
diff --git a/src/com/android/cellbroadcastservice/GsmCellBroadcastHandler.java b/src/com/android/cellbroadcastservice/GsmCellBroadcastHandler.java
index 8449166..dec379d 100644
--- a/src/com/android/cellbroadcastservice/GsmCellBroadcastHandler.java
+++ b/src/com/android/cellbroadcastservice/GsmCellBroadcastHandler.java
@@ -20,6 +20,7 @@
import static com.android.cellbroadcastservice.CellBroadcastStatsLog.CELL_BROADCAST_MESSAGE_ERROR__TYPE__UNEXPECTED_GSM_MESSAGE_TYPE_FROM_FWK;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
@@ -32,11 +33,18 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Telephony.CellBroadcasts;
+import android.telephony.AccessNetworkConstants;
import android.telephony.CbGeoUtils.Geometry;
import android.telephony.CellBroadcastIntents;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityGsm;
+import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityNr;
+import android.telephony.CellIdentityTdscdma;
+import android.telephony.CellIdentityWcdma;
import android.telephony.CellInfo;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
import android.telephony.SubscriptionManager;
@@ -55,6 +63,8 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
@@ -328,23 +338,93 @@
}
}
- // return the GSM cell location from the first GSM cell info
- private Pair<Integer, Integer> getGsmLacAndCid() {
- TelephonyManager tm =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- List<CellInfo> infos = tm.getAllCellInfo();
- for (CellInfo info : infos) {
- CellIdentity ci = info.getCellIdentity();
- if (ci instanceof CellIdentityGsm) {
- CellIdentityGsm ciGsm = (CellIdentityGsm) ci;
- int lac = ciGsm.getLac() != CellInfo.UNAVAILABLE ? ciGsm.getLac() : -1;
- int cid = ciGsm.getCid() != CellInfo.UNAVAILABLE ? ciGsm.getCid() : -1;
- return Pair.create(lac, cid);
- }
+ /**
+ * Get LAC (location area code for GSM/UMTS) / TAC (tracking area code for LTE/NR) and CID
+ * (Cell id) from the cell identity
+ *
+ * @param ci Cell identity
+ * @return Pair of LAC and CID. {@code null} if not available.
+ */
+ private @Nullable Pair<Integer, Integer> getLacAndCid(CellIdentity ci) {
+ if (ci == null) return null;
+ int lac = CellInfo.UNAVAILABLE;
+ int cid = CellInfo.UNAVAILABLE;
+ if (ci instanceof CellIdentityGsm) {
+ lac = ((CellIdentityGsm) ci).getLac();
+ cid = ((CellIdentityGsm) ci).getCid();
+ } else if (ci instanceof CellIdentityWcdma) {
+ lac = ((CellIdentityWcdma) ci).getLac();
+ cid = ((CellIdentityWcdma) ci).getCid();
+ } else if ((ci instanceof CellIdentityTdscdma)) {
+ lac = ((CellIdentityTdscdma) ci).getLac();
+ cid = ((CellIdentityTdscdma) ci).getCid();
+ } else if (ci instanceof CellIdentityLte) {
+ lac = ((CellIdentityLte) ci).getTac();
+ cid = ((CellIdentityLte) ci).getCi();
+ } else if (ci instanceof CellIdentityNr) {
+ lac = ((CellIdentityNr) ci).getTac();
+ cid = ((CellIdentityNr) ci).getPci();
}
+
+ if (lac != CellInfo.UNAVAILABLE || cid != CellInfo.UNAVAILABLE) {
+ return Pair.create(lac, cid);
+ }
+
+ // When both LAC and CID are not available.
return null;
}
+ /**
+ * Get LAC (location area code for GSM/UMTS) / TAC (tracking area code for LTE/NR) and CID
+ * (Cell id) of the registered network.
+ *
+ * @param slotIndex SIM slot index
+ *
+ * @return lac and cid. {@code null} if cell identity is not available from the registered
+ * network.
+ */
+ private @Nullable Pair<Integer, Integer> getLacAndCid(int slotIndex) {
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ tm.createForSubscriptionId(getSubIdForPhone(mContext, slotIndex));
+
+ ServiceState serviceState = tm.getServiceState();
+
+ if (serviceState == null) return null;
+
+ // The list of cell identity to extract LAC and CID. The higher priority one will be added
+ // into the top of list.
+ List<CellIdentity> cellIdentityList = new ArrayList<>();
+
+ // CS network
+ NetworkRegistrationInfo nri = serviceState.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ if (nri != null) {
+ cellIdentityList.add(nri.getCellIdentity());
+ }
+
+ // PS network
+ nri = serviceState.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ if (nri != null) {
+ cellIdentityList.add(nri.getCellIdentity());
+ }
+
+ // When SIM is not inserted, we use the cell identity from the nearby cell. This is
+ // best effort.
+ List<CellInfo> infos = tm.getAllCellInfo();
+ if (infos != null) {
+ cellIdentityList.addAll(
+ infos.stream().map(CellInfo::getCellIdentity).collect(Collectors.toList()));
+ }
+
+ // Return the first valid LAC and CID from the list.
+ return cellIdentityList.stream()
+ .map(this::getLacAndCid)
+ .filter(Objects::nonNull)
+ .findFirst()
+ .orElse(null);
+ }
+
/**
* Handle 3GPP format SMS-CB message.
@@ -373,35 +453,17 @@
TelephonyManager tm =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
tm.createForSubscriptionId(getSubIdForPhone(mContext, slotIndex));
- // TODO make a systemAPI for getNetworkOperatorForSlotIndex
- String plmn = tm.getSimOperator();
+ String plmn = tm.getNetworkOperator();
int lac = -1;
int cid = -1;
- Pair<Integer, Integer> lacAndCid = getGsmLacAndCid();
- // Check if GSM lac and cid are available. This is required to support
- // dual-mode devices such as CDMA/LTE devices that require support for
- // both 3GPP and 3GPP2 format messages
+ // Get LAC and CID of the current camped cell.
+ Pair<Integer, Integer> lacAndCid = getLacAndCid(slotIndex);
if (lacAndCid != null) {
lac = lacAndCid.first;
cid = lacAndCid.second;
}
- SmsCbLocation location;
- switch (header.getGeographicalScope()) {
- case SmsCbMessage.GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE:
- location = new SmsCbLocation(plmn, lac, -1);
- break;
-
- case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE:
- case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE:
- location = new SmsCbLocation(plmn, lac, cid);
- break;
-
- case SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE:
- default:
- location = new SmsCbLocation(plmn, -1, -1);
- break;
- }
+ SmsCbLocation location = new SmsCbLocation(plmn, lac, cid);
byte[][] pdus;
int pageCount = header.getNumberOfPages();
@@ -456,7 +518,8 @@
return GsmSmsCbMessage.createSmsCbMessage(mContext, header, location, pdus, slotIndex);
} catch (RuntimeException e) {
- final String errorMessage = "Error in decoding SMS CB pdu" + e.toString();
+ final String errorMessage = "Error in decoding SMS CB pdu: " + e.toString();
+ e.printStackTrace();
loge(errorMessage);
CellBroadcastStatsLog.write(CellBroadcastStatsLog.CB_MESSAGE_ERROR,
CELL_BROADCAST_MESSAGE_ERROR__TYPE__GSM_INVALID_PDU, errorMessage);
diff --git a/tests/src/com/android/cellbroadcastservice/tests/CellBroadcastServiceTestBase.java b/tests/src/com/android/cellbroadcastservice/tests/CellBroadcastServiceTestBase.java
index f1c7430..dfdb2e2 100644
--- a/tests/src/com/android/cellbroadcastservice/tests/CellBroadcastServiceTestBase.java
+++ b/tests/src/com/android/cellbroadcastservice/tests/CellBroadcastServiceTestBase.java
@@ -126,6 +126,8 @@
doReturn(powerManager).when(mMockedContext).getSystemService(Context.POWER_SERVICE);
doReturn(mMockedTelephonyManager).when(mMockedContext)
.getSystemService(Context.TELEPHONY_SERVICE);
+ doReturn(Context.TELEPHONY_SERVICE).when(mMockedContext)
+ .getSystemServiceName(TelephonyManager.class);
doReturn(mMockedSubscriptionManager).when(mMockedContext)
.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
doReturn(mMockedLocationManager).when(mMockedContext)
diff --git a/tests/src/com/android/cellbroadcastservice/tests/GsmCellBroadcastHandlerTest.java b/tests/src/com/android/cellbroadcastservice/tests/GsmCellBroadcastHandlerTest.java
index a124faa..e94aabb 100644
--- a/tests/src/com/android/cellbroadcastservice/tests/GsmCellBroadcastHandlerTest.java
+++ b/tests/src/com/android/cellbroadcastservice/tests/GsmCellBroadcastHandlerTest.java
@@ -34,8 +34,14 @@
import android.os.Bundle;
import android.provider.Settings;
import android.provider.Telephony;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.CellIdentityLte;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
import android.telephony.SmsCbCmasInfo;
+import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
+import android.telephony.TelephonyManager;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;
@@ -244,4 +250,43 @@
verify(mMockedContext, never()).sendOrderedBroadcast(any(), anyString(), anyString(),
any(), any(), anyInt(), any(), any());
}
+
+ @Test
+ @SmallTest
+ public void testSmsCbLocation() {
+ final byte[] pdu = hexStringToBytes("01111B40110101C366701A09368545692408000000000000000"
+ + "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ + "000000000000000000000000000000000000000000000000B");
+
+ final String fakePlmn = "310999";
+ final int fakeTac = 1234;
+ final int fakeCid = 5678;
+
+ doReturn(fakePlmn).when(mMockedTelephonyManager).getNetworkOperator();
+ ServiceState ss = Mockito.mock(ServiceState.class);
+ doReturn(ss).when(mMockedTelephonyManager).getServiceState();
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .setCellIdentity(new CellIdentityLte(0, 0, fakeCid, 0, fakeTac))
+ .build();
+ doReturn(nri).when(ss).getNetworkRegistrationInfo(anyInt(), anyInt());
+
+ mGsmCellBroadcastHandler.onGsmCellBroadcastSms(0, pdu);
+ mTestableLooper.processAllMessages();
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockedContext).sendOrderedBroadcast(intentCaptor.capture(), any(),
+ (Bundle) any(), any(), any(), anyInt(), any(), any());
+ Intent intent = intentCaptor.getValue();
+ assertEquals(Telephony.Sms.Intents.ACTION_SMS_EMERGENCY_CB_RECEIVED, intent.getAction());
+ SmsCbMessage msg = intent.getParcelableExtra("message");
+
+ SmsCbLocation location = msg.getLocation();
+ assertEquals(fakePlmn, location.getPlmn());
+ assertEquals(fakeTac, location.getLac());
+ assertEquals(fakeCid, location.getCid());
+ }
}