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