Merge changes I2dd18f9d,I5cc02c8a into main am: 25e0517124

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/3364270

Change-Id: If8ee4fb7cc1876a8949fa46611dad65adc1d2391
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java b/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
index cd57c8d..fb16226 100644
--- a/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
+++ b/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
@@ -167,6 +167,11 @@
                 } else {
                     mLog.e("Current user (" + currentUserId
                             + ") is not allowed to perform entitlement check.");
+                    // If the user is not allowed to perform an entitlement check
+                    // (e.g., a non-admin user), notify the receiver immediately.
+                    // This is necessary because the entitlement check app cannot
+                    // be launched to conduct the check and deliver the results.
+                    receiver.send(TETHER_ERROR_PROVISIONING_FAILED, null);
                     return null;
                 }
             } else {
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
index 8626b18..51c2d56 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
@@ -84,6 +84,7 @@
 
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.modules.utils.build.SdkLevel;
+import com.android.net.module.util.ArrayTrackRecord;
 import com.android.net.module.util.SharedLog;
 import com.android.testutils.DevSdkIgnoreRule;
 
@@ -187,8 +188,9 @@
             if (intent != null) {
                 assertUiTetherProvisioningIntent(type, config, receiver, intent);
                 uiProvisionCount++;
+                // If the intent is null, the result is sent by the underlying method.
+                receiver.send(fakeEntitlementResult, null);
             }
-            receiver.send(fakeEntitlementResult, null);
             return intent;
         }
 
@@ -348,99 +350,43 @@
     public void testRequestLastEntitlementCacheValue() throws Exception {
         // 1. Entitlement check is not required.
         mDeps.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
-        ResultReceiver receiver = new ResultReceiver(null) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
-            }
-        };
-        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
-        mLooper.dispatchAll();
+        assertLatestEntitlementResult(TETHERING_WIFI, TETHER_ERROR_NO_ERROR, true);
         assertEquals(0, mDeps.uiProvisionCount);
         mDeps.reset();
 
         setupForRequiredProvisioning();
         // 2. No cache value and don't need to run entitlement check.
-        receiver = new ResultReceiver(null) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
-            }
-        };
-        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
-        mLooper.dispatchAll();
+        assertLatestEntitlementResult(TETHERING_WIFI, TETHER_ERROR_ENTITLEMENT_UNKNOWN, false);
         assertEquals(0, mDeps.uiProvisionCount);
         mDeps.reset();
         // 3. No cache value and ui entitlement check is needed.
         mDeps.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
-        receiver = new ResultReceiver(null) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_PROVISIONING_FAILED, resultCode);
-            }
-        };
-        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
-        mLooper.dispatchAll();
+        assertLatestEntitlementResult(TETHERING_WIFI, TETHER_ERROR_PROVISIONING_FAILED, true);
         assertEquals(1, mDeps.uiProvisionCount);
         mDeps.reset();
         // 4. Cache value is TETHER_ERROR_PROVISIONING_FAILED and don't need to run entitlement
         // check.
         mDeps.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
-        receiver = new ResultReceiver(null) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_PROVISIONING_FAILED, resultCode);
-            }
-        };
-        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
-        mLooper.dispatchAll();
+        assertLatestEntitlementResult(TETHERING_WIFI, TETHER_ERROR_PROVISIONING_FAILED, false);
         assertEquals(0, mDeps.uiProvisionCount);
         mDeps.reset();
         // 5. Cache value is TETHER_ERROR_PROVISIONING_FAILED and ui entitlement check is needed.
         mDeps.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
-        receiver = new ResultReceiver(null) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
-            }
-        };
-        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
-        mLooper.dispatchAll();
+        assertLatestEntitlementResult(TETHERING_WIFI, TETHER_ERROR_NO_ERROR, true);
         assertEquals(1, mDeps.uiProvisionCount);
         mDeps.reset();
         // 6. Cache value is TETHER_ERROR_NO_ERROR.
         mDeps.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
-        receiver = new ResultReceiver(null) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
-            }
-        };
-        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
-        mLooper.dispatchAll();
+        assertLatestEntitlementResult(TETHERING_WIFI, TETHER_ERROR_NO_ERROR, true);
         assertEquals(0, mDeps.uiProvisionCount);
         mDeps.reset();
         // 7. Test get value for other downstream type.
-        receiver = new ResultReceiver(null) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
-            }
-        };
-        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_USB, receiver, false);
-        mLooper.dispatchAll();
+        assertLatestEntitlementResult(TETHERING_USB, TETHER_ERROR_ENTITLEMENT_UNKNOWN, false);
         assertEquals(0, mDeps.uiProvisionCount);
         mDeps.reset();
         // 8. Test get value for invalid downstream type.
         mDeps.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
-        receiver = new ResultReceiver(null) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
-            }
-        };
-        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI_P2P, receiver, true);
-        mLooper.dispatchAll();
+        assertLatestEntitlementResult(TETHERING_WIFI_P2P, TETHER_ERROR_ENTITLEMENT_UNKNOWN, true);
         assertEquals(0, mDeps.uiProvisionCount);
         mDeps.reset();
     }
@@ -660,6 +606,34 @@
         doTestUiProvisioningMultiUser(false, 1);
     }
 
+    private static class TestableResultReceiver extends ResultReceiver {
+        private static final long DEFAULT_TIMEOUT_MS = 200L;
+        private final ArrayTrackRecord<Integer>.ReadHead mHistory =
+                new ArrayTrackRecord<Integer>().newReadHead();
+
+        TestableResultReceiver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+            mHistory.add(resultCode);
+        }
+
+        void expectResult(int resultCode) {
+            final int event = mHistory.poll(DEFAULT_TIMEOUT_MS, it -> true);
+            assertEquals(resultCode, event);
+        }
+    }
+
+    void assertLatestEntitlementResult(int downstreamType, int expectedCode,
+            boolean showEntitlementUi) {
+        final TestableResultReceiver receiver = new TestableResultReceiver(null);
+        mEnMgr.requestLatestTetheringEntitlementResult(downstreamType, receiver, showEntitlementUi);
+        mLooper.dispatchAll();
+        receiver.expectResult(expectedCode);
+    }
+
     private void doTestUiProvisioningMultiUser(boolean isAdminUser, int expectedUiProvisionCount) {
         setupForRequiredProvisioning();
         doReturn(isAdminUser).when(mUserManager).isAdminUser();
@@ -671,10 +645,19 @@
         mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
         mLooper.dispatchAll();
         assertEquals(expectedUiProvisionCount, mDeps.uiProvisionCount);
+        if (expectedUiProvisionCount == 0) { // Failed to launch entitlement UI.
+            assertLatestEntitlementResult(TETHERING_USB, TETHER_ERROR_PROVISIONING_FAILED, false);
+            verify(mTetherProvisioningFailedListener).onTetherProvisioningFailed(TETHERING_USB,
+                    FAILED_TETHERING_REASON);
+        } else {
+            assertLatestEntitlementResult(TETHERING_USB, TETHER_ERROR_NO_ERROR, false);
+            verify(mTetherProvisioningFailedListener, never()).onTetherProvisioningFailed(anyInt(),
+                    anyString());
+        }
     }
 
     @Test
-    public void testsetExemptedDownstreamType() throws Exception {
+    public void testSetExemptedDownstreamType() {
         setupForRequiredProvisioning();
         // Cellular upstream is not permitted when no entitlement result.
         assertFalse(mEnMgr.isCellularUpstreamPermitted());
@@ -737,14 +720,7 @@
         setupCarrierConfig(false);
         setupForRequiredProvisioning();
         mDeps.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
-        ResultReceiver receiver = new ResultReceiver(null) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_PROVISIONING_FAILED, resultCode);
-            }
-        };
-        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
-        mLooper.dispatchAll();
+        assertLatestEntitlementResult(TETHERING_WIFI, TETHER_ERROR_PROVISIONING_FAILED, false);
         assertEquals(0, mDeps.uiProvisionCount);
         mDeps.reset();
     }