build/soong side of move the module-info.json commands into standalone scripts.

Bug: 340648588
Test: run them
Change-Id: I5c072ee8481630327be9dccbbca501293a7b34cd
diff --git a/bin/allmod b/bin/allmod
new file mode 100755
index 0000000..f7d25e5
--- /dev/null
+++ b/bin/allmod
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# List all modules for the current device, as cached in all_modules.txt. If any build change is
+# made and it should be reflected in the output, you should run 'refreshmod' first.
+
+cat $ANDROID_PRODUCT_OUT/all_modules.txt 2>/dev/null
+
diff --git a/bin/dirmods b/bin/dirmods
new file mode 100755
index 0000000..d43506a
--- /dev/null
+++ b/bin/dirmods
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2024 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.
+
+import sys
+sys.dont_write_bytecode = True
+
+import modinfo
+
+import os
+
+# Get the path of a specific module in the android tree, as cached in module-info.json.
+# If any build change is made, and it should be reflected in the output, you should run
+# 'refreshmod' first.  Note: This is the inverse of pathmod.
+
+def main(argv):
+    if len(argv) != 2:
+        sys.stderr.write("usage: usage: dirmods <path>\n")
+        sys.exit(1)
+
+    d = argv[1]
+    while d.endswith('/'):
+        d = d[:-1]
+    prefix = d + '/'
+
+    module_info = modinfo.ReadModuleInfo()
+
+    results = set()
+    for m in module_info.values():
+        for path in m.get(u'path', []):
+            if path == d or path.startswith(prefix):
+                name = m.get(u'module_name')
+                if name:
+                    results.add(name)
+
+    for name in sorted(results):
+        print(name)
+
+if __name__ == "__main__":
+    main(sys.argv)
diff --git a/bin/installmod b/bin/installmod
new file mode 100755
index 0000000..1d0d836
--- /dev/null
+++ b/bin/installmod
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# adb install a module's apk, as cached in module-info.json. If any build change
+# is made, and it should be reflected in the output, you should run 'refreshmod' first.
+# Usage: installmod [adb install arguments] <module>
+# For example: installmod -r Dialer -> adb install -r /path/to/Dialer.apk
+
+if [[ $# -eq 0 ]]; then
+    echo "usage: installmod [adb install arguments] <module>" >&2
+    echo "" >&2
+    echo "Only flags to be passed after the \"install\" in adb install are supported," >&2
+    echo "with the exception of -s. If -s is passed it will be placed before the \"install\"." >&2
+    echo "-s must be the first flag passed if it exists." >&2
+    return 1
+fi
+
+local _path
+_path=$(outmod ${@:$#:1})
+if [ $? -ne 0 ]; then
+    return 1
+fi
+
+_path=$(echo "$_path" | grep -E \\.apk$ | head -n 1)
+if [ -z "$_path" ]; then
+    echo "Module '$1' does not produce a file ending with .apk (try 'refreshmod' if there have been build changes?)" >&2
+    return 1
+fi
+local serial_device=""
+if [[ "$1" == "-s" ]]; then
+    if [[ $# -le 2 ]]; then
+        echo "-s requires an argument" >&2
+        return 1
+    fi
+    serial_device="-s $2"
+    shift 2
+fi
+local length=$(( $# - 1 ))
+echo adb $serial_device install ${@:1:$length} $_path
+adb $serial_device install ${@:1:$length} $_path
+
diff --git a/bin/modinfo.py b/bin/modinfo.py
new file mode 100644
index 0000000..015129f
--- /dev/null
+++ b/bin/modinfo.py
@@ -0,0 +1,44 @@
+# Copyright (C) 2024 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.
+
+import json
+import os
+import pathlib
+import sys
+
+
+def OpenModuleInfoFile():
+    product_out = os.getenv("ANDROID_PRODUCT_OUT")
+    if not product_out:
+        if os.getenv("QUIET_VERIFYMODINFO") != "true":
+            sys.stderr.write("No ANDROID_PRODUCT_OUT. Try running 'lunch' first.\n")
+        sys.exit(1)
+    try:
+        return open(pathlib.Path(product_out) / "module-info.json")
+    except (FileNotFoundError, PermissionError):
+        if os.getenv("QUIET_VERIFYMODINFO") != "true":
+            sys.stderr.write("Could not find module-info.json. Please run 'refreshmod' first.\n")
+        sys.exit(1)
+
+
+def ReadModuleInfo():
+    with OpenModuleInfoFile() as f:
+        return json.load(f)
+
+def GetModule(modules, module_name):
+    if module_name not in modules:
+        sys.stderr.write(f"Could not find module '{module_name}' (try 'refreshmod' if there have been build changes?)\n")
+        sys.exit(1)
+    return modules[module_name]
+
diff --git a/bin/outmod b/bin/outmod
new file mode 100755
index 0000000..681b405
--- /dev/null
+++ b/bin/outmod
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2024 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.
+
+# Get the path of a specific module in the android tree, as cached in module-info.json.
+# If any build change is made, and it should be reflected in the output, you should run
+# 'refreshmod' first.  Note: This is the inverse of dirmods.
+
+import sys
+sys.dont_write_bytecode = True
+
+import modinfo
+
+import os
+
+
+def main(argv):
+    if len(argv) != 2:
+        sys.stderr.write("usage: outmod <module>\n")
+        sys.exit(1)
+
+    for output in modinfo.GetModule(modinfo.ReadModuleInfo(), argv[1])['installed']:
+        print(os.path.join(os.getenv("ANDROID_BUILD_TOP"), output))
+
+if __name__ == "__main__":
+    main(sys.argv)
+
diff --git a/bin/pathmod b/bin/pathmod
new file mode 100755
index 0000000..90d84b5
--- /dev/null
+++ b/bin/pathmod
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2024 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.
+
+# Get the path of a specific module in the android tree, as cached in module-info.json.
+# If any build change is made, and it should be reflected in the output, you should run
+# 'refreshmod' first.  Note: This is the inverse of dirmods.
+
+import sys
+sys.dont_write_bytecode = True
+
+import modinfo
+
+import os
+
+
+def main(argv):
+    if len(argv) != 2:
+        sys.stderr.write("usage: pathmod <module>\n")
+        sys.exit(1)
+
+    print(modinfo.GetModule(modinfo.ReadModuleInfo(), argv[1])['path'][0])
+
+if __name__ == "__main__":
+    main(sys.argv)
diff --git a/bin/qpid b/bin/qpid
new file mode 100755
index 0000000..b47cb6b
--- /dev/null
+++ b/bin/qpid
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+# Copyright (C) 2024 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.
+
+# adb install a module's apk, as cached in module-info.json. If any build change
+# is made, and it should be reflected in the output, you should run 'refreshmod' first.
+# Usage: installmod [adb install arguments] <module>
+# For example: installmod -r Dialer -> adb install -r /path/to/Dialer.apk
+
+function _impl() {
+    local prepend=''
+    local append=''
+    if [ "$1" = "--exact" ]; then
+        prepend=' '
+        append='$'
+        shift
+    elif [ "$1" = "--help" -o "$1" = "-h" ]; then
+        echo "usage: qpid [[--exact] <process name|pid>"
+        return 255
+    fi
+
+    local EXE="$1"
+    if [ "$EXE" ] ; then
+        _impl | \grep "$prepend$EXE$append"
+    else
+        adb shell ps \
+            | tr -d '\r' \
+            | sed -e 1d -e 's/^[^ ]* *\([0-9]*\).* \([^ ]*\)$/\1 \2/'
+    fi
+}
+
+_impl "$@"