├── .classpath ├── .gitignore ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── LICENSE ├── README.md ├── build.gradle ├── doc ├── allclasses-frame.html ├── allclasses-noframe.html ├── com │ └── cgutman │ │ └── adblib │ │ ├── AdbBase64.html │ │ ├── AdbConnection.html │ │ ├── AdbCrypto.html │ │ ├── AdbProtocol.html │ │ ├── AdbStream.html │ │ ├── class-use │ │ ├── AdbBase64.html │ │ ├── AdbConnection.html │ │ ├── AdbCrypto.html │ │ ├── AdbProtocol.html │ │ └── AdbStream.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html ├── constant-values.html ├── deprecated-list.html ├── help-doc.html ├── index-files │ ├── index-1.html │ ├── index-10.html │ ├── index-11.html │ ├── index-12.html │ ├── index-2.html │ ├── index-3.html │ ├── index-4.html │ ├── index-5.html │ ├── index-6.html │ ├── index-7.html │ ├── index-8.html │ └── index-9.html ├── index.html ├── overview-tree.html ├── package-list ├── resources │ ├── background.gif │ ├── tab.gif │ ├── titlebar.gif │ └── titlebar_end.gif └── stylesheet.css └── src └── com └── cgutman └── adblib ├── AdbBase64.java ├── AdbConnection.java ├── AdbCrypto.java ├── AdbProtocol.java ├── AdbStream.java └── package-info.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | .gradle/ 8 | build/ 9 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | AdbLib 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.6 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Cameron Gutman 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AdbLib 2 | ====== 3 | 4 | A Java library implementation of the ADB network protocol 5 | 6 | An example project using this library can be found here: https://github.com/cgutman/AdbLibTest 7 | 8 | An Android demo can be installed from [Google Play](https://play.google.com/store/apps/details?id=com.cgutman.androidremotedebugger). 9 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | sourceSets { 4 | 5 | main { 6 | java.srcDirs = ['src'] 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /doc/allclasses-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes 7 | 8 | 9 | 10 | 11 |

All Classes

12 |
13 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /doc/allclasses-noframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes 7 | 8 | 9 | 10 | 11 |

All Classes

12 |
13 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/AdbBase64.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | AdbBase64 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 78 | 79 | 80 |
81 |
com.cgutman.adblib
82 |

Interface AdbBase64

83 |
84 |
85 |
86 | 97 |
98 |
99 | 125 |
126 |
127 | 152 |
153 |
154 | 155 | 156 |
157 | 158 | 159 | 160 | 161 | 170 |
171 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/class-use/AdbBase64.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Uses of Interface com.cgutman.adblib.AdbBase64 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Uses of Interface
com.cgutman.adblib.AdbBase64

66 |
67 |
68 | 102 |
103 | 104 |
105 | 106 | 107 | 108 | 109 | 118 |
119 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/class-use/AdbConnection.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Uses of Class com.cgutman.adblib.AdbConnection 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Uses of Class
com.cgutman.adblib.AdbConnection

66 |
67 |
68 | 111 |
112 | 113 |
114 | 115 | 116 | 117 | 118 | 127 |
128 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/class-use/AdbCrypto.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Uses of Class com.cgutman.adblib.AdbCrypto 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Uses of Class
com.cgutman.adblib.AdbCrypto

66 |
67 |
68 | 119 |
120 | 121 |
122 | 123 | 124 | 125 | 126 | 135 |
136 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/class-use/AdbProtocol.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Uses of Class com.cgutman.adblib.AdbProtocol 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Uses of Class
com.cgutman.adblib.AdbProtocol

66 |
67 |
No usage of com.cgutman.adblib.AdbProtocol
68 | 69 |
70 | 71 | 72 | 73 | 74 | 83 |
84 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/class-use/AdbStream.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Uses of Class com.cgutman.adblib.AdbStream 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Uses of Class
com.cgutman.adblib.AdbStream

66 |
67 |
68 | 94 |
95 | 96 |
97 | 98 | 99 | 100 | 101 | 110 |
111 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.cgutman.adblib 7 | 8 | 9 | 10 | 11 |

com.cgutman.adblib

12 |
13 |

Interfaces

14 | 17 |

Classes

18 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.cgutman.adblib 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package com.cgutman.adblib

66 |
67 |
This package provides a native Java implementation of the ADB protocol.
68 |
69 |

See: Description

70 |
71 |
72 | 128 | 129 | 130 | 131 |

Package com.cgutman.adblib Description

132 |
This package provides a native Java implementation of the ADB protocol.
133 |
Author:
134 |
Cameron Gutman
135 |
136 | 137 |
138 | 139 | 140 | 141 | 142 | 151 |
152 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.cgutman.adblib Class Hierarchy 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package com.cgutman.adblib

66 |
67 |
68 |

Class Hierarchy

69 | 79 |

Interface Hierarchy

80 | 83 |
84 | 85 |
86 | 87 | 88 | 89 | 90 | 99 |
100 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /doc/com/cgutman/adblib/package-use.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Uses of Package com.cgutman.adblib 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Uses of Package
com.cgutman.adblib

66 |
67 |
68 | 104 |
105 | 106 |
107 | 108 | 109 | 110 | 111 | 120 |
121 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /doc/constant-values.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Constant Field Values 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Constant Field Values

66 |

Contents

67 | 70 |
71 |
72 | 73 | 74 |

com.cgutman.*

75 | 213 |
214 | 215 |
216 | 217 | 218 | 219 | 220 | 229 |
230 | 257 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /doc/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Deprecated List 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Deprecated API

66 |

Contents

67 |
68 | 69 |
70 | 71 | 72 | 73 | 74 | 83 |
84 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /doc/help-doc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | API Help 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

How This API Document Is Organized

66 |
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
67 |
68 |
69 | 168 | This help file applies to API documentation generated using the standard doclet.
169 | 170 |
171 | 172 | 173 | 174 | 175 | 184 |
185 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /doc/index-files/index-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | A-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

A

68 |
69 |
ADB_HEADER_LENGTH - Static variable in class com.cgutman.adblib.AdbProtocol
70 |
71 |
The length of the ADB message header
72 |
73 |
AdbBase64 - Interface in com.cgutman.adblib
74 |
75 |
This interface specifies the required functions for AdbCrypto to 76 | perform Base64 encoding of its public key.
77 |
78 |
AdbConnection - Class in com.cgutman.adblib
79 |
80 |
This class represents an ADB connection.
81 |
82 |
AdbCrypto - Class in com.cgutman.adblib
83 |
84 |
This class encapsulates the ADB cryptography functions and provides 85 | an interface for the storage and retrieval of keys.
86 |
87 |
AdbCrypto() - Constructor for class com.cgutman.adblib.AdbCrypto
88 |
 
89 |
AdbProtocol - Class in com.cgutman.adblib
90 |
91 |
This class provides useful functions and fields for ADB protocol details.
92 |
93 |
AdbProtocol() - Constructor for class com.cgutman.adblib.AdbProtocol
94 |
 
95 |
AdbStream - Class in com.cgutman.adblib
96 |
97 |
This class abstracts the underlying ADB streams
98 |
99 |
AdbStream(AdbConnection, int) - Constructor for class com.cgutman.adblib.AdbStream
100 |
101 |
Creates a new AdbStream object on the specified AdbConnection 102 | with the given local ID.
103 |
104 |
AUTH_TYPE_RSA_PUBLIC - Static variable in class com.cgutman.adblib.AdbProtocol
105 |
106 |
This authentication type represents a RSA public key
107 |
108 |
AUTH_TYPE_SIGNATURE - Static variable in class com.cgutman.adblib.AdbProtocol
109 |
110 |
This authentication type represents the signed SHA1 hash
111 |
112 |
AUTH_TYPE_TOKEN - Static variable in class com.cgutman.adblib.AdbProtocol
113 |
114 |
This authentication type represents a SHA1 hash to sign
115 |
116 |
117 | A C E G I K L O R S V W 
118 | 119 |
120 | 121 | 122 | 123 | 124 | 133 |
134 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /doc/index-files/index-10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | S-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

S

68 |
69 |
saveAdbKeyPair(File, File) - Method in class com.cgutman.adblib.AdbCrypto
70 |
71 |
Saves the AdbCrypto's key pair to the specified files.
72 |
73 |
signAdbTokenPayload(byte[]) - Method in class com.cgutman.adblib.AdbCrypto
74 |
75 |
Signs the ADB SHA1 payload with the private key of this object.
76 |
77 |
SIGNATURE_PADDING - Static variable in class com.cgutman.adblib.AdbCrypto
78 |
79 |
The RSA signature padding as a byte array
80 |
81 |
SIGNATURE_PADDING_AS_INT - Static variable in class com.cgutman.adblib.AdbCrypto
82 |
83 |
The RSA signature padding as an int array
84 |
85 |
86 | A C E G I K L O R S V W 
87 | 88 |
89 | 90 | 91 | 92 | 93 | 102 |
103 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /doc/index-files/index-11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | V-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

V

68 |
69 |
validateMessage(AdbProtocol.AdbMessage) - Static method in class com.cgutman.adblib.AdbProtocol
70 |
71 |
This function validate the ADB message by checking 72 | its command, magic, and payload checksum.
73 |
74 |
75 | A C E G I K L O R S V W 
76 | 77 |
78 | 79 | 80 | 81 | 82 | 91 |
92 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /doc/index-files/index-12.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | W-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

W

68 |
69 |
write(String) - Method in class com.cgutman.adblib.AdbStream
70 |
71 |
Sends a write packet with a given String payload.
72 |
73 |
write(byte[]) - Method in class com.cgutman.adblib.AdbStream
74 |
75 |
Sends a write packet with a given byte array payload.
76 |
77 |
write(byte[], boolean) - Method in class com.cgutman.adblib.AdbStream
78 |
79 |
Queues a write packet and optionally sends it immediately.
80 |
81 |
82 | A C E G I K L O R S V W 
83 | 84 |
85 | 86 | 87 | 88 | 89 | 98 |
99 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /doc/index-files/index-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | C-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

C

68 |
69 |
close() - Method in class com.cgutman.adblib.AdbConnection
70 |
71 |
This routine closes the Adb connection and underlying socket
72 |
73 |
close() - Method in class com.cgutman.adblib.AdbStream
74 |
75 |
Closes the stream.
76 |
77 |
CMD_AUTH - Static variable in class com.cgutman.adblib.AdbProtocol
78 |
79 |
AUTH is the authentication message.
80 |
81 |
CMD_CLSE - Static variable in class com.cgutman.adblib.AdbProtocol
82 |
83 |
CLSE is the close stream message.
84 |
85 |
CMD_CNXN - Static variable in class com.cgutman.adblib.AdbProtocol
86 |
87 |
CNXN is the connect message.
88 |
89 |
CMD_OKAY - Static variable in class com.cgutman.adblib.AdbProtocol
90 |
91 |
OKAY is a success message.
92 |
93 |
CMD_OPEN - Static variable in class com.cgutman.adblib.AdbProtocol
94 |
95 |
OPEN is the open stream message.
96 |
97 |
CMD_SYNC - Static variable in class com.cgutman.adblib.AdbProtocol
98 |
 
99 |
CMD_WRTE - Static variable in class com.cgutman.adblib.AdbProtocol
100 |
101 |
WRTE is the write stream message.
102 |
103 |
com.cgutman.adblib - package com.cgutman.adblib
104 |
105 |
This package provides a native Java implementation of the ADB protocol.
106 |
107 |
connect() - Method in class com.cgutman.adblib.AdbConnection
108 |
109 |
Connects to the remote device.
110 |
111 |
CONNECT_MAXDATA - Static variable in class com.cgutman.adblib.AdbProtocol
112 |
113 |
The maximum data payload supported by the ADB implementation
114 |
115 |
CONNECT_PAYLOAD - Static variable in class com.cgutman.adblib.AdbProtocol
116 |
117 |
The payload sent with the connect message
118 |
119 |
CONNECT_VERSION - Static variable in class com.cgutman.adblib.AdbProtocol
120 |
121 |
The current version of the ADB protocol
122 |
123 |
create(Socket, AdbCrypto) - Static method in class com.cgutman.adblib.AdbConnection
124 |
125 |
Creates a AdbConnection object associated with the socket and 126 | crypto object specified.
127 |
128 |
129 | A C E G I K L O R S V W 
130 | 131 |
132 | 133 | 134 | 135 | 136 | 145 |
146 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /doc/index-files/index-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | E-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

E

68 |
69 |
encodeToString(byte[]) - Method in interface com.cgutman.adblib.AdbBase64
70 |
71 |
This function must encoded the specified data as a base 64 string, without 72 | appending any extra newlines or other characters.
73 |
74 |
75 | A C E G I K L O R S V W 
76 | 77 |
78 | 79 | 80 | 81 | 82 | 91 |
92 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /doc/index-files/index-4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | G-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

G

68 |
69 |
generateAdbKeyPair(AdbBase64) - Static method in class com.cgutman.adblib.AdbCrypto
70 |
71 |
Creates a new AdbCrypto object by generating a new key pair.
72 |
73 |
generateAuth(int, byte[]) - Static method in class com.cgutman.adblib.AdbProtocol
74 |
75 |
Generates an auth message with the specified type and payload.
76 |
77 |
generateClose(int, int) - Static method in class com.cgutman.adblib.AdbProtocol
78 |
79 |
Generates a close stream message with the specified IDs.
80 |
81 |
generateConnect() - Static method in class com.cgutman.adblib.AdbProtocol
82 |
83 |
Generates a connect message with default parameters.
84 |
85 |
generateMessage(int, int, int, byte[]) - Static method in class com.cgutman.adblib.AdbProtocol
86 |
87 |
This function generates an ADB message given the fields.
88 |
89 |
generateOpen(int, String) - Static method in class com.cgutman.adblib.AdbProtocol
90 |
91 |
Generates an open stream message with the specified local ID and destination.
92 |
93 |
generateReady(int, int) - Static method in class com.cgutman.adblib.AdbProtocol
94 |
95 |
Generates an okay message with the specified IDs.
96 |
97 |
generateWrite(int, int, byte[]) - Static method in class com.cgutman.adblib.AdbProtocol
98 |
99 |
Generates a write stream message with the specified IDs and payload.
100 |
101 |
getAdbPublicKeyPayload() - Method in class com.cgutman.adblib.AdbCrypto
102 |
103 |
Gets the RSA public key in ADB format.
104 |
105 |
getMaxData() - Method in class com.cgutman.adblib.AdbConnection
106 |
107 |
Gets the max data size that the remote client supports.
108 |
109 |
110 | A C E G I K L O R S V W 
111 | 112 |
113 | 114 | 115 | 116 | 117 | 126 |
127 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /doc/index-files/index-5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | I-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

I

68 |
69 |
isClosed() - Method in class com.cgutman.adblib.AdbStream
70 |
71 |
Retreives whether the stream is closed or not
72 |
73 |
74 | A C E G I K L O R S V W 
75 | 76 |
77 | 78 | 79 | 80 | 81 | 90 |
91 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /doc/index-files/index-6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | K-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

K

68 |
69 |
KEY_LENGTH_BITS - Static variable in class com.cgutman.adblib.AdbCrypto
70 |
71 |
The ADB RSA key length in bits
72 |
73 |
KEY_LENGTH_BYTES - Static variable in class com.cgutman.adblib.AdbCrypto
74 |
75 |
The ADB RSA key length in bytes
76 |
77 |
KEY_LENGTH_WORDS - Static variable in class com.cgutman.adblib.AdbCrypto
78 |
79 |
The ADB RSA key length in words
80 |
81 |
82 | A C E G I K L O R S V W 
83 | 84 |
85 | 86 | 87 | 88 | 89 | 98 |
99 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /doc/index-files/index-7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | L-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

L

68 |
69 |
loadAdbKeyPair(AdbBase64, File, File) - Static method in class com.cgutman.adblib.AdbCrypto
70 |
71 |
Creates a new AdbCrypto object from a key pair loaded from files.
72 |
73 |
74 | A C E G I K L O R S V W 
75 | 76 |
77 | 78 | 79 | 80 | 81 | 90 |
91 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /doc/index-files/index-8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | O-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

O

68 |
69 |
open(String) - Method in class com.cgutman.adblib.AdbConnection
70 |
71 |
Opens an AdbStream object corresponding to the specified destination.
72 |
73 |
74 | A C E G I K L O R S V W 
75 | 76 |
77 | 78 | 79 | 80 | 81 | 90 |
91 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /doc/index-files/index-9.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | R-Index 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
A C E G I K L O R S V W  65 | 66 | 67 |

R

68 |
69 |
read() - Method in class com.cgutman.adblib.AdbStream
70 |
71 |
Reads a pending write payload from the other side.
72 |
73 |
74 | A C E G I K L O R S V W 
75 | 76 |
77 | 78 | 79 | 80 | 81 | 90 |
91 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generated Documentation (Untitled) 7 | 52 | 53 | 54 | 55 | 56 | 57 | <noscript> 58 | <div>JavaScript is disabled on your browser.</div> 59 | </noscript> 60 | <h2>Frame Alert</h2> 61 | <p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="com/cgutman/adblib/package-summary.html">Non-frame version</a>.</p> 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /doc/overview-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Class Hierarchy 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For All Packages

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 83 |

Interface Hierarchy

84 | 87 |
88 | 89 |
90 | 91 | 92 | 93 | 94 | 103 |
104 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /doc/package-list: -------------------------------------------------------------------------------- 1 | com.cgutman.adblib 2 | -------------------------------------------------------------------------------- /doc/resources/background.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cgutman/AdbLib/d6937951eb98557c76ee2081e383d50886ce109a/doc/resources/background.gif -------------------------------------------------------------------------------- /doc/resources/tab.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cgutman/AdbLib/d6937951eb98557c76ee2081e383d50886ce109a/doc/resources/tab.gif -------------------------------------------------------------------------------- /doc/resources/titlebar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cgutman/AdbLib/d6937951eb98557c76ee2081e383d50886ce109a/doc/resources/titlebar.gif -------------------------------------------------------------------------------- /doc/resources/titlebar_end.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cgutman/AdbLib/d6937951eb98557c76ee2081e383d50886ce109a/doc/resources/titlebar_end.gif -------------------------------------------------------------------------------- /doc/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* Javadoc style sheet */ 2 | /* 3 | Overall document style 4 | */ 5 | body { 6 | background-color:#ffffff; 7 | color:#353833; 8 | font-family:Arial, Helvetica, sans-serif; 9 | font-size:76%; 10 | margin:0; 11 | } 12 | a:link, a:visited { 13 | text-decoration:none; 14 | color:#4c6b87; 15 | } 16 | a:hover, a:focus { 17 | text-decoration:none; 18 | color:#bb7a2a; 19 | } 20 | a:active { 21 | text-decoration:none; 22 | color:#4c6b87; 23 | } 24 | a[name] { 25 | color:#353833; 26 | } 27 | a[name]:hover { 28 | text-decoration:none; 29 | color:#353833; 30 | } 31 | pre { 32 | font-size:1.3em; 33 | } 34 | h1 { 35 | font-size:1.8em; 36 | } 37 | h2 { 38 | font-size:1.5em; 39 | } 40 | h3 { 41 | font-size:1.4em; 42 | } 43 | h4 { 44 | font-size:1.3em; 45 | } 46 | h5 { 47 | font-size:1.2em; 48 | } 49 | h6 { 50 | font-size:1.1em; 51 | } 52 | ul { 53 | list-style-type:disc; 54 | } 55 | code, tt { 56 | font-size:1.2em; 57 | } 58 | dt code { 59 | font-size:1.2em; 60 | } 61 | table tr td dt code { 62 | font-size:1.2em; 63 | vertical-align:top; 64 | } 65 | sup { 66 | font-size:.6em; 67 | } 68 | /* 69 | Document title and Copyright styles 70 | */ 71 | .clear { 72 | clear:both; 73 | height:0px; 74 | overflow:hidden; 75 | } 76 | .aboutLanguage { 77 | float:right; 78 | padding:0px 21px; 79 | font-size:.8em; 80 | z-index:200; 81 | margin-top:-7px; 82 | } 83 | .legalCopy { 84 | margin-left:.5em; 85 | } 86 | .bar a, .bar a:link, .bar a:visited, .bar a:active { 87 | color:#FFFFFF; 88 | text-decoration:none; 89 | } 90 | .bar a:hover, .bar a:focus { 91 | color:#bb7a2a; 92 | } 93 | .tab { 94 | background-color:#0066FF; 95 | background-image:url(resources/titlebar.gif); 96 | background-position:left top; 97 | background-repeat:no-repeat; 98 | color:#ffffff; 99 | padding:8px; 100 | width:5em; 101 | font-weight:bold; 102 | } 103 | /* 104 | Navigation bar styles 105 | */ 106 | .bar { 107 | background-image:url(resources/background.gif); 108 | background-repeat:repeat-x; 109 | color:#FFFFFF; 110 | padding:.8em .5em .4em .8em; 111 | height:auto;/*height:1.8em;*/ 112 | font-size:1em; 113 | margin:0; 114 | } 115 | .topNav { 116 | background-image:url(resources/background.gif); 117 | background-repeat:repeat-x; 118 | color:#FFFFFF; 119 | float:left; 120 | padding:0; 121 | width:100%; 122 | clear:right; 123 | height:2.8em; 124 | padding-top:10px; 125 | overflow:hidden; 126 | } 127 | .bottomNav { 128 | margin-top:10px; 129 | background-image:url(resources/background.gif); 130 | background-repeat:repeat-x; 131 | color:#FFFFFF; 132 | float:left; 133 | padding:0; 134 | width:100%; 135 | clear:right; 136 | height:2.8em; 137 | padding-top:10px; 138 | overflow:hidden; 139 | } 140 | .subNav { 141 | background-color:#dee3e9; 142 | border-bottom:1px solid #9eadc0; 143 | float:left; 144 | width:100%; 145 | overflow:hidden; 146 | } 147 | .subNav div { 148 | clear:left; 149 | float:left; 150 | padding:0 0 5px 6px; 151 | } 152 | ul.navList, ul.subNavList { 153 | float:left; 154 | margin:0 25px 0 0; 155 | padding:0; 156 | } 157 | ul.navList li{ 158 | list-style:none; 159 | float:left; 160 | padding:3px 6px; 161 | } 162 | ul.subNavList li{ 163 | list-style:none; 164 | float:left; 165 | font-size:90%; 166 | } 167 | .topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { 168 | color:#FFFFFF; 169 | text-decoration:none; 170 | } 171 | .topNav a:hover, .bottomNav a:hover { 172 | text-decoration:none; 173 | color:#bb7a2a; 174 | } 175 | .navBarCell1Rev { 176 | background-image:url(resources/tab.gif); 177 | background-color:#a88834; 178 | color:#FFFFFF; 179 | margin: auto 5px; 180 | border:1px solid #c9aa44; 181 | } 182 | /* 183 | Page header and footer styles 184 | */ 185 | .header, .footer { 186 | clear:both; 187 | margin:0 20px; 188 | padding:5px 0 0 0; 189 | } 190 | .indexHeader { 191 | margin:10px; 192 | position:relative; 193 | } 194 | .indexHeader h1 { 195 | font-size:1.3em; 196 | } 197 | .title { 198 | color:#2c4557; 199 | margin:10px 0; 200 | } 201 | .subTitle { 202 | margin:5px 0 0 0; 203 | } 204 | .header ul { 205 | margin:0 0 25px 0; 206 | padding:0; 207 | } 208 | .footer ul { 209 | margin:20px 0 5px 0; 210 | } 211 | .header ul li, .footer ul li { 212 | list-style:none; 213 | font-size:1.2em; 214 | } 215 | /* 216 | Heading styles 217 | */ 218 | div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { 219 | background-color:#dee3e9; 220 | border-top:1px solid #9eadc0; 221 | border-bottom:1px solid #9eadc0; 222 | margin:0 0 6px -8px; 223 | padding:2px 5px; 224 | } 225 | ul.blockList ul.blockList ul.blockList li.blockList h3 { 226 | background-color:#dee3e9; 227 | border-top:1px solid #9eadc0; 228 | border-bottom:1px solid #9eadc0; 229 | margin:0 0 6px -8px; 230 | padding:2px 5px; 231 | } 232 | ul.blockList ul.blockList li.blockList h3 { 233 | padding:0; 234 | margin:15px 0; 235 | } 236 | ul.blockList li.blockList h2 { 237 | padding:0px 0 20px 0; 238 | } 239 | /* 240 | Page layout container styles 241 | */ 242 | .contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { 243 | clear:both; 244 | padding:10px 20px; 245 | position:relative; 246 | } 247 | .indexContainer { 248 | margin:10px; 249 | position:relative; 250 | font-size:1.0em; 251 | } 252 | .indexContainer h2 { 253 | font-size:1.1em; 254 | padding:0 0 3px 0; 255 | } 256 | .indexContainer ul { 257 | margin:0; 258 | padding:0; 259 | } 260 | .indexContainer ul li { 261 | list-style:none; 262 | } 263 | .contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { 264 | font-size:1.1em; 265 | font-weight:bold; 266 | margin:10px 0 0 0; 267 | color:#4E4E4E; 268 | } 269 | .contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { 270 | margin:10px 0 10px 20px; 271 | } 272 | .serializedFormContainer dl.nameValue dt { 273 | margin-left:1px; 274 | font-size:1.1em; 275 | display:inline; 276 | font-weight:bold; 277 | } 278 | .serializedFormContainer dl.nameValue dd { 279 | margin:0 0 0 1px; 280 | font-size:1.1em; 281 | display:inline; 282 | } 283 | /* 284 | List styles 285 | */ 286 | ul.horizontal li { 287 | display:inline; 288 | font-size:0.9em; 289 | } 290 | ul.inheritance { 291 | margin:0; 292 | padding:0; 293 | } 294 | ul.inheritance li { 295 | display:inline; 296 | list-style:none; 297 | } 298 | ul.inheritance li ul.inheritance { 299 | margin-left:15px; 300 | padding-left:15px; 301 | padding-top:1px; 302 | } 303 | ul.blockList, ul.blockListLast { 304 | margin:10px 0 10px 0; 305 | padding:0; 306 | } 307 | ul.blockList li.blockList, ul.blockListLast li.blockList { 308 | list-style:none; 309 | margin-bottom:25px; 310 | } 311 | ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { 312 | padding:0px 20px 5px 10px; 313 | border:1px solid #9eadc0; 314 | background-color:#f9f9f9; 315 | } 316 | ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { 317 | padding:0 0 5px 8px; 318 | background-color:#ffffff; 319 | border:1px solid #9eadc0; 320 | border-top:none; 321 | } 322 | ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { 323 | margin-left:0; 324 | padding-left:0; 325 | padding-bottom:15px; 326 | border:none; 327 | border-bottom:1px solid #9eadc0; 328 | } 329 | ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { 330 | list-style:none; 331 | border-bottom:none; 332 | padding-bottom:0; 333 | } 334 | table tr td dl, table tr td dl dt, table tr td dl dd { 335 | margin-top:0; 336 | margin-bottom:1px; 337 | } 338 | /* 339 | Table styles 340 | */ 341 | .contentContainer table, .classUseContainer table, .constantValuesContainer table { 342 | border-bottom:1px solid #9eadc0; 343 | width:100%; 344 | } 345 | .contentContainer ul li table, .classUseContainer ul li table, .constantValuesContainer ul li table { 346 | width:100%; 347 | } 348 | .contentContainer .description table, .contentContainer .details table { 349 | border-bottom:none; 350 | } 351 | .contentContainer ul li table th.colOne, .contentContainer ul li table th.colFirst, .contentContainer ul li table th.colLast, .classUseContainer ul li table th, .constantValuesContainer ul li table th, .contentContainer ul li table td.colOne, .contentContainer ul li table td.colFirst, .contentContainer ul li table td.colLast, .classUseContainer ul li table td, .constantValuesContainer ul li table td{ 352 | vertical-align:top; 353 | padding-right:20px; 354 | } 355 | .contentContainer ul li table th.colLast, .classUseContainer ul li table th.colLast,.constantValuesContainer ul li table th.colLast, 356 | .contentContainer ul li table td.colLast, .classUseContainer ul li table td.colLast,.constantValuesContainer ul li table td.colLast, 357 | .contentContainer ul li table th.colOne, .classUseContainer ul li table th.colOne, 358 | .contentContainer ul li table td.colOne, .classUseContainer ul li table td.colOne { 359 | padding-right:3px; 360 | } 361 | .overviewSummary caption, .packageSummary caption, .contentContainer ul.blockList li.blockList caption, .summary caption, .classUseContainer caption, .constantValuesContainer caption { 362 | position:relative; 363 | text-align:left; 364 | background-repeat:no-repeat; 365 | color:#FFFFFF; 366 | font-weight:bold; 367 | clear:none; 368 | overflow:hidden; 369 | padding:0px; 370 | margin:0px; 371 | } 372 | caption a:link, caption a:hover, caption a:active, caption a:visited { 373 | color:#FFFFFF; 374 | } 375 | .overviewSummary caption span, .packageSummary caption span, .contentContainer ul.blockList li.blockList caption span, .summary caption span, .classUseContainer caption span, .constantValuesContainer caption span { 376 | white-space:nowrap; 377 | padding-top:8px; 378 | padding-left:8px; 379 | display:block; 380 | float:left; 381 | background-image:url(resources/titlebar.gif); 382 | height:18px; 383 | } 384 | .overviewSummary .tabEnd, .packageSummary .tabEnd, .contentContainer ul.blockList li.blockList .tabEnd, .summary .tabEnd, .classUseContainer .tabEnd, .constantValuesContainer .tabEnd { 385 | width:10px; 386 | background-image:url(resources/titlebar_end.gif); 387 | background-repeat:no-repeat; 388 | background-position:top right; 389 | position:relative; 390 | float:left; 391 | } 392 | ul.blockList ul.blockList li.blockList table { 393 | margin:0 0 12px 0px; 394 | width:100%; 395 | } 396 | .tableSubHeadingColor { 397 | background-color: #EEEEFF; 398 | } 399 | .altColor { 400 | background-color:#eeeeef; 401 | } 402 | .rowColor { 403 | background-color:#ffffff; 404 | } 405 | .overviewSummary td, .packageSummary td, .contentContainer ul.blockList li.blockList td, .summary td, .classUseContainer td, .constantValuesContainer td { 406 | text-align:left; 407 | padding:3px 3px 3px 7px; 408 | } 409 | th.colFirst, th.colLast, th.colOne, .constantValuesContainer th { 410 | background:#dee3e9; 411 | border-top:1px solid #9eadc0; 412 | border-bottom:1px solid #9eadc0; 413 | text-align:left; 414 | padding:3px 3px 3px 7px; 415 | } 416 | td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { 417 | font-weight:bold; 418 | } 419 | td.colFirst, th.colFirst { 420 | border-left:1px solid #9eadc0; 421 | white-space:nowrap; 422 | } 423 | td.colLast, th.colLast { 424 | border-right:1px solid #9eadc0; 425 | } 426 | td.colOne, th.colOne { 427 | border-right:1px solid #9eadc0; 428 | border-left:1px solid #9eadc0; 429 | } 430 | table.overviewSummary { 431 | padding:0px; 432 | margin-left:0px; 433 | } 434 | table.overviewSummary td.colFirst, table.overviewSummary th.colFirst, 435 | table.overviewSummary td.colOne, table.overviewSummary th.colOne { 436 | width:25%; 437 | vertical-align:middle; 438 | } 439 | table.packageSummary td.colFirst, table.overviewSummary th.colFirst { 440 | width:25%; 441 | vertical-align:middle; 442 | } 443 | /* 444 | Content styles 445 | */ 446 | .description pre { 447 | margin-top:0; 448 | } 449 | .deprecatedContent { 450 | margin:0; 451 | padding:10px 0; 452 | } 453 | .docSummary { 454 | padding:0; 455 | } 456 | /* 457 | Formatting effect styles 458 | */ 459 | .sourceLineNo { 460 | color:green; 461 | padding:0 30px 0 0; 462 | } 463 | h1.hidden { 464 | visibility:hidden; 465 | overflow:hidden; 466 | font-size:.9em; 467 | } 468 | .block { 469 | display:block; 470 | margin:3px 0 0 0; 471 | } 472 | .strong { 473 | font-weight:bold; 474 | } 475 | -------------------------------------------------------------------------------- /src/com/cgutman/adblib/AdbBase64.java: -------------------------------------------------------------------------------- 1 | package com.cgutman.adblib; 2 | 3 | /** 4 | * This interface specifies the required functions for AdbCrypto to 5 | * perform Base64 encoding of its public key. 6 | * @author Cameron Gutman 7 | */ 8 | public interface AdbBase64 { 9 | /** 10 | * This function must encoded the specified data as a base 64 string, without 11 | * appending any extra newlines or other characters. 12 | * @param data Data to encode 13 | * @return String containing base 64 encoded data 14 | */ 15 | public String encodeToString(byte[] data); 16 | } 17 | -------------------------------------------------------------------------------- /src/com/cgutman/adblib/AdbConnection.java: -------------------------------------------------------------------------------- 1 | package com.cgutman.adblib; 2 | 3 | 4 | import java.io.Closeable; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | import java.io.UnsupportedEncodingException; 9 | import java.net.ConnectException; 10 | import java.net.Socket; 11 | import java.util.HashMap; 12 | 13 | /** 14 | * This class represents an ADB connection. 15 | * @author Cameron Gutman 16 | */ 17 | public class AdbConnection implements Closeable { 18 | 19 | /** The underlying socket that this class uses to 20 | * communicate with the target device. 21 | */ 22 | private Socket socket; 23 | 24 | /** The last allocated local stream ID. The ID 25 | * chosen for the next stream will be this value + 1. 26 | */ 27 | private int lastLocalId; 28 | 29 | /** 30 | * The input stream that this class uses to read from 31 | * the socket. 32 | */ 33 | private InputStream inputStream; 34 | 35 | /** 36 | * The output stream that this class uses to read from 37 | * the socket. 38 | */ 39 | OutputStream outputStream; 40 | 41 | /** 42 | * The backend thread that handles responding to ADB packets. 43 | */ 44 | private Thread connectionThread; 45 | 46 | /** 47 | * Specifies whether a connect has been attempted 48 | */ 49 | private boolean connectAttempted; 50 | 51 | /** 52 | * Specifies whether a CNXN packet has been received from the peer. 53 | */ 54 | private boolean connected; 55 | 56 | /** 57 | * Specifies the maximum amount data that can be sent to the remote peer. 58 | * This is only valid after connect() returns successfully. 59 | */ 60 | private int maxData; 61 | 62 | /** 63 | * An initialized ADB crypto object that contains a key pair. 64 | */ 65 | private AdbCrypto crypto; 66 | 67 | /** 68 | * Specifies whether this connection has already sent a signed token. 69 | */ 70 | private boolean sentSignature; 71 | 72 | /** 73 | * A hash map of our open streams indexed by local ID. 74 | **/ 75 | private HashMap openStreams; 76 | 77 | /** 78 | * Internal constructor to initialize some internal state 79 | */ 80 | private AdbConnection() 81 | { 82 | openStreams = new HashMap(); 83 | lastLocalId = 0; 84 | connectionThread = createConnectionThread(); 85 | } 86 | 87 | /** 88 | * Creates a AdbConnection object associated with the socket and 89 | * crypto object specified. 90 | * @param socket The socket that the connection will use for communcation. 91 | * @param crypto The crypto object that stores the key pair for authentication. 92 | * @return A new AdbConnection object. 93 | * @throws IOException If there is a socket error 94 | */ 95 | public static AdbConnection create(Socket socket, AdbCrypto crypto) throws IOException 96 | { 97 | AdbConnection newConn = new AdbConnection(); 98 | 99 | newConn.crypto = crypto; 100 | 101 | newConn.socket = socket; 102 | newConn.inputStream = socket.getInputStream(); 103 | newConn.outputStream = socket.getOutputStream(); 104 | 105 | /* Disable Nagle because we're sending tiny packets */ 106 | socket.setTcpNoDelay(true); 107 | 108 | return newConn; 109 | } 110 | 111 | /** 112 | * Creates a new connection thread. 113 | * @return A new connection thread. 114 | */ 115 | private Thread createConnectionThread() 116 | { 117 | @SuppressWarnings("resource") 118 | final AdbConnection conn = this; 119 | return new Thread(new Runnable() { 120 | @Override 121 | public void run() { 122 | while (!connectionThread.isInterrupted()) 123 | { 124 | try { 125 | /* Read and parse a message off the socket's input stream */ 126 | AdbProtocol.AdbMessage msg = AdbProtocol.AdbMessage.parseAdbMessage(inputStream); 127 | 128 | /* Verify magic and checksum */ 129 | if (!AdbProtocol.validateMessage(msg)) 130 | continue; 131 | 132 | switch (msg.command) 133 | { 134 | /* Stream-oriented commands */ 135 | case AdbProtocol.CMD_OKAY: 136 | case AdbProtocol.CMD_WRTE: 137 | case AdbProtocol.CMD_CLSE: 138 | /* We must ignore all packets when not connected */ 139 | if (!conn.connected) 140 | continue; 141 | 142 | /* Get the stream object corresponding to the packet */ 143 | AdbStream waitingStream = openStreams.get(msg.arg1); 144 | if (waitingStream == null) 145 | continue; 146 | 147 | synchronized (waitingStream) { 148 | if (msg.command == AdbProtocol.CMD_OKAY) 149 | { 150 | /* We're ready for writes */ 151 | waitingStream.updateRemoteId(msg.arg0); 152 | waitingStream.readyForWrite(); 153 | 154 | /* Unwait an open/write */ 155 | waitingStream.notify(); 156 | } 157 | else if (msg.command == AdbProtocol.CMD_WRTE) 158 | { 159 | /* Got some data from our partner */ 160 | waitingStream.addPayload(msg.payload); 161 | 162 | /* Tell it we're ready for more */ 163 | waitingStream.sendReady(); 164 | } 165 | else if (msg.command == AdbProtocol.CMD_CLSE) 166 | { 167 | /* He doesn't like us anymore :-( */ 168 | conn.openStreams.remove(msg.arg1); 169 | 170 | /* Notify readers and writers */ 171 | waitingStream.notifyClose(); 172 | } 173 | } 174 | 175 | break; 176 | 177 | case AdbProtocol.CMD_AUTH: 178 | 179 | byte[] packet; 180 | 181 | if (msg.arg0 == AdbProtocol.AUTH_TYPE_TOKEN) 182 | { 183 | /* This is an authentication challenge */ 184 | if (conn.sentSignature) 185 | { 186 | /* We've already tried our signature, so send our public key */ 187 | packet = AdbProtocol.generateAuth(AdbProtocol.AUTH_TYPE_RSA_PUBLIC, 188 | conn.crypto.getAdbPublicKeyPayload()); 189 | } 190 | else 191 | { 192 | /* We'll sign the token */ 193 | packet = AdbProtocol.generateAuth(AdbProtocol.AUTH_TYPE_SIGNATURE, 194 | conn.crypto.signAdbTokenPayload(msg.payload)); 195 | conn.sentSignature = true; 196 | } 197 | 198 | /* Write the AUTH reply */ 199 | conn.outputStream.write(packet); 200 | conn.outputStream.flush(); 201 | } 202 | break; 203 | 204 | case AdbProtocol.CMD_CNXN: 205 | synchronized (conn) { 206 | /* We need to store the max data size */ 207 | conn.maxData = msg.arg1; 208 | 209 | /* Mark us as connected and unwait anyone waiting on the connection */ 210 | conn.connected = true; 211 | conn.notifyAll(); 212 | } 213 | break; 214 | 215 | default: 216 | /* Unrecognized packet, just drop it */ 217 | break; 218 | } 219 | } catch (Exception e) { 220 | /* The cleanup is taken care of by a combination of this thread 221 | * and close() */ 222 | break; 223 | } 224 | } 225 | 226 | /* This thread takes care of cleaning up pending streams */ 227 | synchronized (conn) { 228 | cleanupStreams(); 229 | conn.notifyAll(); 230 | conn.connectAttempted = false; 231 | } 232 | } 233 | }); 234 | } 235 | 236 | /** 237 | * Gets the max data size that the remote client supports. 238 | * A connection must have been attempted before calling this routine. 239 | * This routine will block if a connection is in progress. 240 | * @return The maximum data size indicated in the connect packet. 241 | * @throws InterruptedException If a connection cannot be waited on. 242 | * @throws IOException if the connection fails 243 | */ 244 | public int getMaxData() throws InterruptedException, IOException 245 | { 246 | if (!connectAttempted) 247 | throw new IllegalStateException("connect() must be called first"); 248 | 249 | synchronized (this) { 250 | /* Block if a connection is pending, but not yet complete */ 251 | if (!connected) 252 | wait(); 253 | 254 | if (!connected) { 255 | throw new IOException("Connection failed"); 256 | } 257 | } 258 | 259 | return maxData; 260 | } 261 | 262 | /** 263 | * Connects to the remote device. This routine will block until the connection 264 | * completes. 265 | * @throws IOException If the socket fails while connecting 266 | * @throws InterruptedException If we are unable to wait for the connection to finish 267 | */ 268 | public void connect() throws IOException, InterruptedException 269 | { 270 | if (connected) 271 | throw new IllegalStateException("Already connected"); 272 | 273 | /* Write the CONNECT packet */ 274 | outputStream.write(AdbProtocol.generateConnect()); 275 | outputStream.flush(); 276 | 277 | /* Start the connection thread to respond to the peer */ 278 | connectAttempted = true; 279 | connectionThread.start(); 280 | 281 | /* Wait for the connection to go live */ 282 | synchronized (this) { 283 | if (!connected) 284 | wait(); 285 | 286 | if (!connected) { 287 | throw new IOException("Connection failed"); 288 | } 289 | } 290 | } 291 | 292 | /** 293 | * Opens an AdbStream object corresponding to the specified destination. 294 | * This routine will block until the connection completes. 295 | * @param destination The destination to open on the target 296 | * @return AdbStream object corresponding to the specified destination 297 | * @throws UnsupportedEncodingException If the destination cannot be encoded to UTF-8 298 | * @throws IOException If the stream fails while sending the packet 299 | * @throws InterruptedException If we are unable to wait for the connection to finish 300 | */ 301 | public AdbStream open(String destination) throws UnsupportedEncodingException, IOException, InterruptedException 302 | { 303 | int localId = ++lastLocalId; 304 | 305 | if (!connectAttempted) 306 | throw new IllegalStateException("connect() must be called first"); 307 | 308 | /* Wait for the connect response */ 309 | synchronized (this) { 310 | if (!connected) 311 | wait(); 312 | 313 | if (!connected) { 314 | throw new IOException("Connection failed"); 315 | } 316 | } 317 | 318 | /* Add this stream to this list of half-open streams */ 319 | AdbStream stream = new AdbStream(this, localId); 320 | openStreams.put(localId, stream); 321 | 322 | /* Send the open */ 323 | outputStream.write(AdbProtocol.generateOpen(localId, destination)); 324 | outputStream.flush(); 325 | 326 | /* Wait for the connection thread to receive the OKAY */ 327 | synchronized (stream) { 328 | stream.wait(); 329 | } 330 | 331 | /* Check if the open was rejected */ 332 | if (stream.isClosed()) 333 | throw new ConnectException("Stream open actively rejected by remote peer"); 334 | 335 | /* We're fully setup now */ 336 | return stream; 337 | } 338 | 339 | /** 340 | * This function terminates all I/O on streams associated with this ADB connection 341 | */ 342 | private void cleanupStreams() { 343 | /* Close all streams on this connection */ 344 | for (AdbStream s : openStreams.values()) { 345 | /* We handle exceptions for each close() call to avoid 346 | * terminating cleanup for one failed close(). */ 347 | try { 348 | s.close(); 349 | } catch (IOException e) {} 350 | } 351 | 352 | /* No open streams anymore */ 353 | openStreams.clear(); 354 | } 355 | 356 | /** This routine closes the Adb connection and underlying socket 357 | * @throws IOException if the socket fails to close 358 | */ 359 | @Override 360 | public void close() throws IOException { 361 | /* If the connection thread hasn't spawned yet, there's nothing to do */ 362 | if (connectionThread == null) 363 | return; 364 | 365 | /* Closing the socket will kick the connection thread */ 366 | socket.close(); 367 | 368 | /* Wait for the connection thread to die */ 369 | connectionThread.interrupt(); 370 | try { 371 | connectionThread.join(); 372 | } catch (InterruptedException e) { } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /src/com/cgutman/adblib/AdbCrypto.java: -------------------------------------------------------------------------------- 1 | package com.cgutman.adblib; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.math.BigInteger; 8 | import java.nio.ByteBuffer; 9 | import java.nio.ByteOrder; 10 | import java.security.GeneralSecurityException; 11 | import java.security.KeyFactory; 12 | import java.security.KeyPair; 13 | import java.security.KeyPairGenerator; 14 | import java.security.NoSuchAlgorithmException; 15 | import java.security.interfaces.RSAPublicKey; 16 | import java.security.spec.EncodedKeySpec; 17 | import java.security.spec.InvalidKeySpecException; 18 | import java.security.spec.PKCS8EncodedKeySpec; 19 | import java.security.spec.X509EncodedKeySpec; 20 | import javax.crypto.Cipher; 21 | 22 | /** 23 | * This class encapsulates the ADB cryptography functions and provides 24 | * an interface for the storage and retrieval of keys. 25 | * @author Cameron Gutman 26 | */ 27 | public class AdbCrypto { 28 | 29 | /** An RSA keypair encapsulated by the AdbCrypto object */ 30 | private KeyPair keyPair; 31 | 32 | /** The base 64 conversion interface to use */ 33 | private AdbBase64 base64; 34 | 35 | /** The ADB RSA key length in bits */ 36 | public static final int KEY_LENGTH_BITS = 2048; 37 | 38 | /** The ADB RSA key length in bytes */ 39 | public static final int KEY_LENGTH_BYTES = KEY_LENGTH_BITS / 8; 40 | 41 | /** The ADB RSA key length in words */ 42 | public static final int KEY_LENGTH_WORDS = KEY_LENGTH_BYTES / 4; 43 | 44 | /** The RSA signature padding as an int array */ 45 | public static final int[] SIGNATURE_PADDING_AS_INT = new int[] 46 | { 47 | 0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 48 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 49 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 50 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 51 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 52 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 53 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 54 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 55 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 56 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 57 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 58 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 59 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 60 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 61 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 62 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 63 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 64 | 0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00, 65 | 0x04,0x14 66 | }; 67 | 68 | /** The RSA signature padding as a byte array */ 69 | public static byte[] SIGNATURE_PADDING; 70 | 71 | static { 72 | SIGNATURE_PADDING = new byte[SIGNATURE_PADDING_AS_INT.length]; 73 | 74 | for (int i = 0; i < SIGNATURE_PADDING.length; i++) 75 | SIGNATURE_PADDING[i] = (byte)SIGNATURE_PADDING_AS_INT[i]; 76 | } 77 | 78 | /** 79 | * Converts a standard RSAPublicKey object to the special ADB format 80 | * @param pubkey RSAPublicKey object to convert 81 | * @return Byte array containing the converted RSAPublicKey object 82 | */ 83 | private static byte[] convertRsaPublicKeyToAdbFormat(RSAPublicKey pubkey) 84 | { 85 | /* 86 | * ADB literally just saves the RSAPublicKey struct to a file. 87 | * 88 | * typedef struct RSAPublicKey { 89 | * int len; // Length of n[] in number of uint32_t 90 | * uint32_t n0inv; // -1 / n[0] mod 2^32 91 | * uint32_t n[RSANUMWORDS]; // modulus as little endian array 92 | * uint32_t rr[RSANUMWORDS]; // R^2 as little endian array 93 | * int exponent; // 3 or 65537 94 | * } RSAPublicKey; 95 | */ 96 | 97 | /* ------ This part is a Java-ified version of RSA_to_RSAPublicKey from adb_host_auth.c ------ */ 98 | BigInteger r32, r, rr, rem, n, n0inv; 99 | 100 | r32 = BigInteger.ZERO.setBit(32); 101 | n = pubkey.getModulus(); 102 | r = BigInteger.ZERO.setBit(KEY_LENGTH_WORDS * 32); 103 | rr = r.modPow(BigInteger.valueOf(2), n); 104 | rem = n.remainder(r32); 105 | n0inv = rem.modInverse(r32); 106 | 107 | int myN[] = new int[KEY_LENGTH_WORDS]; 108 | int myRr[] = new int[KEY_LENGTH_WORDS]; 109 | BigInteger res[]; 110 | for (int i = 0; i < KEY_LENGTH_WORDS; i++) 111 | { 112 | res = rr.divideAndRemainder(r32); 113 | rr = res[0]; 114 | rem = res[1]; 115 | myRr[i] = rem.intValue(); 116 | 117 | res = n.divideAndRemainder(r32); 118 | n = res[0]; 119 | rem = res[1]; 120 | myN[i] = rem.intValue(); 121 | } 122 | 123 | /* ------------------------------------------------------------------------------------------- */ 124 | 125 | ByteBuffer bbuf = ByteBuffer.allocate(524).order(ByteOrder.LITTLE_ENDIAN); 126 | 127 | 128 | bbuf.putInt(KEY_LENGTH_WORDS); 129 | bbuf.putInt(n0inv.negate().intValue()); 130 | for (int i : myN) 131 | bbuf.putInt(i); 132 | for (int i : myRr) 133 | bbuf.putInt(i); 134 | 135 | bbuf.putInt(pubkey.getPublicExponent().intValue()); 136 | return bbuf.array(); 137 | } 138 | 139 | /** 140 | * Creates a new AdbCrypto object from a key pair loaded from files. 141 | * @param base64 Implementation of base 64 conversion interface required by ADB 142 | * @param privateKey File containing the RSA private key 143 | * @param publicKey File containing the RSA public key 144 | * @return New AdbCrypto object 145 | * @throws IOException If the files cannot be read 146 | * @throws NoSuchAlgorithmException If an RSA key factory cannot be found 147 | * @throws InvalidKeySpecException If a PKCS8 or X509 key spec cannot be found 148 | */ 149 | public static AdbCrypto loadAdbKeyPair(AdbBase64 base64, File privateKey, File publicKey) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException 150 | { 151 | AdbCrypto crypto = new AdbCrypto(); 152 | 153 | int privKeyLength = (int)privateKey.length(); 154 | int pubKeyLength = (int)publicKey.length(); 155 | byte[] privKeyBytes = new byte[privKeyLength]; 156 | byte[] pubKeyBytes = new byte[pubKeyLength]; 157 | 158 | FileInputStream privIn = new FileInputStream(privateKey); 159 | FileInputStream pubIn = new FileInputStream(publicKey); 160 | 161 | privIn.read(privKeyBytes); 162 | pubIn.read(pubKeyBytes); 163 | 164 | privIn.close(); 165 | pubIn.close(); 166 | 167 | KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 168 | EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privKeyBytes); 169 | EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(pubKeyBytes); 170 | 171 | crypto.keyPair = new KeyPair(keyFactory.generatePublic(publicKeySpec), 172 | keyFactory.generatePrivate(privateKeySpec)); 173 | crypto.base64 = base64; 174 | 175 | return crypto; 176 | } 177 | 178 | /** 179 | * Creates a new AdbCrypto object by generating a new key pair. 180 | * @param base64 Implementation of base 64 conversion interface required by ADB 181 | * @return A new AdbCrypto object 182 | * @throws NoSuchAlgorithmException If an RSA key factory cannot be found 183 | */ 184 | public static AdbCrypto generateAdbKeyPair(AdbBase64 base64) throws NoSuchAlgorithmException 185 | { 186 | AdbCrypto crypto = new AdbCrypto(); 187 | 188 | KeyPairGenerator rsaKeyPg = KeyPairGenerator.getInstance("RSA"); 189 | rsaKeyPg.initialize(KEY_LENGTH_BITS); 190 | 191 | crypto.keyPair = rsaKeyPg.genKeyPair(); 192 | crypto.base64 = base64; 193 | 194 | return crypto; 195 | } 196 | 197 | /** 198 | * Signs the ADB SHA1 payload with the private key of this object. 199 | * @param payload SHA1 payload to sign 200 | * @return Signed SHA1 payload 201 | * @throws GeneralSecurityException If signing fails 202 | */ 203 | public byte[] signAdbTokenPayload(byte[] payload) throws GeneralSecurityException 204 | { 205 | Cipher c = Cipher.getInstance("RSA/ECB/NoPadding"); 206 | 207 | c.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate()); 208 | 209 | c.update(SIGNATURE_PADDING); 210 | 211 | return c.doFinal(payload); 212 | } 213 | 214 | /** 215 | * Gets the RSA public key in ADB format. 216 | * @return Byte array containing the RSA public key in ADB format. 217 | * @throws IOException If the key cannot be retrived 218 | */ 219 | public byte[] getAdbPublicKeyPayload() throws IOException 220 | { 221 | byte[] convertedKey = convertRsaPublicKeyToAdbFormat((RSAPublicKey)keyPair.getPublic()); 222 | StringBuilder keyString = new StringBuilder(720); 223 | 224 | /* The key is base64 encoded with a user@host suffix and terminated with a NUL */ 225 | keyString.append(base64.encodeToString(convertedKey)); 226 | keyString.append(" unknown@unknown"); 227 | keyString.append('\0'); 228 | 229 | return keyString.toString().getBytes("UTF-8"); 230 | } 231 | 232 | /** 233 | * Saves the AdbCrypto's key pair to the specified files. 234 | * @param privateKey The file to store the encoded private key 235 | * @param publicKey The file to store the encoded public key 236 | * @throws IOException If the files cannot be written 237 | */ 238 | public void saveAdbKeyPair(File privateKey, File publicKey) throws IOException 239 | { 240 | FileOutputStream privOut = new FileOutputStream(privateKey); 241 | FileOutputStream pubOut = new FileOutputStream(publicKey); 242 | 243 | privOut.write(keyPair.getPrivate().getEncoded()); 244 | pubOut.write(keyPair.getPublic().getEncoded()); 245 | 246 | privOut.close(); 247 | pubOut.close(); 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /src/com/cgutman/adblib/AdbProtocol.java: -------------------------------------------------------------------------------- 1 | package com.cgutman.adblib; 2 | 3 | 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.UnsupportedEncodingException; 7 | import java.nio.ByteBuffer; 8 | import java.nio.ByteOrder; 9 | 10 | 11 | /** 12 | * This class provides useful functions and fields for ADB protocol details. 13 | * @author Cameron Gutman 14 | */ 15 | public class AdbProtocol { 16 | 17 | /** The length of the ADB message header */ 18 | public static final int ADB_HEADER_LENGTH = 24; 19 | 20 | public static final int CMD_SYNC = 0x434e5953; 21 | 22 | /** CNXN is the connect message. No messages (except AUTH) 23 | * are valid before this message is received. */ 24 | public static final int CMD_CNXN = 0x4e584e43; 25 | 26 | /** The current version of the ADB protocol */ 27 | public static final int CONNECT_VERSION = 0x01000000; 28 | 29 | /** The maximum data payload supported by the ADB implementation */ 30 | public static final int CONNECT_MAXDATA = 4096; 31 | 32 | /** The payload sent with the connect message */ 33 | public static byte[] CONNECT_PAYLOAD; 34 | static { 35 | try { 36 | CONNECT_PAYLOAD = "host::\0".getBytes("UTF-8"); 37 | } catch (UnsupportedEncodingException e) {} 38 | } 39 | 40 | /** AUTH is the authentication message. It is part of the 41 | * RSA public key authentication added in Android 4.2.2. */ 42 | public static final int CMD_AUTH = 0x48545541; 43 | 44 | /** This authentication type represents a SHA1 hash to sign */ 45 | public static final int AUTH_TYPE_TOKEN = 1; 46 | 47 | /** This authentication type represents the signed SHA1 hash */ 48 | public static final int AUTH_TYPE_SIGNATURE = 2; 49 | 50 | /** This authentication type represents a RSA public key */ 51 | public static final int AUTH_TYPE_RSA_PUBLIC = 3; 52 | 53 | /** OPEN is the open stream message. It is sent to open 54 | * a new stream on the target device. */ 55 | public static final int CMD_OPEN = 0x4e45504f; 56 | 57 | /** OKAY is a success message. It is sent when a write is 58 | * processed successfully. */ 59 | public static final int CMD_OKAY = 0x59414b4f; 60 | 61 | /** CLSE is the close stream message. It it sent to close an 62 | * existing stream on the target device. */ 63 | public static final int CMD_CLSE = 0x45534c43; 64 | 65 | /** WRTE is the write stream message. It is sent with a payload 66 | * that is the data to write to the stream. */ 67 | public static final int CMD_WRTE = 0x45545257; 68 | 69 | /** 70 | * This function performs a checksum on the ADB payload data. 71 | * @param payload Payload to checksum 72 | * @return The checksum of the payload 73 | */ 74 | private static int getPayloadChecksum(byte[] payload) 75 | { 76 | int checksum = 0; 77 | 78 | for (byte b : payload) 79 | { 80 | /* We have to manually "unsign" these bytes because Java sucks */ 81 | if (b >= 0) 82 | checksum += b; 83 | else 84 | checksum += b+256; 85 | } 86 | 87 | return checksum; 88 | } 89 | 90 | /** 91 | * This function validate the ADB message by checking 92 | * its command, magic, and payload checksum. 93 | * @param msg ADB message to validate 94 | * @return True if the message was valid, false otherwise 95 | */ 96 | public static boolean validateMessage(AdbMessage msg) 97 | { 98 | /* Magic is cmd ^ 0xFFFFFFFF */ 99 | if (msg.command != (msg.magic ^ 0xFFFFFFFF)) 100 | return false; 101 | 102 | if (msg.payloadLength != 0) 103 | { 104 | if (getPayloadChecksum(msg.payload) != msg.checksum) 105 | return false; 106 | } 107 | 108 | return true; 109 | } 110 | 111 | /** 112 | * This function generates an ADB message given the fields. 113 | * @param cmd Command identifier 114 | * @param arg0 First argument 115 | * @param arg1 Second argument 116 | * @param payload Data payload 117 | * @return Byte array containing the message 118 | */ 119 | public static byte[] generateMessage(int cmd, int arg0, int arg1, byte[] payload) 120 | { 121 | /* struct message { 122 | * unsigned command; // command identifier constant 123 | * unsigned arg0; // first argument 124 | * unsigned arg1; // second argument 125 | * unsigned data_length; // length of payload (0 is allowed) 126 | * unsigned data_check; // checksum of data payload 127 | * unsigned magic; // command ^ 0xffffffff 128 | * }; 129 | */ 130 | 131 | ByteBuffer message; 132 | 133 | if (payload != null) 134 | { 135 | message = ByteBuffer.allocate(ADB_HEADER_LENGTH + payload.length).order(ByteOrder.LITTLE_ENDIAN); 136 | } 137 | else 138 | { 139 | message = ByteBuffer.allocate(ADB_HEADER_LENGTH).order(ByteOrder.LITTLE_ENDIAN); 140 | } 141 | 142 | message.putInt(cmd); 143 | message.putInt(arg0); 144 | message.putInt(arg1); 145 | 146 | if (payload != null) 147 | { 148 | message.putInt(payload.length); 149 | message.putInt(getPayloadChecksum(payload)); 150 | } 151 | else 152 | { 153 | message.putInt(0); 154 | message.putInt(0); 155 | } 156 | 157 | message.putInt(cmd ^ 0xFFFFFFFF); 158 | 159 | if (payload != null) 160 | { 161 | message.put(payload); 162 | } 163 | 164 | return message.array(); 165 | } 166 | 167 | /** 168 | * Generates a connect message with default parameters. 169 | * @return Byte array containing the message 170 | */ 171 | public static byte[] generateConnect() 172 | { 173 | return generateMessage(CMD_CNXN, CONNECT_VERSION, CONNECT_MAXDATA, CONNECT_PAYLOAD); 174 | } 175 | 176 | /** 177 | * Generates an auth message with the specified type and payload. 178 | * @param type Authentication type (see AUTH_TYPE_* constants) 179 | * @param data The payload for the message 180 | * @return Byte array containing the message 181 | */ 182 | public static byte[] generateAuth(int type, byte[] data) 183 | { 184 | return generateMessage(CMD_AUTH, type, 0, data); 185 | } 186 | 187 | /** 188 | * Generates an open stream message with the specified local ID and destination. 189 | * @param localId A unique local ID identifying the stream 190 | * @param dest The destination of the stream on the target 191 | * @return Byte array containing the message 192 | * @throws UnsupportedEncodingException If the destination cannot be encoded to UTF-8 193 | */ 194 | public static byte[] generateOpen(int localId, String dest) throws UnsupportedEncodingException 195 | { 196 | ByteBuffer bbuf = ByteBuffer.allocate(dest.length() + 1); 197 | bbuf.put(dest.getBytes("UTF-8")); 198 | bbuf.put((byte)0); 199 | return generateMessage(CMD_OPEN, localId, 0, bbuf.array()); 200 | } 201 | 202 | /** 203 | * Generates a write stream message with the specified IDs and payload. 204 | * @param localId The unique local ID of the stream 205 | * @param remoteId The unique remote ID of the stream 206 | * @param data The data to provide as the write payload 207 | * @return Byte array containing the message 208 | */ 209 | public static byte[] generateWrite(int localId, int remoteId, byte[] data) 210 | { 211 | return generateMessage(CMD_WRTE, localId, remoteId, data); 212 | } 213 | 214 | /** 215 | * Generates a close stream message with the specified IDs. 216 | * @param localId The unique local ID of the stream 217 | * @param remoteId The unique remote ID of the stream 218 | * @return Byte array containing the message 219 | */ 220 | public static byte[] generateClose(int localId, int remoteId) 221 | { 222 | return generateMessage(CMD_CLSE, localId, remoteId, null); 223 | } 224 | 225 | /** 226 | * Generates an okay message with the specified IDs. 227 | * @param localId The unique local ID of the stream 228 | * @param remoteId The unique remote ID of the stream 229 | * @return Byte array containing the message 230 | */ 231 | public static byte[] generateReady(int localId, int remoteId) 232 | { 233 | return generateMessage(CMD_OKAY, localId, remoteId, null); 234 | } 235 | 236 | /** 237 | * This class provides an abstraction for the ADB message format. 238 | * @author Cameron Gutman 239 | */ 240 | final static class AdbMessage { 241 | /** The command field of the message */ 242 | public int command; 243 | /** The arg0 field of the message */ 244 | public int arg0; 245 | /** The arg1 field of the message */ 246 | public int arg1; 247 | /** The payload length field of the message */ 248 | public int payloadLength; 249 | /** The checksum field of the message */ 250 | public int checksum; 251 | /** The magic field of the message */ 252 | public int magic; 253 | /** The payload of the message */ 254 | public byte[] payload; 255 | 256 | /** 257 | * Read and parse an ADB message from the supplied input stream. 258 | * This message is NOT validated. 259 | * @param in InputStream object to read data from 260 | * @return An AdbMessage object represented the message read 261 | * @throws IOException If the stream fails while reading 262 | */ 263 | public static AdbMessage parseAdbMessage(InputStream in) throws IOException 264 | { 265 | AdbMessage msg = new AdbMessage(); 266 | ByteBuffer packet = ByteBuffer.allocate(ADB_HEADER_LENGTH).order(ByteOrder.LITTLE_ENDIAN); 267 | 268 | /* Read the header first */ 269 | int dataRead = 0; 270 | do 271 | { 272 | int bytesRead = in.read(packet.array(), dataRead, 24 - dataRead); 273 | 274 | if (bytesRead < 0) 275 | throw new IOException("Stream closed"); 276 | else 277 | dataRead += bytesRead; 278 | } 279 | while (dataRead < ADB_HEADER_LENGTH); 280 | 281 | /* Pull out header fields */ 282 | msg.command = packet.getInt(); 283 | msg.arg0 = packet.getInt(); 284 | msg.arg1 = packet.getInt(); 285 | msg.payloadLength = packet.getInt(); 286 | msg.checksum = packet.getInt(); 287 | msg.magic = packet.getInt(); 288 | 289 | /* If there's a payload supplied, read that too */ 290 | if (msg.payloadLength != 0) 291 | { 292 | msg.payload = new byte[msg.payloadLength]; 293 | 294 | dataRead = 0; 295 | do 296 | { 297 | int bytesRead = in.read(msg.payload, dataRead, msg.payloadLength - dataRead); 298 | 299 | if (bytesRead < 0) 300 | throw new IOException("Stream closed"); 301 | else 302 | dataRead += bytesRead; 303 | } 304 | while (dataRead < msg.payloadLength); 305 | } 306 | 307 | return msg; 308 | } 309 | } 310 | } 311 | -------------------------------------------------------------------------------- /src/com/cgutman/adblib/AdbStream.java: -------------------------------------------------------------------------------- 1 | package com.cgutman.adblib; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | import java.util.Queue; 6 | import java.util.concurrent.ConcurrentLinkedQueue; 7 | import java.util.concurrent.atomic.AtomicBoolean; 8 | 9 | /** 10 | * This class abstracts the underlying ADB streams 11 | * @author Cameron Gutman 12 | */ 13 | public class AdbStream implements Closeable { 14 | 15 | /** The AdbConnection object that the stream communicates over */ 16 | private AdbConnection adbConn; 17 | 18 | /** The local ID of the stream */ 19 | private int localId; 20 | 21 | /** The remote ID of the stream */ 22 | private int remoteId; 23 | 24 | /** Indicates whether a write is currently allowed */ 25 | private AtomicBoolean writeReady; 26 | 27 | /** A queue of data from the target's write packets */ 28 | private Queue readQueue; 29 | 30 | /** Indicates whether the connection is closed already */ 31 | private boolean isClosed; 32 | 33 | /** 34 | * Creates a new AdbStream object on the specified AdbConnection 35 | * with the given local ID. 36 | * @param adbConn AdbConnection that this stream is running on 37 | * @param localId Local ID of the stream 38 | */ 39 | public AdbStream(AdbConnection adbConn, int localId) 40 | { 41 | this.adbConn = adbConn; 42 | this.localId = localId; 43 | this.readQueue = new ConcurrentLinkedQueue(); 44 | this.writeReady = new AtomicBoolean(false); 45 | this.isClosed = false; 46 | } 47 | 48 | /** 49 | * Called by the connection thread to indicate newly received data. 50 | * @param payload Data inside the write message 51 | */ 52 | void addPayload(byte[] payload) 53 | { 54 | synchronized (readQueue) { 55 | readQueue.add(payload); 56 | readQueue.notifyAll(); 57 | } 58 | } 59 | 60 | /** 61 | * Called by the connection thread to send an OKAY packet, allowing the 62 | * other side to continue transmission. 63 | * @throws IOException If the connection fails while sending the packet 64 | */ 65 | void sendReady() throws IOException 66 | { 67 | /* Generate and send a READY packet */ 68 | byte[] packet = AdbProtocol.generateReady(localId, remoteId); 69 | adbConn.outputStream.write(packet); 70 | adbConn.outputStream.flush(); 71 | } 72 | 73 | /** 74 | * Called by the connection thread to update the remote ID for this stream 75 | * @param remoteId New remote ID 76 | */ 77 | void updateRemoteId(int remoteId) 78 | { 79 | this.remoteId = remoteId; 80 | } 81 | 82 | /** 83 | * Called by the connection thread to indicate the stream is okay to send data. 84 | */ 85 | void readyForWrite() 86 | { 87 | writeReady.set(true); 88 | } 89 | 90 | /** 91 | * Called by the connection thread to notify that the stream was closed by the peer. 92 | */ 93 | void notifyClose() 94 | { 95 | /* We don't call close() because it sends another CLOSE */ 96 | isClosed = true; 97 | 98 | /* Unwait readers and writers */ 99 | synchronized (this) { 100 | notifyAll(); 101 | } 102 | synchronized (readQueue) { 103 | readQueue.notifyAll(); 104 | } 105 | } 106 | 107 | /** 108 | * Reads a pending write payload from the other side. 109 | * @return Byte array containing the payload of the write 110 | * @throws InterruptedException If we are unable to wait for data 111 | * @throws IOException If the stream fails while waiting 112 | */ 113 | public byte[] read() throws InterruptedException, IOException 114 | { 115 | byte[] data = null; 116 | 117 | synchronized (readQueue) { 118 | /* Wait for the connection to close or data to be received */ 119 | while (!isClosed && (data = readQueue.poll()) == null) { 120 | readQueue.wait(); 121 | } 122 | 123 | if (isClosed) { 124 | throw new IOException("Stream closed"); 125 | } 126 | } 127 | 128 | return data; 129 | } 130 | 131 | /** 132 | * Sends a write packet with a given String payload. 133 | * @param payload Payload in the form of a String 134 | * @throws IOException If the stream fails while sending data 135 | * @throws InterruptedException If we are unable to wait to send data 136 | */ 137 | public void write(String payload) throws IOException, InterruptedException 138 | { 139 | /* ADB needs null-terminated strings */ 140 | write(payload.getBytes("UTF-8"), false); 141 | write(new byte[]{0}, true); 142 | } 143 | 144 | /** 145 | * Sends a write packet with a given byte array payload. 146 | * @param payload Payload in the form of a byte array 147 | * @throws IOException If the stream fails while sending data 148 | * @throws InterruptedException If we are unable to wait to send data 149 | */ 150 | public void write(byte[] payload) throws IOException, InterruptedException 151 | { 152 | write(payload, true); 153 | } 154 | 155 | /** 156 | * Queues a write packet and optionally sends it immediately. 157 | * @param payload Payload in the form of a byte array 158 | * @param flush Specifies whether to send the packet immediately 159 | * @throws IOException If the stream fails while sending data 160 | * @throws InterruptedException If we are unable to wait to send data 161 | */ 162 | public void write(byte[] payload, boolean flush) throws IOException, InterruptedException 163 | { 164 | synchronized (this) { 165 | /* Make sure we're ready for a write */ 166 | while (!isClosed && !writeReady.compareAndSet(true, false)) 167 | wait(); 168 | 169 | if (isClosed) { 170 | throw new IOException("Stream closed"); 171 | } 172 | } 173 | 174 | /* Generate a WRITE packet and send it */ 175 | byte[] packet = AdbProtocol.generateWrite(localId, remoteId, payload); 176 | adbConn.outputStream.write(packet); 177 | 178 | if (flush) 179 | adbConn.outputStream.flush(); 180 | } 181 | 182 | /** 183 | * Closes the stream. This sends a close message to the peer. 184 | * @throws IOException If the stream fails while sending the close message. 185 | */ 186 | @Override 187 | public void close() throws IOException { 188 | synchronized (this) { 189 | /* This may already be closed by the remote host */ 190 | if (isClosed) 191 | return; 192 | 193 | /* Notify readers/writers that we've closed */ 194 | notifyClose(); 195 | } 196 | 197 | byte[] packet = AdbProtocol.generateClose(localId, remoteId); 198 | adbConn.outputStream.write(packet); 199 | adbConn.outputStream.flush(); 200 | } 201 | 202 | /** 203 | * Retreives whether the stream is closed or not 204 | * @return True if the stream is close, false if not 205 | */ 206 | public boolean isClosed() { 207 | return isClosed; 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/com/cgutman/adblib/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package provides a native Java implementation of the ADB protocol. 3 | * @author Cameron Gutman 4 | */ 5 | package com.cgutman.adblib; --------------------------------------------------------------------------------