Skip to content

Commit

Permalink
fix: NullPointerException in adb device viewer (skylot#1585)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpstotz committed Jul 25, 2022
1 parent 8b4f8fb commit 1083a0c
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 54 deletions.
4 changes: 2 additions & 2 deletions jadx-gui/src/main/java/jadx/gui/device/protocol/ADB.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ static byte[] readServiceProtocol(InputStream stream) {
}
return result;
} catch (SocketException e) {
LOG.error("Aborting readServiceProtocol: socket closed");
LOG.warn("Aborting readServiceProtocol: {}", e.toString());
} catch (IOException e) {
LOG.error("Failed to read readServiceProtocol", e);
}
Expand Down Expand Up @@ -207,7 +207,7 @@ public static Socket listenForDeviceState(DeviceStateListener listener, String h
List<ADBDeviceInfo> deviceInfoList = new ArrayList<>(deviceLines.length);
for (String deviceLine : deviceLines) {
if (!deviceLine.trim().isEmpty()) {
deviceInfoList.add(ADBDeviceInfo.make(deviceLine, host, port));
deviceInfoList.add(new ADBDeviceInfo(deviceLine, host, port));
}
}
listener.onDeviceStatusChange(deviceInfoList);
Expand Down
36 changes: 20 additions & 16 deletions jadx-gui/src/main/java/jadx/gui/device/protocol/ADBDevice.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,32 @@ public ADBDeviceInfo getDeviceInfo() {
}

public boolean updateDeviceInfo(ADBDeviceInfo info) {
boolean matched = this.info.serial.equals(info.serial);
if (info.getSerial() == null || info.getSerial().isEmpty()) {
return false;
}
boolean matched = this.info.getSerial().equals(info.getSerial());
if (matched) {
this.info = info;
}
return matched;
}

public String getSerial() {
return info.serial;
return info.getSerial();
}

public boolean removeForward(String localPort) throws IOException {
return ADB.removeForward(info.adbHost, info.adbPort, info.serial, localPort);
return ADB.removeForward(info.getAdbHost(), info.getAdbPort(), info.getSerial(), localPort);
}

public ForwardResult forwardJDWP(String localPort, String jdwpPid) throws IOException {
try (Socket socket = ADB.connect(info.adbHost, info.adbPort)) {
try (Socket socket = ADB.connect(info.getAdbHost(), info.getAdbPort())) {
String cmd = String.format("host:forward:tcp:%s;jdwp:%s", localPort, jdwpPid);
cmd = String.format("%04x%s", cmd.length(), cmd);
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
ForwardResult rst;
if (ADB.setSerial(info.serial, outputStream, inputStream)) {
if (ADB.setSerial(info.getSerial(), outputStream, inputStream)) {
outputStream.write(cmd.getBytes());
if (!ADB.isOkay(inputStream)) {
rst = new ForwardResult(1, ADB.readServiceProtocol(inputStream));
Expand Down Expand Up @@ -99,9 +102,9 @@ public ForwardResult(int state, byte[] desc) {
*/
public int launchApp(String fullAppName) throws IOException, InterruptedException {
byte[] res;
try (Socket socket = ADB.connect(info.adbHost, info.adbPort)) {
try (Socket socket = ADB.connect(info.getAdbHost(), info.getAdbPort())) {
String cmd = "am start -D -n " + fullAppName;
res = ADB.execShellCommandRaw(info.serial, cmd, socket.getOutputStream(), socket.getInputStream());
res = ADB.execShellCommandRaw(info.getSerial(), cmd, socket.getOutputStream(), socket.getInputStream());
if (res == null) {
return -1;
}
Expand Down Expand Up @@ -134,13 +137,13 @@ public String getAndroidReleaseVersion() {
}

public List<String> getProp(String entry) throws IOException {
try (Socket socket = ADB.connect(info.adbHost, info.adbPort)) {
try (Socket socket = ADB.connect(info.getAdbHost(), info.getAdbPort())) {
List<String> props = Collections.emptyList();
String cmd = "getprop";
if (!StringUtils.isEmpty(entry)) {
cmd += " " + entry;
}
byte[] payload = ADB.execShellCommandRaw(info.serial, cmd,
byte[] payload = ADB.execShellCommandRaw(info.getSerial(), cmd,
socket.getOutputStream(), socket.getInputStream());
if (payload != null) {
props = new ArrayList<>();
Expand All @@ -166,9 +169,9 @@ public List<Process> getProcessList() throws IOException {
}

private List<Process> getProcessList(String cmd, int index) throws IOException {
try (Socket socket = ADB.connect(info.adbHost, info.adbPort)) {
try (Socket socket = ADB.connect(info.getAdbHost(), info.getAdbPort())) {
List<Process> procs = new ArrayList<>();
byte[] payload = ADB.execShellCommandRaw(info.serial, cmd,
byte[] payload = ADB.execShellCommandRaw(info.getSerial(), cmd,
socket.getOutputStream(), socket.getInputStream());
if (payload != null) {
String ps = new String(payload);
Expand All @@ -194,10 +197,10 @@ public boolean listenForJDWP(JDWPProcessListener listener) throws IOException {
if (this.jdwpListenerSock != null) {
return false;
}
jdwpListenerSock = ADB.connect(this.info.adbHost, this.info.adbPort);
jdwpListenerSock = ADB.connect(this.info.getAdbHost(), this.info.getAdbPort());
InputStream inputStream = jdwpListenerSock.getInputStream();
OutputStream outputStream = jdwpListenerSock.getOutputStream();
if (ADB.setSerial(info.serial, outputStream, inputStream)
if (ADB.setSerial(info.getSerial(), outputStream, inputStream)
&& ADB.execCommandAsync(outputStream, inputStream, CMD_TRACK_JDWP)) {
Executors.newFixedThreadPool(1).execute(() -> {
for (;;) {
Expand Down Expand Up @@ -244,19 +247,20 @@ public void stopListenForJDWP() {

@Override
public int hashCode() {
return info.serial.hashCode();
return info.getSerial().hashCode();
}

@Override
public boolean equals(Object obj) {
if (obj instanceof ADBDevice) {
return ((ADBDevice) obj).getDeviceInfo().serial.equals(info.serial);
String otherSerial = ((ADBDevice) obj).getDeviceInfo().getSerial();
return otherSerial.equals(info.getSerial());
}
return false;
}

@Override
public String toString() {
return info.allInfo;
return info.getAllInfo();
}
}
105 changes: 77 additions & 28 deletions jadx-gui/src/main/java/jadx/gui/device/protocol/ADBDeviceInfo.java
Original file line number Diff line number Diff line change
@@ -1,42 +1,91 @@
package jadx.gui.device.protocol;

import java.util.Map;
import java.util.TreeMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jadx.core.utils.log.LogUtils;

public class ADBDeviceInfo {
public String adbHost;
public int adbPort;
public String serial;
public String state;
public String model;
public String allInfo;
private static final Logger LOG = LoggerFactory.getLogger(ADBDeviceInfo.class);
private final String adbHost;
private final int adbPort;
private final String serial;
private final String state;
private final String model;
private final String allInfo;

/**
* Store the device info property values like "device" "model" "product" or "transport_id"
*/
private final Map<String, String> propertiesMap = new TreeMap<>();

ADBDeviceInfo(String info, String host, int port) {
String[] infoFields = info.trim().split("\\s+");
allInfo = String.join(" ", infoFields);
if (infoFields.length > 2) {
serial = infoFields[0];
state = infoFields[1];

for (int i = 2; i < infoFields.length; i++) {
String field = infoFields[i];
int idx = field.indexOf(':');
if (idx > 0) {
String key = field.substring(0, idx);
String value = field.substring(idx + 1);
if (!value.isEmpty()) {
propertiesMap.put(key, value);
}
}
}
model = propertiesMap.getOrDefault("model", serial);
} else {
LOG.error("Unable to extract device information from {}", LogUtils.escape(info));
serial = "";
state = "unknown";
model = "unknown";
}
adbHost = host;
adbPort = port;
}

public boolean isOnline() {
return state.equals("device");
}

public String getAdbHost() {
return adbHost;
}

public int getAdbPort() {
return adbPort;
}

public String getSerial() {
return serial;
}

public String getState() {
return state;
}

public String getModel() {
return model;
}

public String getAllInfo() {
return allInfo;
}

public String getProperty(String key) {
return this.propertiesMap.get(key);
}

@Override
public String toString() {
return allInfo;
}

static ADBDeviceInfo make(String info, String host, int port) {
ADBDeviceInfo deviceInfo = new ADBDeviceInfo();
String[] infoFields = info.trim().split("\\s+");
deviceInfo.allInfo = String.join(" ", infoFields);
if (infoFields.length > 2) {
deviceInfo.serial = infoFields[0];
deviceInfo.state = infoFields[1];
}
int pos = info.indexOf("model:");
if (pos != -1) {
int spacePos = info.indexOf(" ", pos);
if (spacePos != -1) {
deviceInfo.model = info.substring(pos + "model:".length(), spacePos);
}
}
if (deviceInfo.model == null || deviceInfo.model.equals("")) {
deviceInfo.model = deviceInfo.serial;
}
deviceInfo.adbHost = host;
deviceInfo.adbPort = port;
return deviceInfo;
}
}
16 changes: 8 additions & 8 deletions jadx-gui/src/main/java/jadx/gui/ui/dialog/ADBDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ private static boolean attachProcess(MainWindow mainWindow) {
try {
return mainWindow.getDebuggerPanel().showDebugger(
debugSetter.name,
debugSetter.device.getDeviceInfo().adbHost,
debugSetter.device.getDeviceInfo().getAdbHost(),
debugSetter.forwardTcpPort,
debugSetter.ver);
} catch (Exception e) {
Expand Down Expand Up @@ -569,10 +569,10 @@ private static class DeviceNode {

void refresh() {
ADBDeviceInfo info = device.getDeviceInfo();
String text = info.model;
String text = info.getModel();
if (text != null) {
if (!text.equals(info.serial)) {
text += String.format(" [serial: %s]", info.serial);
if (!text.equals(info.getSerial())) {
text += String.format(" [serial: %s]", info.getSerial());
}
text += String.format(" [state: %s]", info.isOnline() ? "online" : "offline");
tNode.setUserObject(text);
Expand Down Expand Up @@ -668,8 +668,8 @@ private void clearForward() {
String jdwpPid = " jdwp:" + pid;
String tcpPort = " tcp:" + forwardTcpPort;
try {
List<String> list = ADB.listForward(device.getDeviceInfo().adbHost,
device.getDeviceInfo().adbPort);
List<String> list = ADB.listForward(device.getDeviceInfo().getAdbHost(),
device.getDeviceInfo().getAdbPort());
for (String s : list) {
if (s.startsWith(device.getSerial()) && s.endsWith(jdwpPid) && !s.contains(tcpPort)) {
String[] fields = s.split("\\s+");
Expand All @@ -693,8 +693,8 @@ private boolean isBeingDebugged() {
String jdwpPid = " jdwp:" + pid;
String tcpPort = " tcp:" + forwardTcpPort;
try {
List<String> list = ADB.listForward(device.getDeviceInfo().adbHost,
device.getDeviceInfo().adbPort);
List<String> list = ADB.listForward(device.getDeviceInfo().getAdbHost(),
device.getDeviceInfo().getAdbPort());
for (String s : list) {
if (s.startsWith(device.getSerial()) && s.endsWith(jdwpPid)) {
return !s.contains(tcpPort);
Expand Down

0 comments on commit 1083a0c

Please sign in to comment.