New interactive functions to send commands to a device.
This is still a bit crude but now we can remount,sync,reboot and flash
a device from emacs.
Support product aliases.
diff --git a/ide/emacs/android-common.el b/ide/emacs/android-common.el
index a4cd1e5..8988598 100644
--- a/ide/emacs/android-common.el
+++ b/ide/emacs/android-common.el
@@ -1,20 +1,34 @@
-;;;
-;;; Copyright (C) 2009 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.
+;;; android-common.el --- Common functions/variables to dev Android in Emacs.
+;;
+;; Copyright (C) 2009 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.
-;;; Variables to customize and common function for the android build
-;;; support in Emacs.
+;;; Commentary:
+;;
+;; Variables to customize and common functions for the Android build
+;; support in Emacs.
+;; There should be no interactive function in this module.
+;;
+;; You need to have a proper buildspec.mk file in your root directory
+;; for this module to work (see $TOP/build/buildspec.mk.default).
+;; If the path the product's files/image uses an a product alias, you
+;; need to add a mapping in `android-product-alias-map'. For instance
+;; if TARGET_PRODUCT is foo but the build directory is out/target/product/bar,
+;; you need to add a mapping Target:foo -> Alias:bar
+;;
+
+;;; Code:
(defgroup android nil
"Support for android development in Emacs."
@@ -26,26 +40,122 @@
:type 'integer
:group 'android)
+;;;###autoload
+(defcustom android-product-alias-map nil
+ "Alist between product targets (declared in buildspec.mk) and actual
+ product build directory used by `android-product'.
+
+For instance if TARGET_PRODUCT is 'foo' but the build directory
+ is 'out/target/product/bar', you need to add a mapping Target:foo -> Alias:bar."
+ :type '(repeat (list (string :tag "Target")
+ (string :tag "Alias")))
+ :group 'android)
+
(defun android-find-build-tree-root ()
"Ascend the current path until the root of the android build tree is found.
Similarly to the shell functions in envsetup.sh, for the root both ./Makefile
and ./build/core/envsetup.mk are exiting files.
-Return the root of the build tree. Signal an error if not found."
+Return the root of the build tree. Signal an error if not found."
(let ((default-directory default-directory))
(while (and (> (length default-directory) 2)
- (not (file-exists-p (concat default-directory "Makefile")))
- (not (file-exists-p (concat default-directory "build/core/envsetup.mk"))))
+ (not (file-exists-p (concat default-directory
+ "Makefile")))
+ (not (file-exists-p (concat default-directory
+ "build/core/envsetup.mk"))))
(setq default-directory
(substring default-directory 0
(string-match "[^/]+/$" default-directory))))
(if (> (length default-directory) 2)
default-directory
- (error "Not in a valid android tree."))))
+ (error "Not in a valid android tree"))))
(defun android-project-p ()
-"Return nil if not in an android build tree."
+ "Return nil if not in an android build tree."
(condition-case nil
(android-find-build-tree-root)
(error nil)))
+(defun android-host ()
+ "Return the <system>-<arch> string (e.g linux-x86).
+Only linux and darwin on x86 architectures are supported."
+ (or (string-match "x86" system-configuration)
+ (string-match "i386" system-configuration)
+ (error "Unknown arch"))
+ (or (and (string-match "darwin" system-configuration) "darwin-x86")
+ (and (string-match "linux" system-configuration) "linux-x86")
+ (error "Unknown system")))
+
+(defun android-product ()
+ "Return the product built according to the buildspec.mk.
+You must have buildspec.mk file in the top directory.
+
+Additional product aliases can be listed in `android-product-alias-map'
+if the product actually built is different from the one listed
+in buildspec.mk"
+ (save-excursion
+ (let* ((buildspec (concat (android-find-build-tree-root) "buildspec.mk"))
+ (product (with-current-buffer (find-file-noselect buildspec)
+ (goto-char (point-min))
+ (search-forward "TARGET_PRODUCT:=")
+ (buffer-substring-no-properties (point)
+ (scan-sexps (point) 1))))
+ (alias (assoc product android-product-alias-map)))
+ ; Post processing, adjust the names.
+ (if (not alias)
+ product
+ (nth 1 alias)))))
+
+(defun android-product-path ()
+ "Return the full path to the product directory.
+
+Additional product aliases can be added in `android-product-alias-map'
+if the product actually built is different from the one listed
+in buildspec.mk"
+ (let ((path (concat (android-find-build-tree-root) "out/target/product/"
+ (android-product))))
+ (when (not (file-exists-p path))
+ (error (format "%s does not exist. If product %s maps to another one,
+add an entry to android-product-map." path (android-product))))
+ path))
+
+(defun android-find-host-bin (binary)
+ "Return the full path to the host BINARY.
+Binaries don't depend on the device, just on the host type.
+Try first to locate BINARY in the out/host tree. Fallback using
+the shell exec PATH setup."
+ (if (android-project-p)
+ (let ((path (concat (android-find-build-tree-root) "out/host/"
+ (android-host) "/bin/" binary)))
+ (if (file-exists-p path)
+ path
+ (error (concat binary " is missing."))))
+ (executable-find binary)))
+
+(defun android-adb ()
+ "Return the path to the adb executable.
+If not in the build tree use the PATH env variable."
+ (android-find-host-bin "adb"))
+
+(defun android-fastboot ()
+ "Return the path to the fastboot executable.
+If not in the build tree use the PATH env variable."
+ ; For fastboot -p is the name of the product, *not* the full path to
+ ; its directory like adb requests sometimes.
+ (concat (android-find-host-bin "fastboot") " -p " (android-product)))
+
+(defun android-adb-command (command &optional product)
+ "Execute 'adb COMMAND'.
+If the optional PRODUCT is not nil, -p (android-product-path) is used
+when adb is invoked."
+ (if product
+ (shell-command (concat (android-adb) " -p " (android-product-path)
+ " " command))
+ (shell-command (concat (android-adb) " " command))))
+
+(defun android-adb-shell-command (command)
+ "Execute 'adb shell COMMAND'."
+ (android-adb-command (concat " shell " command)))
+
(provide 'android-common)
+
+;;; android-common.el ends here