[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: a37ba2ca9e -s ours am: 773e9741b1 -s ours am: bd117217f1 -s ours

am skip reason: subject contains skip directive

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telephony/+/23982845

Change-Id: I4ece9b731b905ba96c9e13f1f4b3c79e4fb97e6e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index 124badf..59ff11d 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -207,6 +207,7 @@
     private static final int EVENT_QUERY_SMSC_DONE = 1005;
     private static final int EVENT_UPDATE_SMSC_DONE = 1006;
     private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 1007;
+    private static final int EVENT_UPDATE_NR_STATS = 1008;
 
     private static final int MENU_ITEM_VIEW_ADN            = 1;
     private static final int MENU_ITEM_VIEW_FDN            = 2;
@@ -379,7 +380,14 @@
             updateNetworkType();
             updateRawRegistrationState(serviceState);
             updateImsProvisionedState();
-            updateNrStats(serviceState);
+
+            // Since update NR stats includes a ril message to get slicing information, it runs
+            // as blocking during the timeout period of 1 second. if ServiceStateChanged event
+            // fires consecutively, RadioInfo can run for more than 10 seconds. This can cause ANR.
+            // Therefore, send event only when there is no same event being processed.
+            if (!mHandler.hasMessages(EVENT_UPDATE_NR_STATS)) {
+                mHandler.obtainMessage(EVENT_UPDATE_NR_STATS).sendToTarget();
+            }
         }
 
         @Override
@@ -465,6 +473,10 @@
                     }
                     updatePhysicalChannelConfiguration((List<PhysicalChannelConfig>) ar.result);
                     break;
+                case EVENT_UPDATE_NR_STATS:
+                    log("got EVENT_UPDATE_NR_STATS");
+                    updateNrStats();
+                    break;
                 default:
                     super.handleMessage(msg);
                     break;
@@ -690,7 +702,7 @@
         updateProperties();
         updateDnsCheckState();
         updateNetworkType();
-        updateNrStats(null);
+        updateNrStats();
 
         updateCellInfo(mCellInfoResult);
         updateSubscriptionIds();
@@ -1235,15 +1247,12 @@
                     AccessNetworkConstants.TRANSPORT_TYPE_WLAN));
     }
 
-    private void updateNrStats(ServiceState serviceState) {
+    private void updateNrStats() {
         if ((mTelephonyManager.getSupportedRadioAccessFamily()
                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
             return;
         }
-        ServiceState ss = serviceState;
-        if (ss == null && mPhone != null) {
-            ss = mPhone.getServiceState();
-        }
+        ServiceState ss = (mPhone == null) ? null : mPhone.getServiceState();
         if (ss != null) {
             NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
                     NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
@@ -1257,6 +1266,13 @@
             }
             mNrState.setText(NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
             mNrFrequency.setText(ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
+        } else {
+            Log.e(TAG, "Clear Nr stats by null service state");
+            mEndcAvailable.setText("");
+            mDcnrRestricted.setText("");
+            mNrAvailable.setText("");
+            mNrState.setText("");
+            mNrFrequency.setText("");
         }
 
         CompletableFuture<NetworkSlicingConfig> resultFuture = new CompletableFuture<>();
diff --git a/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java b/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java
index d5ef816..3bfe1a4 100644
--- a/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java
+++ b/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java
@@ -46,6 +46,7 @@
     private static final String PROVISION_STATUS_KEY = "ProvStatus";
     private static final String SERVICE_FLOW_URL_KEY = "ServiceFlow_URL";
     private static final String SERVICE_FLOW_USERDATA_KEY = "ServiceFlow_UserData";
+    private static final String SERVICE_FLOW_CONTENTS_TYPE_KEY = "ServiceFlow_ContentsType";
     private static final String DEFAULT_EAP_AKA_RESPONSE = "Default EAP AKA response";
     /**
      * UUID to report an anomaly if an unexpected error is received during entitlement check.
@@ -120,13 +121,11 @@
         }
         try {
             JSONObject jsonAuthResponse = new JSONObject(response);
-            String entitlementStatus = null;
-            String provisionStatus = null;
             if (jsonAuthResponse.has(ServiceEntitlement.APP_DATA_PLAN_BOOST)) {
                 JSONObject jsonToken = jsonAuthResponse.getJSONObject(
                         ServiceEntitlement.APP_DATA_PLAN_BOOST);
                 if (jsonToken.has(ENTITLEMENT_STATUS_KEY)) {
-                    entitlementStatus = jsonToken.getString(ENTITLEMENT_STATUS_KEY);
+                    String entitlementStatus = jsonToken.getString(ENTITLEMENT_STATUS_KEY);
                     if (entitlementStatus == null) {
                         return null;
                     }
@@ -134,7 +133,7 @@
                             Integer.parseInt(entitlementStatus);
                 }
                 if (jsonToken.has(PROVISION_STATUS_KEY)) {
-                    provisionStatus = jsonToken.getString(PROVISION_STATUS_KEY);
+                    String provisionStatus = jsonToken.getString(PROVISION_STATUS_KEY);
                     if (provisionStatus != null) {
                         premiumNetworkEntitlementResponse.mProvisionStatus =
                                 Integer.parseInt(provisionStatus);
@@ -148,6 +147,10 @@
                     premiumNetworkEntitlementResponse.mServiceFlowUserData =
                             jsonToken.getString(SERVICE_FLOW_USERDATA_KEY);
                 }
+                if (jsonToken.has(SERVICE_FLOW_CONTENTS_TYPE_KEY)) {
+                    premiumNetworkEntitlementResponse.mServiceFlowContentsType =
+                            jsonToken.getString(SERVICE_FLOW_CONTENTS_TYPE_KEY);
+                }
             } else {
                 Log.e(TAG, "queryEntitlementStatus failed with no app");
             }
diff --git a/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java b/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java
index ba44581..9126244 100644
--- a/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java
+++ b/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java
@@ -25,19 +25,19 @@
  *
  * The relationship between entitlement status (left column) and provision status (top row)
  * is defined in the table below:
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * |              | Not Provisioned |    Provisioned    |   Not Available   |  In Progress  |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * |   Disabled   |   Check failed  |    Check failed   |    Check failed   |  Check failed |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * |    Enabled   |  Carrier error  |  Display webview  |  Display webview  | Carrier error |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * | Incompatible |   Check failed  |    Check failed   |    Check failed   |  Check failed |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * | Provisioning |  Carrier error  |   Carrier error   |    In Progress    |  In Progress  |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * |   Included   |  Carrier error  | Already purchased | Already purchased | Carrier error |
- * +--------------+-----------------+-------------------+-------------------+---------------+
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * |              | Not Provisioned |    Provisioned    |   Not Available   |   In Progress   |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * |   Disabled   |   Check failed  |    Check failed   |    Check failed   |   Check failed  |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * |    Enabled   | Display webview | Already purchased | Already purchased |   In progress   |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * | Incompatible |   Check failed  |    Check failed   |    Check failed   |   Check failed  |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * | Provisioning |  Carrier error  |   Carrier error   |    In progress    |   In progress   |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * |   Included   |  Carrier error  | Already purchased | Already purchased |  Carrier error  |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
  */
 public class PremiumNetworkEntitlementResponse {
     public static final int PREMIUM_NETWORK_ENTITLEMENT_STATUS_DISABLED = 0;
@@ -72,13 +72,19 @@
     @PremiumNetworkProvisionStatus public int mProvisionStatus;
     @NonNull public String mServiceFlowURL;
     @NonNull public String mServiceFlowUserData;
+    @NonNull public String mServiceFlowContentsType;
 
     /**
-     * @return {@code true} if the premium network is provisioned and {@code false} otherwise.
+     * @return {@code true} if the premium network is already purchased and {@code false} otherwise.
      */
-    public boolean isProvisioned() {
-        return !isInvalidResponse()
-                && mEntitlementStatus == PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCLUDED;
+    public boolean isAlreadyPurchased() {
+        switch (mEntitlementStatus) {
+            case PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED:
+            case PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCLUDED:
+                return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_PROVISIONED
+                        || mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_NOT_AVAILABLE;
+        }
+        return false;
     }
 
     /**
@@ -86,8 +92,14 @@
      *         {@code false} otherwise.
      */
     public boolean isProvisioningInProgress() {
-        return !isInvalidResponse()
-                && mEntitlementStatus == PREMIUM_NETWORK_ENTITLEMENT_STATUS_PROVISIONING;
+        switch (mEntitlementStatus) {
+            case PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED:
+                return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS;
+            case PREMIUM_NETWORK_ENTITLEMENT_STATUS_PROVISIONING:
+                return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS
+                        || mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_NOT_AVAILABLE;
+        }
+        return false;
     }
 
     /**
@@ -108,7 +120,6 @@
      */
     public boolean isInvalidResponse() {
         switch (mEntitlementStatus) {
-            case PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED:
             case PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCLUDED:
                 return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_NOT_PROVISIONED
                         || mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS;
@@ -123,6 +134,7 @@
     @NonNull public String toString() {
         return "PremiumNetworkEntitlementResponse{mEntitlementStatus=" + mEntitlementStatus
                 + ", mProvisionStatus=" + mProvisionStatus + ", mServiceFlowURL=" + mServiceFlowURL
-                + ", mServiceFlowUserData" + mServiceFlowUserData + "}";
+                + ", mServiceFlowUserData=" + mServiceFlowUserData + ", mServiceFlowContentsType="
+                + mServiceFlowContentsType + "}";
     }
 }
diff --git a/src/com/android/phone/slice/SlicePurchaseController.java b/src/com/android/phone/slice/SlicePurchaseController.java
index b1abe56..888d169 100644
--- a/src/com/android/phone/slice/SlicePurchaseController.java
+++ b/src/com/android/phone/slice/SlicePurchaseController.java
@@ -92,12 +92,15 @@
     public static final int FAILURE_CODE_UNKNOWN = 0;
     /** Performance boost purchase failed because the carrier URL is unavailable. */
     public static final int FAILURE_CODE_CARRIER_URL_UNAVAILABLE = 1;
-    /** Performance boost purchase failed because the server is unreachable. */
-    public static final int FAILURE_CODE_SERVER_UNREACHABLE = 2;
     /** Performance boost purchase failed because user authentication failed. */
-    public static final int FAILURE_CODE_AUTHENTICATION_FAILED = 3;
+    public static final int FAILURE_CODE_AUTHENTICATION_FAILED = 2;
     /** Performance boost purchase failed because the payment failed. */
-    public static final int FAILURE_CODE_PAYMENT_FAILED = 4;
+    public static final int FAILURE_CODE_PAYMENT_FAILED = 3;
+    /**
+     * Performance boost purchase failed because the content type was specified but
+     * user data does not exist.
+     */
+    public static final int FAILURE_CODE_NO_USER_DATA = 4;
 
     /**
      * Failure codes that the carrier website can return when a premium capability purchase fails.
@@ -106,9 +109,9 @@
     @IntDef(prefix = { "FAILURE_CODE_" }, value = {
             FAILURE_CODE_UNKNOWN,
             FAILURE_CODE_CARRIER_URL_UNAVAILABLE,
-            FAILURE_CODE_SERVER_UNREACHABLE,
             FAILURE_CODE_AUTHENTICATION_FAILED,
-            FAILURE_CODE_PAYMENT_FAILED})
+            FAILURE_CODE_PAYMENT_FAILED,
+            FAILURE_CODE_NO_USER_DATA})
     public @interface FailureCode {}
 
     /** Value for an invalid premium capability. */
@@ -209,6 +212,8 @@
     public static final String EXTRA_CARRIER = "com.android.phone.slice.extra.CARRIER";
     /** Extra for the user data received from the entitlement service to send to the webapp. */
     public static final String EXTRA_USER_DATA = "com.android.phone.slice.extra.USER_DATA";
+    /** Extra for the contents type received from the entitlement service to send to the webapp. */
+    public static final String EXTRA_CONTENTS_TYPE = "com.android.phone.slice.extra.CONTENTS_TYPE";
     /**
      * Extra for the canceled PendingIntent that the slice purchase application can send as a
      * response if the performance boost notification or WebView was canceled by the user.
@@ -690,6 +695,17 @@
 
     private void onStartSlicePurchaseApplication(
             @TelephonyManager.PremiumCapability int capability) {
+        updateNotificationCounts();
+        if (mMonthlyCount >= getCarrierConfigs().getInt(
+                CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_MONTHLY_NOTIFICATION_COUNT_INT)
+                || mDailyCount >= getCarrierConfigs().getInt(
+                CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_DAILY_NOTIFICATION_COUNT_INT)) {
+            logd("Reached maximum number of performance boost notifications.");
+            handlePurchaseResult(capability,
+                    TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, false);
+            return;
+        }
+
         final PremiumNetworkEntitlementApi premiumNetworkEntitlementApi =
                 getPremiumNetworkEntitlementApi();
         PremiumNetworkEntitlementResponse premiumNetworkEntitlementResponse =
@@ -711,8 +727,8 @@
             return;
         }
 
-        if (premiumNetworkEntitlementResponse.isProvisioned()) {
-            logd("Entitlement Check: Already provisioned.");
+        if (premiumNetworkEntitlementResponse.isAlreadyPurchased()) {
+            logd("Entitlement Check: Already purchased/provisioned.");
             handlePurchaseResult(capability,
                     PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED, true);
             return;
@@ -725,7 +741,6 @@
             return;
         }
 
-        String userData = premiumNetworkEntitlementResponse.mServiceFlowUserData;
         String purchaseUrl = getPurchaseUrl(premiumNetworkEntitlementResponse);
         String carrier = getSimOperator();
         if (TextUtils.isEmpty(purchaseUrl) || TextUtils.isEmpty(carrier)) {
@@ -734,17 +749,6 @@
             return;
         }
 
-        updateNotificationCounts();
-        if (mMonthlyCount >= getCarrierConfigs().getInt(
-                CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_MONTHLY_NOTIFICATION_COUNT_INT)
-                || mDailyCount >= getCarrierConfigs().getInt(
-                CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_DAILY_NOTIFICATION_COUNT_INT)) {
-            logd("Reached maximum number of performance boost notifications.");
-            handlePurchaseResult(capability,
-                    TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, false);
-            return;
-        }
-
         // Start timeout for purchase completion.
         long timeout = getCarrierConfigs().getLong(CarrierConfigManager
                 .KEY_PREMIUM_CAPABILITY_NOTIFICATION_DISPLAY_TIMEOUT_MILLIS_LONG);
@@ -761,9 +765,9 @@
         intent.putExtra(EXTRA_PREMIUM_CAPABILITY, capability);
         intent.putExtra(EXTRA_PURCHASE_URL, purchaseUrl);
         intent.putExtra(EXTRA_CARRIER, carrier);
-        if (!TextUtils.isEmpty(userData)) {
-            intent.putExtra(EXTRA_USER_DATA, userData);
-        }
+        intent.putExtra(EXTRA_USER_DATA, premiumNetworkEntitlementResponse.mServiceFlowUserData);
+        intent.putExtra(EXTRA_CONTENTS_TYPE,
+                premiumNetworkEntitlementResponse.mServiceFlowContentsType);
         intent.putExtra(EXTRA_INTENT_CANCELED, createPendingIntent(
                 ACTION_SLICE_PURCHASE_APP_RESPONSE_CANCELED, capability, false));
         intent.putExtra(EXTRA_INTENT_CARRIER_ERROR, createPendingIntent(
@@ -1094,9 +1098,9 @@
         switch (failureCode) {
             case FAILURE_CODE_UNKNOWN: return "UNKNOWN";
             case FAILURE_CODE_CARRIER_URL_UNAVAILABLE: return "CARRIER_URL_UNAVAILABLE";
-            case FAILURE_CODE_SERVER_UNREACHABLE: return "SERVER_UNREACHABLE";
             case FAILURE_CODE_AUTHENTICATION_FAILED: return "AUTHENTICATION_FAILED";
             case FAILURE_CODE_PAYMENT_FAILED: return "PAYMENT_FAILED";
+            case FAILURE_CODE_NO_USER_DATA: return "NO_USER_DATA";
             default:
                 return "UNKNOWN(" + failureCode + ")";
         }
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 6d136b0..7aa0e7b 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -149,6 +149,8 @@
     private static final int MSG_DTMF_DONE = 22;
     private static final int MSG_MEDIA_ATTRIBUTES_CHANGED = 23;
     private static final int MSG_ON_RTT_INITIATED = 24;
+    private static final int MSG_HOLD = 25;
+    private static final int MSG_UNHOLD = 26;
 
     private static final String JAPAN_COUNTRY_CODE_WITH_PLUS_SIGN = "+81";
     private static final String JAPAN_ISO_COUNTRY_CODE = "JP";
@@ -344,6 +346,12 @@
                     }
                     sendRttInitiationSuccess();
                     break;
+                case MSG_HOLD:
+                    performHold();
+                    break;
+                case MSG_UNHOLD:
+                    performUnhold();
+                    break;
             }
         }
     };
@@ -1049,12 +1057,12 @@
 
     @Override
     public void onHold() {
-        performHold();
+        mHandler.obtainMessage(MSG_HOLD).sendToTarget();
     }
 
     @Override
     public void onUnhold() {
-        performUnhold();
+        mHandler.obtainMessage(MSG_UNHOLD).sendToTarget();
     }
 
     @Override
diff --git a/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java b/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java
index b2a4a9f..e9a2e90 100644
--- a/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java
+++ b/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java
@@ -578,7 +578,7 @@
         intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
                 TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
         intent.putExtra(SlicePurchaseController.EXTRA_FAILURE_CODE,
-                SlicePurchaseController.FAILURE_CODE_SERVER_UNREACHABLE);
+                SlicePurchaseController.FAILURE_CODE_CARRIER_URL_UNAVAILABLE);
         mContext.getBroadcastReceiver().onReceive(mContext, intent);
         mTestableLooper.processAllMessages();
         assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR, mResult);
@@ -726,7 +726,7 @@
         mEntitlementResponse.mEntitlementStatus =
                 PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED;
         mEntitlementResponse.mProvisionStatus =
-                PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_PROVISION_STATUS_PROVISIONED;
+                PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_PROVISION_STATUS_NOT_PROVISIONED;
 
         // send purchase request
         mSlicePurchaseController.purchasePremiumCapability(