Merge "Revert "Revert "Pass entitlement configuration to Settings for entitlement check""" into rvc-dev
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
index fd6f171..f14def6a 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
@@ -37,8 +37,8 @@
     private TetheringConstants() { }
 
     /**
-     * Extra used for communicating with the TetherService. Includes the type of tethering to
-     * enable if any.
+     * Extra used for communicating with the TetherService and TetherProvisioningActivity.
+     * Includes the type of tethering to enable if any.
      */
     public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
     /**
@@ -56,8 +56,38 @@
      */
     public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
     /**
-     * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
-     * which will receive provisioning results. Can be left empty.
+     * Extra used for communicating with the TetherService and TetherProvisioningActivity.
+     * Contains the {@link ResultReceiver} which will receive provisioning results.
+     * Can not be empty.
      */
     public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
+
+    /**
+     * Extra used for communicating with the TetherService and TetherProvisioningActivity.
+     * Contains the subId of current active cellular upstream.
+     * @hide
+     */
+    public static final String EXTRA_TETHER_SUBID = "android.net.extra.TETHER_SUBID";
+
+    /**
+     * Extra used for telling TetherProvisioningActivity the entitlement package name and class
+     * name to start UI entitlement check.
+     * @hide
+     */
+    public static final String EXTRA_TETHER_UI_PROVISIONING_APP_NAME =
+            "android.net.extra.TETHER_UI_PROVISIONING_APP_NAME";
+
+    /**
+     * Extra used for telling TetherService the intent action to start silent entitlement check.
+     * @hide
+     */
+    public static final String EXTRA_TETHER_SILENT_PROVISIONING_ACTION =
+            "android.net.extra.TETHER_SILENT_PROVISIONING_ACTION";
+
+    /**
+     * Extra used for TetherService to receive the response of provisioning check.
+     * @hide
+     */
+    public static final String EXTRA_TETHER_PROVISIONING_RESPONSE =
+            "android.net.extra.TETHER_PROVISIONING_RESPONSE";
 }
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
index 3c6e8d8..9dace70 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
@@ -19,6 +19,10 @@
 import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
 import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
 import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
+import static android.net.TetheringConstants.EXTRA_TETHER_PROVISIONING_RESPONSE;
+import static android.net.TetheringConstants.EXTRA_TETHER_SILENT_PROVISIONING_ACTION;
+import static android.net.TetheringConstants.EXTRA_TETHER_SUBID;
+import static android.net.TetheringConstants.EXTRA_TETHER_UI_PROVISIONING_APP_NAME;
 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
 import static android.net.TetheringManager.TETHERING_ETHERNET;
 import static android.net.TetheringManager.TETHERING_INVALID;
@@ -69,7 +73,6 @@
     protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning";
     private static final String ACTION_PROVISIONING_ALARM =
             "com.android.networkstack.tethering.PROVISIONING_RECHECK_ALARM";
-    private static final String EXTRA_SUBID = "subId";
 
     private final ComponentName mSilentProvisioningService;
     private static final int MS_PER_HOUR = 60 * 60 * 1000;
@@ -197,9 +200,9 @@
         // till upstream change to cellular.
         if (mUsingCellularAsUpstream) {
             if (showProvisioningUi) {
-                runUiTetherProvisioning(downstreamType, config.activeDataSubId);
+                runUiTetherProvisioning(downstreamType, config);
             } else {
-                runSilentTetherProvisioning(downstreamType, config.activeDataSubId);
+                runSilentTetherProvisioning(downstreamType, config);
             }
             mNeedReRunProvisioningUi = false;
         } else {
@@ -262,9 +265,9 @@
             if (mCurrentEntitlementResults.indexOfKey(downstream) < 0) {
                 if (mNeedReRunProvisioningUi) {
                     mNeedReRunProvisioningUi = false;
-                    runUiTetherProvisioning(downstream, config.activeDataSubId);
+                    runUiTetherProvisioning(downstream, config);
                 } else {
-                    runSilentTetherProvisioning(downstream, config.activeDataSubId);
+                    runSilentTetherProvisioning(downstream, config);
                 }
             }
         }
@@ -361,7 +364,7 @@
      * @param subId default data subscription ID.
      */
     @VisibleForTesting
-    protected void runSilentTetherProvisioning(int type, int subId) {
+    protected Intent runSilentTetherProvisioning(int type, final TetheringConfiguration config) {
         if (DBG) mLog.i("runSilentTetherProvisioning: " + type);
         // For silent provisioning, settings would stop tethering when entitlement fail.
         ResultReceiver receiver = buildProxyReceiver(type, false/* notifyFail */, null);
@@ -369,17 +372,20 @@
         Intent intent = new Intent();
         intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
         intent.putExtra(EXTRA_RUN_PROVISION, true);
+        intent.putExtra(EXTRA_TETHER_SILENT_PROVISIONING_ACTION, config.provisioningAppNoUi);
+        intent.putExtra(EXTRA_TETHER_PROVISIONING_RESPONSE, config.provisioningResponse);
         intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
-        intent.putExtra(EXTRA_SUBID, subId);
+        intent.putExtra(EXTRA_TETHER_SUBID, config.activeDataSubId);
         intent.setComponent(mSilentProvisioningService);
         // Only admin user can change tethering and SilentTetherProvisioning don't need to
         // show UI, it is fine to always start setting's background service as system user.
         mContext.startService(intent);
+        return intent;
     }
 
-    private void runUiTetherProvisioning(int type, int subId) {
+    private void runUiTetherProvisioning(int type, final TetheringConfiguration config) {
         ResultReceiver receiver = buildProxyReceiver(type, true/* notifyFail */, null);
-        runUiTetherProvisioning(type, subId, receiver);
+        runUiTetherProvisioning(type, config, receiver);
     }
 
     /**
@@ -389,17 +395,20 @@
      * @param receiver to receive entitlement check result.
      */
     @VisibleForTesting
-    protected void runUiTetherProvisioning(int type, int subId, ResultReceiver receiver) {
+    protected Intent runUiTetherProvisioning(int type, final TetheringConfiguration config,
+            ResultReceiver receiver) {
         if (DBG) mLog.i("runUiTetherProvisioning: " + type);
 
         Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING_UI);
         intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
+        intent.putExtra(EXTRA_TETHER_UI_PROVISIONING_APP_NAME, config.provisioningApp);
         intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
-        intent.putExtra(EXTRA_SUBID, subId);
+        intent.putExtra(EXTRA_TETHER_SUBID, config.activeDataSubId);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         // Only launch entitlement UI for system user. Entitlement UI should not appear for other
         // user because only admin user is allowed to change tethering.
         mContext.startActivity(intent);
+        return intent;
     }
 
     // Not needed to check if this don't run on the handler thread because it's private.
@@ -631,7 +640,7 @@
             receiver.send(cacheValue, null);
         } else {
             ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver);
-            runUiTetherProvisioning(downstream, config.activeDataSubId, proxy);
+            runUiTetherProvisioning(downstream, config, proxy);
         }
     }
 }
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 48a600d..1d45f12 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -107,6 +107,7 @@
     public final String[] provisioningApp;
     public final String provisioningAppNoUi;
     public final int provisioningCheckPeriod;
+    public final String provisioningResponse;
 
     public final int activeDataSubId;
 
@@ -141,10 +142,13 @@
         enableLegacyDhcpServer = getEnableLegacyDhcpServer(res);
 
         provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app);
-        provisioningAppNoUi = getProvisioningAppNoUi(res);
+        provisioningAppNoUi = getResourceString(res,
+                R.string.config_mobile_hotspot_provision_app_no_ui);
         provisioningCheckPeriod = getResourceInteger(res,
                 R.integer.config_mobile_hotspot_provision_check_period,
                 0 /* No periodic re-check */);
+        provisioningResponse = getResourceString(res,
+                R.string.config_mobile_hotspot_provision_response);
 
         mOffloadPollInterval = getResourceInteger(res,
                 R.integer.config_tether_offload_poll_interval,
@@ -337,9 +341,9 @@
         return copy(LEGACY_DHCP_DEFAULT_RANGE);
     }
 
-    private static String getProvisioningAppNoUi(Resources res) {
+    private static String getResourceString(Resources res, final int resId) {
         try {
-            return res.getString(R.string.config_mobile_hotspot_provision_app_no_ui);
+            return res.getString(resId);
         } catch (Resources.NotFoundException e) {
             return "";
         }
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
index 72fa916..354e753 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
@@ -16,8 +16,16 @@
 
 package com.android.networkstack.tethering;
 
+import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
+import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
+import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
+import static android.net.TetheringConstants.EXTRA_TETHER_PROVISIONING_RESPONSE;
+import static android.net.TetheringConstants.EXTRA_TETHER_SILENT_PROVISIONING_ACTION;
+import static android.net.TetheringConstants.EXTRA_TETHER_SUBID;
+import static android.net.TetheringConstants.EXTRA_TETHER_UI_PROVISIONING_APP_NAME;
 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
 import static android.net.TetheringManager.TETHERING_ETHERNET;
+import static android.net.TetheringManager.TETHERING_INVALID;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
 import static android.net.TetheringManager.TETHERING_WIFI_P2P;
@@ -44,6 +52,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.Resources;
 import android.net.util.SharedLog;
 import android.os.Bundle;
@@ -53,6 +62,7 @@
 import android.os.SystemProperties;
 import android.os.test.TestLooper;
 import android.provider.DeviceConfig;
+import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
 
 import androidx.test.filters.SmallTest;
@@ -76,6 +86,7 @@
 
     private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
     private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app";
+    private static final String PROVISIONING_APP_RESPONSE = "app_response";
 
     @Mock private CarrierConfigManager mCarrierConfigManager;
     @Mock private Context mContext;
@@ -122,15 +133,51 @@
         }
 
         @Override
-        protected void runUiTetherProvisioning(int type, int subId, ResultReceiver receiver) {
+        protected Intent runUiTetherProvisioning(int type,
+                final TetheringConfiguration config, final ResultReceiver receiver) {
+            Intent intent = super.runUiTetherProvisioning(type, config, receiver);
+            assertUiTetherProvisioningIntent(type, config, receiver, intent);
             uiProvisionCount++;
             receiver.send(fakeEntitlementResult, null);
+            return intent;
+        }
+
+        private void assertUiTetherProvisioningIntent(int type, final TetheringConfiguration config,
+                final ResultReceiver receiver, final Intent intent) {
+            assertEquals(Settings.ACTION_TETHER_PROVISIONING_UI, intent.getAction());
+            assertEquals(type, intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID));
+            final String[] appName = intent.getStringArrayExtra(
+                    EXTRA_TETHER_UI_PROVISIONING_APP_NAME);
+            assertEquals(PROVISIONING_APP_NAME.length, appName.length);
+            for (int i = 0; i < PROVISIONING_APP_NAME.length; i++) {
+                assertEquals(PROVISIONING_APP_NAME[i], appName[i]);
+            }
+            assertEquals(receiver, intent.getParcelableExtra(EXTRA_PROVISION_CALLBACK));
+            assertEquals(config.activeDataSubId,
+                    intent.getIntExtra(EXTRA_TETHER_SUBID, INVALID_SUBSCRIPTION_ID));
         }
 
         @Override
-        protected void runSilentTetherProvisioning(int type, int subId) {
+        protected Intent runSilentTetherProvisioning(int type,
+                final TetheringConfiguration config) {
+            Intent intent = super.runSilentTetherProvisioning(type, config);
+            assertSilentTetherProvisioning(type, config, intent);
             silentProvisionCount++;
             addDownstreamMapping(type, fakeEntitlementResult);
+            return intent;
+        }
+
+        private void assertSilentTetherProvisioning(int type, final TetheringConfiguration config,
+                final Intent intent) {
+            assertEquals(type, intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID));
+            assertEquals(true, intent.getBooleanExtra(EXTRA_RUN_PROVISION, false));
+            assertEquals(PROVISIONING_NO_UI_APP_NAME,
+                    intent.getStringExtra(EXTRA_TETHER_SILENT_PROVISIONING_ACTION));
+            assertEquals(PROVISIONING_APP_RESPONSE,
+                    intent.getStringExtra(EXTRA_TETHER_PROVISIONING_RESPONSE));
+            assertTrue(intent.hasExtra(EXTRA_PROVISION_CALLBACK));
+            assertEquals(config.activeDataSubId,
+                    intent.getIntExtra(EXTRA_TETHER_SUBID, INVALID_SUBSCRIPTION_ID));
         }
     }
 
@@ -187,6 +234,8 @@
                 .thenReturn(PROVISIONING_APP_NAME);
         when(mResources.getString(R.string.config_mobile_hotspot_provision_app_no_ui))
                 .thenReturn(PROVISIONING_NO_UI_APP_NAME);
+        when(mResources.getString(R.string.config_mobile_hotspot_provision_response)).thenReturn(
+                PROVISIONING_APP_RESPONSE);
         // Act like the CarrierConfigManager is present and ready unless told otherwise.
         when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
                 .thenReturn(mCarrierConfigManager);
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
index 1999ad7..3121863 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
@@ -61,6 +61,8 @@
     private final SharedLog mLog = new SharedLog("TetheringConfigurationTest");
 
     private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
+    private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app";
+    private static final String PROVISIONING_APP_RESPONSE = "app_response";
     @Mock private Context mContext;
     @Mock private TelephonyManager mTelephonyManager;
     @Mock private Resources mResources;
@@ -388,6 +390,8 @@
                 new MockTetheringConfiguration(mMockContext, mLog, anyValidSubId);
         assertEquals(mockCfg.provisioningApp[0], PROVISIONING_APP_NAME[0]);
         assertEquals(mockCfg.provisioningApp[1], PROVISIONING_APP_NAME[1]);
+        assertEquals(mockCfg.provisioningAppNoUi, PROVISIONING_NO_UI_APP_NAME);
+        assertEquals(mockCfg.provisioningResponse, PROVISIONING_APP_RESPONSE);
     }
 
     private void setUpResourceForSubId() {
@@ -403,6 +407,10 @@
                 new int[0]);
         when(mResourcesForSubId.getStringArray(
                 R.array.config_mobile_hotspot_provision_app)).thenReturn(PROVISIONING_APP_NAME);
+        when(mResourcesForSubId.getString(R.string.config_mobile_hotspot_provision_app_no_ui))
+                .thenReturn(PROVISIONING_NO_UI_APP_NAME);
+        when(mResourcesForSubId.getString(
+                R.string.config_mobile_hotspot_provision_response)).thenReturn(
+                PROVISIONING_APP_RESPONSE);
     }
-
 }