diff --git a/lisp/tramp-adb.el b/lisp/tramp-adb.el index 1a7a34f..89c10c4 100644 --- a/lisp/tramp-adb.el +++ b/lisp/tramp-adb.el @@ -45,6 +45,13 @@ :version "24.4" :type 'string) +(defcustom tramp-adb-connect-if-not-connected nil + "Try to run adb connect if provided device is not connected currently. +It is used in `tramp-adb-get-host-for-execution'." + :group 'tramp + :version "24.5" + :type 'boolean) + ;;;###tramp-autoload (defconst tramp-adb-method "adb" "*When this method name is used, forward all calls to Android Debug Bridge.") @@ -71,7 +78,8 @@ ;;;###tramp-autoload (add-to-list 'tramp-methods `(,tramp-adb-method - (tramp-tmpdir "/data/local/tmp"))) + (tramp-tmpdir "/data/local/tmp") + (tramp-default-adb-port "5555"))) ;;;###tramp-autoload (add-to-list 'tramp-default-host-alist `(,tramp-adb-method nil "")) @@ -991,11 +999,69 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (tramp-set-connection-property v "process-buffer" nil)))))) ;; Helper functions. +(defun tramp-adb-search-host-in-devices (host devices) + "Return host:port string by searching HOST in DEVICES. +If failed, return nil." + (if (null devices) nil + (if (string-match (concat "^" host) (car devices)) + (car devices) + (tramp-adb-search-host-in-devices host (cdr devices))))) + +(defun tramp-adb-get-host-for-execution (vec) + "Return full host name from VEC to be used in shell exceution. +E.g. a host name \"192.168.1.1#5555\" returns \"192.168.1.1:5555\" + a host name \"R38273882DE\" returns \"R38273882DE\"." + (let* ((port (tramp-file-name-port vec)) + (host (tramp-file-name-real-host vec)) + (method (tramp-file-name-method vec)) + (exe-name (if port + (format "%s:%s" host port) + host)) + (devices (mapcar 'cadr (tramp-adb-parse-device-names nil)))) + ;; Checking whether exe-name is in devices. Follow cases are checked: + ;; - yes, correct exe-name returns. + ;; - not, true device name is: xxxx + ;; user types: xxxx:port-number. Error returns with tips of correct name + ;; - not, true device name is: xxxx:port-number + ;; user types: xxxx. Tramp will auto-complete port-number for user + ;; - not, no device name is similar as user gives. if + ;; tramp-adb-connect-if-not-connected is t, try to connect that device, + ;; else return error + (cond ((member exe-name devices) exe-name) + ((member host devices) (tramp-error + vec 'file-error + "Port number is not needed for device %s" + host)) + ((tramp-adb-search-host-in-devices host devices)) + (tramp-adb-connect-if-not-connected + ;; Try to connect exe-name device. + (if (tramp-adb-execute-adb-command + vec "connect" exe-name) + (tramp-error vec 'file-error "Could not connect %s" exe-name) + ;; If port is not provided, adb will connect to default port + ;; number, which must be appended to return to get a full host + ;; name. + (if port + exe-name + (format "%s:%s" + host + (tramp-get-method-parameter + method 'tramp-default-adb-port))))) + (t (tramp-error + vec + 'file-error + "Could not find device %s" + exe-name))))) (defun tramp-adb-execute-adb-command (vec &rest args) "Returns nil on success error-output on failure." - (when (> (length (tramp-file-name-host vec)) 0) - (setq args (append (list "-s" (tramp-file-name-host vec)) args))) + (let ((host (tramp-file-name-host vec))) + (when (and (> (length host) 0) + ;; The -s switch is only available for ADB device commands. + (not (member + (car args) + (list "connect" "disconnect" "devices")))) + (setq args (append (list "-s" (tramp-adb-get-host-for-execution vec)) args)))) (with-temp-buffer (prog1 (unless @@ -1097,9 +1163,12 @@ connection if a previous connection has died for some reason." (let* ((buf (tramp-get-connection-buffer vec)) (p (get-buffer-process buf)) (host (tramp-file-name-host vec)) + (exe-host (tramp-adb-get-host-for-execution vec)) (user (tramp-file-name-user vec)) - devices) - + ;; Adding the exe-host to devices ensures a new connected exe-host + ;; is in devices. Because tramp-adb-parse-device-names can't + ;; discover new connected device. + (devices (list exe-host))) ;; Maybe we know already that "su" is not supported. We cannot ;; use a connection property, because we have not checked yet ;; whether it is still the same device. @@ -1110,10 +1179,10 @@ connection if a previous connection has died for some reason." (and p (processp p) (memq (process-status p) '(run open))) (save-match-data (when (and p (processp p)) (delete-process p)) - (setq devices (mapcar 'cadr (tramp-adb-parse-device-names nil))) + (append devices (mapcar 'cadr (tramp-adb-parse-device-names nil))) (if (not devices) (tramp-error vec 'file-error "No device connected")) - (if (and (> (length host) 0) (not (member host devices))) + (if (and (> (length host) 0) (not (member exe-host devices))) (tramp-error vec 'file-error "Device %s not connected" host)) (if (and (> (length devices) 1) (zerop (length host))) (tramp-error @@ -1123,7 +1192,7 @@ connection if a previous connection has died for some reason." (let* ((coding-system-for-read 'utf-8-dos) ;is this correct? (process-connection-type tramp-process-connection-type) (args (if (> (length host) 0) - (list "-s" host "shell") + (list "-s" exe-host "shell") (list "shell"))) (p (let ((default-directory (tramp-compat-temporary-file-directory)))