Upload libraries for an alternative ABI if the native ABI of the device is not supported in the app to be installed.

--
MOS_MIGRATED_REVID=101004548
diff --git a/tools/android/incremental_install.py b/tools/android/incremental_install.py
index c8b15eb..aa2f710 100644
--- a/tools/android/incremental_install.py
+++ b/tools/android/incremental_install.py
@@ -60,6 +60,14 @@
 
 DEVICE_DIRECTORY = "/data/local/tmp/incrementaldeployment"
 
+# Some devices support ABIs other than those reported by getprop. In this case,
+# if the most specific ABI is not available in the .apk, we push the more
+# general ones.
+COMPATIBLE_ABIS = {
+    "armeabi-v7a": ["armeabi"],
+    "arm64-v8a": ["armeabi-v7a", "armeabi"]
+}
+
 
 class AdbError(Exception):
   """An exception class signaling an error in an adb invocation."""
@@ -467,17 +475,31 @@
   return native_libs
 
 
+def FindAbi(device_abi, app_abis):
+  """Selects which ABI native libs should be installed for."""
+  if device_abi in app_abis:
+    return device_abi
+
+  if device_abi in COMPATIBLE_ABIS:
+    for abi in COMPATIBLE_ABIS[device_abi]:
+      if abi in app_abis:
+        logging.warn("App does not have native libs for ABI '%s'. Using ABI "
+                     "'%s'.", device_abi, abi)
+        return abi
+
+  logging.warn("No native libs for device ABI '%s'. App has native libs for "
+               "ABIs: %s", device_abi, ", ".join(app_abis))
+  return None
+
+
 def UploadNativeLibs(adb, native_lib_args, app_dir, full_install):
   """Uploads native libraries to the device."""
 
   native_libs = ConvertNativeLibs(native_lib_args)
   libs = set()
   if native_libs:
-    abi = adb.GetAbi()
-    if abi not in native_libs:
-      logging.warn("No native libs for device ABI '%s'. Available ABIs: %s",
-                   abi, ", ".join(native_libs))
-    else:
+    abi = FindAbi(adb.GetAbi(), native_libs.keys())
+    if abi:
       libs = native_libs[abi]
 
   basename_to_path = {}
diff --git a/tools/android/incremental_install_test.py b/tools/android/incremental_install_test.py
index 0006187..c92fae7 100644
--- a/tools/android/incremental_install_test.py
+++ b/tools/android/incremental_install_test.py
@@ -32,6 +32,7 @@
     self.package_timestamp = None
     self._last_package_timestamp = 0
     self.shell_cmdlns = []
+    self.abi = "armeabi-v7a"
 
   def Exec(self, args):
     if self._error:
@@ -79,7 +80,7 @@
         file_path = shell_cmdln.split()[2]
         self.files.pop(file_path, None)
       elif shell_cmdln.startswith("getprop ro.product.cpu.abi"):
-        return self._CreatePopenMock(0, "armeabi-v7a", "")
+        return self._CreatePopenMock(0, self.abi, "")
       else:
         raise Exception("Unknown shell command line: %s" % shell_cmdln)
     # Return a mock subprocess.Popen object
@@ -92,6 +93,9 @@
   def SetError(self, returncode, stdout, stderr, for_arg=None):
     self._error = ((returncode, stdout, stderr), for_arg)
 
+  def SetAbi(self, abi):
+    self.abi = abi
+
 
 class IncrementalInstallTest(unittest.TestCase):
   """Unit tests for incremental install."""
@@ -233,6 +237,16 @@
     self._CallIncrementalInstall(incremental=False, native_libs=native_libs)
     self.assertEquals("liba_1", self._GetDeviceFile("native/liba.so"))
 
+  def testNativeAbiCompatibility(self):
+    self._CreateZip()
+    with open("liba.so", "w") as f:
+      f.write("liba")
+
+    native_libs = ["armeabi:liba.so"]
+    self._mock_adb.SetAbi("arm64-v8a")
+    self._CallIncrementalInstall(incremental=False, native_libs=native_libs)
+    self.assertEquals("liba", self._GetDeviceFile("native/liba.so"))
+
   def testUploadNativeLibs(self):
     self._CreateZip()
     with open("liba.so", "w") as f: