Merge "Finalize the deepCopy to handle DEVICE tags"
diff --git a/src/com/android/tradefed/config/Configuration.java b/src/com/android/tradefed/config/Configuration.java
index 879bc77..d4fd319 100644
--- a/src/com/android/tradefed/config/Configuration.java
+++ b/src/com/android/tradefed/config/Configuration.java
@@ -713,10 +713,37 @@
                                 QuotationAwareTokenizer.tokenizeLine(this.getCommandLine()),
                                 null,
                                 client);
-        for (String objType : objectToDeepClone) {
-            // TODO: Might need to handle internal device objects
+        boolean shouldCopyDevice = false;
+        if (objectToDeepClone.contains(Configuration.DEVICE_NAME)) {
+            shouldCopyDevice = true;
+        } else {
+            for (String objType : objectToDeepClone) {
+                if (doesBuiltInObjSupportMultiDevice(objType)) {
+                    shouldCopyDevice = true;
+                }
+            }
+        }
+        if (shouldCopyDevice) {
             clonedConfig.setConfigurationObjectList(
-                    objType, deepCopy.getConfigurationObjectList(objType));
+                    Configuration.DEVICE_NAME,
+                    deepCopy.getConfigurationObjectList(Configuration.DEVICE_NAME));
+        }
+
+        for (String objType : objectToDeepClone) {
+            if (objType.equals(Configuration.DEVICE_NAME)) {
+                continue;
+            }
+            if (doesBuiltInObjSupportMultiDevice(objType)) {
+                for (int i = 0; i < deepCopy.getDeviceConfig().size(); i++) {
+                    IDeviceConfiguration deepCopyConfig = deepCopy.getDeviceConfig().get(i);
+                    for (Object o : deepCopyConfig.getAllObjectOfType(objType)) {
+                        clonedConfig.getDeviceConfig().get(i).addSpecificConfig(o);
+                    }
+                }
+            } else {
+                clonedConfig.setConfigurationObjectList(
+                        objType, deepCopy.getConfigurationObjectList(objType));
+            }
         }
         return clonedConfig;
     }
diff --git a/src/com/android/tradefed/invoker/shard/ShardHelper.java b/src/com/android/tradefed/invoker/shard/ShardHelper.java
index 6afe312..65deabf 100644
--- a/src/com/android/tradefed/invoker/shard/ShardHelper.java
+++ b/src/com/android/tradefed/invoker/shard/ShardHelper.java
@@ -68,8 +68,12 @@
         CONFIG_OBJ_TO_CLONE.add(Configuration.SYSTEM_STATUS_CHECKER_TYPE_NAME);
         CONFIG_OBJ_TO_CLONE.add(Configuration.DEVICE_METRICS_COLLECTOR_TYPE_NAME);
         // Copy all the objects under the <device> tag from
-        // {@link Configuration#getMultiDeviceSupportedTag()}.
-        CONFIG_OBJ_TO_CLONE.add(Configuration.DEVICE_NAME);
+        // {@link Configuration#getMultiDeviceSupportedTag()} except DEVICE_REQUIREMENTS_TYPE_NAME
+        // which should be shared since all shards should have the same requirements.
+        CONFIG_OBJ_TO_CLONE.add(Configuration.BUILD_PROVIDER_TYPE_NAME);
+        CONFIG_OBJ_TO_CLONE.add(Configuration.TARGET_PREPARER_TYPE_NAME);
+        CONFIG_OBJ_TO_CLONE.add(Configuration.DEVICE_RECOVERY_TYPE_NAME);
+        CONFIG_OBJ_TO_CLONE.add(Configuration.DEVICE_OPTIONS_TYPE_NAME);
 
         CONFIG_OBJ_TO_CLONE.add(Configuration.MULTI_PREPARER_TYPE_NAME);
         CONFIG_OBJ_TO_CLONE.add(Configuration.CMD_OPTIONS_TYPE_NAME);
diff --git a/tests/src/com/android/tradefed/config/ConfigurationTest.java b/tests/src/com/android/tradefed/config/ConfigurationTest.java
index 005bdac..a706175 100644
--- a/tests/src/com/android/tradefed/config/ConfigurationTest.java
+++ b/tests/src/com/android/tradefed/config/ConfigurationTest.java
@@ -753,4 +753,26 @@
                 copy.getDeviceConfig().get(0).getTargetPreparers().get(0));
         assertNotEquals(original.getTests().get(0), copy.getTests().get(0));
     }
+
+    public void testDeepClone_innerDevice() throws Exception {
+        Configuration original =
+                (Configuration)
+                        ConfigurationFactory.getInstance()
+                                .createConfigurationFromArgs(
+                                        new String[] {"instrumentations"}, null, null);
+        IConfiguration copy =
+                original.partialDeepClone(
+                        Arrays.asList(
+                                Configuration.TARGET_PREPARER_TYPE_NAME,
+                                Configuration.TEST_TYPE_NAME),
+                        null);
+        assertNotEquals(
+                original.getDeviceConfigByName(ConfigurationDef.DEFAULT_DEVICE_NAME),
+                copy.getDeviceConfigByName(ConfigurationDef.DEFAULT_DEVICE_NAME));
+        assertNotEquals(original.getTargetPreparers().get(0), copy.getTargetPreparers().get(0));
+        assertNotEquals(
+                original.getDeviceConfig().get(0).getTargetPreparers().get(0),
+                copy.getDeviceConfig().get(0).getTargetPreparers().get(0));
+        assertNotEquals(original.getTests().get(0), copy.getTests().get(0));
+    }
 }