Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: NullPointerException in adb device viewer (#1585) #1586

Merged
merged 1 commit into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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