Merge "ATest: Update test case names and expected results."
diff --git a/src/com/android/tradefed/invoker/shard/token/TelephonyTokenProvider.java b/src/com/android/tradefed/invoker/shard/token/TelephonyTokenProvider.java
index 2935918..2b62177 100644
--- a/src/com/android/tradefed/invoker/shard/token/TelephonyTokenProvider.java
+++ b/src/com/android/tradefed/invoker/shard/token/TelephonyTokenProvider.java
@@ -22,16 +22,21 @@
 import com.android.tradefed.device.helper.TelephonyHelper.SimCardInformation;
 import com.android.tradefed.log.LogUtil.CLog;
 
+import com.google.common.annotations.VisibleForTesting;
+
 /** Token provider for telephony related tokens. */
 public class TelephonyTokenProvider implements ITokenProvider {
 
+    public static final String ORANGE_SIM_ID = "20801";
+    public static final String GSM_OPERATOR_PROP = "gsm.sim.operator.numeric";
+
     @Override
     public boolean hasToken(ITestDevice device, TokenProperty token) {
         if (device.getIDevice() instanceof StubDevice) {
             return false;
         }
         try {
-            SimCardInformation info = TelephonyHelper.getSimInfo(device);
+            SimCardInformation info = getSimInfo(device);
             if (info == null || !info.mHasTelephonySupport) {
                 CLog.e("SimcardInfo: %s", info);
                 return false;
@@ -56,8 +61,16 @@
                     return false;
                 case SECURE_ELEMENT_SIM_CARD:
                     if (info.mHasSecuredElement && info.mHasSeService) {
-                        return true;
+                        // TODO: Improve how we detect this use case.
+                        if (ORANGE_SIM_ID.equals(device.getProperty(GSM_OPERATOR_PROP))) {
+                            return true;
+                        } else {
+                            CLog.w(
+                                    "%s doesn't have a Orange Sim card for secured elements.",
+                                    device.getSerialNumber());
+                        }
                     }
+
                     CLog.w(
                             "%s cannot run with token '%s' - Sim info: %s",
                             device.getSerialNumber(), token, info);
@@ -71,4 +84,9 @@
         }
         return false;
     }
+
+    @VisibleForTesting
+    SimCardInformation getSimInfo(ITestDevice device) throws DeviceNotAvailableException {
+        return TelephonyHelper.getSimInfo(device);
+    }
 }
diff --git a/src/com/android/tradefed/sandbox/SandboxConfigDump.java b/src/com/android/tradefed/sandbox/SandboxConfigDump.java
index 0cff43f..63eefd9 100644
--- a/src/com/android/tradefed/sandbox/SandboxConfigDump.java
+++ b/src/com/android/tradefed/sandbox/SandboxConfigDump.java
@@ -28,6 +28,7 @@
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.result.SubprocessResultsReporter;
 import com.android.tradefed.result.proto.StreamProtoResultReporter;
+import com.android.tradefed.testtype.SubprocessTfLauncher;
 import com.android.tradefed.util.StreamUtil;
 
 import java.io.File;
@@ -110,6 +111,11 @@
 
                 // Ensure in special conditions (placeholder devices) we can still allocate.
                 secureDeviceAllocation(config);
+
+                // Mark as subprocess
+                config.getCommandOptions()
+                        .getInvocationData()
+                        .put(SubprocessTfLauncher.SUBPROCESS_TAG_NAME, "true");
             }
             if (DumpCmd.TEST_MODE.equals(cmd)) {
                 // We allow one more layer of sandbox to be generated
diff --git a/tests/src/com/android/tradefed/UnitTests.java b/tests/src/com/android/tradefed/UnitTests.java
index 2513806..8c4aa0d 100644
--- a/tests/src/com/android/tradefed/UnitTests.java
+++ b/tests/src/com/android/tradefed/UnitTests.java
@@ -126,6 +126,7 @@
 import com.android.tradefed.invoker.shard.ShardHelperTest;
 import com.android.tradefed.invoker.shard.StrictShardHelperTest;
 import com.android.tradefed.invoker.shard.TestsPoolPollerTest;
+import com.android.tradefed.invoker.shard.token.TelephonyTokenProviderTest;
 import com.android.tradefed.invoker.shard.token.TokenProviderHelperTest;
 import com.android.tradefed.log.FileLoggerTest;
 import com.android.tradefed.log.HistoryLoggerTest;
@@ -518,6 +519,7 @@
     TestsPoolPollerTest.class,
 
     // invoker.shard.token
+    TelephonyTokenProviderTest.class,
     TokenProviderHelperTest.class,
 
     // invoker.sandbox
diff --git a/tests/src/com/android/tradefed/config/ConfigurationTest.java b/tests/src/com/android/tradefed/config/ConfigurationTest.java
index f8b5150..747cf03 100644
--- a/tests/src/com/android/tradefed/config/ConfigurationTest.java
+++ b/tests/src/com/android/tradefed/config/ConfigurationTest.java
@@ -824,4 +824,32 @@
                 differentObject.contains(
                         "<cmd_options class=\"com.android.tradefed.command.CommandOptions\" />"));
     }
+
+    /** Ensure we print modified option if they are structures. */
+    public void testDumpChangedOption_structure() throws Exception {
+        CommandOptions options1 = new CommandOptions();
+        Configuration one = new Configuration("test", "test");
+        one.setCommandOptions(options1);
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        one.dumpXml(pw, new ArrayList<>(), true, false);
+        String noOption = sw.toString();
+        assertTrue(
+                noOption.contains(
+                        "<cmd_options class=\"com.android.tradefed.command.CommandOptions\" />"));
+
+        OptionSetter setter = new OptionSetter(options1);
+        setter.setOptionValue("invocation-data", "key", "value");
+        setter.setOptionValue("auto-collect", "LOGCAT_ON_FAILURE");
+        sw = new StringWriter();
+        pw = new PrintWriter(sw);
+        one.dumpXml(pw, new ArrayList<>(), true, false);
+        String withOption = sw.toString();
+        assertTrue(
+                withOption.contains(
+                        "<option name=\"invocation-data\" key=\"key\" value=\"value\" />"));
+        assertTrue(
+                withOption.contains(
+                        "<option name=\"auto-collect\" value=\"LOGCAT_ON_FAILURE\" />"));
+    }
 }
diff --git a/tests/src/com/android/tradefed/invoker/shard/token/TelephonyTokenProviderTest.java b/tests/src/com/android/tradefed/invoker/shard/token/TelephonyTokenProviderTest.java
new file mode 100644
index 0000000..c89f8e8
--- /dev/null
+++ b/tests/src/com/android/tradefed/invoker/shard/token/TelephonyTokenProviderTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 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.tradefed.invoker.shard.token;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.helper.TelephonyHelper.SimCardInformation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
+
+/** Unit tests for {@link TelephonyTokenProvider}. */
+@RunWith(JUnit4.class)
+public class TelephonyTokenProviderTest {
+
+    private TelephonyTokenProvider provider;
+    private ITestDevice mDevice;
+    private SimCardInformation mSimInfo;
+
+    @Before
+    public void setUp() {
+        provider =
+                new TelephonyTokenProvider() {
+                    @Override
+                    SimCardInformation getSimInfo(ITestDevice device)
+                            throws DeviceNotAvailableException {
+                        return mSimInfo;
+                    }
+                };
+        mDevice = Mockito.mock(ITestDevice.class);
+    }
+
+    @Test
+    public void testSimCard() {
+        mSimInfo = new SimCardInformation();
+        mSimInfo.mHasTelephonySupport = true;
+        mSimInfo.mSimState = "5"; // Ready
+        assertTrue(provider.hasToken(mDevice, TokenProperty.SIM_CARD));
+    }
+
+    @Test
+    public void testSimCard_noSupport() {
+        mSimInfo = new SimCardInformation();
+        mSimInfo.mHasTelephonySupport = false;
+        assertFalse(provider.hasToken(mDevice, TokenProperty.SIM_CARD));
+    }
+
+    @Test
+    public void testSimCard_carrier() {
+        mSimInfo = new SimCardInformation();
+        mSimInfo.mHasTelephonySupport = true;
+        mSimInfo.mCarrierPrivileges = true;
+        assertTrue(provider.hasToken(mDevice, TokenProperty.UICC_SIM_CARD));
+    }
+
+    @Test
+    public void testSimCard_securedElementOrange() throws Exception {
+        mSimInfo = new SimCardInformation();
+        mSimInfo.mHasTelephonySupport = true;
+        mSimInfo.mHasSecuredElement = true;
+        mSimInfo.mHasSeService = true;
+        Mockito.doReturn(TelephonyTokenProvider.ORANGE_SIM_ID)
+                .when(mDevice)
+                .getProperty(TelephonyTokenProvider.GSM_OPERATOR_PROP);
+        assertTrue(provider.hasToken(mDevice, TokenProperty.SECURE_ELEMENT_SIM_CARD));
+    }
+
+    @Test
+    public void testSimCard_securedElement_anySim() throws Exception {
+        mSimInfo = new SimCardInformation();
+        mSimInfo.mHasTelephonySupport = true;
+        mSimInfo.mHasSecuredElement = true;
+        mSimInfo.mHasSeService = true;
+        Mockito.doReturn("8888")
+                .when(mDevice)
+                .getProperty(TelephonyTokenProvider.GSM_OPERATOR_PROP);
+        assertFalse(provider.hasToken(mDevice, TokenProperty.SECURE_ELEMENT_SIM_CARD));
+    }
+}