• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jiangxincode / ApkToolBoxGUI / #1207

13 Sep 2025 11:58PM UTC coverage: 2.895% (-0.006%) from 2.901%
#1207

push

jiangxincode
fix #569: 可能在完全初始化子类之前逃逸了 'this'

0 of 32 new or added lines in 22 files covered. (0.0%)

9 existing lines in 8 files now uncovered.

248 of 8567 relevant lines covered (2.89%)

0.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/edu/jiangxin/apktoolbox/android/dumpsys/DumpsysPanel.java
1
package edu.jiangxin.apktoolbox.android.dumpsys;
2

3
import edu.jiangxin.apktoolbox.android.dumpsys.tojson.IDumpsys2Json;
4
import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
5
import edu.jiangxin.apktoolbox.swing.extend.filepanel.FilePanel;
6
import edu.jiangxin.apktoolbox.utils.Constants;
7
import org.apache.commons.exec.CommandLine;
8
import org.apache.commons.exec.DefaultExecutor;
9
import org.apache.commons.exec.PumpStreamHandler;
10
import org.apache.commons.io.FileUtils;
11
import org.apache.commons.io.FilenameUtils;
12
import org.apache.commons.lang3.StringUtils;
13
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
14
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
15
import org.fife.ui.rtextarea.RTextScrollPane;
16

17
import javax.swing.*;
18
import java.awt.*;
19
import java.awt.event.ActionEvent;
20
import java.awt.event.ActionListener;
21
import java.io.ByteArrayOutputStream;
22
import java.io.File;
23
import java.io.IOException;
24
import java.io.Serial;
25
import java.text.SimpleDateFormat;
26
import java.util.Date;
27

28
public class DumpsysPanel extends EasyPanel {
29
    @Serial
30
    private static final long serialVersionUID = 1L;
31

32
    private JPanel dumpsysPanel;
33

34
    private FilePanel dumpsysTargetDirPanel;
35

36
    private JPanel dumpsysOptionPanel;
37
    private JPanel dumpsysTypeChoosePanel;
38

39
    private JPanel dumpsysOperationPanel;
40
    private JButton dumpsysStartButton;
41

42
    private JPanel analysisPanel;
43
    private FilePanel analysisFilePanel;
44
    private RSyntaxTextArea analysisOutputTextArea;
45
    private RTextScrollPane analysisOutputScrollPane;
46

47
    private JPanel analysisOperationPanel;
48

49
    public DumpsysPanel() {
50
        super();
×
51
    }
×
52

53
    @Override
54
    public void initUI() {
55
        setPreferredSize(new Dimension(700, 400));
×
56

57
        JTabbedPane tabbedPane = new JTabbedPane();
×
58
        add(tabbedPane);
×
59

60
        createDumpsysPanel();
×
61
        tabbedPane.addTab("Dumpsys", null, dumpsysPanel, "Dumpsys");
×
62

63
        createAnalysisPanel();
×
64
        tabbedPane.addTab("Analysis", null, analysisPanel, "Analysis");
×
65
    }
×
66

67
    @Override
68
    public void afterPainted() {
69
        super.afterPainted();
×
70
        dumpsysTargetDirPanel.setPersistentKey(Constants.KEY_PREFIX + "dumpsysTargetDirPanel");
×
71
        analysisFilePanel.setPersistentKey(Constants.KEY_PREFIX + "dumpsysAnalysisFilePanel");
×
72
    }
×
73

74
    private void createDumpsysPanel() {
75
        dumpsysPanel = new JPanel();
×
76
        BoxLayout layout = new BoxLayout(dumpsysPanel, BoxLayout.Y_AXIS);
×
77
        dumpsysPanel.setLayout(layout);
×
78
        dumpsysPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
79

80
        createDumpsysTargetDirPanel();
×
81
        dumpsysPanel.add(dumpsysTargetDirPanel);
×
82
        dumpsysPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
83

84
        createDumpsysOptionPanel();
×
85
        dumpsysPanel.add(dumpsysOptionPanel);
×
86
        dumpsysPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
87

88
        createDumpsysOperationPanel();
×
89
        dumpsysPanel.add(dumpsysOperationPanel);
×
90
    }
×
91

92
    private void createAnalysisPanel() {
93
        analysisPanel = new JPanel();
×
94
        BoxLayout layout = new BoxLayout(analysisPanel, BoxLayout.Y_AXIS);
×
95
        analysisPanel.setLayout(layout);
×
96
        dumpsysPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
97

98
        createAnalysisTargetFilePanel();
×
99
        analysisPanel.add(analysisFilePanel);
×
100
        analysisPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
101

102
        createAnalysisOutputPanel();
×
103
        analysisPanel.add(analysisOutputScrollPane);
×
104
        analysisPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
105

106
        createAnalysisOperationPanel();
×
107
        analysisPanel.add(analysisOperationPanel);
×
108
    }
×
109

110
    private void createAnalysisTargetFilePanel() {
111
        analysisFilePanel = new FilePanel("Analysis File");
×
NEW
112
        analysisFilePanel.initialize();
×
113
        analysisFilePanel.setFileSelectionMode(JFileChooser.FILES_ONLY);
×
114
    }
×
115

116
    private void createAnalysisOutputPanel() {
117
        analysisOutputTextArea = new RSyntaxTextArea();
×
118
        analysisOutputTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JSON);
×
119
        analysisOutputTextArea.setCodeFoldingEnabled(true);
×
120
        analysisOutputTextArea.setEditable(false);
×
121

122
        analysisOutputScrollPane = new RTextScrollPane(analysisOutputTextArea);
×
123
        analysisOutputScrollPane.setPreferredSize(new Dimension(400, 250));
×
124
    }
×
125

126
    private void createAnalysisOperationPanel() {
127
        analysisOperationPanel = new JPanel();
×
128
        BoxLayout boxLayout = new BoxLayout(analysisOperationPanel, BoxLayout.X_AXIS);
×
129
        analysisOperationPanel.setLayout(boxLayout);
×
130

131
        JButton analysisStartButton = new JButton("Start");
×
132
        analysisStartButton.setEnabled(true);
×
133
        analysisStartButton.addActionListener(new AnalysisStartButtonActionListener());
×
134
        analysisOperationPanel.add(analysisStartButton);
×
135
    }
×
136

137
    private void createDumpsysTargetDirPanel() {
138
        dumpsysTargetDirPanel = new FilePanel("Target Directory");
×
NEW
139
        dumpsysTargetDirPanel.initialize();
×
140
        dumpsysTargetDirPanel.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
×
141
    }
×
142

143
    private void createDumpsysOptionPanel() {
144
        dumpsysOptionPanel = new JPanel();
×
145
        BoxLayout boxLayout = new BoxLayout(dumpsysOptionPanel, BoxLayout.Y_AXIS);
×
146
        dumpsysOptionPanel.setLayout(boxLayout);
×
147

148
        JPanel dumpsysCheckboxPanel = new JPanel();
×
149
        dumpsysCheckboxPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 3));
×
150

151
        JCheckBox allSelectedCheckBox = new JCheckBox("Select All");
×
152
        allSelectedCheckBox.setSelected(false);
×
153
        allSelectedCheckBox.addActionListener(e -> {
×
154
            boolean selected = allSelectedCheckBox.isSelected();
×
155
            if (selected) {
×
156
                Component[] components = dumpsysTypeChoosePanel.getComponents();
×
157
                for (Component component : components) {
×
158
                    if (component instanceof JCheckBox checkBox) {
×
159
                        checkBox.setSelected(true);
×
160
                        checkBox.setEnabled(false);
×
161
                    }
162
                }
163
            } else {
×
164
                Component[] components = dumpsysTypeChoosePanel.getComponents();
×
165
                for (Component component : components) {
×
166
                    if (component instanceof JCheckBox checkBox) {
×
167
                        checkBox.setSelected(false);
×
168
                        checkBox.setEnabled(true);
×
169
                    }
170
                }
171
            }
172

173
        });
×
174
        dumpsysCheckboxPanel.add(allSelectedCheckBox);
×
175

176
        dumpsysTypeChoosePanel = new JPanel();
×
177
        dumpsysTypeChoosePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 3));
×
178
        dumpsysTypeChoosePanel.setPreferredSize(new Dimension(500, 200));
×
179

180
        JCheckBox inputCheckBox = new JCheckBox("input");
×
181
        inputCheckBox.setSelected(true);
×
182
        JCheckBox windowCheckBox = new JCheckBox("window");
×
183
        dumpsysTypeChoosePanel.add(windowCheckBox);
×
184
        JCheckBox SurfaceFlingerCheckBox = new JCheckBox("SurfaceFlinger");
×
185
        dumpsysTypeChoosePanel.add(SurfaceFlingerCheckBox);
×
186
        JCheckBox activityCheckBox = new JCheckBox("activity");
×
187
        dumpsysTypeChoosePanel.add(activityCheckBox);
×
188
        JCheckBox accessibilityCheckBox = new JCheckBox("accessibility");
×
189
        dumpsysTypeChoosePanel.add(accessibilityCheckBox);
×
190
        JCheckBox packageCheckBox = new JCheckBox("package");
×
191
        dumpsysTypeChoosePanel.add(packageCheckBox);
×
192
        JCheckBox alarmCheckBox = new JCheckBox("alarm");
×
193
        dumpsysTypeChoosePanel.add(alarmCheckBox);
×
194
        JCheckBox inputMethodCheckBox = new JCheckBox("input_method");
×
195
        dumpsysTypeChoosePanel.add(inputMethodCheckBox);
×
196
        JCheckBox sensorServiceCheckBox = new JCheckBox("sensorservice");
×
197
        dumpsysTypeChoosePanel.add(sensorServiceCheckBox);
×
198
        JCheckBox accountCheckBox = new JCheckBox("account");
×
199
        dumpsysTypeChoosePanel.add(accountCheckBox);
×
200
        JCheckBox displayCheckBox = new JCheckBox("display");
×
201
        dumpsysTypeChoosePanel.add(displayCheckBox);
×
202
        JCheckBox powerCheckBox = new JCheckBox("power");
×
203
        dumpsysTypeChoosePanel.add(powerCheckBox);
×
204
        JCheckBox batteryCheckBox = new JCheckBox("battery");
×
205
        dumpsysTypeChoosePanel.add(batteryCheckBox);
×
206

207
        dumpsysOptionPanel.add(dumpsysCheckboxPanel);
×
208
        dumpsysOptionPanel.add(new JSeparator(JSeparator.HORIZONTAL));
×
209
        dumpsysOptionPanel.add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
210
        dumpsysOptionPanel.add(dumpsysTypeChoosePanel);
×
211
    }
×
212

213
    private void createDumpsysOperationPanel() {
214
        dumpsysOperationPanel = new JPanel();
×
215
        BoxLayout boxLayout = new BoxLayout(dumpsysOperationPanel, BoxLayout.X_AXIS);
×
216
        dumpsysOperationPanel.setLayout(boxLayout);
×
217

218
        dumpsysStartButton = new JButton("Start");
×
219
        dumpsysStartButton.setEnabled(true);
×
220
        dumpsysStartButton.addActionListener(new DumpsysStartButtonActionListener());
×
221
        dumpsysOperationPanel.add(dumpsysStartButton);
×
222
    }
×
223

224
    class DumpsysStartButtonActionListener implements ActionListener {
×
225
        @Override
226
        public void actionPerformed(ActionEvent e) {
227
            dumpsysStartButton.setEnabled(false);
×
228
            File targetDirFile = dumpsysTargetDirPanel.getFile();
×
229
            if (!targetDirFile.exists()) {
×
230
                JOptionPane.showMessageDialog(getFrame(), "Target directory does not exist!", "ERROR", JOptionPane.ERROR_MESSAGE);
×
231
                return;
×
232
            }
233

234
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date(System.currentTimeMillis()));
×
235
            File targetDirWithTimestamp = new File(targetDirFile, timeStamp);
×
236

237
            if (!targetDirWithTimestamp.exists()) {
×
238
                boolean success = targetDirWithTimestamp.mkdirs();
×
239
                if (!success) {
×
240
                    JOptionPane.showMessageDialog(getFrame(), "Create target directory failed!", "ERROR", JOptionPane.ERROR_MESSAGE);
×
241
                    return;
×
242
                }
243
            }
244

245
            Component[] components = dumpsysTypeChoosePanel.getComponents();
×
246
            for (Component component : components) {
×
247
                if (component instanceof JCheckBox checkBox) {
×
248
                    String dumpsysType = checkBox.getText();
×
249
                    if (checkBox.isSelected()) {
×
250
                        dumpsysAndSaveToFile(dumpsysType, targetDirWithTimestamp);
×
251
                    }
252
                }
253
            }
254
            dumpsysStartButton.setEnabled(true);
×
255
        }
×
256

257
        private void dumpsysAndSaveToFile(String dumpsysType, File targetDir) {
258
            String command = "adb shell dumpsys " + dumpsysType;
×
259
            CommandLine cmdLine = CommandLine.parse(command);
×
260
            DefaultExecutor executor = new DefaultExecutor();
×
261
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
×
262
                 ByteArrayOutputStream errorStream = new ByteArrayOutputStream();) {
×
263
                PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, errorStream);
×
264
                executor.setStreamHandler(streamHandler);
×
265
                int exitValue = executor.execute(cmdLine);
×
266
                if (exitValue == 0) {
×
267
                    String result = outputStream.toString().trim();
×
268
                    if (StringUtils.isNotEmpty(result)) {
×
269
                        File outputFile = new File(targetDir, dumpsysType + ".dumpsys");
×
270
                        FileUtils.writeStringToFile(outputFile, result, "UTF-8");
×
271
                    }
272
                } else {
×
273
                    String errorResult = errorStream.toString().trim();
×
274
                    if (StringUtils.isNotEmpty(errorResult)) {
×
275
                        File errorFile = new File(targetDir, dumpsysType + ".error");
×
276
                        FileUtils.writeStringToFile(errorFile, errorResult, "UTF-8");
×
277
                    }
278
                }
279
            } catch (IOException ex) {
×
280
                JOptionPane.showMessageDialog(getFrame(), "Execute command failed:\n" + ex.getMessage(), "ERROR", JOptionPane.ERROR_MESSAGE);
×
281
            }
×
282
        }
×
283
    }
284

285
    class AnalysisStartButtonActionListener implements ActionListener {
×
286

287
        @Override
288
        public void actionPerformed(ActionEvent e) {
289
            File analysisFile = analysisFilePanel.getFile();
×
290
            if (!analysisFile.exists()) {
×
291
                JOptionPane.showMessageDialog(getFrame(), "Analysis file does not exist!", "ERROR", JOptionPane.ERROR_MESSAGE);
×
292
                return;
×
293
            }
294
            String fileNameWithoutExtension = FilenameUtils.getBaseName(analysisFile.getName());
×
295
            String className = StringUtils.capitalize(fileNameWithoutExtension) + "2Json";
×
296
            IDumpsys2Json dumpsys2Json = getDumpsys2JsonInstance(className);
×
297
            if (dumpsys2Json != null) {
×
298
                String jsonResult = dumpsys2Json.dumpsys2Json(analysisFile);
×
299
                analysisOutputTextArea.setText(jsonResult);
×
300
                analysisOutputTextArea.setCaretPosition(0);
×
301
            }
302
        }
×
303

304
        private IDumpsys2Json getDumpsys2JsonInstance(String className) {
305
            try {
306
                String fullClassName = "edu.jiangxin.apktoolbox.android.dumpsys.tojson." + className;
×
307
                Class<?> clazz = Class.forName(fullClassName);
×
308
                if (IDumpsys2Json.class.isAssignableFrom(clazz)) {
×
309
                    return (IDumpsys2Json) clazz.getDeclaredConstructor().newInstance();
×
310
                } else {
311
                    JOptionPane.showMessageDialog(getFrame(), "Class " + fullClassName + " does not implement IDumpsys2Json!", "ERROR", JOptionPane.ERROR_MESSAGE);
×
312
                    return null;
×
313
                }
314
            } catch (ClassNotFoundException e) {
×
315
                JOptionPane.showMessageDialog(getFrame(), "Class not found: " + className, "ERROR", JOptionPane.ERROR_MESSAGE);
×
316
                return null;
×
317
            } catch (Exception e) {
×
318
                JOptionPane.showMessageDialog(getFrame(), "Error loading class: " + e.getMessage(), "ERROR", JOptionPane.ERROR_MESSAGE);
×
319
                return null;
×
320
            }
321
        }
322
    }
323
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc