Merge "Use System property to get the slot count"
diff --git a/src/java/com/android/internal/telephony/CellularNetworkService.java b/src/java/com/android/internal/telephony/CellularNetworkService.java
index 387904e..104b5c3 100644
--- a/src/java/com/android/internal/telephony/CellularNetworkService.java
+++ b/src/java/com/android/internal/telephony/CellularNetworkService.java
@@ -60,6 +60,9 @@
     private static final int GET_PS_REGISTRATION_STATE_DONE = 2;
     private static final int NETWORK_REGISTRATION_STATE_CHANGED = 3;
 
+    // From 24.008 6.1.3.0 and 10.5.6.2 the maximum number of PDP Contexts is 16.
+    private static final int MAX_DATA_CALLS = 16;
+
     private class CellularNetworkServiceProvider extends NetworkServiceProvider {
 
         private final Map<Message, NetworkServiceCallback> mCallbackMap = new HashMap<>();
@@ -216,7 +219,13 @@
             int transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
             int domain = NetworkRegistrationInfo.DOMAIN_CS;
 
-            if (result instanceof android.hardware.radio.V1_0.VoiceRegStateResult) {
+            // 1.5 at the top so that we can do an "early exit" from the method
+            if (result instanceof android.hardware.radio.V1_5.RegStateResult) {
+                return getNetworkRegistrationInfo(
+                        NetworkRegistrationInfo.DOMAIN_PS,
+                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+                        (android.hardware.radio.V1_5.RegStateResult) result);
+            } else if (result instanceof android.hardware.radio.V1_0.VoiceRegStateResult) {
                 android.hardware.radio.V1_0.VoiceRegStateResult voiceRegState =
                         (android.hardware.radio.V1_0.VoiceRegStateResult) result;
                 int regState = getRegStateFromHalRegState(voiceRegState.regState);
@@ -285,7 +294,13 @@
                     new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
                             LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);
 
-            if (result instanceof android.hardware.radio.V1_0.DataRegStateResult) {
+            // 1.5 at the top so that we can do an "early exit" from the method
+            if (result instanceof android.hardware.radio.V1_5.RegStateResult) {
+                return getNetworkRegistrationInfo(
+                        NetworkRegistrationInfo.DOMAIN_PS,
+                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+                        (android.hardware.radio.V1_5.RegStateResult) result);
+            } else if (result instanceof android.hardware.radio.V1_0.DataRegStateResult) {
                 android.hardware.radio.V1_0.DataRegStateResult dataRegState =
                         (android.hardware.radio.V1_0.DataRegStateResult) result;
                 regState = getRegStateFromHalRegState(dataRegState.regState);
@@ -341,8 +356,14 @@
             List<Integer> availableServices = getAvailableServices(
                     regState, domain, emergencyOnly);
 
+            // In earlier versions of the HAL, LTE_CA was allowed to indicate that the device
+            // is on CA; however, that has been superseded by the PHYSICAL_CHANNEL_CONFIG signal.
+            // Because some vendors provide both NETWORK_TYPE_LTE_CA *and* PHYSICAL_CHANNEL_CONFIG,
+            // this tweak is left for compatibility; however, the network type is no longer allowed
+            // to be used to declare that carrier aggregation is in effect, because the other
+            // signal provides a much richer information set, and we want to mitigate confusion in
+            // how CA information is being provided.
             if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
-                isUsingCarrierAggregation = true;
                 networkType = TelephonyManager.NETWORK_TYPE_LTE;
             }
 
@@ -352,6 +373,87 @@
                     lteVopsSupportInfo, isUsingCarrierAggregation);
         }
 
+        private @NonNull NetworkRegistrationInfo getNetworkRegistrationInfo(
+                int domain, int transportType,
+                android.hardware.radio.V1_5.RegStateResult regResult) {
+
+            // Perform common conversions that aren't domain specific
+            final int regState = getRegStateFromHalRegState(regResult.regState);
+            final boolean isEmergencyOnly = isEmergencyOnly(regResult.regState);
+            final List<Integer> availableServices = getAvailableServices(
+                    regState, domain, isEmergencyOnly);
+            final int rejectCause = regResult.reasonForDenial;
+            final CellIdentity cellIdentity = CellIdentity.create(regResult.cellIdentity);
+            final String rplmn = regResult.registeredPlmn;
+            final int reasonForDenial = regResult.reasonForDenial;
+
+            // Network Type fixup for carrier aggregation
+            int networkType = ServiceState.rilRadioTechnologyToNetworkType(regResult.rat);
+            boolean isUsingCarrierAggregation = false;
+            if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
+                isUsingCarrierAggregation = true;
+                networkType = TelephonyManager.NETWORK_TYPE_LTE;
+            }
+
+            // Conditional parameters for specific RANs
+            boolean cssSupported = false;
+            int roamingIndicator = 0;
+            int systemIsInPrl = 0;
+            int defaultRoamingIndicator = 0;
+            boolean isEndcAvailable = false;
+            boolean isNrAvailable = false;
+            boolean isDcNrRestricted = false;
+            LteVopsSupportInfo vopsInfo = new LteVopsSupportInfo(
+                    LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
+                    LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);
+
+            switch (regResult.accessTechnologySpecificInfo.getDiscriminator()) {
+                case android.hardware.radio.V1_5.RegStateResult
+                        .AccessTechnologySpecificInfo.hidl_discriminator.cdmaInfo:
+                    android.hardware.radio.V1_5.RegStateResult
+                            .AccessTechnologySpecificInfo.Cdma2000RegistrationInfo cdmaInfo =
+                                    regResult.accessTechnologySpecificInfo.cdmaInfo();
+                    cssSupported = cdmaInfo.cssSupported;
+                    roamingIndicator = cdmaInfo.roamingIndicator;
+                    systemIsInPrl = cdmaInfo.systemIsInPrl;
+                    defaultRoamingIndicator = cdmaInfo.defaultRoamingIndicator;
+                    break;
+                case android.hardware.radio.V1_5.RegStateResult
+                        .AccessTechnologySpecificInfo.hidl_discriminator.eutranInfo:
+                    android.hardware.radio.V1_5.RegStateResult
+                            .AccessTechnologySpecificInfo.EutranRegistrationInfo eutranInfo =
+                                    regResult.accessTechnologySpecificInfo.eutranInfo();
+
+                    isEndcAvailable = eutranInfo.nrIndicators.isDcNrRestricted;
+                    isNrAvailable = eutranInfo.nrIndicators.isNrAvailable;
+                    isDcNrRestricted = eutranInfo.nrIndicators.isEndcAvailable;
+                    vopsInfo = convertHalLteVopsSupportInfo(
+                            eutranInfo.lteVopsInfo.isVopsSupported,
+                            eutranInfo.lteVopsInfo.isEmcBearerSupported);
+                    break;
+                default:
+                    log("No access tech specific info passes for RegStateResult");
+                    break;
+            }
+
+            // build the result based on the domain for the request
+            switch(domain) {
+                case NetworkRegistrationInfo.DOMAIN_CS:
+                    return new NetworkRegistrationInfo(domain, transportType, regState,
+                            networkType, reasonForDenial, isEmergencyOnly, availableServices,
+                            cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl,
+                            defaultRoamingIndicator);
+                default:
+                    loge("Unknown domain passed to CellularNetworkService= " + domain);
+                    // fall through
+                case NetworkRegistrationInfo.DOMAIN_PS:
+                    return new NetworkRegistrationInfo(domain, transportType, regState, networkType,
+                            reasonForDenial, isEmergencyOnly, availableServices, cellIdentity,
+                            rplmn, MAX_DATA_CALLS, isDcNrRestricted, isNrAvailable, isEndcAvailable,
+                            vopsInfo, isUsingCarrierAggregation);
+            }
+        }
+
         private LteVopsSupportInfo convertHalLteVopsSupportInfo(
                 boolean vopsSupport, boolean emcBearerSupport) {
             int vops = LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED;
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index d937530..4e7899a 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -1347,10 +1347,20 @@
 
             if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
-            try {
-                radioProxy.getVoiceRegistrationState(rr.mSerial);
-            } catch (RemoteException | RuntimeException e) {
-                handleRadioProxyExceptionForRR(rr, "getVoiceRegistrationState", e);
+            if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+                final android.hardware.radio.V1_5.IRadio radioProxy15 =
+                        (android.hardware.radio.V1_5.IRadio) radioProxy;
+                try {
+                    radioProxy15.getVoiceRegistrationState_1_5(rr.mSerial);
+                } catch (RemoteException | RuntimeException e) {
+                    handleRadioProxyExceptionForRR(rr, "getVoiceRegistrationState_1_5", e);
+                }
+            } else {
+                try {
+                    radioProxy.getVoiceRegistrationState(rr.mSerial);
+                } catch (RemoteException | RuntimeException e) {
+                    handleRadioProxyExceptionForRR(rr, "getVoiceRegistrationState", e);
+                }
             }
         }
     }
@@ -1364,10 +1374,21 @@
 
             if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
-            try {
-                radioProxy.getDataRegistrationState(rr.mSerial);
-            } catch (RemoteException | RuntimeException e) {
-                handleRadioProxyExceptionForRR(rr, "getDataRegistrationState", e);
+
+            if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+                final android.hardware.radio.V1_5.IRadio radioProxy15 =
+                        (android.hardware.radio.V1_5.IRadio) radioProxy;
+                try {
+                    radioProxy15.getDataRegistrationState_1_5(rr.mSerial);
+                } catch (RemoteException | RuntimeException e) {
+                    handleRadioProxyExceptionForRR(rr, "getDataRegistrationState_1_5", e);
+                }
+            } else {
+                try {
+                    radioProxy.getDataRegistrationState(rr.mSerial);
+                } catch (RemoteException | RuntimeException e) {
+                    handleRadioProxyExceptionForRR(rr, "getDataRegistrationState", e);
+                }
             }
         }
     }
@@ -4957,9 +4978,9 @@
 
             req.cid = contextId;
 
-            if (packetData.dstAddress instanceof Inet4Address) {
+            if (packetData.getDstAddress() instanceof Inet4Address) {
                 req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV4;
-            } else if (packetData.dstAddress instanceof Inet6Address) {
+            } else if (packetData.getDstAddress() instanceof Inet6Address) {
                 req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV6;
             } else {
                 AsyncResult.forMessage(result, null,
@@ -4968,12 +4989,14 @@
                 return;
             }
 
+            final InetAddress srcAddress = packetData.getSrcAddress();
+            final InetAddress dstAddress = packetData.getDstAddress();
             appendPrimitiveArrayToArrayList(
-                    packetData.srcAddress.getAddress(), req.sourceAddress);
-            req.sourcePort = packetData.srcPort;
+                    srcAddress.getAddress(), req.sourceAddress);
+            req.sourcePort = packetData.getSrcPort();
             appendPrimitiveArrayToArrayList(
-                    packetData.dstAddress.getAddress(), req.destinationAddress);
-            req.destinationPort = packetData.dstPort;
+                    dstAddress.getAddress(), req.destinationAddress);
+            req.destinationPort = packetData.getDstPort();
             req.maxKeepaliveIntervalMillis = intervalMillis;
 
             radioProxy11.startKeepalive(rr.mSerial, req);
diff --git a/src/java/com/android/internal/telephony/RadioResponse.java b/src/java/com/android/internal/telephony/RadioResponse.java
index 7165a40..8e2033e 100644
--- a/src/java/com/android/internal/telephony/RadioResponse.java
+++ b/src/java/com/android/internal/telephony/RadioResponse.java
@@ -192,6 +192,18 @@
         responseInts(responseInfo, retriesRemaining);
     }
 
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param persoType SIM Personalisation type
+     * @param remainingRetries postiive values indicates number of retries remaining,
+     * must be equal to -1 if number of retries is infinite.
+     */
+    public void supplySimDepersonalizationResponse(RadioResponseInfo info,
+            int persoType, int remainingRetries) {
+        //short-term stub method
+    }
+
     /**
      * @param responseInfo Response info struct containing response type, serial no. and error
      * @param calls Current call list
@@ -339,6 +351,23 @@
 
     /**
      * @param responseInfo Response info struct containing response type, serial no. and error
+     * @param voiceRegResponse Current Voice registration response as defined by VoiceRegStateResult
+     *        in 1.5/types.hal
+     */
+    public void getVoiceRegistrationStateResponse_1_5(RadioResponseInfo responseInfo,
+            android.hardware.radio.V1_5.RegStateResult voiceRegResponse) {
+        RILRequest rr = mRil.processResponse(responseInfo);
+
+        if (rr != null) {
+            if (responseInfo.error == RadioError.NONE) {
+                sendMessageResponse(rr.mResult, voiceRegResponse);
+            }
+            mRil.processResponseDone(rr, responseInfo, voiceRegResponse);
+        }
+    }
+
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error
      * @param dataRegResponse Current Data registration response as defined by DataRegStateResult in
      *        types.hal
      */
@@ -388,6 +417,22 @@
         }
     }
 
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error
+     * @param dataRegResponse Current Data registration response as defined by DataRegStateResult in
+     *        1.5/types.hal
+     */
+    public void getDataRegistrationStateResponse_1_5(RadioResponseInfo responseInfo,
+            android.hardware.radio.V1_5.RegStateResult dataRegResponse) {
+        RILRequest rr = mRil.processResponse(responseInfo);
+
+        if (rr != null) {
+            if (responseInfo.error == RadioError.NONE) {
+                sendMessageResponse(rr.mResult, dataRegResponse);
+            }
+            mRil.processResponseDone(rr, responseInfo, dataRegResponse);
+        }
+    }
 
     /**
      * @param responseInfo Response info struct containing response type, serial no. and error
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 41fd67d..3eb22f7 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -1656,37 +1656,6 @@
                                 + " drs=" + mDataRegState
                                 + " mRilRat=" + mRilRat);
                     }
-                    updateNetworkInfoSuspendState();
-                    if (mNetworkAgent != null) {
-                        mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(),
-                                DataConnection.this);
-                        mNetworkAgent.sendNetworkInfo(mNetworkInfo, DataConnection.this);
-                        mNetworkAgent.sendLinkProperties(mLinkProperties, DataConnection.this);
-                    }
-                    break;
-                case EVENT_DATA_CONNECTION_METEREDNESS_CHANGED:
-                    boolean isUnmetered = (boolean) msg.obj;
-                    if (isUnmetered == mUnmeteredOverride) {
-                        break;
-                    }
-                    mUnmeteredOverride = isUnmetered;
-                    // fallthrough
-                case EVENT_NR_FREQUENCY_CHANGED:
-                case EVENT_DATA_CONNECTION_ROAM_ON:
-                case EVENT_DATA_CONNECTION_ROAM_OFF:
-                case EVENT_DATA_CONNECTION_OVERRIDE_CHANGED:
-                    if (mNetworkAgent != null) {
-                        mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(),
-                                DataConnection.this);
-                        mNetworkAgent.sendNetworkInfo(mNetworkInfo, DataConnection.this);
-                    }
-                    break;
-                case EVENT_KEEPALIVE_START_REQUEST:
-                case EVENT_KEEPALIVE_STOP_REQUEST:
-                    if (mNetworkAgent != null) {
-                        mNetworkAgent.sendSocketKeepaliveEvent(
-                                msg.arg1, SocketKeepalive.ERROR_INVALID_NETWORK);
-                    }
                     break;
                 default:
                     if (DBG) {
@@ -2261,9 +2230,38 @@
                     retVal = HANDLED;
                     break;
                 }
+                case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED: {
+                    AsyncResult ar = (AsyncResult) msg.obj;
+                    Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>) ar.result;
+                    mDataRegState = drsRatPair.first;
+                    updateTcpBufferSizes(drsRatPair.second);
+                    mRilRat = drsRatPair.second;
+                    if (DBG) {
+                        log("DcActiveState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
+                                + " drs=" + mDataRegState
+                                + " mRilRat=" + mRilRat);
+                    }
+                    updateNetworkInfoSuspendState();
+                    if (mNetworkAgent != null) {
+                        mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(),
+                                DataConnection.this);
+                        mNetworkAgent.sendNetworkInfo(mNetworkInfo, DataConnection.this);
+                        mNetworkAgent.sendLinkProperties(mLinkProperties, DataConnection.this);
+                    }
+                    retVal = HANDLED;
+                    break;
+                }
+                case EVENT_DATA_CONNECTION_METEREDNESS_CHANGED:
+                    boolean isUnmetered = (boolean) msg.obj;
+                    if (isUnmetered == mUnmeteredOverride) {
+                        retVal = HANDLED;
+                        break;
+                    }
+                    mUnmeteredOverride = isUnmetered;
+                    // fallthrough
+                case EVENT_NR_FREQUENCY_CHANGED:
                 case EVENT_DATA_CONNECTION_ROAM_ON:
                 case EVENT_DATA_CONNECTION_ROAM_OFF:
-                case EVENT_DATA_CONNECTION_METEREDNESS_CHANGED:
                 case EVENT_DATA_CONNECTION_OVERRIDE_CHANGED: {
                     if (mNetworkAgent != null) {
                         mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(),
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RadioAccessFamilyTest.java b/tests/telephonytests/src/com/android/internal/telephony/RadioAccessFamilyTest.java
new file mode 100644
index 0000000..83c362b
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/RadioAccessFamilyTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.telephony.RadioAccessFamily;
+import android.telephony.TelephonyManager;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+public class RadioAccessFamilyTest extends TelephonyTest {
+    @Test
+    @SmallTest
+    public void testCompareSameFamily() throws Exception {
+        // same family same number results in no clear winner
+        assertEquals(0, RadioAccessFamily.compare(
+                    TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA,
+                    TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA));
+
+        // same family, return the one with more total bits, in this case RHS,
+        // so compare should be negative.
+        assertTrue(0 > RadioAccessFamily.compare(
+                TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA,
+                TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA
+                        | TelephonyManager.NETWORK_TYPE_BITMASK_HSPA));
+    }
+
+    @Test
+    @SmallTest
+    public void testComparedGreatestUnique() throws Exception {
+        // Because LHS supports a unique higher-generation RAT, prefer that to a large list of
+        // older RATs. Since RHS is greater, compare should be positive.
+        assertTrue(0 < RadioAccessFamily.compare(
+                TelephonyManager.NETWORK_TYPE_BITMASK_LTE
+                        | TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA,
+                TelephonyManager.NETWORK_TYPE_BITMASK_LTE
+                        | TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA
+                        | TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA
+                        | TelephonyManager.NETWORK_TYPE_BITMASK_HSPA));
+    }
+}