Change --fastdeploy behaviour

--fastdeploy does not require -r anymore, and reverts to a normal install
if the application is not already on the device.

Bug: 120828611

Test: mm -j72
Test: adb install --fastdeploy --force-agent --local-agent /mnt/raid/boat-attack-apk/boat-attack-swappy.apk
Change-Id: Ice2a71493a34ee7d0debabcce6a9aebb0af79e62
diff --git a/client/adb_install.cpp b/client/adb_install.cpp
index 7f37c45..b62ef6a 100644
--- a/client/adb_install.cpp
+++ b/client/adb_install.cpp
@@ -341,11 +341,6 @@
         error_exit("Attempting to use streaming install on unsupported device");
     }
 
-    if (use_fastdeploy == true && is_reinstall == false) {
-        printf("Fast Deploy is only available with -r.\n");
-        use_fastdeploy = false;
-    }
-
     if (use_fastdeploy == true && get_device_api_level() < kFastDeployMinApi) {
         printf("Fast Deploy is only compatible with devices of API version %d or higher, "
                "ignoring.\n",
@@ -360,10 +355,17 @@
             passthrough_argv.push_back(argv[i]);
         }
     }
+    if (passthrough_argv.size() < 2) {
+        error_exit("install requires an apk argument");
+    }
 
     if (use_fastdeploy == true) {
         fastdeploy_set_local_agent(use_localagent);
         update_agent(agent_update_strategy);
+
+        // The last argument must be the APK file
+        const char* file = passthrough_argv.back();
+        use_fastdeploy = find_package(file);
     }
 
     switch (installMode) {
diff --git a/client/commandline.cpp b/client/commandline.cpp
index c11052d..6c1def7 100644
--- a/client/commandline.cpp
+++ b/client/commandline.cpp
@@ -156,8 +156,8 @@
         "     --instant: cause the app to be installed as an ephemeral install app\n"
         "     --no-streaming: always push APK to device and invoke Package Manager as separate steps\n"
         "     --streaming: force streaming APK directly into Package Manager\n"
-        "     --fastdeploy: use fast deploy (only valid with -r)\n"
-        "     --no-fastdeploy: prevent use of fast deploy (only valid with -r)\n"
+        "     --fastdeploy: use fast deploy\n"
+        "     --no-fastdeploy: prevent use of fast deploy\n"
         "     --force-agent: force update of deployment agent when using fast deploy\n"
         "     --date-check-agent: update deployment agent when local version is newer and using fast deploy\n"
         "     --version-check-agent: update deployment agent when local version has different version code and using fast deploy\n"
diff --git a/client/fastdeploy.cpp b/client/fastdeploy.cpp
index e82f15a..f4e8664 100644
--- a/client/fastdeploy.cpp
+++ b/client/fastdeploy.cpp
@@ -16,6 +16,7 @@
 
 #include "fastdeploy.h"
 
+#include <string.h>
 #include <algorithm>
 #include <array>
 #include <memory>
@@ -31,7 +32,7 @@
 
 #include "adb_utils.h"
 
-static constexpr long kRequiredAgentVersion = 0x00000001;
+static constexpr long kRequiredAgentVersion = 0x00000002;
 
 static constexpr const char* kDeviceAgentPath = "/data/local/tmp/";
 
@@ -313,9 +314,16 @@
     std::vector<unsigned char> applyErrorBuffer;
     std::string argsString;
 
+    bool rSwitchPresent = false;
     for (int i = 0; i < argc; i++) {
         argsString.append(argv[i]);
         argsString.append(" ");
+        if (!strcmp(argv[i], "-r")) {
+            rSwitchPresent = true;
+        }
+    }
+    if (!rSwitchPresent) {
+        argsString.append("-r");
     }
 
     std::string applyPatchCommand =
@@ -326,3 +334,9 @@
         error_exit("Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
     }
 }
+
+bool find_package(const char* apkPath) {
+    const std::string findCommand =
+            "/data/local/tmp/deployagent find " + get_packagename_from_apk(apkPath);
+    return !send_shell_command(findCommand);
+}
diff --git a/client/fastdeploy.h b/client/fastdeploy.h
index a6b10d3..7b7f2ec 100644
--- a/client/fastdeploy.h
+++ b/client/fastdeploy.h
@@ -32,3 +32,4 @@
 void apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
 void install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
 std::string get_patch_path(const char* apkPath);
+bool find_package(const char* apkPath);
diff --git a/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java b/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java
index 17845e2..2d3b135 100644
--- a/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java
+++ b/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java
@@ -35,7 +35,7 @@
 
 public final class DeployAgent {
     private static final int BUFFER_SIZE = 128 * 1024;
-    private static final int AGENT_VERSION = 0x00000001;
+    private static final int AGENT_VERSION = 0x00000002;
 
     public static void main(String[] args) {
         int exitCode = 0;
@@ -53,6 +53,15 @@
 
                 String packageName = args[1];
                 extractMetaData(packageName);
+            } else if (commandString.equals("find")) {
+                if (args.length != 2) {
+                    showUsage(1);
+                }
+
+                String packageName = args[1];
+                if (getFilenameFromPackageName(packageName) == null) {
+                    exitCode = 3;
+                }
             } else if (commandString.equals("apply")) {
                 if (args.length < 4) {
                     showUsage(1);
@@ -112,6 +121,7 @@
             "usage: deployagent <command> [<args>]\n\n" +
             "commands:\n" +
             "version                             get the version\n" +
+            "find PKGNAME                        return zero if package found, else non-zero\n" +
             "extract PKGNAME                     extract an installed package's metadata\n" +
             "apply PKGNAME PATCHFILE [-o|-pm]    apply a patch from PATCHFILE (- for stdin) to an installed package\n" +
             " -o <FILE> directs output to FILE, default or - for stdout\n" +
@@ -134,7 +144,7 @@
         return null;
     }
 
-    private static File getFileFromPackageName(String packageName) throws IOException {
+    private static String getFilenameFromPackageName(String packageName) throws IOException {
         StringBuilder commandBuilder = new StringBuilder();
         commandBuilder.append("pm list packages -f " + packageName);
 
@@ -153,10 +163,19 @@
                 int equalsIndex = line.lastIndexOf(packageSuffix);
                 String fileName =
                     line.substring(packageIndex + packagePrefix.length(), equalsIndex);
-                return new File(fileName);
+                return fileName;
             }
         }
-        throw new IOException("package not found");
+        return null;
+    }
+
+    private static File getFileFromPackageName(String packageName) throws IOException {
+        String filename = getFilenameFromPackageName(packageName);
+        if (filename == null) {
+            // Should not happen (function is only called when we know the package exists)
+            throw new IOException("package not found");
+        }
+        return new File(filename);
     }
 
     private static void extractMetaData(String packageName) throws IOException {